我的表:
TableA (id number, state number)
TableB (id number, tableAId number, state number)
TableC (id number, tableBId number, state number)
所以表C 中的项是表B 的子项,而表B 中的项是表A 的子项。反之亦然 - TableA 中的项是 TableB 的父项,TableB 中的项是 TableC 的父项。
我想控制父项的状态……例如,我们有以下数据:
TableA (id, state):
1, 40
TableB (id, tableAId, state):
1, 1, 40
2, 1, 60
TableC (id, tableBId, state):
1, 1, 40
2, 1, 50
3, 2, 60
4, 2, 70
父状态应该始终是他 child 的最小状态。因此,如果我们现在像这样更新 TableC:
update TableC set state = 50 where Id = 1;
我的触发器应该自动更新 TableB(设置状态 = 50,其中 id = 1),然后也更新 TableA(设置状态 = 50,其中 id = 1)
我想用触发器(更新后,插入,删除,在表A,表B,表C上)来做到这一点,以便在每个操作之后执行这些步骤:
如何避免“变异表错误”?在这个例子中使用自治事务是否省钱?我看到了一些意见,变异表错误表明应用程序逻辑存在缺陷 - 这是真的,我该如何更改逻辑以防止出现此错误?
谢谢
编辑:
感谢所有伟大的答案!
最后,我使用了触发器(感谢 Vincent Malgrat,他指出了 Tom Kyte 的文章)。
编辑:
在 REAL END 中,我使用了存储过程并删除了触发器:)
最佳答案
正如您已经注意到的那样,很难用触发器来满足您的业务需求。原因是Oracle 5 月 为单个查询(并行 DML)同时更新/插入多个线程的表。这意味着您的 session 无法查询它更新的表 更新发生时 .
如果您真的想使用触发器执行此操作,则必须遵循 kind of logic shown in this article by Tom Kyte .如您所见,这并不简单。
还有另一种更简单、更优雅、更易于维护的方法:使用过程。撤销应用程序用户的更新/插入权限,并编写一组允许应用程序更新状态列的过程。
这些过程将锁定父行(以防止多个 session 修改同一组行),并将以高效、可读和易于维护的方式应用您的业务逻辑。
关于Oracle 触发器 - 变异表的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2138363/