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 TRANSACTIONROLLBACK

尝试这样的事情:

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