ORA-4088、ORA-6512 使用触发器和 RAISE_APPLICATION_ERROR
Posted
技术标签:
【中文标题】ORA-4088、ORA-6512 使用触发器和 RAISE_APPLICATION_ERROR【英文标题】:ORA-4088, ORA-6512 Using Triggers and RAISE_APPLICATION_ERROR 【发布时间】:2020-06-06 14:36:08 【问题描述】:在尝试使用触发器在 Oracle 中强制执行外键完整性时
CREATE OR REPLACE TRIGGER TRG_IU_SPONSORID_user_registration
BEFORE INSERT OR UPDATE OF U_SPONSORID ON user_registration
FOR EACH ROW
DECLARE l_SPONSORID VARCHAR2 (2000);
BEGIN
SELECT U_SPONSORID
Into l_SPONSORID
FROM U_SPONSOR WHERE U_SPONSORID = :NEW.U_SPONSORID;
If l_SPONSORID is null
THEN raise_application_error(-20010, 'Not a valid SPONSORID: '|| ':NEW.U_SPONSORID');
End if;
END;
我收到以下错误,但未打印引发错误消息
ORA-6512: at "BPORTD1.TRG_IU_SPONSOR_USER_REGISTRATION", line 3
ORA-4088: error during execution of trigger 'BPORTD1.TRG_IU_SPONSOR_USER_REGISTRATION'
知道为什么会这样吗?
【问题讨论】:
【参考方案1】:你写的代码有 1.5 个错误:
1st:如果U_SPONSOR
表中没有这样的行,select
不会像你想的那样返回NULL
,但是no_data_found
你应该处理;我想这就是发生在你身上的事
0.5th:从dbms_output.put_line
中的':new.u_sponsorid'
中删除单引号,因为您将按字面意思显示,而不是ID 值。
示例表和触发器:
SQL> create table u_sponsor (u_sponsorid number);
Table created.
SQL> create table user_registration(u_sponsorid number);
Table created.
SQL> create or replace trigger trg_iu_sponsor
2 before insert or update of u_sponsorid on user_registration
3 for each row
4 declare
5 l_sponsorid varchar2 (2000);
6 begin
7 select u_sponsorid
8 into l_sponsorid
9 from u_sponsor
10 where u_sponsorid = :new.u_sponsorid;
11 exception
12 when no_data_found then
13 raise_application_error(-20010,
14 'Not a valid SPONSORID: '|| :new.u_sponsorid);
15 end;
16 /
Trigger created.
测试:主行优先:
SQL> insert into u_sponsor values (200);
1 row created.
两个细节:
SQL> insert into user_registration values (100);
insert into user_registration values (100)
*
ERROR at line 1:
ORA-20010: Not a valid SPONSORID: 100
ORA-06512: at "SCOTT.TRG_IU_SPONSOR", line 10
ORA-04088: error during execution of trigger 'SCOTT.TRG_IU_SPONSOR'
SQL> insert into user_registration values (200);
1 row created.
SQL>
但是,我猜您只是出于教育目的使用触发器来强制执行参照完整性,因为 - 如果您想正确地这样做,请创建外键约束。像这样的:
SQL> create table u_sponsor (u_sponsorid number primary key);
Table created.
SQL> create table user_registration(u_sponsorid number references u_sponsor);
Table created.
SQL> insert into u_sponsor values (200);
1 row created.
SQL> insert into user_registration values (100);
insert into user_registration values (100)
*
ERROR at line 1:
ORA-02291: integrity constraint (SCOTT.SYS_C009854) violated - parent key not found
SQL> insert into user_registration values (200);
1 row created.
SQL>
【讨论】:
我有另一个与此相关的问题:还有另一个表“U_PROJECT”,我还需要在此触发器中同时验证“PROJECTID”并打印消息。 在同一个触发器中包含另一个 SELECT 语句。或者,您可以创建另一个触发器(只是名称不同)。但是,正如我所说,您宁愿创建外键约束,而不是通过触发器强制引用完整性。 这些主表是从 prod 复制到 test Env 的,为了避免主数据安全,建议使用这种触发器。 如果您的数据安全建议使用这种触发器,那么您的数据安全不了解数据库功能。这似乎是一个很大的安全问题。那是建议还是要求? Hey Belayer,没有外键事务表将无法同步数据,因此绝对要求在此基础上,他们建议不要用作主键,只需使用参考检查值扳机。您能否详细说明在这种情况下会出现什么安全问题。以上是关于ORA-4088、ORA-6512 使用触发器和 RAISE_APPLICATION_ERROR的主要内容,如果未能解决你的问题,请参考以下文章
PL/SQL ORA-01422 SELECT INTO 错误,Oracle 匿名块(NOVA 环境)