Luk*_*der 6 sql oracle triggers plsql
假设我有这样的触发器规范:
create table "t" (
"i" number(10)
);
create or replace trigger "trg"
before insert on "t"
referencing new as "n"
for each row
begin
null;
end;
Run Code Online (Sandbox Code Playgroud)
如何"n"从正文中引用标识符?这些都不起作用:
"n"."i" := 2;
:"n"."i" := 2;
":n"."i" := 2;
:n."i" := 2;
Run Code Online (Sandbox Code Playgroud)
所有这些尝试都可以编译,但在尝试插入表时会产生此错误:
ORA-04098: 触发器 'TEST.trg' 无效且重新验证失败
显然,我可以避免引用变量名,但是 1) 这是关于从工具生成代码,无论引用如何,它都必须正确使用此语法,并且 2) 我对正确的语法很好奇。
在CREATE TRIGGERdocs,有一个参考(强调我的):
在简单触发器的 trigger_body 或复合触发器的 tps_body 中,相关名称是绑定变量的占位符。
似乎绑定变量一般不支持引用,例如虽然这有效:
BEGIN
EXECUTE IMMEDIATE 'BEGIN dbms_output.put_line(:x); END;' USING 'a';
END;
Run Code Online (Sandbox Code Playgroud)
这或任何类似的语法不会:
BEGIN
EXECUTE IMMEDIATE 'BEGIN dbms_output.put_line(:"x"); END;' USING 'a';
END;
Run Code Online (Sandbox Code Playgroud)
所以,这似乎是一致的,但我仍然很好奇为什么我可以像这样声明名称,但似乎无法引用它。
数据库版本为 Oracle Database 18c Express Edition Release 18.0.0.0.0
根据文档,这些不是正常的标识符,而是“相关名称”,预计为new,old或parent:
指定相关名称,它引用当前行的旧值、新值和父值。默认值:旧的、新的和父级。
可以使用替代名称:
如果触发器与名为 OLD、NEW 或 PARENT 的表关联,则使用此子句指定不同的相关名称,以避免表名称和相关名称之间的混淆。
但您不能在对相关名称的"任何引用中使用。有趣的是,如果标识符全部大写,则可以成功引用它:
create or replace trigger "trg"
before insert on "t"
referencing new as "N"
for each row
begin
:N."i" := 2;
:n."i" := 2;
end;
Run Code Online (Sandbox Code Playgroud)