伝票 テーブル名 SLIP のレコード新規作成で insert 文を発行しているのですが、別の帳票を印刷すると、レコードの挿入に失敗してしまいます。
帳票のコード中で、現象を引き起こす部分を特定したところ、全く関係のない 日別伝票集計 テーブル名 DSLIP を SELECT * FROM DSLIP WHERE RDATE='2013/8/29'; という極めてシンプルなクエリーをオープンして、クローズするだけで発生していました。
訳がわからなくて、コンポーネントを別にしてみたり、接続をクローズしてオープンしてみたり、SELECT文末に FOR READ ONLY を加えてみたりしましたが、エラーは直りません。もうお手上げに近い感じですが、ふとトリガー?というキーワードが浮かびました。それでも原因がわからなくて、助っ人を頼んで原因を特定できました。
よくある事ですが、日別で伝票番号をシーケンシャルで発生させたいという要望から、DSLIP 中に伝票番号の最大値を持たせて SLIP の INSERT TRIGGER で伝票番号を発生させていました。
問題のトリガーは、こんな感じ
ALTER TRIGGER "insert_slip" before insert order 1 on "DBA".SLIP referencing new as new_val for each row begin declare AINC smallint; declare thisDSlip cursor for select SCNT from DSLIP where RDATE=new_val.RDATE; -- %IF CURRENT REMOTE USER IS NULL THEN if new_val.SLIPCD is null then if not exists(select* from DSLIP where RDATE=new_val.RDATE) then insert into DSLIP(RDATE,LDATE) values(new_val.RDATE,TODAY(*)) end if ; open thisDSlip; fetch first thisDSlip into AINC for update; set new_val.SLIPCD=AINC; update DSLIP set SCNT=AINC+1,LDATE=TODAY(*) where current of thisDSlip; close thisDSlip else if not exists(select* from DSLIP where RDATE=new_val.RDATE) then insert into DSLIP(RDATE,LDATE,SCNT) values(new_val.RDATE,TODAY(*),new_val.SLIPCD) end if ; open thisDSlip; fetch first thisDSlip into AINC for update; if AINC<new_val.SLIPCD then set AINC=new_val.SLIPCD; update DSLIP set SCNT=AINC+1,LDATE=TODAY(*) where current of thisDSlip end if ; close thisDSlip end if ; if(ISNULL(new_val.RENT,0)<>0) or(ISNULL(new_val.EMFLG,0)<>0) then set new_val.ACFLG=5 end if -- %END IF; end;はい、cursor 宣言がまずくて
declare thisDSlip cursor for select SCNT from DSLIP where RDATE=new_val.RDATE FOR UPDATE;というように更新をかけるタイプのカーソルですよと、FOR UPDATE 句が必要でした。これが抜けていたために、データベースの状況により読み取り専用カーソルに対して更新をかけるという事態が発生し、エラーを引き押していたと。
0 件のコメント:
コメントを投稿