【问题标题】:SQL Immediately exit and rollback from "Instead Of" trigger if condition is met如果满足条件,SQL 立即退出并从“Instead Of”触发器回滚
【发布时间】:2015-03-04 16:54:27
【问题描述】:

我在一个数据库中有一个表,它引用了另一个数据库中表的 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 上调用插入,但我只是想知道是否有一种方法可以立即退出并回滚整个事务。

【问题讨论】:

  • 为什么要为此编写触发器?为什么不在student 表上创建外键约束?这样会更高效、更标准,并且不太可能导致维护问题。
  • 同意,但表在不同的数据库中。

标签: sql-server tsql triggers abort raiserror


【解决方案1】:

您需要在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

【讨论】:

  • 这成功了!我唯一不同的是删除了 BEGIN 和 END,因为在我(诚然有限的)经验中,它们似乎是不必要的。 CREATE TRIGGER AS [foo] BEGIN TRY ... END TRY ... BEGIN CATCH .. END CATCH 似乎工作得很好。
  • @Kevin,没有争论。 :) 只是没有清理我的代码。很高兴我能帮上忙!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多