[pgsql-jp: 25802] Re: PL/pgSQL 文での関数について
Jun Kitamura
kitamura @ zoozee.jp
2002年 5月 5日 (日) 01:13:58 JST
北村@zoozee です。
> PL/pgSQL文でストアドプロシージャーを作成中なのですが、
> select intoではFOUNDにてエラー検知しアボートできますが、
> insertやupdateを実行したときのエラー処理(エラーの検知)はできるのでしょうか
> ?
> 出来るのでしたらそのやり方を、どなたかご教授下さい。
出来ません。(あっさり)
INSERT や UPDATE を行なった時のエラーが(重複エラーや NOT NULL などの制約
エラーなのだと思いますが)発生する時は、その(エラー元となる)データのために
整合性が既にとれていないわけです。そのため、強制的にトランザクションがロー
ルバックされ、アボートされます。
もし、既存なら○○とか、重複しているなら××、という処理をしたいなら、
INSERTや UPDATEの前には、本来制約チェックで自動的にエラーになるそれらを自
分で調べる必要があります。調べついでにロックをかける事になるのだと・・・。
そのための FOUND だと思います。
例:
create table t1(
a int4, primary key(a),
b int4 not null
);
-- a をキーにして、b に NULL を入れようとすると 0 が、
-- 追加したら 1、更新したら 2 が返る関数です。
create function f1(int4,int4) returns int2 as
'
DECLARE
val_a ALIAS FOR $1;
val_b ALIAS FOR $2;
retval int2;
poi_a int4;
BEGIN
-- b の NOT NULL チェック
IF val_b IS NULL THEN
retval := 0;
ELSE
-- 既存?ついでにロック
select val_a into poi_a from t1 where a = val_a FOR UPDATE;
IF NOT FOUND THEN
-- 無ければ追加
insert into t1 (a,b) values (val_a,val_b);
retval := 1;
ELSE
-- あったら更新
update t1 set b = val_b where a = val_a;
retval := 2;
END IF;
END IF;
return retval;
END;
'
language 'plpgsql';
例が悪い(笑)ので何とも言えないのですが、「こんな感じ」って事で。
このままだと INSERT 時に重複エラーになる可能性ありますね。BEGIN の後でテー
ブルロックかけたほうが良いのかな?ほんと悪い例ですんません。
では。
pgsql-jp メーリングリストの案内