单行列字段的 Postgresql 触发器

Posted

技术标签:

【中文标题】单行列字段的 Postgresql 触发器【英文标题】:Postgresql Trigger for a Single Row Column Field 【发布时间】:2018-03-27 17:09:02 【问题描述】:

我需要一些帮助来修复我的 Postgres 9.4 表触发器配置。在过去的几天里,我一直在尝试几种不同的 *** 搜索想法,但都没有成功。如何修复我的代码以满足下面描述的简单要求?

要求是根据当前总线状态字段值更改颜色字段状态。颜色更新应该只发生在单行而不是整个 BusColor 表中。因此,当 AI_Bus ‘1145’ 操作状态 (BusStatus) 为 INSERT 或 UPDATED 时,触发器会将颜色字段更改为正确的关联颜色。假设“1145”的 BusStatus 从“NSCH”更新为“SCH”,那么触发器会将颜色值从“白色”更改为“黄色”。以下是我的 Posgresql 9.4 对象配置:

CREATE TABLE  BusColor (
AI_Bus      serial PRIMARY KEY,
BusStatus   character varying NOT NULL,
color       character varying NOT NULL );

SELECT * FROM “MyDB”.”BusColor”;
AI_Bus      BusStatus   color
1145        NSCH        white
1146        SCH         yellow
1147        NSCH        white
1148        OPER        green

CREATE TRIGGER “UpdateBusColor” BEFORE INSERT OR UPDATE ON “BusColor”
FOR EACH STATEMENT EXECUTE PROCEDURE “TrigFuncBusColor”();

CREATE FUNCTION “TrigFuncBusColor”() RETURNS trigger
LANGUAGE plpgsql
AS $$BEGIN
IF (TG_OP = ‘UPDATE’) THEN
    IF (NEW.”BusStatus” <> OLD.”BusStatus”) THEN
        IF NEW.“BusStatus” = ‘NSCH’ THEN
            UPDATE “MyDB”.”BusColor” SET “color” = ‘white’;
            RETURN NEW;
        END IF;

        IF NEW.“BusStatus” = ‘SCH’ THEN
            UPDATE “MyDB”.”BusColor” SET “color” = ‘yellow’;
            RETURN NEW;
        END IF;

         IF NEW.“ID_BusStatus” = ‘OPER’ THEN
            UPDATE “MyDB”.”BusColor” SET “color” = ‘green’;
            RETURN NEW;
         END IF;
   END IF;
END IF;
RETURN NULL;
END;
$$;

【问题讨论】:

您理解触发器更新错误,而不是使用update set .... 命令,您只需为新字段设置值,例如NEW.color = 'somevalue' 我刚刚尝试使用 UPDATE 语句,因为 NEW & OLD 产生错误:尚未分配记录“new”。元组结构未分配记录是不确定的。这对我来说就像是第 50 版......尝试了互联网上所有疯狂的东西。 将触发器从FOR EACH STATEMENT 更改为FOR EACH ROW 并使用NEW.field 谢谢豪尔赫!我切换回FOR EACH ROW 并将更新字段改回原来的。 CREATE TRIGGER “UpdateBusColor4” BEFORE INSERT OR UPDATE OF “BusStatus”, color ON “BusColor” FOR EACH ROW EXECUTE PROCEDURE “TrigFuncBusColor”(); 我也改了触发功能:CREATE FUNCTION “TrigFuncBusColor”() RETURNS trigger LANGUAGE plpgsql AS $$BEGIN IF TG_OP = ‘UPDATE’ THEN IF (OLD.”BusStatus” &lt;&gt; NEW .”BusStatus”) THEN IF (NEW.“BusStatus” = ‘SCH’) THEN NEW.“color” = ‘yellow’; RETURN NEW; END IF; IF (NEW.“BusStatus” = ‘NSCH’) THEN NEW.“color” = ‘white’; RETURN NEW; END IF; IF (NEW.“BusStatus” = ‘OPER’) THEN NEW.“color” = ‘green’; RETURN NEW; END IF; END IF; END IF; RETURN NULL; END; $$; 【参考方案1】:

为什么要为每个总线状态使用条件,只需选择替换状态的颜色并更新所有状态的颜色是新的。

CREATE FUNCTION “TrigFuncBusColor”() RETURNS trigger
    LANGUAGE plpgsql
    declare newColor varchar;
    AS $$BEGIN
    IF (TG_OP = ‘UPDATE’) THEN
        IF (NEW.”BusStatus” <> OLD.”BusStatus”) THEN
            SELECT "color" INTO newColor FROM “MyDB”.”BusColor” WHERE BusStatus = NEW.“BusStatus” LIMIT 1;
            UPDATE “MyDB”.”BusColor” SET “color” = newColor where BusStatus = NEW.“BusStatus”;
            RETURN NEW;
       END IF;
    END IF;
    RETURN NULL;
    END;

【讨论】:

以上是关于单行列字段的 Postgresql 触发器的主要内容,如果未能解决你的问题,请参考以下文章

插入后触发,更新相关模型Postgresql

Play、Anorm 和 PostgreSQL:串行列的问题?

postgresql行列转换

postgresql行列转换

PostgreSQL字段名和表名大小写的问题

postgresql:给表添加触发器