从触发器调用过程
call procedure from trigger
我用游标创建过程,我想通过更新触发器调用它,但它失败了。错误消息已翻译。在此过程中,我使用游标检查列 STATE 中的所有行是否具有相同的值,如果条件为真,我在 table 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;
我将你的 cursors 替换为 select into 并将你的程序更改为 AUTONOMOUS 它会起作用,但我建议您避免在触发器中更新相同的 table,并可能插入其他一些 table,例如: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;
我用游标创建过程,我想通过更新触发器调用它,但它失败了。错误消息已翻译。在此过程中,我使用游标检查列 STATE 中的所有行是否具有相同的值,如果条件为真,我在 table 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;
我将你的 cursors 替换为 select into 并将你的程序更改为 AUTONOMOUS 它会起作用,但我建议您避免在触发器中更新相同的 table,并可能插入其他一些 table,例如: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;