【发布时间】:2016-09-28 19:55:11
【问题描述】:
我有一个 Items 表和一个 Items_Log 表来记录对 Item 表的所有更改。
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
)
对 Items 表的更新在 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
Items 表上有一个触发器,它会在旧数据以任何方式更新时记录它。
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”。这将使一切都按我想要的方式工作。但在这一点上,我会采用几乎所有可行的解决方案。
谁能帮我解决这个问题?
【问题讨论】:
标签: sql sql-server triggers transactions rollback