SQL立即从"而不是"退出和回滚如果满足条件则触发

时间:2015-03-04 16:54:27

标签: sql-server tsql triggers abort raiserror

我在一个数据库中有一个表,它引用另一个数据库中表的ID。我已设置而不是插入/更新触发器,以防止插入另一个表中不存在的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上调用insert,但我只是想知道是否有办法立即退出并回滚整个事务。

1 个答案:

答案 0 :(得分:1)

您需要在BEGIN TRANSACTION ROLLBACK

中使用TRYCATCH

尝试这样的事情:

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