2016-10-13 51 views
0

AS400で現在挿入されている行のフィールドを更新しようとしています。私はバージョン4.5,5.3、および7.1を使用しています。AS400の挿入時に更新トリガー

私のテストでは、CRTDTフィールド(NUMERIC 7,0)を含むテーブルWC(Work Center)を作成しました このテーブルに新しいレコードを挿入するとき、このフィールドの値が小さいそれが200,000であればそれに1,000,000を加えます。

私のSQLは次のとおりです。

-- Generate SQL 
-- Version:     V5R4M0 060210 
-- Generated on:    10/13/16 10:03:49 
-- Relational Database:  S65BEE7B 
-- Standards Option:   DB2 UDB iSeries 
CREATE TRIGGER RAVONLIB.WC_TRIGGER 
    AFTER INSERT ON RAVONLIB.WC 
    FOR EACH STATEMENT 
    MODE DB2SQL 
    SET OPTION ALWBLK = *ALLREAD , 
    ALWCPYDTA = *OPTIMIZE , 
    COMMIT = *NONE , 
    DECRESULT = (31, 31, 00) , 
    DFTRDBCOL = *NONE , 
    DYNDFTCOL = *NO , 
    DYNUSRPRF = *USER , 
    SRTSEQ = *HEX 
    BEGIN ATOMIC 
IF WC.CRTDT<200000 THEN 
    UPDATE RAVONLIB . WC SET CRTDT = 1000000 + CRTDT ; 
END IF; 
END ; 

私は変数CRTDTが定義されていないか、使用できないというエラーを取得しています。 CRTDTが200000より小さい場合にCRTDTを正しく更新するための正しい構文は何ですか?

+0

このDB2または別のdbmsですか? – jarlh

+0

はいIBM DB2 – ehh

+0

テーブルWCの** After ** Updateトリガーで、テーブルWCへの更新を実行する理由はありますか? – user2338816

答えて

4

BEFORE INSERTトリガーを使用する必要があります。

さらに、挿入された列の値を変更する必要があります。SQL UPDATEステートメントを、挿入されたばかりの行のトリガーで実行することはできません。

最後に、ステートメントトリガーではなく、行トリガーが必要です。ほとんど啓発

CREATE TRIGGER RAVONLIB.WC_TRIGGER 
    BEFORE INSERT ON RAVONLIB.WC 
    REFERENCING NEW AS new_row 
    FOR EACH ROW MODE DB2ROW 
    SET OPTION ALWBLK = *ALLREAD , 
    ALWCPYDTA = *OPTIMIZE , 
    COMMIT = *NONE , 
    DECRESULT = (31, 31, 00) , 
    DFTRDBCOL = *NONE , 
    DYNDFTCOL = *NO , 
    DYNUSRPRF = *USER , 
    SRTSEQ = *HEX 
    BEGIN ATOMIC 
IF new_row.CRTDT<200000 THEN 
    SET new_row.CRTDT = 1000000 + new_row.CRTDT ; 
END IF; 
END ; 
+0

私は挿入後の構文ソリューションを見つけましたが、あなたのソリューションはさらに優れたロジックです。ありがとうございました – ehh

+1

FWiW:UPDATEステートメント*は、[AFTER INSERTトリガ内から挿入されたばかりの]行で実行でき、FOR EACH STATEMENTトリガ*はより望ましいことがあります。 -table data]をFOR EACH ROWトリガよりも優先します。つまり、私は***にすべきことに同意します。***はBEFORE INSERTトリガーを使用します。•SETステートメントを使用してBEFORE INSERTトリガーの特定の入力値を更新します。•[したがって] ROWトリガーを使用します。 – CRPence

1

FWIW、これはほとんどすでにが受け入れ答えに私のコメントを与え答えされていないよう:V5R3に検証として、次の模倣論理的にOPから声明トリガー結論;テストするv4r5システムを持っている人は誰もいません - ¡聖なる煙!

create table wc 
(PKfld int not null 
, CRTDT numeric(7) 
, constraint WC_PK primary key (PKfld) 
)    
; 
CREATE TRIGGER wc_trg_ai      
After Insert on WC        
REFERENCING NEW TABLE AS xt      
FOR EACH STATEMENT MODE DB2SQL     
SET OPTION COMMIT = *NONE      
    BEGIN ATOMIC         
    update WC set WC.CRTDT = WC.CRTDT + 1000000 
    where WC.CRTDT<200000      
    and exists (select '1' from XT as xt  
        where xt.PKfld = WC.PKfld) ; 
    END           
; -- semicolon as statement separator, not end of trigger-body 
insert into wc values         
    ( 1, '0000001'), ( 2, '0200000'), ( 3, '0000300') 
, ( 4, '0400000'), ( 5, '0050000'), ( 6, '0600000') 
; -- per trigger dfn, the even-numbered key values will not see an UPDATE 
select * from WC 
; -- likeness of report from above query: 
    PKFLD  CRTDT 
     1 1,000,001 
     2  200,000 
     3 1,000,300 
     4  400,000 
     5 1,050,000 
     6  600,000 
*** End of data *** 
+0

なぜxtを参照しなければならなかったのか、それがなぜ新しいテーブルであるのかを完全には明らかにしていない。それは私のためにうまく動作するのでupvoted – ehh

+0

XTは、SQLトリガーが参照する必要があるWC内の実際のレコードが何であるかを知るために、SQL挿入の影響を受けたすべての行のコピーを含む遷移テーブルを表しますUPDATE文の対象となる。示されているものはAFTER INSERTであるため、データはすでにWCに挿入されており、UPDATEステートメントはINSERTステートメントに挿入された行のみを更新する必要があります。 WHERE EXISTSロジックが削除された場合、アクションは挿入されたものより多くのデータを更新します。おそらくこの特定のシナリオでは問題ないかもしれませんが、その影響は通常、破損*とみなされます。 – CRPence

+0

非常に明確で、すばらしい説明のおかげで – ehh

関連する問題