2011-07-07 31 views
1

我有一个Oracle触发器调用PRAGMA AUTONOMOUS_TRANSACTION定义的存储过程。从触发器传递的值已经被提交,但似乎这些值在存储过程中不可用?我对此并不积极,因为调试/日志/提交的能力很困难,输出的时间让我感到困惑。我想知道是否期望任何传递值都可以在存储过程中使用,而不管AUTONOMOUS_TRANSACTION是什么? 谢谢从触发器调用Oracle自主存储过程

回答

5

作为参数传递给存储过程的值始终可供存储过程使用。这个过程是否使用自治事务来声明并不重要。

在自治事务中运行的代码无法看到调用事务所做的更改。当人们在看到他们期望的数据时出现问题时,10次中有9次是这个问题的根源。

如果您的存储过程除了向日志表中写入内容之外的任何操作,我对使用自治事务格外谨慎。如果您将自主事务用于记录以外的其他任何事情,则几乎肯定会错误地使用它们。而且您可能会引入大量与竞争条件和交易完整性相关的错误。

+0

表ABC上的触发器调用在同一个ABC表上进行选择的存储过程。在这种情况下,如果没有编译指示,我从存储过程中收到“ORA-04091:表ABC变异,触发器/函数可能看不到它”错误。存储过程中除SELECT语句以外的唯一活动是在执行INSERT/COMMIT的异常情况下完成的日志记录。 – McArthey

+2

@McArthey - 使用自治事务处理突变触发器错误几乎总是一个错误。由于SELECT语句无法看到触发语句所做的更改,这意味着您的SELECT应该在before语句触发器中完成(因为您不关心当前语句正在进行的更改)或者您需要更强大的解决方案。 –

+0

谢谢。是的,的确,我并不在乎触发器正在发生的变化,但我们正在关注具体的变化。当发生更改时,会调用存储过程来对行值进行一些分析。存储过程不会进行任何更新或插入到有问题的表中。 – McArthey

0

“的触发逻辑是有条件 它调用 存储过程以从上表A中 值中选择,使得表B可以 与计算出的值来更新更新表B”。

也许表B真的应该是从表A派生的物化视图?我们可以在填充MViews的查询的WHERE子句中构建很多复杂性。 Find out more.

0

如果你在table_x上有一个行级触发器,那么这个触发器可以被相同的语句多次触发,因为不同的行受到该语句的影响。

这些行受到影响的顺序是不确定的。因此,在执行行级触发期间,table_x的状态是不确定的。这就是为什么会引发MUTATING TABLE异常。

通过查看表的提交状态(即排除该语句和交易中的其他语句所做的所有更改),自治事务“欺骗”。

如果您希望存储过程查看table_x的状态以响应该表上的活动,则需要在所有行更改完成后完成(即在语句级触发器中,而不是行中级别触发器)。

设计模式通常是在行级别触发器中设置一个标志(包级别变量),在AFTER语句级别触发器中检查该标志,并在必要时对其进行操作并将其重置。

+0

在我的场景中,我相信那么Table_A触发器会插入到Table_B中。 Table_B AFTER触发器会触发并执行将从Table_A中SELECT并更新Table_B的存储过程?我不会有与存储过程相同的问题,因为它是同一事务的所有部分? – McArthey