Plsql 用于检查插入值的触发器
这里有两个表,它们来自两个不同的模式 架构服务和表任务-列ID Schme mona_内部和表officius_unos-列任务 在列任务表OFFICUS_unos中插入时需要触发器,以检查是否存在从表任务插入列id中的值。如果存在,则要继续插入,则不存在引发错误 触发因素如下:Plsql 用于检查插入值的触发器,plsql,triggers,Plsql,Triggers,这里有两个表,它们来自两个不同的模式 架构服务和表任务-列ID Schme mona_内部和表officius_unos-列任务 在列任务表OFFICUS_unos中插入时需要触发器,以检查是否存在从表任务插入列id中的值。如果存在,则要继续插入,则不存在引发错误 触发因素如下: CREATE OR REPLACE TRIGGER mona_internal.PROBA_PROBA BEFORE INSERT ON OFFICIUS_UNOS FOR EACH ROW
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;
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;
触发器已编译,但尝试在列任务表OFFICUS_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
和值291504存在于列id的表任务中
另外,还尝试使用check约束来解决此问题,但存在禁止的子查询。我用来解决问题的方法就在这里
您不需要在插入触发器中插入 如果触发成功,Oracle将自行继续插入 因此,立即的解决方案是从触发器中移除插入:
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;
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;
然而,上述观点仍然不正确。如果servis.tak中不存在该id,则SELECT将抛出“未找到数据”异常
一种解决方案是使用一个始终返回一行的聚合函数。如果没有与WHERE条件匹配的行,则返回空值:
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用户运行以下命令:
else在mona_internal.OFFICIUS_UNOS任务值中插入:new.task;不需要。这就是错误的原因为什么不使用外键约束呢?伙计,非常感谢你的详细解释,你给我澄清了一个新的问题,这让我很困扰