[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 メーリングリストの案内