触发器上的变异错误以计算平均成本

Posted

技术标签:

【中文标题】触发器上的变异错误以计算平均成本【英文标题】:Mutating Error on a trigger to calculate average cost 【发布时间】:2013-04-18 21:05:51 【问题描述】:

我有两张表,PRODUCTS 和 STATE_PRICE。每种产品的价格因州而异。 PRODUCTS 表跟踪所有州的每种产品的平均成本。我正在尝试编写一个触发器,当在 STATE_PRICE 表中插入、更新或删除价格时,该触发器将更新 PRODUCTS 表中商品的平均价格。我编写了以下触发器,它可以编译,但是当我测试它时,我收到一条变异错误消息。我了解变异错误的概念,即我正在尝试更新正在对其执行触发器的表,但我实际上是在尝试在 STATE_PRICE 表上执行触发器时更新 PRODUCTS 表。

create or replace trigger trg_avg_cost
after insert or update or delete on state_price
for each row

declare
w_price state_price.list_price%type;
w_product state_price.productid%type;

begin
w_price := :new.list_price;
w_product := :new.productid;

update products
set avg_cost_per_unit = (select avg(w_price) from state_price
where productid = w_product);

end;
/

我收到的具体错误消息是:

错误报告:

SQL Error: ORA-04091: table STATE_PRICE is mutating, trigger/function may not see it
ORA-06512: at "TRG_AVG_COST", line 9
ORA-04088: error during execution of trigger 'TRG_AVG_COST'
04091. 00000 -  "table %s.%s is mutating, trigger/function may not see it"
*Cause:    A trigger (or a user defined plsql function that is referenced in
           this statement) attempted to look at (or modify) a table that was
           in the middle of being modified by the statement which fired it.
*Action:   Rewrite the trigger (or function) so it does not read that table.

【问题讨论】:

我认为您必须在声明中使用 Pragma Autonomous_transaction 并再次检查 【参考方案1】:

可能存在引用完整性约束(在 productid 上),这也可能引发相同的错误。如果是这种情况,下面的链接可以帮助您避免错误。

http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551198119097816936

【讨论】:

ORA-04091 只会在触发器中的 SQL 语句尝试访问触发器所在的表时从行触发器中抛出。外键违规会导致不同的错误(ORA-02291、ORA-02292 或 ORA-02298,具体取决于具体情况)。【参考方案2】:

在行触发器中,没有 SQL 语句可以访问触发器所在的表。您的 SELECT AVG(W_PRICE) FROM STATE_PRICE WHERE PRODUCTID = W_PRODUCT 是导致错误的原因。解决此限制的经典方法是使用复合触发器 - 文档 here。另请参阅我对 this *** question 的回答,了解实现复合触发器的示例。

分享和享受。

【讨论】:

感谢您的帮助。看来复合触发器正是我所需要的!

以上是关于触发器上的变异错误以计算平均成本的主要内容,如果未能解决你的问题,请参考以下文章

如何避免“表变异”错误

SQL 表正在变异...错误

插入上的 Oracle 变异触发器

如何修复 ORA-04091:表正在变异,触发器/函数可能看不到它?

表正在变异,触发器/函数可能看不到它;需要后/行级查询

错误触发器:表正在变异,触发器/函数可能看不到它