在删除触发器上选择 table 时改变触发器
Mutating trigger while selecting a table on delete trigger
请帮忙解决以下问题。
我有一个有两行的 table,在删除一行时我写了一个触发器,我想将记录写入另一行的暂存 table(staging_tbl)删除后。
但它会抛出一个有效的变异触发器错误。但是有没有一种方法可以避免它并将记录写入暂存 table 只有 main table 中有 2 行并且其中一个被删除(而不是 [=15= 上的所有删除) ]).
create or replace TRIGGER a_del_trg
after delete on item_master
for each row
DECLARE
l_item NUMBER :=0;
l_item_parent number :=0;
BEGIN
INSERT INTO tmp_chk (item,item_parent) VALUES (:OLD.item,:OLD.item_parent);
SELECT a.item,a.item_parent INTO l_item , l_item_parent
FROM item_master a , tmp_chk b WHERE a.item_parent = b.item_parent
and a.item != b.item;
INSERT INTO staging_tbl
(create_date, table_name, item_sku, if_name)
values
(SYSDATE, 'Item_master', l_item, 'W'); -- want to add the remaining item here
END IF;
END a_del_trg;
我使用以下语句重现了您的错误:
create table item_master(item number, item_parent number);
insert into item_master values (1, 10);
insert into item_master values (2, 10);
create table tmp_chk(item number, item_parent number);
create table staging_tbl(create_date date, table_name varchar2(30), item_sku number, if_name varchar2(10));
我使用了你的触发器(在从你的触发器末尾删除 END IF
残留代码之后)。我收到错误 "ORA-04091: table name is mutating, trigger/function may not see it." message.
提到这个很好的解释Fix Oracle mutating trigger table errors,必须重申以下摘录:
At the end of the day, the mutating table error is usually the result of a poor application design and mutating triggers should be avoided whenever possible.
根据参考文献autonomous transactions
中的第四个选项,我将你的触发器重写如下:
create or replace TRIGGER a_del_trg
after delete on item_master
for each row
DECLARE
l_item NUMBER :=0;
l_item_parent number :=0;
pragma autonomous_transaction;
BEGIN
INSERT INTO tmp_chk (item,item_parent) VALUES (:OLD.item,:OLD.item_parent);
SELECT a.item,a.item_parent INTO l_item , l_item_parent
FROM item_master a , tmp_chk b WHERE a.item_parent = b.item_parent
and a.item != b.item;
INSERT INTO staging_tbl
(create_date, table_name, item_sku, if_name)
values
(SYSDATE, 'Item_master', l_item, 'W'); -- want to add the remaining item here
commit;
END a_del_trg;
/
运行 查询:
select * from item_master;
2 10
select * from tmp_chk ;
1 10
select * from staging_tbl;
27-NOV-15 Item_master 2 W
回滚
来自here:
"... in 999 times out of 1000, if you find yourself "forced" to use an
autonomous transaction - it likely means you have a serious data
integrity issue you haven't thought about.
Where do people try to use them?
- in that trigger that calls a procedure that commits (not an error
logging routine). Ouch, that has to hurt when you rollback.
- in that trigger that is getting the mutating table constraint. Ouch, that
hurts even more
- Error logging - OK.
- Almost everything else - not OK."
请帮忙解决以下问题。 我有一个有两行的 table,在删除一行时我写了一个触发器,我想将记录写入另一行的暂存 table(staging_tbl)删除后。 但它会抛出一个有效的变异触发器错误。但是有没有一种方法可以避免它并将记录写入暂存 table 只有 main table 中有 2 行并且其中一个被删除(而不是 [=15= 上的所有删除) ]).
create or replace TRIGGER a_del_trg
after delete on item_master
for each row
DECLARE
l_item NUMBER :=0;
l_item_parent number :=0;
BEGIN
INSERT INTO tmp_chk (item,item_parent) VALUES (:OLD.item,:OLD.item_parent);
SELECT a.item,a.item_parent INTO l_item , l_item_parent
FROM item_master a , tmp_chk b WHERE a.item_parent = b.item_parent
and a.item != b.item;
INSERT INTO staging_tbl
(create_date, table_name, item_sku, if_name)
values
(SYSDATE, 'Item_master', l_item, 'W'); -- want to add the remaining item here
END IF;
END a_del_trg;
我使用以下语句重现了您的错误:
create table item_master(item number, item_parent number);
insert into item_master values (1, 10);
insert into item_master values (2, 10);
create table tmp_chk(item number, item_parent number);
create table staging_tbl(create_date date, table_name varchar2(30), item_sku number, if_name varchar2(10));
我使用了你的触发器(在从你的触发器末尾删除 END IF
残留代码之后)。我收到错误 "ORA-04091: table name is mutating, trigger/function may not see it." message.
提到这个很好的解释Fix Oracle mutating trigger table errors,必须重申以下摘录:
At the end of the day, the mutating table error is usually the result of a poor application design and mutating triggers should be avoided whenever possible.
根据参考文献autonomous transactions
中的第四个选项,我将你的触发器重写如下:
create or replace TRIGGER a_del_trg
after delete on item_master
for each row
DECLARE
l_item NUMBER :=0;
l_item_parent number :=0;
pragma autonomous_transaction;
BEGIN
INSERT INTO tmp_chk (item,item_parent) VALUES (:OLD.item,:OLD.item_parent);
SELECT a.item,a.item_parent INTO l_item , l_item_parent
FROM item_master a , tmp_chk b WHERE a.item_parent = b.item_parent
and a.item != b.item;
INSERT INTO staging_tbl
(create_date, table_name, item_sku, if_name)
values
(SYSDATE, 'Item_master', l_item, 'W'); -- want to add the remaining item here
commit;
END a_del_trg;
/
运行 查询:
select * from item_master;
2 10
select * from tmp_chk ;
1 10
select * from staging_tbl;
27-NOV-15 Item_master 2 W
回滚
来自here:
"... in 999 times out of 1000, if you find yourself "forced" to use an autonomous transaction - it likely means you have a serious data integrity issue you haven't thought about.
Where do people try to use them?
- in that trigger that calls a procedure that commits (not an error logging routine). Ouch, that has to hurt when you rollback.
- in that trigger that is getting the mutating table constraint. Ouch, that hurts even more
- Error logging - OK.
- Almost everything else - not OK."