TRIGGER 中的 ROLLBACK 导致 Msg 3609

ROLLBACK in TRIGGER causes Msg 3609

我有一个项目 table 和一个 Items_Log table 来记录对项目 table.

的所有更改
CREATE TABLE [dbo].[Items] (
  [item_id] [int] IDENTITY(1,1) NOT NULL,
  [item_name] [varchar](50) NOT NULL,
  [item_desc] [varchar](250) NULL,
  [modified_by_id] [int] NOT NULL,
  [modified_date] [datetime] NOT NULL
)

CREATE TABLE [dbo].[Items_Log] (
  [item_log_id] [int] IDENTITY(1,1) NOT NULL,
  [item_id] [int] NOT NULL,
  [item_name] [varchar](50) NOT NULL,
  [item_desc] [varchar](250) NULL,
  [modified_by_id] [int] NOT NULL,
  [modified_date] [datetime] NOT NULL
)

项目 table 的更新是在 SPROC 中执行的。 ([modified_by_id] 有意注释掉,如下所述)

CREATE PROCEDURE [dbo].[pUpdateItem]
  @ItemID INT,
  @Name VARCHAR(100),
  @ByID INT
AS
  UPDATE [Items] SET
    item_name = @Name,
    --modified_by_id = @ByID,
    modified_date = GETDATE()
  WHERE item_id = @ItemID;
GO

项目 table 上有一个触发器,它在以任何方式更新时记录旧数据。

ALTER TRIGGER [dbo].[tItemsUpdate] 
   ON [dbo].[Items] 
   AFTER UPDATE
AS
BEGIN
  SET NOCOUNT ON;

  IF (UPDATE(modified_by_id) AND UPDATE(modified_date))
    BEGIN
      INSERT INTO [Items_Log]
        SELECT * FROM Deleted
    END
  ELSE
    BEGIN
      RAISERROR ('[modified_by_id] and [modified_date] must be updated.', 16, 1)
      ROLLBACK TRANSACTION
    END
END

为了测试触发器,[modified_by_id] 被注释掉以便调用 RAISERROR。我收到 2 个错误:

Msg 50000, Level 18, State 1, Procedure tItemsUpdate, Line 15
[modified_by_id] and [modified_date] must be updated.
Msg 3609, Level 16, State 1, Procedure pUpdateItem, Line 5
The transaction ended in the trigger. The batch has been aborted.

第一个错误显然是我想看到的错误,事务正确回滚。但我真的希望它在不抛出第二个错误的情况下退出,因为它会像这样为用户显示。

因此,根据我在其他地方看到的建议,我尝试在 SPROC 中执行 Try...Catch,并在那里正式声明事务和回滚(并从触发器中取出回滚) .它在 SPROC 中看起来像这样:

BEGIN TRY
  BEGIN TRANSACTION
    UPDATE [Items] SET
      item_name = @Name,
      --modified_by_id = @ByID,
      modified_date = GETDATE()
    WHERE item_id = @ItemID;
  COMMIT TRANSACTION
END TRY
BEGIN CATCH
  ROLLBACK TRANSACTION
END CATCH

现在更新没有发生,但我没有收到任何错误消息。连 RAISERROR 的那个都不行。

我希望我能简单地压制 "Msg 3609"。这将使一切都按照我想要的方式工作。但在这一点上,我将采用几乎所有可行的解决方案。

谁能帮我解决这个问题?

BEGIN CATCH  
    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; 
    ROLLBACK TRANSACTION;
END CATCH;  

https://msdn.microsoft.com/en-us/library/ms190358.aspx

BEGIN CATCH  
    DECLARE @ErrorSeverity INT, @ErrorState INT, @ErrorMessage VARCHAR(100); 
    SELECT @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(), @ErrorMessage = ERROR_MESSAGE(); 
    ROLLBACK TRANSACTION; 
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH