我有两个涉及两个不同模式的表。
模式服务和表任务-列ID
Schme mona_internal和table officius_unos-列任务
我在插入列任务表officius_unos时需要触发器,以检查是否存在从表任务的列id中插入值。如果存在,则要继续插入,就不会出现该错误。
这是触发因素:
CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA
BEFORE INSERT ON OFFICIUS_UNOS
FOR EACH ROW
DECLARE
task_provera number(10);
BEGIN
select id into task_provera from servis.task
where id=:new.task;
if (task_provera is null)
then raise_application_error(-20101, 'No task');
else insert into mona_internal.OFFICIUS_UNOS (task) values (:new.task);
end if;
END;
触发器已编译,但是尝试在列任务表officius_unos中插入新值时出现问题, 它向我返回此消息
insert into officius_unos (task) values (291504);
Error report -
ORA-00036: maximum number of recursive SQL levels (50) exceeded
ORA-00036: maximum number of recursive SQL levels (50) exceeded
ORA-06512: at "MONA_INTERNAL.PROBA_PROBA", line 5
ORA-04088: error during execution of trigger 'MONA_INTERNAL.PROBA_PROBA'
ORA-06512: at "MONA_INTERNAL.PROBA_PROBA", line 10
表任务的ID列中存在值291504。
P.S。也可以尝试通过检查约束来解决此问题,但是存在禁止的子查询。用来解决问题的解决方案在这里
答案 0 :(得分:1)
您不需要在插入触发器中插入。
如果触发成功,Oracle将自行继续执行INSERT。
因此,直接的解决方案是从触发器中删除INSERT:
CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA
BEFORE INSERT ON OFFICIUS_UNOS
FOR EACH ROW
DECLARE
task_provera number(10);
BEGIN
select id
into task_provera
from servis.task
where id=:new.task;
if (task_provera is null) then
raise_application_error(-20101, 'No task');
end if;
// nothing do do here
END;
但是,以上仍然不正确。如果id
中不存在servis.tak
,则SELECT将抛出NO_DATA_FOUND
异常。
一种解决方案是使用将始终返回一行的聚合函数。如果没有任何行符合WHERE条件,则返回NULL值:
CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA
BEFORE INSERT ON OFFICIUS_UNOS
FOR EACH ROW
DECLARE
task_provera number(10);
BEGIN
select max(id)
into task_provera
from servis.task
where id=:new.task;
if (task_provera is null) then
raise_application_error(-20101, 'No task');
end if;
// nothing do do here
END;
或者您可以明确地捕获异常:
CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA
BEFORE INSERT ON OFFICIUS_UNOS
FOR EACH ROW
DECLARE
task_provera number(10);
BEGIN
select max(id)
into task_provera
from servis.task
where id=:new.task;
if (task_provera is null) then
raise_application_error(-20101, 'No task');
end if;
EXCEPTION
WHEN NOT_DATA_FOUND THEN
raise_application_error(-20101, 'No task');
END;
但是正确的方法是对此类内容使用外键约束。
alter table mona_internal.PROBA_PROBA
add constraint fk_proba_task
foreign key (task)
references servis.task (id);
那么您根本不需要触发器。
这要求不仅向用户mona_internal
授予servis.task的SELECT
特权,而且还授予references
特权:
为此,请以SERVIS
用户身份运行以下命令:
grant references on task to mona_internal;