我有一个Items表&一个Items_Log表,用于记录对Item表的所有更改。TRIGGER中的ROLLBACK导致消息3609
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
)
项目表的更新在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
有上时,它以任何方式被更新该记录中的旧数据的项目表的触发器。
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,以及正式声明事务和回滚(并将回滚从触发器中取出)。它看起来像这样的存储过程:
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”。这将使所有事情都以我想要的方式工作。但在这一点上,我会采取几乎任何有效的解决方案。
任何人都可以帮助我吗?
好吧,我得到了错误的信息这种方式,但现在它不是引发错误回到我的课。我想我可以用捕获的值再次做RAISERROR? – Bob
是的,你可能会提出新的错误,可能会添加一些信息。 – Serg
是的,这将是一个庞大的一点,如果我有在做几乎所有的存储过程,但是这基本上是我现在有: BEGIN CATCH DECLARE @ErrorSeverity INT' 'DECLARE @ErrorState INT' ' DECLARE @ErrorMessage VARCHAR(100)' SET @ErrorSeverity = ERROR_SEVERITY() SET @ErrorState = ERROR_STATE() SET @ErrorMessage = ERROR_MESSAGE() 回滚事务; RAISERROR(@ErrorMessage,@ErrorSeverity,@ErrorState); END CATCH' – Bob