2017-08-03 108 views
0

我的问题如下:我插入或更新postgresql数据库中的一行,并需要修改此行中的一个字段。但我需要知道新的串行PK,当我插入一个新行,使SELECTJOIN在其他表上。使用触发器更新新创建的行值

我现在陷入困境,因为我已经做了AFTER INSERT AND UPDATE触发器来获得新的PK(kkw_block_id)。我用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放置默认值并将其分配到您的之前触发器。您将不得不将现有触发器从AFTER更改为BEFORE。

您可以从序列一样,分配PK:

NEW.kkw_block_id = nextval('your_sequence_name_here'); 

由于您使用的两个插入相同的功能和DELETE,你需要检查它是否是INSERT,然后才使用顺序。我还包括检查PK是否为空。我想这一点足以在更新期间不覆盖它。

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

只要此触发器适用于每个新行,似乎就是这种情况,这将会很好。这将允许您修改NEW,它将反映在保存在表格中的数据中。