【发布时间】:2019-11-14 01:39:33
【问题描述】:
我有 3 张桌子,比如说 A 桌、B 桌和 C 桌。
我在表 A 上有一个触发器,它将数据插入到表 B 中,我在表 b 上也有一个触发器,将数据输入到表 C 中。在表 C 上,有一个执行过程的触发器。
任务是即使在对表 C 的操作过程中发生了某些事情,即(发生任何错误),对表 A、B 和 C 的操作也应该继续并完成。问题是如果程序出现问题,对表 A、B 和 C 的操作也会中止。
我的表 C 触发器是:
CREATE TRIGGER [dbo].[Trg_Mst_TableC]
ON [dbo].[TableC]
FOR UPDATE
AS
BEGIN
DECLARE @flg_Error INT
SET @flg_Error = 0
DECLARE @SLQString NVARCHAR(MAX)
SELECT @SLQString = 'Text Message'
SAVE TRANSACTION MySavePoint
IF ISNULL(@SLQString, '') <> ''
BEGIN
EXEC spMsc_SendMsg 'Test', 'POST', @SLQString
IF @@error <> 0 BEGIN
ROLLBACK TRAN MySavePoint
END
END
END
这是我的程序:
CREATE PROCEDURE [dbo].[spMsc_SendMsg]
@msg_type NVARCHAR(50),
@getpost NVARCHAR(20),
@msg_txt NVARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON
SAVE TRANSACTION MySavePoint
CREATE TABLE Test (XXX NVARCHAR(MAX))
SELECT @msg_type, @getpost, @msg_txt
END
现在此过程返回“测试”表的错误消息。但我需要保存完成的剩余事务直到触发器 C。 请给我解决方案。
【问题讨论】:
-
您不能在触发器中
COMMIT事务。事务的处理应该在它之外完成,而不是在里面。您在这里真正要解决的问题是什么? -
我推荐
XACT_ABORT ON、TRY .. CATCH并在您尝试任何非平凡的错误处理之前阅读所有this。如果可能的话,如果您不希望原始事务中止,请不要在触发器中做任何可能出错的事情——如有必要,通过插入表或服务代理队列来推迟处理。 -
哦,触发其他触发器的触发器本质上是撒旦的工具。可能应该重新考虑这样的设计,以支持在表 A、B 和 C 上操作的存储过程调用,因为整个操作显然代表的不仅仅是单个插入。即使由于无法更改客户端代码而必须使用触发器,但最好不要嵌套触发器,而是将所有逻辑放在一个级别上。
TRIGGER_NESTLEVEL()可用于检查是否从嵌套上下文中调用了触发器,如果是这种情况,则无需执行任何操作即可返回。
标签: sql-server tsql stored-procedures database-trigger savepoints