[pgsql-jp: 40434] Re: 「行が存在していなかったらinsert」の処理

武田 憲太郎 takeda @ youmind.jp
2010年 9月 28日 (火) 11:36:27 JST


 板垣様

 武田です。迅速なご回答ありがとうございます。

>> ■案3(これがNGなのが痛い)
>> ====================================
>> insert into t(pkey) select [_pkey]
>>  where not exists(select 1 from t where pkey = [_pkey]) ;
>> ====================================
>現状、同時挿入は行ロックでは防げないので、「エラーが起こったら無視」
>という方針が妥当と思います。案3の処理を、PL/pgSQL の BEGIN~EXCEPTION
>ブロック (try~catch 相当) で囲むのが一般的ではないでしょうか。

 ありがとうございます。言われてみるとそうですよね。参考URLまで貼りつけて頂いて、大変助かりました。

(ご案内頂いたドキュメントより)
=============================
EXCEPTION句を含んだブロックの実行に要する時間は、含まないブロックに比べてとても長くなります。したがって、必要のない時にEXCEPTIONを使用してはいけません。
=============================

 ここが不安だったのですが、ベンチマークしたところ、実際ほとんど変らないようですね。


 MERGEは初耳でした。9.1に期待したいと思います。

-----Original Message-----
From: pgsql-jp-bounces @ ml.postgresql.jp [mailto:pgsql-jp-bounces @ ml.postgresql.jp] On Behalf Of Itagaki Takahiro
Sent: Monday, September 27, 2010 6:57 PM
To: PostgreSQL Japanese Mailing List
Subject: [pgsql-jp: 40432] Re: 「行が存在していなかったらinsert」の処理

2010/9/27 武田 憲太郎 <takeda @ youmind.jp>:
> ・行が存在しなかった場合のみinsertする。
> ・存在した場合は何もしない。
> ・アプリケーション側の処理は行ないたくない。SQLのみで完結したい。
> ・ストアドプロシージャを使うのはOK

> ■案3(これがNGなのが痛い)
> ====================================
> insert into t(pkey) select [_pkey]
>  where not exists(select 1 from t where pkey = [_pkey]) ;
> ====================================

現状、同時挿入は行ロックでは防げないので、「エラーが起こったら無視」
という方針が妥当と思います。案3の処理を、PL/pgSQL の BEGIN~EXCEPTION
ブロック (try~catch 相当) で囲むのが一般的ではないでしょうか。

ドキュメントにある 例 38-2. UPDATE/INSERTの例外 も参考になるかもしれません。
http://www.postgresql.jp/document/current/html/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING


ちなみ、お求めの動作は標準SQLの MERGE というコマンドに相当します。
目下 9.1 に向けて開発中です。
https://commitfest.postgresql.org/action/patch_view?id=365

-- 
Itagaki Takahiro


pgsql-jp メーリングリストの案内