Postgresql 使用触发器更新新创建的行值

Postgresql 使用触发器更新新创建的行值,postgresql,triggers,sql-update,Postgresql,Triggers,Sql Update,我的问题如下:我在postgresql数据库中插入或更新了一行,需要修改此行中的一个字段。但是,当我插入新行以在其他表上使用JOIN进行SELECT时,我需要知道新的序列主键 我现在很沮丧,因为我在INSERT和UPDATE之后做了一个触发器来获得新的PK(kkw\u block\u id)。我通过选择获得所需的值,但之后我无法修改行中的值:在插入和更新之后,使用修改NEW.value是不可能的,如果我对行执行更新,我将进入无限循环,触发器将在触发器中调用 CREATE TRIGGER tsve

我的问题如下:我在postgresql数据库中插入或更新了一行,需要修改此行中的一个字段。但是,当我插入新行以在其他表上使用
JOIN
进行
SELECT
时,我需要知道新的序列主键

我现在很沮丧,因为我在INSERT和UPDATE之后做了一个
触发器来获得新的PK(
kkw\u block\u id
)。我通过
选择
获得所需的值,但之后我无法修改行中的值:在插入和更新
之后,使用
修改NEW.value是不可能的,如果我对行执行
更新
,我将进入无限循环,触发器将在触发器中调用

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$

有什么想法吗?

在触发之前,删除PK的默认值并将其分配到。您必须将现有触发器从“之后”更改为“之前”

您可以按如下顺序分配PK:

NEW.kkw_block_id = nextval('your_sequence_name_here');
由于您对INSERT和DELETE使用相同的函数,因此需要检查它是否为INSERT,然后才使用sequence。我还包括检查PK是否为空。我想这就足以在更新期间不覆盖它

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

只要该触发器对每一新行都有效,就可以了,情况似乎就是这样。这将允许您修改新的,它将反映在表中保存的数据中。

删除PK的默认值,并将其分配到触发器之前的。您必须将现有触发器从“之后”更改为“之前”

您可以按如下顺序分配PK:

NEW.kkw_block_id = nextval('your_sequence_name_here');
由于您对INSERT和DELETE使用相同的函数,因此需要检查它是否为INSERT,然后才使用sequence。我还包括检查PK是否为空。我想这就足以在更新期间不覆盖它

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

只要该触发器对每一新行都有效,就可以了,情况似乎就是这样。这将允许您修改新的,并将反映在表中保存的数据中。

我最终得到以下解决方案。我在触发器之前做了一个
。问题在于引用新行尚不存在的表的
左联接。这并不理想,但在这里:

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$

我最终得到以下解决方案。我在触发器之前做了一个
。问题在于引用新行尚不存在的表的
左联接。这并不理想,但在这里:

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$