如果我的触发器在存储过程中更新后失败怎么办?

What if my trigger fails after an update inside a stored procedure?

如果我在 SQL 服务器的存储过程中有一个更新,并且存储过程成功运行,但是,无论出于何种原因,该更新的触发失败,我的更新会被回滚吗?

是的,如果在您的触发器中发生回滚或任何 运行时间错误,它将回滚上面的特定(或隐含)事务。

要在您询问的更新中看到这种情况,运行 这个:

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;

您会看到 MyTable 中 ID 的值仍然是 1,而 OtherTable 仍然是空的,因为触发器在 UPDATE 期间抛出了错误。

即使您在触发器和更新批次中设置 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 来处理 运行 时间错误并允许触发器完成。