вызов процедуры из триггера - PullRequest
0 голосов
/ 10 сентября 2018

Я создаю процедуру с курсором и хочу вызвать ее с помощью триггера обновления, но она не удалась. Сообщение об ошибке переведено. В этой процедуре я использую курсоры, чтобы проверить, все ли строки имеют одинаковое значение в столбце STATE, и если условие истинно, я добавляю еще одну строку в таблицу 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'

Trigger:

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 голосов
/ 11 сентября 2018

Я заменил курсоры на , выделил и изменил вашу процедуру на АВТОНОМНО , и она будет работать, но я рекомендую вам не обновлять ту же таблицу в триггер и, возможно, вставить в другую таблицу, например: 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; 
...