【发布时间】:2012-08-02 04:28:10
【问题描述】:
我的数据库上有一个触发器,用于执行业务规则:当某个“事件”发生时,其中一个表上的标志会更新。我知道这不是触发器的建议使用,最好的办法是在数据库之外,在生成事件的代码中强制执行此规则。但是由于我无法控制的原因,这是不可能的,并且该标志的维护落在了数据库中。
所以,我设计了适当的查询来维护这个标志。查询是这样的:
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 是要更新的表,I 是触发器所在的表):
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)
【问题讨论】:
-
如何手动运行它?
inserted不存在于触发器范围之外。 -
您在哪些表上放置了触发器?
-
@AaronBertrand 我用插入的 id 替换了 (SELECT id FROM inserted)。
-
@hatchet 我把触发器放在了一个内部连接表上。其中有 5 个,我将触发器放在外部代码插入的最后一个上。
-
@Klazen108 - 所以一个特定的 id 值将在所有这些表中都有一个条目,在每个名为 Id 的列中?如果仅更新 flg_tbl 时所有内部联接都在 flg_tbl.id 上联接,那么它们的目的是什么?我怀疑 id 列在连接中混淆了,和/或
WHERE子句总是返回 false。
标签: sql-server tsql triggers