如何在 Oracle 触发器主体中使用带引号的“引用”标识符

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

Jef*_*emp 3

根据文档,这些不是正常的标识符,而是“相关名称”,预计为new,oldparent

指定相关名称,它引用当前行的旧值、新值和父值。默认值:旧的、新的和父级。

可以使用替代名称:

如果触发器与名为 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)

https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/CREATE-TRIGGER-statement.html#GUID-AF9E33F1-64D1-4382-A6A4-EC33C36F237B__BABEBAAB