【发布时间】:2021-05-18 21:50:29
【问题描述】:
这是一个旧的 SQL Server 2008 Express 数据库(实际上有五个),我刚刚迁移到 SQL Server 2019 Express。在我的工作人员进来之前,一切似乎都运行良好,我们到处都遇到了错误。结果我们在触发器中有RAISEERROR,即使我的兼容性似乎设置为2008(100),我们仍然收到错误。所以我升级到THROW。现在一切似乎都运行良好,但由于我不是 DBA,我担心我的升级会损坏一些数据或留下孤儿。以下是其中一个触发器的示例:
USE [toddAPB]
GO
/****** Object: Trigger [dbo].[T_tSaleLineItem_ITrig] Script Date: 5/18/2021 1:32:55 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[T_tSaleLineItem_ITrig] ON [dbo].[tSaleLineItem] FOR INSERT AS
SET NOCOUNT ON
/* * PREVENT INSERTS IF NO MATCHING KEY IN 'tProduct' */
IF (SELECT COUNT(*) FROM inserted) !=
(SELECT COUNT(*) FROM tProduct, inserted WHERE (tProduct.RecNumP = inserted.RecNumP))
BEGIN
;THROW 44447, 'The record can''t be added or changed. Referential integrity rules require a related record in table ''tProduct''.',1;
ROLLBACK TRANSACTION
END
/* * PREVENT INSERTS IF NO MATCHING KEY IN 'tSale' */
IF (SELECT COUNT(*) FROM inserted) !=
(SELECT COUNT(*) FROM tSale, inserted WHERE (tSale.RecNumS = inserted.RecNumS))
BEGIN
;THROW 44447, 'The record can''t be added or changed. Referential integrity rules require a related record in table ''tSale''.',1;
ROLLBACK TRANSACTION
END
我需要在每个触发器(数百个)上加上SET XACT_ABORT ON 吗?我是不是该?在每个THROW 之后我还需要ROLLBACK TRANSACTION 吗?
在我调整为 THROW 之前,我遇到了“44447 附近的语法错误”错误。该行以前看起来更像这样:
RAISERROR 44447 'The record can''t be added or changed. Referential integrity rules require a related record in table ''tProduct''.'
感谢您的帮助。
【问题讨论】:
-
SET XACT_ABORT ON是触发器的默认值。这与从raiserror更改为throw有什么关系?throw默认回滚。此外,如果您使用;正确终止语句,则无需在throw前面添加一个(但由于错误,SSMS 仍将其显示为红色)。你得到的实际错误是什么?raiserror还支持吗? -
@DauntlessRob 我会相信official docs 在一个 SO 问题上。
-
您可以将 xact_abort 配置为在服务器级别打开,如果您为每个过程都设置它会更有意义?
-
我建议实施适当的外键约束并完全转储此触发器。
-
@Stu 谢谢!我不知道。刚打开...等待尖叫声...
标签: sql sql-server error-handling triggers