INSTERT或UPDATE上的PL / SQL触发器:":NEW" IS NULL =>暧昧?

时间:2017-09-01 10:18:41

标签: oracle triggers

我是PL/SQL中的新手,我试图通过触发器进行相当复杂的数据完整性检查。

我已经理解了如何在同一个桌面上使用的触发器内调用表(通过临时外部表)时如何避免问题,但现在我面临一个非常令人兴奋的问题:我认为":NEW"引用了我的表AFTER中的值更新,但事情看起来并不那么简单......这是更新或插入的新值SET ...如果没有指定任何内容,它看起来是NULL,即使更新后相应的字段值为NOT NULL ...这让我发疯了。

插入或更新多个变量时设置了我的触发器:

CREATE OR REPLACE TRIGGER TRG_INS_UP_INSTRUMENT_EVENT 
AFTER INSERT OR UPDATE OF EVENT_ID, DATE_BEGIN,DATE_END,INSTR_ID,TYPE_EVENT_ID ON AIS_INSTRUMENT_EVENT

但是现在......如果已经有一个非空字段的行,我会做

UPDATE AIS_INSTRUMENT_EVENT SET INSTR_ID='642' WHERE EVENT_ID='6479'

我实际上得到的":NEW.DATE_BEGIN"NULL ...事件被认为,旧的或更新的值都是NULL(因为我没有更新它)。

我如何区分 - 在我的触发器中 - DATE_BEGIN更新的情况和SET自愿到NULL的情况,其中没有指定任何内容(此字段必须因此保持不变但不一定是NULL ...)。我需要多种可能的组合来逐一检查...

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

你说的不是真的。 :new包含完整行,无论该列是否在UPDATE语句中引用:

CREATE TABLE test (test INTEGER, last_changed DATE);

CREATE OR REPLACE TRIGGER TRG_INS_UP_TEST 
AFTER INSERT OR UPDATE OF test, last_changed ON test
FOR EACH ROW
BEGIN
 dbms_output.put_line('LAST CHANGED IS ' || :new.last_changed);
END;

INSERT INTO test (test, last_changed) VALUES  (1, SYSDATE);

COMMIT;

UPDATE test SET test = test + 1;

DBMS输出:

LAST CHANGED IS 01.09.17

为了达到你想要的效果,机制的工作方式略有不同。您必须查看两个不同的用例:

1。)除非提到某个列,否则您希望触发器不会触发。此用例是通过触发器声明中的引用(INSERT OR UDATE OF“column_name”)。如果INSERT / UPDATE语句仅影响未提及的列,则触发器将不会触发。

2.。)除非修改某一行,否则不要触发触发器。因此,只有当fire值实际发生了变化时,才需要触发器。这是通过WHEN限制触发器来完成的。它通常与DECODE一起使用,如下所示:

CREATE OR REPLACE TRIGGER TRG_INS_UP_TEST 
AFTER INSERT OR UPDATE OF test, last_changed ON test  
FOR EACH ROW
WHEN (DECODE(new.test,old.test,0,1)=1 OR DECODE(new. last_changed,old. last_changed,0,1)=1)
BEGIN 
   ...
END;

所以回答你原来的问题:如果你想要触发器,只有在DATE_BEGIN列设置为NULL的情况下才会触发,你必须使用两种方法声明你的触发器

CREATE OR REPLACE TRIGGER TRG_INS_UP_INSTRUMENT_EVENT 
AFTER INSERT OR UPDATE OF DATE_BEGIN ON AIS_INSTRUMENT_EVENT
FOR EACH ROW
WHEN (DECODE(new.DATE_BEGIN,old. DATE_BEGIN,0,1)=1 AND new.DATE_BEGIN IS NULL)

对某些列的限制(“INSERT OR DATE_BATE更新”)并不是绝对必要的,但这是一种很好的做法,因为它可以提高性能,因为它根本不会触发触发器。

答案 1 :(得分:0)

抱歉,我想我快速得出结论......这个错误是我的。我已经测试了玩具"表,实际上,即使没有UPDATE设置,NEW也不为null。我在此期间发现了这个错误。这对我来说太新了; - )。

抱歉令人不安。