使用触发器中断 Oracle 数据库删除和更新行
Posted
技术标签:
【中文标题】使用触发器中断 Oracle 数据库删除和更新行【英文标题】:Interrupt Oracle Database Delete and Update Row using Trigger 【发布时间】:2017-10-31 17:27:04 【问题描述】:我有两个表(T1 和 T2),其中 T2.T1_ID 引用 T1.ID。我正在尝试使用触发器对 T1 中的行删除操作进行操作,这样如果 T2 中没有对 T1 行的引用,则删除 T1 行。否则,它只是在 T1 行的 HIDDEN 列上设置一个标志值。我已经尝试通过检查 T2 是否匹配引用来做到这一点,如果是这样,我会引发一个异常,取消删除并尝试设置标志,但它似乎不起作用。编译触发器时,我得到一个错误
“ORA-04084: 无法更改此触发器类型的新值”
我猜这与我试图在删除操作期间更改数据的事实有关。我已经尝试使用具有类似问题的“删除后”触发器做类似的事情。这是我正在尝试做的一个简单示例:
create table "T1" (
"ID" number not null enable,
"HIDDEN" number,
constraint "T1_PK" primary key ("ID")
);
create table "T2" (
"T1_ID" number not null enable,
"VAL" number,
constraint "T2_FK1" foreign key ("T1_ID") references "T1" ("ID") enable
);
create or replace trigger "BD_T1"
before delete on "T1"
for each row
declare
cnt NUMBER;
records_found EXCEPTION;
begin
select count(*) into cnt from T2 where T1_ID = :OLD."ID";
if cnt > 0 then
RAISE records_found;
end if;
exception
when records_found then
:NEW."HIDDEN" := 1; -- set hidden flag and abort delete operation
end;
insert into T1 ("ID") values (1);
insert into T1 ("ID") values (2);
insert into T2 ("T1_ID", "VAL") values (1, 100);
insert into T2 ("T1_ID", "VAL") values (1, 200);
select * from T1;
delete from T1 where ID = 2; --no references so row deleted
select * from T2;
delete from T1 where ID = 1; -- references found so abort delete and set hidden flag`
【问题讨论】:
如果找到子记录,您不想引发异常或触发。 Oracle 将自动提升ORA-02292 Constraint violation - child records found
。
【参考方案1】:
基本上,您的触发器正在尝试将 DELETE 语句更改为 UPDATE 语句。你不可以做这个!但是,您可以通过完全消除触发器并将 DELETE 语句替换为带有删除选项的 MERGE 语句来完成您需要的操作。试试:
merge into t1
using (select 1 t1id from dual
union all
select 2 t1id from dual) t
on (t1.id = t.t1id)
when matched then
update set t1.hidden = 1
delete where not exists
(select null from t2 where t2.t1_id = t1id);
【讨论】:
【参考方案2】:基本上,您的触发器正在尝试将 DELETE 语句更改为 UPDATE 语句。你不可以做这个!但是,您可以通过完全消除触发器并将 DELETE 语句替换为带有删除选项的 MERGE 语句来完成您需要的操作。试试:
merge into t1
using (select 1 t1id from dual
union all
select 2 t1id from dual) t
on (t1.id = t.t1id)
when matched then
update set t1.hidden = 1
delete where not exists
(select null from t2 where t2.t1_id = t1id);
【讨论】:
以上是关于使用触发器中断 Oracle 数据库删除和更新行的主要内容,如果未能解决你的问题,请参考以下文章