触发功能→使用无唯一列

时间:2016-07-05 08:00:45

标签: sql postgresql triggers

我遇到了一个棘手的情况,我设置了一个更新表的触发器(自我更新功能)。我在这里得到的是,该函数能够识别出存在更新操作,但是由于列中没有唯一值,因此无法找到要更新的行。

TRIG_NS_ABS4_To_Area_func(触发功能):

BEGIN
IF (TG_OP = 'UPDATE') AND (OLD."ABS4" <> NEW."ABS4")
THEN UPDATE systems."NS_HandoverReportInput_tbl" SET ("Area") = ((SELECT "NS_AREA" FROM systems."NS_ABS4Area Match_tbl" WHERE "NS_ABS4" = NEW."ABS4"))
WHERE "NSItemNumber" =  NEW."NSItemNumber";
END IF;
RETURN NEW;
END; 

我想知道是否有人想知道要更新的行。

请注意 &#34; NSItemNumber&#34;字段是唯一的,否则其余字段可能具有重复值。

脚本:

CREATE TABLE systems."NS_HandoverReportInput_tbl" (
"NSItemNumber" SERIAL,
"ABS4" TEXT,
"Area" TEXT,
CONSTRAINT "PK_NS_HandoverReportInput_tbl" PRIMARY KEY("NSItemNumber"),
) 
WITH (oids = false);

CREATE TRIGGER "NS_ABS4Area Match_tbl"
AFTER INSERT OR UPDATE 
ON systems."NS_HandoverReportInput_tbl" FOR EACH ROW 
EXECUTE PROCEDURE systems."TRIG_NS_ABS4_To_Area_func"();

NS_ABS4Area Match_tbl显示信息如下:

NSItemNumber | ABS4 | Area
1001         | AAAA |Toilet
1002         | AABB |Central Area
1003         | AACC |Carpark
1004         | AAAA |Toilet
1005         | AABB |Central Area   

1 个答案:

答案 0 :(得分:0)

我会给你两个解决方案,一个是有效的,一个是好的。

工作解决方案

使用BEFORE INSERT OR UPDATE触发器,然后您不必找到要更新的行,因为您不必更改表,而是在将值写入表之前更改这些值。

您可以像这样定义触发器:

CREATE OR REPLACE FUNCTION "TRIG_NS_ABS4_To_Area_func"() RETURNS trigger LANGUAGE plpgsql AS
$$BEGIN
   -- this will fail if there is more than one "NS_AREA" per "NS_ABS4"
   SELECT DISTINCT "NS_AREA" INTO STRICT NEW."NS_AREA"
      FROM "NS_ABS4Area Match_tbl"
      WHERE "NS_ABS4" = NEW."ABS4";
   RETURN NEW;
END;$$;

CREATE TRIGGER "NS_ABS4Area Match_tbl"
   BEFORE INSERT OR UPDATE 
   ON systems."NS_HandoverReportInput_tbl" FOR EACH ROW 
   EXECUTE PROCEDURE systems."TRIG_NS_ABS4_To_Area_func"();

好的解决方案

通过规范化数据库设计可以避免整个混乱。

这样就不会发生任何不一致,而且你不需要触发器。

CREATE TABLE area_description (
   abs4 text PRIMARY KEY,
   area text NOT NULL
);

COPY area_description FROM STDIN (FORMAT 'csv');
'AAAA', 'Toilet'
'AABB', 'Central Area'
'AACC', 'Carpark'
\.

CREATE TABLE ns_report_input (
   ns_item_number serial PRIMARY KEY,
   abs4 text REFERENCES area_description(abs4)
);

CREATE INDEX ns_report_input_fkex_ind ON ns_report_input(abs4);

如果您想要与原始表格类似的内容,则可以定义视图。