#sql-server #stored-procedures #triggers
#sql-server #хранимые процедуры #триггеры
Вопрос:
Однако, если у меня есть обновление внутри хранимой процедуры в SQL Server, и хранимая процедура выполняется успешно, триггер для этого обновления по какой-либо причине завершается с ошибкой, будет ли мое обновление откатываться?
Комментарии:
1. Это зависит от различных настроек. Покажите ваш фактический код (сократите до соответствующих частей).
2. Вы хотите прочитать о XACT_ABORT , который включен по умолчанию для триггера, но может быть отключен.
3. Мне еще предстоит написать код, но я пытаюсь учесть это раньше.
Ответ №1:
Да, если в вашем триггере произойдет откат или какая-либо ошибка во время выполнения, он откатит конкретную (или подразумеваемую) транзакцию над ней.
Чтобы увидеть, что это произойдет при обновлении, о котором вы спрашиваете, запустите это:
DROP TABLE IF EXISTS dbo.MyTable;
DROP TABLE IF EXISTS dbo.OtherTable;
GO
CREATE TABLE dbo.MyTable (ID INT);
GO
CREATE TABLE dbo.OtherTable (ID INT);
GO
CREATE TRIGGER dbo.UpdateTrigger
ON dbo.MyTable
FOR UPDATE
AS
BEGIN
INSERT dbo.OtherTable (ID) VALUES ('Blah');
END;
GO
INSERT dbo.MyTable (ID) VALUES (1);
GO
UPDATE dbo.MyTable SET ID = 2;
GO
SELECT ID FROM dbo.MyTable;
SELECT ID FROM dbo.OtherTable;
Вы увидите, что значение ID в MyTable по-прежнему равно 1, а OtherTable по-прежнему пуст, потому что триггер выдал ошибку во время ОБНОВЛЕНИЯ.
Даже если вы установите XACT_ABORT OFF
в триггере и в пакете обновления, обновление все равно будет откатываться.
DROP TABLE IF EXISTS dbo.MyTable;
DROP TABLE IF EXISTS dbo.OtherTable;
GO
CREATE TABLE dbo.MyTable (ID INT);
GO
CREATE TABLE dbo.OtherTable (ID INT);
GO
CREATE TRIGGER dbo.UpdateTrigger
ON dbo.MyTable
FOR UPDATE
AS
BEGIN
SET XACT_ABORT OFF;
INSERT dbo.OtherTable (ID) VALUES ('Blah');
END;
GO
INSERT dbo.MyTable (ID) VALUES (1);
GO
SET XACT_ABORT OFF;
UPDATE dbo.MyTable SET ID = 2;
GO
SELECT ID FROM dbo.MyTable;
SELECT ID FROM dbo.OtherTable;
Если вы хотите продолжить ОБНОВЛЕНИЕ, даже если триггер завершается с ошибкой, вам следует использовать TRY / CATCH в вашем триггере для обработки ошибки времени выполнения и разрешить триггеру завершиться.