[pgsql-jp: 38168] RULE〜ON INSERT と serial 型
Kawasaki Yusuke
u-suke @ kawa.net
2007年 3月 18日 (日) 01:01:14 JST
川崎です。こんにちは。
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
※ルールシステムの動作内容を、正しく理解できていない気がしますが・・・。
--
川崎 有亮 Kawasaki Yusuke
http://www.kawa.net/
pgsql-jp メーリングリストの案内