[pgsql-jp: 38183] Re: RULE〜ON INSERT と serial 型

Hiroki Kataoka kataoka @ interwiz.jp
2007年 3月 21日 (水) 02:33:13 JST


片岡です。

 私もずいぶん昔に悩んだことあります。なので、このスレッドを楽しみに見て
いましたが、どうも、これだ!という策はなさそうですね(どれもidを明示的に
指定してINSERTした場合に期待通りにならないので)。

 無難にトリガを使ったほうがいいと思います。

Kawasaki Yusuke wrote:
> 川崎です。こんにちは。
> 
> RULE〜ON INSERT 時の serial 型の動作について、教えて下さい。
> 以下のような2つのテーブルがある構成で、src テーブルの id・val の値を
> リアルタイムに dst テーブルに反映していきたいとします。
> 
> CREATE TABLE src ( id serial, val text );
> CREATE TABLE dst ( id serial, val text );
> 
> 実際には、コピー以外の操作もあるので、ビューでは実現できません。
> 具体的には、src に INSERT されれば、その id・val を dst にも INSERT して、
> src が UPDATE されれば、dst でも同じ id の val を UPDATE して、
> src から DELETE されれば、dst でも同じ id のレコードを DELETE します。
> これを実現するため、以下の3つのルールを定義しました。
> 
> CREATE OR REPLACE RULE rule_src2dst_ins AS ON INSERT TO src
>    DO INSERT INTO dst VALUES ( NEW.id, NEW.val );
> CREATE OR REPLACE RULE rule_src2dst_upd AS ON UPDATE TO src
>    DO UPDATE dst SET val = NEW.val WHERE dst.id = NEW.id;
> CREATE OR REPLACE RULE rule_src2dst_del AS ON DELETE TO src
>    DO DELETE FROM dst WHERE dst.id = OLD.id;
> 
> ON UPDATE と ON DELETE のルールは期待通り動作しているように見えます。
> しかし INSERT 時は、src_id_seq のシーケンスが1つカウントアップして、
> dst 側の id には src 側の id+1 の値が入ってしまします。
> 
> hoge=# INSERT INTO src ( val ) VALUES ( 'HELLO' );
> hoge=# SELECT * FROM src;
> id |  val
> ----+-------
>  1 | HELLO
> hoge=# SELECT * FROM dst;
> id |  val
> ----+-------
>  2 | HELLO    ← id=1 でなくて id=2 になってる
> hoge=# SELECT currval('src_id_seq');
> currval
> ---------
>       2      ← 1 でなくて 2 にカウントアップしている
> 
> INSERT 時に id に値を指定した場合は、正しく動作します。
> 
> kawatest=# INSERT INTO src VALUES ( 100, 'WORLD' );
> kawatest=# SELECT * FROM src;
> id  |  val
> -----+-------
>   1 | HELLO
> 100 | WORLD
> kawatest=# SELECT * FROM dst;
> id  |  val
> -----+-------
>   2 | HELLO
> 100 | WORLD    ← ちゃんと id=100 だった
> kawatest=# SELECT currval('src_id_seq');
> currval
> ---------
>       2      ← カウントアップしていない(当たり前か)
> 
> serial 型を利用せずに、予めシリアル値を取得しておいて、
> 上記のように INSERT 時に明示的に値を指定すれば良いのかもしれませんが、
> ON INSERT のルールとシーケンスは、併用できないのでしょうか?
> 
> http://archives.postgresql.org/pgsql-bugs/2002-11/msg00104.php
> のスレッドを見ると、トリガを使うべし、とも読めるのですが、
> ルールで対応することはできるのでしょうか?
> 
> <ドキュメント>
> http://postgresql.jp/document/current/html/rules-update.html
> 
> ※ルールシステムの動作内容を、正しく理解できていない気がしますが・・・。
> 

-- 
Hiroki Kataoka <kataoka @ interwiz.jp>



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