[pgsql-jp: 27939] view/rule/insert
Satoshi Nagayasu
snaga @ snaga.org
2002年 11月 12日 (火) 07:23:21 JST
永安です。
一言で言うと、「あれば select、無ければ insert して select」というのを
どのように書くのか、ということだと思うのですが…。
create table t1 (
c1_id integer references c1 ( c1_id ),
memo text
);
create table c1 (
c1_name text primary key,
c1_id serial
);
のように、外部参照のあるテーブルをviewでくるんで、
ユーザーにはひとつのテーブルのように見せるとします。
create view c1v as
select c1.c1_name,t1.memo
from c1,t1
where c1.c1_id = t1.c1_id;
つまり、c1_id という serial をユーザーには見えないように
するわけですが。
この時、データの追加や更新のために、ユーザーがc1vにアクセスしますが、
viewを通しては更新できないので、ruleを用いてc1vへのinsertを
書き換えるとします。
とりあえず、以下のように作りました。
create rule c1v_ins as
on insert to c1v
do instead
insert into t1 values (
(select c1_id from c1 where c1.c1_name=new.c1_name),
new.memo
);
この際、t1.c1_id が参照している c1.c1_id が先に存在していないと
いけないわけですが、c1v に insert する時点では、c1.c1_id に該当する
レコードがあるかもしれないし、無いかもしれない、という状況です。
c1 に該当レコードがあった場合には、単に select して c1_id を取得し、
無い場合には、insert してから select して c1_id を取得したい。
で、その c1_id を使って t1 に insert したい、というのを
rule で書くにはどうすればいいのでしょう?
(select c1_id from c1 where c1.c1_name=new.c1_name),
の部分を、c1の参照先に該当レコードがあってもなくても、
成功するようにしたいのです(というか無ければinsertしたい)。
primary key制約を入れてるので、2レコード以上が返ることはありません。
rule の do 〜 の中で制御構造は書けるのか?ということじゃないかと
思うのですが、あれば select、無ければ insert して select、と
いうのはどのように書けばいいのでしょうか?
とりあえず、あろうが無かろうが insert してみる、というのも
アリと言えばアリなのでしょうが、それだとキーがカチ合って
insertが失敗したときに、トランザクションがまるごとabortしそうな
気がします…(というか試してみたらabortしました。当然ですね…)。
実際に作ってるものは、4つくらいの外部参照があって、
それをviewにくるんでいるので、すべての外部参照先に対する
「あればselect、なければinsertしてselect」というのを、
viewに対する一つのinsert(のdo〜句)ににおいて
implicitに呼び出したいのですが。
そーゆーときはこーやるもんだ、みたいなセオリーがありましたら、
どなたかお教えくださると助かります。
あと、質問の意味が分からなかったらご指摘いただけると幸いです。
よろしくお願いします。
--
NAGAYASU Satoshi <snaga @ snaga.org>
pgsql-jp メーリングリストの案内