#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