创建触发器时使用“REFERENCING NEW AS NEW OLD AS OLD”

Kau*_*iya 6 sql oracle triggers plsql

我在不同的表上发现了两个类似的触发器。

create or replace TRIGGER "GM_OWNER".CHG_TYPE_TRG
AFTER INSERT OR UPDATE OR DELETE
ON CHG_TYPE
FOR EACH ROW
BEGIN
    If Inserting Then
       INSERT INTO CHG_TYPE_H
Run Code Online (Sandbox Code Playgroud)

create or replace TRIGGER invoice_trg
AFTER INSERT  OR  DELETE  OR UPDATE
ON invoice
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
    If Inserting Then
       INSERT INTO INVOICE_H
Run Code Online (Sandbox Code Playgroud)

两者都会触发在 Hist 表中插入或更新或删除与特定表相关的数据。当我们已经使用 :old 和 :new 来引用数据时,“REFERENCING NEW AS NEW OLD AS OLD”有什么用?

Ale*_*ole 5

如果省略该referencing子句,则使用默认值;如果包含它,那么您可以保留默认值,或者更改特定名称,同时保留其他名称为默认值。

因此,如果您不想更改相关名称,那么包含该子句似乎没有任何意义 - 有些人可能认为它是一件好事,因为它更明确,但我个人认为它是噪音只需重述默认值即可。

至于为什么您可能想要更改默认名称,文档说

引用子句

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

OLD如果您的触发器与名为、NEW或 的表关联PARENT,则使用此子句指定不同的相关名称,以避免表名称和相关名称之间的混淆。

混乱部分似乎只是从触发器编写者的角度来看,因为使用与触发器所在的表列等相同的名称似乎没有问题:

create table new (id number, new number);

create trigger trig
before insert on new
for each row
begin
  :new.new := 2;
end;
/

insert into new (id) values (1);

select * from new;

        ID        NEW
---------- ----------
         1          2
Run Code Online (Sandbox Code Playgroud)

该文档实际上有一个示例,其中显示“为了避免表名称和相关名称之间的冲突,...”,但似乎没有任何实际冲突。不过,使用不同的名称可能会更清晰。

如果您有一个具有“冲突”名称的表,我认为无论如何坚持默认值会不会那么:old混乱,因为引用:new可以立即识别,而其他任何内容只会增加(少量)认知负担。

当然, as OLDNEWPARENT是关键字(但不是保留字),您可能应该避免将它们用作标识符,但您可以这样做。


Ren*_*ene 4

:new 和 :old 是用于寻址旧记录和新记录的值的默认名称。

REFERENCING NEW AS A OLD AS B您可以使用例如将它们命名为其他名称。