触发GROUP BY错误! (ORACLE DATABASE)

时间:2017-04-21 00:36:05

标签: sql oracle

我有一个表ORDER_HISTORY,我希望在插入之后,customer_id和totalcost的总和基于要插入MAIN_ORDER的customer_id

ORDER_HISTORY表:

History_id   |  customer_id | totalcost
---------------------------------------
      1      |     1000     |    100
      2      |     1000     |    200
      3      |     2000     |    50
      4      |     2000     |    50

我希望在触发器触发后,Main_order显示这些数据:

MAIN_ORDER表:

 customer_id | order_price
 -------------------------
    1000     |  300
    2000     |  100

我创建了以下触发器但是我有一条错误消息

CREATE TRIGGER triggerHIS
AFTER INSERT ON ORDER_HISTORY FOR EACH ROW
BEGIN
INSERT INTO MAIN_ORDER (CUSTOMER_ID,ORDER_PRICE)
SELECT CUSTOMER_ID, SUM(TOTALCOST) as ORDER_PRICE
FROM ORDER_HISTORY
GROUP BY CUSTOMER_ID;
END;

错误信息是:

One error saving changes to table "PR"."ORDER_HISTORY":
Row 4: ORA-04091: table PR.ORDER_HISTORY is mutating, trigger/function 
may not see it
ORA-06512: at "PR.TRIGGERHIS", line 3
ORA-06512: at line 1

2 个答案:

答案 0 :(得分:1)

对于这种情况,为了避免错误table mutating oracle有compound trigger。 你可以用这种方式编写你的触发器。

create or replace trigger TR_ORDER_HISTORY

   for insert on ORDER_HISTORY
   compound trigger

   type t_recs is table of number index by pls_integer;

   pt_Ins t_recs;

   li_Ins pls_integer := 0;

   after each row is
   begin
      li_Ins := li_Ins + 1;
      pt_Ins(li_Ins) := :new.customer_id;

   end after each row;

   after statement is
   begin
      for li in 1 .. pt_ins.count loop

         update MAIN_ORDER
            set ORDER_PRICE =
                (select sum(TOTALCOST)
                   from ORDER_HISTORY
                  where customer_id = pt_ins(li)
                  group by customer_id)
          where customer_id = pt_ins(li);

         if sql%rowcount = 0 then
            insert into MAIN_ORDER
               (CUSTOMER_ID, ORDER_PRICE)
               select customer_id, sum(TOTALCOST)
                 from ORDER_HISTORY
                where customer_id = pt_ins(li)
                group by customer_id;
         end if;

      end loop;

   end after statement;

end;

答案 1 :(得分:-1)

您可以使用触发器维护值:

CREATE TRIGGER triggerHIS
AFTER INSERT ON ORDER_HISTORY FOR EACH ROW
DECLARE
    v_cnt := int;
BEGIN
    SELECT COUNT(*) INTO v_cnt FROM MAIN_ORDER WHERE CUSTOMER_ID := NEW.CUSTOMER_ID;

    IF V_CNT > 0 THEN
        UPDATE MAIN_ORDER
            SET ORDER_PRICE = ORDER_PRICE + :NEW.TOTALCOST
            WHERE CUSTOMER_ID := :NEW.CUSTOMER_ID;
    ELSE
        INSERT INTO MAIN_ORDER(CUSTOMER_ID, ORDER_PRICE)
            SELECT :NEW.CUSTOMER_ID, :NEW.TOTALOST
            FROM DUAL;
    END;
END;