2011-08-05 24 views
0

2種類の画像を表す2つのテーブルがあります。私はそれらの画像の境界を表すためにPostGISを使用しています。ここでこれらのテーブルの簡単な例である:PostgreSQLのトリガ関数を書く際に助けが必要

CREATE TABLE img_format_a (
    id SERIAL PRIMARY KEY, 
    file_path VARCHAR(1000), 
    boundary GEOGRAPHY(POLYGON, 4326) 
); 

CREATE TABLE img_format_p (
    id SERIAL PRIMARY KEY, 
    file_path VARCHAR(1000), 
    boundary GEOGRAPHY(POLYGON, 4326) 
); 

私も重なるすべての画像IDを含めるしたい、相互参照表を有します。タイプAの画像がデータベースに挿入されるたびに、タイプPの既存の画像と重なり合うかどうかを確認し(逆もまた同様)、対応する項目をimg_a_img_p相互参照テーブルに挿入します。この表は、多対多の関係を表す必要があります。

私の本能は、このimg_a_img_pテーブルを管理するためのトリガーを書くことです。私は前もってトリガーを作ったことがないので、これが愚かなことであれば教えてください。しかしそれは私には意味があるようです。だから私は次のトリガーを作成します:

CREATE TRIGGER update_a_p_cross_reference 
    AFTER INSERT OR DELETE OR UPDATE OF boundary 
    ON img_format_p FOR EACH ROW 
    EXECUTE PROCEDURE check_p_cross_reference(); 

私が立ち往生している部分は、トリガー機能を書くことです。私のコードはJavaであり、PL/pgSQLのようなツールがあることがわかりますが、もし私が使うべきものなのか、それらの特別なアドオンが必要なのか分かりません。

基本的には、新しい画像がimg_format_aまたはimg_format_pのいずれかに挿入されるたびに相互参照テーブルを更新する必要があります。新しい画像が挿入されたら、ST_IntersectsのようなPostGIS関数を使用して、新しい画像が他のテーブルの画像と重なっているかどうかを確認したいと思います。 ST_INTERSECTSがtrueを返す画像ペアごとに、両方の画像のIDを持つimg_a_img_pに新しいエントリを挿入したいと思います。誰かがこのトリガ関数を書く方法を理解するのに役立つことができますか?ここではいくつかの擬似コードは次のとおりです。

SELECT * FROM img_format_p P 
    WHERE ST_Intersects(A.boundary, P.boundary); 

for each match in selection { 
    INSERT INTO img_a_img_p VALUES (A.id, P.id); 
} 

答えて

4

あなたはソートのこのようPL/pgSQL関数で通常のINSERT ... SELECTイディオムをラップすることができます:

create function check_p_cross_reference() returns trigger as 
$$ 
begin 
    insert into img_a_img_p (img_a_id, img_p_id) 
    select a.id, p.id 
    from img_format_a, img_format_p 
    where p.id = NEW.id 
     and ST_Intersects(a.boundary, p.boundary); 
    return null; 
end; 
$$ language plpgsql; 

トリガは2つの余分な変数を持って、NEW and OLD

NEW
Data type RECORD; variable holding the new database row for INSERT/UPDATE operations in row-level triggers. This variable is NULL in statement-level triggers and for DELETE operations.

OLD
Data type RECORD; variable holding the old database row for UPDATE/DELETE operations in row-level triggers. This variable is NULL in statement-level triggers and for INSERT operations.

NEW.idを使用すると、新しいimg_format_pの値にアクセスできます。あなた(現在)can't use the plain SQL言語トリガーの場合:

It is not currently possible to write a trigger function in the plain SQL function language.

しかし、PL/pgSQLはかなり近いです。

CREATE TRIGGER update_a_p_cross_reference 
AFTER INSERT 
ON img_format_p FOR EACH ROW 
EXECUTE PROCEDURE check_p_cross_reference(); 

削除foreign key on img_a_img_p and a cascading deleteで扱うことができます:INSERTトリガーAFTERので、これは理にかなって。

CREATE TRIGGER update_a_p_cross_reference 
AFTER INSERT OR UPDATE OF boundary 
ON img_format_p FOR EACH ROW 
EXECUTE PROCEDURE check_p_cross_reference(); 

しかし、あなたは、おそらくのようなものと新しいものを挿入する前に古いエントリをクリアしたいと思います:あなたは、同様に更新のためのあなたのトリガーを使用することができ INSERT...SELECT文の前に

delete from img_a_img_p where img_p_id = NEW.id; 

+0

うわー、このようなすばらしく詳細な答えに感謝します。それは有り難いです! – Steph

+0

私はあなたのトリガ関数を実行すると、私はこのエラーが発生します: 'ERROR:"または '' LINE 3:img_a_img_p(img_a_id、img_p_id)に挿入 ''を挿入して、なぜ私はこれを得るだろうか知っていますか? PL/pgSQLは、デフォルトでは空間データベース用にインストールする必要があります。このエラーの理解に問題があります。 – Steph

+0

@Steph:プロシージャで「開始」が欠けていたからです(新しい3行目を参照)。申し訳ありません、私はちょうどそれをテストせずに私の頭の上からそれを書いた。 –

関連する問題