0

我的数据库上有一个触发器,用于执行业务规则:当某个“事件”发生时,其中一个表上的标志会更新。我知道这不是触发器的建议使用,最好的办法是在数据库之外,在生成事件的代码中强制执行此规则。但是由于我无法控制的原因,这是不可能的,并且该标志的维护属于数据库。

所以,我设计了适当的查询来维护这个标志。查询是这样的:

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)
4

1 回答 1

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)
于 2012-08-01T19:53:35.543 回答