我的数据库上有一个触发器,用于强制执行业务规则:当某个“事件”发生时,其中一个表上的标志会更新。我知道这不是建议使用触发器,更好的做法是在生成事件的代码中在数据库之外强制执行此规则。但是由于我无法控制的原因,这是不可能的,并且这个标志的维护属于数据库。
所以,我设计了适当的查询来维护这个标志。查询是这样的:
UPDATE flg_tbl
SET flag = 'T'
FROM flag_table AS flg_tbl
INNER JOIN table1 AS tbl1 ON tbl1.id = flg_tbl.id
INNER JOIN table2 AS tbl2 ON tbl2.id = flg_tbl.id
...
WHERE tbl2.id IN (SELECT id FROM inserted)
当我手动运行此查询时,一切都运行良好。但作为触发器,没有任何反应。
此触发器将在表插入流之后执行,这会影响查询中的所有内部联接表。我将触发器作为AFTER INSERT触发器放在表的列表中更新的最后一个表上,但它仍然不起作用。我觉得它在插入流程中被执行的事实是罪魁祸首;也许这些表都尚未提交,触发器正在使用旧数据,尽管已被触发。
有没有办法延迟触发,直到整个交易提交完毕?或者它是否在等待它的确定,我只是没有看到真正的原因?
查询的完整,混淆版本(X是要更新的表,我是触发器所在的表):
UPDATE X
SET X.flag = 'T'
FROM tableA AS A
INNER JOIN tableB AS B ON A.id = B.id
INNER JOIN tableX AS X ON X.otherrow = B.otherrow
INNER JOIN tableA AS A2 ON A.diffrow = A2.diffrow AND X.id = A2.id
INNER JOIN tableC AS C ON B.id = C.id AND C.otherflag = 'A'
INNER JOIN tableI AS I ON I.id = B.id
WHERE I.id IN (SELECT id FROM inserted)
答案 0 :(得分:0)
引用tableI(带触发器的那个)似乎是不必要的,因为它的行在inserted
中。以下似乎是等效的,可以避免这个问题:
UPDATE X
SET X.flag = 'T'
FROM tableA AS A
INNER JOIN tableB AS B ON A.id = B.id
INNER JOIN tableX AS X ON X.otherrow = B.otherrow
INNER JOIN tableA AS A2 ON A.diffrow = A2.diffrow AND X.id = A2.id
INNER JOIN tableC AS C ON B.id = C.id AND C.otherflag = 'A'
WHERE B.id IN (SELECT id FROM inserted)
或
UPDATE X
SET X.flag = 'T'
FROM tableX AS X
INNER JOIN tableB AS B ON X.otherrow = B.otherrow
INNER JOIN tableA AS A ON A.id = B.id
INNER JOIN tableA AS A2 ON A.diffrow = A2.diffrow AND X.id = A2.id
INNER JOIN tableC AS C ON B.id = C.id AND C.otherflag = 'A'
WHERE B.id IN (SELECT id FROM inserted)