pyodbc — получение результатов оператора alter

#python #sql-server #pyodbc

#python #sql-сервер #pyodbc

Вопрос:

Я пытаюсь получить результат оператора ‘alter’, который я выполняю через pyodbc.

Мой код:

 ...
connection = pyodbc.connect(connection_string, autocommit=True)
cursor = connection.cursor()
query = "ALTER INDEX index_name ON schema.table REBUILD"
cursor.execute(query)
...
 

Поскольку это не запрос, я не могу использовать curosr.fetchall() . Как я могу найти результат моего оператора?

Некоторые индексы завершатся ошибкой, потому что у пользователя, выполняющего скрипт, нет разрешений (или по какой-либо другой причине), и я хотел бы отобразить сообщение об ошибке, выданное сервером (курсор не вызывает исключения).).

Комментарии:

1. Я не могу воспроизвести вашу проблему. Когда я пытаюсь запустить эту команду от имени пользователя без достаточных привилегий (т. Е. Нет db_ddladmin ) Я получаю «pyodbc. Ошибка программирования: (‘42000’, ‘[42000] [ Microsoft] [Драйвер ODBC 17 для SQL Server] [SQL Server] Не удается найти объект «dbo.MillionRows», поскольку он не существует или у вас нет разрешений. (1088) (SQLExecDirectW)’)».

Ответ №1:

Вы можете выполнить операторы динамически (exec или sp_executesql) в блоке try / catch, который возвращает сообщение об успехе и ошибке:

 --exec
begin try
    exec('
    --statement goes here
    ALTER INDEX index_name ON schema.table REBUILD
    ');
    select cast(N'success' as nvarchar(2048)) as errormsg, 0 as errornumber;
end try
begin catch
    select error_message() as errormsg, error_number() as errornumber;
    --..maybe some transaction handling...for statements with transactions..
    --if @@trancount > 0
    --begin
    --   rollback transaction
    --end
end catch

--sp_executesql
declare @sql nvarchar(max) = 'ALTER INDEX index_name ON schema.table REBUILD';
begin try
    exec sp_executesql @stmt = @sql;
    
    select cast(N'success' as nvarchar(2048)) as errormsg, 0 as errornumber;
end try
begin catch
    select error_message() as errormsg, error_number() as errornumber;
end catch
 

Попытка / перехват не является полностью изящной, некоторые ошибки прерывают соединение (в зависимости от серьезности ошибки), и у вызывающего абонента должна быть какая-то обработка исключений:

 begin try
    exec ('
    --statement goes here
    raiserror(''xxx'', 20, 1) with log
    ');
    select cast(N'success' as nvarchar(2048)) as errormsg, 0 as errornumber;
end try
begin catch
    select error_message() as errormsg, error_number() as errornumber;
end catch
go

--transaction handling
begin try
    exec ('
    --statement goes here
    begin transaction
        declare @a int;
        select @a = ''A'' --aborts the batch
    commit transaction  --<-- this is not executed
    ');
    select cast(N'success' as nvarchar(2048)) as errormsg, 0 as errornumber;
end try
begin catch
    select error_message() as errormsg, error_number() as errornumber;
end catch
--error here: Uncommittable transaction....
go
begin try
    exec ('
    --statement goes here
    begin transaction
        declare @a int;
        select @a = ''A'' --aborts the batch
    commit transaction  
    ');
    select cast(N'success' as nvarchar(2048)) as errormsg, 0 as errornumber;
end try
begin catch
    select error_message() as errormsg, error_number() as errornumber;
    if @@trancount > 0
    begin
        rollback transaction;
    end
end catch