SQL 如果满足条件,立即退出并从 "Instead Of" 触发器回滚
SQL Immediately exit and rollback from "Instead Of" trigger if condition is met
我在一个数据库中有一个 table,它引用另一个数据库中 table 的 ID。我已经设置了 Instead Of Insert/Update 触发器来防止插入其他 table 中不存在的 ID。我希望这些触发器在发现不存在的 ID 时中止交易,否则继续交易。
这是我尝试过的方法:
CREATE TRIGGER [dbo].[tr_check_student_insert]
ON [dbo].[student]
INSTEAD OF INSERT
AS
BEGIN
SET XACT_ABORT ON
IF (EXISTS ... )
BEGIN
RAISERROR (N'[teacher_id] does not exist in [teacher]',11,1)
END
IF (EXISTS ... )
BEGIN
RAISERROR (N'[class_id] does not exist in [class]',11,1)
END
INSERT INTO [dbo].[student] ...
END
我后来发现 RAISERROR 不会中止事务,即使 SET XACT_ABORT ON,插入(或更新)在出现错误后仍然发生。
我知道我可以将每个条件包装在 IF/ELSE IF 语句中,并在 ELSE 上调用插入,但我只是想知道是否有一种方法可以立即退出并回滚整个事务。
您需要在 TRY
CATCH
中使用 BEGIN TRANSACTION
和 ROLLBACK
尝试这样的事情:
CREATE TRIGGER [dbo].[tr_check_student_insert]
ON [dbo].[student]
INSTEAD OF INSERT
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON;
IF (EXISTS ... )
BEGIN
RAISERROR (N'[teacher_id] does not exist in [teacher]',11,1)
END
IF (EXISTS ... )
BEGIN
RAISERROR (N'[class_id] does not exist in [class]',11,1)
END
INSERT INTO [dbo].[student] ...
;
COMMIT
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
RETURN;
END CATCH
END
我在一个数据库中有一个 table,它引用另一个数据库中 table 的 ID。我已经设置了 Instead Of Insert/Update 触发器来防止插入其他 table 中不存在的 ID。我希望这些触发器在发现不存在的 ID 时中止交易,否则继续交易。
这是我尝试过的方法:
CREATE TRIGGER [dbo].[tr_check_student_insert]
ON [dbo].[student]
INSTEAD OF INSERT
AS
BEGIN
SET XACT_ABORT ON
IF (EXISTS ... )
BEGIN
RAISERROR (N'[teacher_id] does not exist in [teacher]',11,1)
END
IF (EXISTS ... )
BEGIN
RAISERROR (N'[class_id] does not exist in [class]',11,1)
END
INSERT INTO [dbo].[student] ...
END
我后来发现 RAISERROR 不会中止事务,即使 SET XACT_ABORT ON,插入(或更新)在出现错误后仍然发生。
我知道我可以将每个条件包装在 IF/ELSE IF 语句中,并在 ELSE 上调用插入,但我只是想知道是否有一种方法可以立即退出并回滚整个事务。
您需要在 TRY
CATCH
BEGIN TRANSACTION
和 ROLLBACK
尝试这样的事情:
CREATE TRIGGER [dbo].[tr_check_student_insert]
ON [dbo].[student]
INSTEAD OF INSERT
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON;
IF (EXISTS ... )
BEGIN
RAISERROR (N'[teacher_id] does not exist in [teacher]',11,1)
END
IF (EXISTS ... )
BEGIN
RAISERROR (N'[class_id] does not exist in [class]',11,1)
END
INSERT INTO [dbo].[student] ...
;
COMMIT
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
RETURN;
END CATCH
END