从触发器调用过程

时间:2018-09-10 14:39:33

标签: sql oracle plsql database-trigger

我用游标创建了过程,但我想通过更新触发器来调用它,但是失败了。错误消息已翻译。在此过程中,我使用游标检查STATE列中是否所有行都具有相同的值,并且如果条件为true,则在表TRANSACTION内再添加一行。 错误消息:

update TRANSACTIONS
set state = 'accept'
where ORDER_ID = 8
Error report -
ORA-04091: table ADMIN.TRANSACTIONS is changing, trigger/function should not see it
ORA-06512: on "ADMIN.CON_API_PKG", line 57
ORA-06512: on "ADMIN.CON_API_PKG", line 67
ORA-06512: on "ADMIN.INSERT_FINAL_WORKPLACE", line 2
ORA-04088: error meanwhile preparing trigger 'ADMIN.INSERT_FINAL_WORKPLACE'

触发:

CREATE OR REPLACE TRIGGER INSERT_FINAL_WORKPLACE 
BEFORE UPDATE ON TRANSACTIONS 
FOR EACH ROW
BEGIN
  CON_API_PKG.CREATEFINISHTRANSACTION(:NEW.order_id);
END;

程序:

PROCEDURE createFinishTransaction
    (
        pi_tra_order_id    IN TRANSACTIONS.ORDER_ID%TYPE
    )
    AS
    BEGIN
        DECLARE
            var_o_all NUMBER;
            var_o_act NUMBER;
            var_product_id  transactions.product_id%TYPE;
            var_created     transactions.created%TYPE;
            var_note        transactions.note%TYPE;
            var_reporter_id transactions.reporter_id%TYPE;
            var_phase       transactions.phase%TYPE;

            CURSOR cursor_orders IS
                SELECT count(order_id) FROM transactions 
                WHERE order_id = pi_tra_order_id;
            CURSOR cursor_order_act IS
                SELECT count(order_id) FROM transactions 
                WHERE order_id = pi_tra_order_id
                AND state = 'accept';    
            CURSOR cursor_mapper IS
            SELECT product_id, created, note, reporter_id, phase FROM transactions
            WHERE order_id = pi_tra_order_id;
            BEGIN
             OPEN cursor_orders;
            FETCH cursor_orders INTO var_o_all;
            CLOSE cursor_orders;
            OPEN cursor_order_act;
            FETCH cursor_order_act INTO var_o_act;
            CLOSE cursor_order_act;
            OPEN cursor_mapper;
            FETCH cursor_mapper INTO var_product_id, var_created, var_note, var_reporter_id, var_phase;
            CLOSE cursor_mapper;
        IF var_o_all = var_o_act
            AND
            var_phase IS NULL
        THEN 
            INSERT INTO transactions (transaction_id, product_id, created, note,workplace_id, reporter_id, order_id, phase)
            VALUES 
            (
                (SELECT MAX(transaction_id) FROM transactions)+1,
                var_product_id,
                CURRENT_TIMESTAMP,
                var_note,
                (SELECT fw.workplace_id FROM final_workplace fw WHERE var_product_id = fw.product_id),
                var_reporter_id,
                pi_tra_order_id,
                'final'
            );
        END IF;
    END;
    END;

1 个答案:

答案 0 :(得分:0)

我将您的光标替换为 select ins ,并将您的程序更改为 AUTONOMOUS ,该程序可以工作,但是我建议您避免更新触发器中的同一表,也可能插入其他表中,例如:FINALIZED_TRANSACTIONS。

这是我的触发代码:

CREATE OR REPLACE TRIGGER INSERT_FINAL_WORKPLACE
   BEFORE UPDATE
   ON TRANSACTIONS
   FOR EACH ROW
BEGIN
   SELECT COUNT (ORDER_ID), COUNT (DECODE (STATE, 'accept', ORDER_ID, NULL))
   INTO VAR_O_ALL, VAR_O_ACT
   FROM TRANSACTIONS
   WHERE ORDER_ID = PI_TRA_ORDER_ID;

   IF VAR_O_ALL = VAR_O_ACT AND :NEW.ORDER_ID IS NULL
   THEN
      CON_API_PKG.CREATEFINISHTRANSACTION (
                                           :NEW.ORDER_ID,
                                           :NEW.PRODUCT_ID,
                                           :NEW.NOTE,
                                           :NEW.REPORTER_ID
                                          );
   END IF;
END;

这是我的程序代码:

CREATE OR REPLACE PROCEDURE CREATEFINISHTRANSACTION (
   PI_TRA_ORDER_ID   IN TRANSACTIONS.ORDER_ID%TYPE,
   PI_PRODUCT_ID     IN TRANSACTIONS.PRODUCT_ID%TYPE,
   PI_NOTE           IN TRANSACTIONS.NOTE%TYPE,
   PI_REPORTER_ID    IN TRANSACTIONS.REPORTER_ID%TYPE)
AS
   PRAGMA AUTONOMOUS_TRANSACTION;
   VAR_WORKPLACE_ID   FINAL_WORKPLACE.WORKPLACE_ID%TYPE;
BEGIN
   BEGIN
      SELECT FW.WORKPLACE_ID
      INTO VAR_WORKPLACE_ID
      FROM FINAL_WORKPLACE FW
      WHERE PI_PRODUCT_ID = FW.PRODUCT_ID;
   EXCEPTION
      WHEN OTHERS
      THEN
         --Handle exception by displaying dbms output or insert into a log table
         ROLLBACK;
   END;

   INSERT
   INTO TRANSACTIONS (
                      TRANSACTION_ID,
                      PRODUCT_ID,
                      CREATED,
                      NOTE,
                      WORKPLACE_ID,
                      REPORTER_ID,
                      ORDER_ID,
                      PHASE
                     )
      VALUES (
                (SELECT MAX (TRANSACTION_ID) FROM TRANSACTIONS) + 1,
                PI_PRODUCT_ID,
                CURRENT_TIMESTAMP,
                PI_NOTE,
                VAR_WORKPLACE_ID,
                PI_REPORTER_ID,
                PI_TRA_ORDER_ID,
                'final');

   COMMIT;
EXCEPTION
   WHEN OTHERS
   THEN
      --Handle exception by displaying dbms output or insert into a log table
      ROLLBACK;
END;