我在INSERT和UPDATE的表上有一个BEFORE TRIGGER。我正在动态创建此触发器的代码,其中包括检查约束的条件,例如
if colA = 1 then colB must be 0 and colC must be 1
如果是insert,我会检查所有3列的:NEW值,没有问题。但是在更新的情况下这种情况应该如何?用户可以更新这3列中的一个或两个或全部。所以我应该如何使用:NEW或:在UPDATE操作的情况下为OLD。
寻找一些指示。如果需要任何进一步的信息,请告诉我。
此致 萨钦
答案 0 :(得分:1)
您希望强制执行最终值的状态。因此,您应该使用:NEW
进行插入和更新。
if :new.colA = 1
and (:new.colB != 0 or :new.colC != 1 )
then
-- or whatever you want to happen ....
raise_application_error(-20000, 'your message here');
end if;
或者,您应该考虑在表上使用CHECK约束。约束比触发器更有效,并且是执行这样的业务规则的行业标准方法。
SQL> alter table t23 add constraint t23ck
2 check ((cola=1 and colb=0 and colc=1)
3 or cola != 1)
4 /
Table altered.
SQL> insert into t23 (cola, colb, colc) values (1, 0 , 1);
1 row created.
SQL> insert into t23 (cola, colb, colc) values (1, 0 , 2);
insert into t23 (cola, colb, colc) values (1, 0 , 2)
*
ERROR at line 1:
ORA-02290: check constraint (FOX.T23CK) violated
SQL> insert into t23 (cola, colb, colc) values (0, 0 , 2);
1 row created.
SQL>
"如果用户仅为一列提供值,那么:其他列的NEW将没有任何内容。所以我需要现有的值(:OLD)进行条件检查。"
Fnord。 :NEW值表示记录的新版本,而不是更改的值。通过简单的测试来检查这种行为非常容易:
SQL> create or replace trigger t23_upd_trg
2 before update on t23 for each row
3 begin
4 dbms_output.put_line ('new colA ='||:new.colA);
5 dbms_output.put_line ('new colB ='||:new.colB);
6 dbms_output.put_line ('new colC ='||:new.colC);
7 end;
8 /
Trigger created.
SQL> set serveroutput on
SQL> select * from t23
2 where cola = 9
3 /
COLA COLB COLC
---------- ---------- ----------
9 4 4
SQL> update t23
2 set cola = 1
3 where cola = 9
4 /
new colA =1
new colB =4
new colC =4
update t23
*
ERROR at line 1:
ORA-02290: check constraint (FOX.T23CK) violated
请参阅? :NEW.colb
和:NEW.colc
会返回原始值,因为它们保持最新状态。
"如果:在检查条件中明确提供OLD值,那么:如果用户没有为该列提供值,则NEW仍将是记录的新版本? "
:old
和:new
是用于引用记录的不同版本的名称空间。 :new
值是在事务结束时将持久保存到表中的值。如果更新语句没有设置列值,则:new.whatever = :old.whatever
。