Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a quoted “referencing” identifier in an Oracle trigger body

Assuming I have a trigger specification like this:

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;

How can I reference the "n" identifier from within the body? None of these work:

"n"."i" := 2;
:"n"."i" := 2;
":n"."i" := 2;
:n."i" := 2;

All of these attempts compile, but produce this error when trying to insert into the table:

ORA-04098: trigger 'TEST.trg' is invalid and failed re-validation

Obviously, I can avoid quoting the variable name, but 1) this is about code generation from a tool, which has to get this syntax right regardless of the quoting, and 2) I'm curious about the correct syntax.

Bind variables

In the CREATE TRIGGER docs, there's a reference to (emphasis mine):

In the trigger_body of a simple trigger or the tps_body of a compound trigger, a correlation name is a placeholder for a bind variable.

It seems that bind variables in general do not support quoting, e.g. while this works:

BEGIN
  EXECUTE IMMEDIATE 'BEGIN dbms_output.put_line(:x); END;' USING 'a';
END;

This, or any similar syntax, doesn't:

BEGIN
  EXECUTE IMMEDIATE 'BEGIN dbms_output.put_line(:"x"); END;' USING 'a';
END;

So, this seems consistent, but I'm still curious about the specification of why I can declare the name like this, but cannot seem to reference it.

The database version is Oracle Database 18c Express Edition Release 18.0.0.0.0

like image 545
Lukas Eder Avatar asked Feb 02 '21 11:02

Lukas Eder


People also ask

What is $$ Plsql_unit in Oracle?

Script Name The $$PLSQL_UNIT and $$PLSQL_TYPE Conditional Compilation Flags. Description These pre-defined conditional compilation flags, or ccflags, return the name and type of the program unit. Note that they do NOT return the name of the subprogram or nested subprogram within a program unit.

What is cascading trigger in Oracle?

When a statement in a trigger body causes another trigger to be fired, the triggers are said to be cascading. Oracle Database allows up to 32 triggers to cascade at any one time.

What is DDL trigger in Oracle?

Oracle allows you to define triggers that will fire when DDL statements are executed. Simply put, DDL is any SQL statement used to create or modify a database object such as a table or an index. Here are some examples of DDL statements: CREATE TABLE.


1 Answers

According to the documentation, these are not normal identifiers, but "correlation names", expected to be new, old or parent:

Specifies correlation names, which refer to old, new, and parent values of the current row. Defaults: OLD, NEW, and PARENT.

Alternative names may be used:

If your trigger is associated with a table named OLD, NEW, or PARENT, then use this clause to specify different correlation names to avoid confusion between the table names and the correlation names.

But you cannot use " in any references to the correlation name. Interestingly, if the identifier is all uppercase, you can successfully reference it:

create or replace trigger "trg"
before insert on "t"
referencing new as "N"
for each row
begin
  :N."i" := 2;
  :n."i" := 2;
end;

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

like image 168
Jeffrey Kemp Avatar answered Nov 15 '22 00:11

Jeffrey Kemp