2017-03-18 3 views
1

INSERTとUPDATEのテーブルにBEFORE TRIGGERがあります。すべての3列、無問題の新しい値:私は動的に挿入する場合はチェック制約などの条件を含むこのトリガーのコード、トリガーの制約をチェックして、Oracleにカスタマイズされたメッセージを記録したい

if colA = 1 then colB must be 0 and colC must be 1 

を作成しています、私は確認してください。しかし、この状態がどのように見えるかを更新する場合は?ユーザーは、これらの3つの列の1つまたは2つまたはすべてを更新することができます。だから私はどのように使用する必要があります:NEWまたはUPDATE操作の場合:OLD。

いくつかのポインタを探しています。詳しい情報が必要な場合はお知らせください。

よろしく、 サチン

答えて

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> 

「ユーザーがこれだけ1列の値を提供している場合:他の列のための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の値は、トランザクションの最後にテーブルに保持される値です。 update文で列の値が設定されていない場合は、:new.whatever = :old.whateverです。

+0

ご回答いただきありがとうございます。私は実際に制約を使用しています。トリガコードが(コードビルダロジックを介して)生成されると、制約チェックはトリガロジックの一部になります。だから、もし制約が壊れるならば、私はログテーブルに(トリガ自体で)エントリを作らなければなりません。 –

+0

こんにちは、あなたの決断について1つの質問。ユーザーがある列に対してのみ値を提供する場合、他の列のNEWには何もありません。条件チェックには既存の値(:OLD)が必要になります。このシナリオをどのように処理するのですか? –

+0

詳細な説明をありがとう。もう1つの質問。もし:OLD値がチェック条件に明示的に与えられていれば、その列に対してユーザによって値が与えられていない場合、NEWはまだレコードの新しいバージョンとなるでしょうか? –

関連する問題