【问题标题】:PostgreSQL Update triggerPostgreSQL 更新触发器
【发布时间】:2014-08-12 18:48:49
【问题描述】:

我有一张桌子:

CREATE TABLE annotations
(
  gid serial NOT NULL,
  annotation character varying(250),
  the_geom geometry,
  "rotationAngle" character varying(3) DEFAULT 0,
  CONSTRAINT annotations_pkey PRIMARY KEY (gid),
  CONSTRAINT enforce_dims_the_geom CHECK (st_ndims(the_geom) = 2),
  CONSTRAINT enforce_srid_the_geom CHECK (st_srid(the_geom) = 4326)
)

并触发:

CREATE TRIGGER set_angle
AFTER INSERT OR UPDATE
ON annotations
FOR EACH ROW
EXECUTE PROCEDURE setangle();

及功能:

CREATE OR REPLACE FUNCTION setAngle() RETURNS TRIGGER AS $$
BEGIN
IF    TG_OP = 'INSERT' THEN
    UPDATE annotations SET "rotationAngle" = degrees( ST_Azimuth( ST_StartPoint(NEW.the_geom), ST_EndPoint(NEW.the_geom) ) )-90 WHERE gid = NEW.gid;
    RETURN NEW;
ELSIF TG_OP = 'UPDATE' THEN
    UPDATE annotations SET "rotationAngle" = degrees( ST_Azimuth( ST_StartPoint(NEW.the_geom), ST_EndPoint(NEW.the_geom) ) )-90 WHERE gid = NEW.gid;
    RETURN NEW;
END IF;
END;
$$ LANGUAGE plpgsql;

当在表中插入新行或编辑行时,我想用函数结果设置字段rotationAngle。 但是当我在表函数中插入新行时不起作用。我的意思是 rotationAngle 的值没有改变。

有什么问题?

【问题讨论】:

    标签: sql postgresql plpgsql triggers


    【解决方案1】:

    作为@SpartanElite pointed out,您正在触发无限循环。

    简化触发功能:

    CREATE OR REPLACE FUNCTION set_angle()
      RETURNS TRIGGER AS
    $func$
    BEGIN
       NEW."rotationAngle" := degrees(
                                 ST_Azimuth(
                                    ST_StartPoint(NEW.the_geom)
                                  , ST_EndPoint(NEW.the_geom)
                                 )
                              ) - 90;
       RETURN NEW;
    END
    $func$ LANGUAGE plpgsql;
    
    • 直接分配给NEW。在这种情况下没有WHERE
    • 必须用双引号括起非法的列名。最好不要用这样的名字开头。
      Recent related answer.
    • 插入和升级代码相同。我折叠成一个代码路径。

    使用 BEFORE 触发器。这样,您可以在保存触发行之前直接编辑它们的列:

    CREATE TRIGGER set_angle
    BEFORE INSERT OR UPDATE ON annotations
    FOR EACH ROW EXECUTE PROCEDURE set_angle();

    然而

    如果您只是想在表中保留一个功能相关的值(并且没有其他考虑因素):不要。改用视图或生成的列:

    那么你就不需要这些了。

    【讨论】:

    • 谢谢,@Erwin 你是巫师!您的回答再次很棒,您不仅给出了问题的答案而且还给出了解释,真是太好了。
    • 分区表应该怎么做?我无法创建 BEFORE 触发器,并且我的触发器未与 AFTER 触发器一起应用。我测试了 NEWOLD。如果我将UPDATE 查询与 AFTER 触发器一起使用,则可能会导致无限循环。
    • 我从This Question的一个有价值的回答中找到了我的问题的解决方案
    【解决方案2】:

    这里有很多问题。 1) 当您插入行“A”时,会调用函数setAngle()。但是在函数中,您在函数中调用另一个update,这将再次触发该函数,依此类推……要解决此问题,请不要发布更新!只需独立更新 NEW 记录值并将其返回即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-02
      相关资源
      最近更新 更多