【问题标题】:How to update a column in same table using calculated value in oracle trigger如何使用oracle触发器中的计算值更新同一表中的列
【发布时间】:2021-06-14 09:50:11
【问题描述】:

我在 oracle 中创建了一个触发器,只要同一个表的“数量”列有更新,我就需要更新“小计”列。所以我应该触发这个触发器的更新命令是:

更新 TABLENAME set QUANTITY = 6 where Order_ID = 601 AND ITEM_SEQ = 4 ;

这应该会触发我拥有的以下触发器:

AFTER UPDATE ON TABLENAME 
FOR EACH ROW 
BEGIN 
   IF UPDATING THEN UPDATE TABLENAME
          SET SUBTOTAL =  :NEW.QUANTITY * ACTUAL_PRICE
          WHERE  order_id = :NEW.order_id;
   END IF;
END; ```

However i am getting a mutating error issue ORA-04091. I searched and found that this is generally when the table is updating and we try to insert values to it , however i used "AFTER" command and so the table should have been updated by then. 
Any help ? 

【问题讨论】:

    标签: oracle oracle11g triggers mutating-table


    【解决方案1】:

    我的假设是您只是尝试更新导致触发器触发的特定行。而actual_price 也来自被修改的行。如果是这样,您只需为:new.subtotal 分配一个值即可。但是您必须在更新前触发器而不是更新后触发器中执行此操作。

    create or replace trigger your_trigger_name
      before update on your_table_name
      for each row
    begin
      :new.subtotal := :new.quantity * :new.actual_price;
    end;
    

    如果这不是家庭作业,将subtotal 定义为表中的计算列而不是尝试在触发器中维护数据会更有效且不易出错。

    【讨论】:

    • 这行得通!非常感谢贾斯汀!我认为的逻辑是,在我运行更新命令之后,字段 QUANTITY 和 ACTUAL_PRICE 被更新,因此我可以使用这些值来计算小计金额。你能帮我理解为什么我们使用 :new 而字段 ACTUAL_PRICE 没有新值。我们通过命令更新的唯一值是 QUANTITY。
    • @pun_intended - actual_price 确实有一个新值。如果您不更改它,它恰好与旧值相同。 :new 伪记录具有当前行中每一列的新值,:old 伪记录具有当前行中每一列的先前值。您可以根据需要比较 :new:old 值(确保牢记 null 比较语义)以确定 update 语句是否实际更改了特定列中的值。
    • 另一种选择是将您的列创建为生成的虚拟列。 create table ... as (... subtotal number(10,4) 始终生成为 (round(actual_price * quantity, 4)) virtual ...);这完全消除了触发器并防止无意中“设置小计...”注 (10,4) 只是用于示例。
    猜你喜欢
    • 2016-06-17
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2011-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多