【问题标题】:Cycloning in trigger触发中的旋风
【发布时间】:2013-05-12 11:59:50
【问题描述】:

我有这样的桌子

 id | col1 | col2

我需要写触发器:在插入或更新列 col1 之后,我需要在列 col2 中插入(更新)相同的值

这是我的触发函数:

CREATE FUNCTION  upd () RETURNS TRIGGER AS '
   BEGIN 
       UPDATE mytable SET
       col2 =  col1;
       RETURN NULL;
   END;
'
LANGUAGE plpgsql;

这是自触发:

CREATE TRIGGER upd_trigger
AFTER INSERT OR UPDATE ON mytable
FOR EACH ROW
EXECUTE PROCEDURE upd()

这不起作用,因为在UPDATE 事件发生了旋风,对吧?

这样做的正确语法是什么?

【问题讨论】:

    标签: postgresql triggers


    【解决方案1】:

    @a_horse 和 @David 已经为您的案例指出了具有 GIN 索引的优越解决方案。

    但是关于你原来问题的答案还有一件事:因为你只需要触发器after inserting or updating column col1,你应该使用更具体的事件UPDATE OF ...,自 Postgres 9.0 起可用:

    CREATE TRIGGER upd_trigger
    BEFORE INSERT OR UPDATE OF col1 ON mytable
    FOR EACH ROW
    EXECUTE PROCEDURE upd()

    这样您甚至可以防止AFTER 触发器中的无限循环/递归(您称之为“旋风”)。但是使用BEFORE 触发器通常更明智,就像已经提供的@a_horse。

    【讨论】:

    • UPDATE OF 真的对我有帮助,谢谢。但是BEFORE 触发器不起作用,AFTER 起作用,为什么?我的触发函数出了什么问题?
    • @OTARIKI:很难说。需要完整的图片。也许其他触发器会干扰?你试过a_horse提供的改进触发功能吗?
    【解决方案2】:

    您不需要更新,只需分配值:

    CREATE FUNCTION  upd () RETURNS TRIGGER AS 
    $body$
       BEGIN 
          new.col2 := to_tsvector(new.col1);
          RETURN new;
       END;
    $body$
    LANGUAGE plpgsql;
    

    而您需要在 before 触发器中执行此操作:

    CREATE TRIGGER upd_trigger
    BEFORE INSERT OR UPDATE ON mytable
    FOR EACH ROW
    EXECUTE PROCEDURE upd()
    

    编辑

    正如@DavidAldridge 在他的评论中指出的那样,直接索引 ts_vector() 可能更容易:

    create index col1_vector 
        on mytable (to_tsvector(col1)) 
        using gin;
    

    使用

    的查询
    where to_tsvector(col1) = '...'
    

    然后就可以使用该索引了。

    【讨论】:

      【解决方案3】:

      如果 col2 的值确定性地仅取决于 col1 的值,则根本不应该存储 col2。

      【讨论】:

      • col2用于保存tsvector数据,原始数据保存在col1,(用于全文搜索)。但有问题,为了清除,我不写这个。
      • 您是否考虑过在 ts_vector(col1) 上创建 gin 索引?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-30
      • 2010-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      相关资源
      最近更新 更多