如何在使用触发器插入之前成功引用另一个 table
How to successfully reference another table before insert with a trigger
我正在尝试创建一个触发器来验证 table registraties
(注册)中的新条目是否包含有效的 MNR(员工编号),但我卡在了我引用 table medewerkers
(员工)的部分。
有人可以帮我吗?
CREATE OR REPLACE TRIGGER t_MNRcontrole
BEFORE INSERT OR UPDATE
ON registraties
DECLARE
MNR_medewerkers number (SELECT MNR FROM MEDEWERKERS);
FOR EACH ROW
BEGIN
IF :new.MNR <> MNR_medewerkers
THEN raise_application_error(-20111, 'Medewerker niet herkend!');
END IF;
END;
收到的错误消息是
ORA-24344: success with compilation error
MNR_medewerkers number (SELECT MNR FROM MEDEWERKERS);
总是会失败,因为它不是一个数字,除非你的 table 碰巧只有一个条目,即使那样我也不确定 PLSQL 是否允许它通过。
更标准的情况是首先声明数字,然后在代码块中执行 SELECT INTO 以及 WHERE 子句,确保仅从 table。然后你可以将这个数字与新数字进行比较。
但是,如果您不是要与某一特定行进行比较,而是要检查该条目是否存在于该 table 中。
BEGIN
SELECT 1
INTO m_variable
FROM table
WHERE MNR = :new.MNR;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
m_variable = 1;
WHEN OTHERS THEN
m_variable = 0;
END;
预先声明m_variable,然后检查它是否为0然后报错。
too_many_rows 是为了防止 table 中有超过一行的 MNR,而 OTHERS 是为了 NO_DATA_FOUND,但我使用 OTHERS 来处理所有其他可能发生但可能不会发生的事情。
顺便说一句,这是要包含在主代码块中的代码块,因此在 BEGIN 和 IF 之间,只需更改 IF 以检查变量是否为 0。
PL/SQL 赋值运算符是 :=
,或 select x into y from z
从 SQL 查询中填充。
FOR EACH ROW
是触发器规范的一部分,而不是 PL/SQL 代码。
如果 :new.mnr
不存在于父 table 中,您将得到一个 no_data_found
异常,而不是不匹配的变量。
错误消息最好包含失败的详细信息。
在编程中,我们使用缩进来表示代码结构。
固定版本应该是这样的:
create or replace trigger trg_mnrcontrole
before insert or update on registraties
for each row
declare
mnr_medewerkers medewerkers.mnr%type;
begin
select mw.mnr into mnr_medewerkers
from medewerkers mw
where mw.mnr = :new.mnr;
exception
when no_data_found then
raise_application_error(-20111, 'Medewerker '||:new.mnr||' niet herkend!');
end;
但是,我们可以使用 foreign key constraint 更好地实现这种检查,例如:
alter table registraties add constraint registraties_mw_fk
foreign key (mnr) references medewerkers.mnr;
我正在尝试创建一个触发器来验证 table registraties
(注册)中的新条目是否包含有效的 MNR(员工编号),但我卡在了我引用 table medewerkers
(员工)的部分。
有人可以帮我吗?
CREATE OR REPLACE TRIGGER t_MNRcontrole
BEFORE INSERT OR UPDATE
ON registraties
DECLARE
MNR_medewerkers number (SELECT MNR FROM MEDEWERKERS);
FOR EACH ROW
BEGIN
IF :new.MNR <> MNR_medewerkers
THEN raise_application_error(-20111, 'Medewerker niet herkend!');
END IF;
END;
收到的错误消息是
ORA-24344: success with compilation error
MNR_medewerkers number (SELECT MNR FROM MEDEWERKERS);
总是会失败,因为它不是一个数字,除非你的 table 碰巧只有一个条目,即使那样我也不确定 PLSQL 是否允许它通过。
更标准的情况是首先声明数字,然后在代码块中执行 SELECT INTO 以及 WHERE 子句,确保仅从 table。然后你可以将这个数字与新数字进行比较。
但是,如果您不是要与某一特定行进行比较,而是要检查该条目是否存在于该 table 中。
BEGIN
SELECT 1
INTO m_variable
FROM table
WHERE MNR = :new.MNR;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
m_variable = 1;
WHEN OTHERS THEN
m_variable = 0;
END;
预先声明m_variable,然后检查它是否为0然后报错。
too_many_rows 是为了防止 table 中有超过一行的 MNR,而 OTHERS 是为了 NO_DATA_FOUND,但我使用 OTHERS 来处理所有其他可能发生但可能不会发生的事情。
顺便说一句,这是要包含在主代码块中的代码块,因此在 BEGIN 和 IF 之间,只需更改 IF 以检查变量是否为 0。
PL/SQL 赋值运算符是 :=
,或 select x into y from z
从 SQL 查询中填充。
FOR EACH ROW
是触发器规范的一部分,而不是 PL/SQL 代码。
如果 :new.mnr
不存在于父 table 中,您将得到一个 no_data_found
异常,而不是不匹配的变量。
错误消息最好包含失败的详细信息。
在编程中,我们使用缩进来表示代码结构。
固定版本应该是这样的:
create or replace trigger trg_mnrcontrole
before insert or update on registraties
for each row
declare
mnr_medewerkers medewerkers.mnr%type;
begin
select mw.mnr into mnr_medewerkers
from medewerkers mw
where mw.mnr = :new.mnr;
exception
when no_data_found then
raise_application_error(-20111, 'Medewerker '||:new.mnr||' niet herkend!');
end;
但是,我们可以使用 foreign key constraint 更好地实现这种检查,例如:
alter table registraties add constraint registraties_mw_fk
foreign key (mnr) references medewerkers.mnr;