【问题标题】:Update newly created row value with a trigger使用触发器更新新创建的行值
【发布时间】:2017-08-03 10:21:53
【问题描述】:

我的问题如下:我在postgresql数据库中插入或更新一行,需要修改这一行中的一个字段。但是当我插入新行以在其他表上创建SELECTJOIN 时,我需要知道新的串行PK。

我现在卡住了,因为我已经完成了 AFTER INSERT AND UPDATE 触发器来获取新的 PK (kkw_block_id)。我通过SELECT 获得了我需要的值,但之后我无法修改行中的值:使用AFTER INSERT AND UPDATE 修改 NEW.value 是不可能的,如果我在行上执行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$

有什么想法吗?

【问题讨论】:

    标签: postgresql triggers sql-update


    【解决方案1】:

    删除您的 PK 的默认值并将其分配到您的 BEFORE 触发器中。您必须将现有触发器从 AFTER 更改为 BEFORE。

    您可以像这样从序列中分配 PK:

    NEW.kkw_block_id = nextval('your_sequence_name_here');
    

    由于您对 INSERT 和 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,并将反映在保存在表中的数据中。

    【讨论】:

      【解决方案2】:

      我最终得到以下解决方案。我做了一个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$
      

      【讨论】:

        猜你喜欢
        • 2011-03-10
        • 2019-05-03
        • 1970-01-01
        • 2017-03-27
        • 1970-01-01
        • 2012-07-31
        • 2016-05-26
        • 2016-03-01
        • 1970-01-01
        相关资源
        最近更新 更多