伝票 テーブル名 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 件のコメント:
コメントを投稿