2017-08-03 8 views
0

私の問題は次のとおりです。私はpostgresqlデータベースに行を挿入または更新し、この行の1つのフィールドを変更する必要があります。しかし、新しい行を挿入してSELECTJOINとすると、新しいシリアルPKを知る必要があります。トリガーで新しく作成された行の値を更新する

新しいPK(kkw_block_id)を取得するためにAFTER INSERT AND UPDATEトリガーを実行したため、今は固執しています。 SELECTで必要な値が得られますが、それ以降は行の値を変更できません.NEW.valueの変更はAFTER INSERT AND UPDATEでできません。行にUPDATEを実行すると、無限ループに入り、トリガービーイングがトリガーで呼び出されました...

CREATE TRIGGER tsvectorupdate 
    AFTER INSERT OR UPDATE 
    ON kkw_block 
    FOR EACH ROW 
    EXECUTE PROCEDURE kkw_search_trigger(); 

CREATE OR REPLACE FUNCTION kkw_search_trigger() 
    RETURNS trigger AS 
$BODY$ 

DECLARE vector_en TEXT; 
    DECLARE vector_fr TEXT; 
    DECLARE vector_de TEXT; 
    BEGIN 
     -- I need the new serial PK(kkw_id) in the following section. 
     SELECT coalesce(modell_en, '') || ', ' || coalesce(bezeichnung_en,'') || ', ' || coalesce(kkw.kkw_name_en,'') || ', ' || coalesce(kkw_typ.typ_abr,'') || ', ' || coalesce(kkw_typ.typ_desc_en,'') || ', ' || coalesce(kkw_typ.typ_desc_short_en,'') INTO vector_en 
     FROM kkw_block 
     LEFT JOIN kkw ON NEW.kkw_id = kkw.kkw_id 
     LEFT JOIN kkw_typ ON NEW.kkw_typ_id = kkw_typ.kkw_typ_id 
     WHERE kkw_block_id = NEW.kkw_block_id; 

     -- I need to update a field of the newly created or updated row. 
     NEW.search_vector_en := to_tsvector('english', 'new test vector'); --- This doesn't work with 'AFTER UPDATE' trigger. 

     RETURN NULL; 
    END 
$BODY$ 

ご存じですか?

答えて

0

私は以下の解決策になります。私はBEFOREトリガーを作った。問題は新しい行がまだ存在しないテーブルを参照してLEFT JOINでした。理想的ではありませんが、ここにあります:

CREATE TRIGGER tsvectorupdate 
    BEFORE INSERT OR UPDATE 
    ON kkw_block 
    FOR EACH ROW 
    EXECUTE PROCEDURE kkw_search_trigger(); 

CREATE TYPE kkw_type_record_type AS (typ_abr TEXT, typ_desc_en TEXT, typ_desc_short_en TEXT); 
CREATE TYPE kkw_record_type AS (kkw_name_en TEXT); 

CREATE OR REPLACE FUNCTION kkw_search_trigger() 
    RETURNS trigger AS 
$BODY$ 

    DECLARE kkw_rec kkw_record_type; 
    DECLARE kkw_typ_rec kkw_type_record_type; 

    DECLARE vector_en TEXT; 

    BEGIN 
     --- make a individual select instead of LEFT JOIN 
     SELECT kkw_name_en INTO kkw_rec.kkw_name_en 
     FROM kkw 
     WHERE kkw.kkw_id = NEW.kkw_id; 

     --- make a individual select instead of LEFT JOIN 
     SELECT typ_abr, typ_desc_en, typ_desc_short_en INTO kkw_typ_rec.typ_abr, kkw_typ_rec.typ_desc_en, kkw_typ_rec.typ_desc_short_en 
     FROM kkw_typ 
     WHERE kkw_typ.kkw_typ_id = NEW.kkw_typ_id; 

     vector_en := coalesce(NEW.modell_en, '') || ', ' || coalesce(NEW.bezeichnung_en,'') || ', ' || coalesce(kkw_rec.kkw_name_en,'') || ', ' || coalesce(kkw_typ_rec.typ_abr,'') || ', ' || coalesce(kkw_typ_rec.typ_desc_en,'') || ', ' || coalesce(kkw_typ_rec.typ_desc_short_en,''); 

     NEW.search_vector_en := to_tsvector('english', vector_en);   
     RETURN NEW; 
    END 
$BODY$ 
1

あなたのPKのデフォルトを破棄し、BEFOREトリガーに割り当てます。既存のトリガーをAFTERからBEFOREに変更する必要があります。

あなたがそのような順序からPKを割り当てることができます。あなたは、両方のINSERTのために同じ機能を使用しているので

NEW.kkw_block_id = nextval('your_sequence_name_here'); 

とDELETE、あなたはそれがINSERTであるだけにしてシーケンスを使用するかどうかを確認する必要があります。私はまた、PKがnullかどうかのチェックを含んでいます。私は、更新中に上書きしないだけで十分だと思います。

IF (TG_OP = 'INSERT') AND NEW.kkw_block_id IS NULL THEN 
    NEW.kkw_block_id = nextval('your_sequence_name_here'); 
END IF; 

このトリガーが新しい行ごとに機能する限り、これは問題ありません。これにより、NEWを変更できるようになり、テーブルに保存されたデータに反映されます。

関連する問題