我遇到了一个棘手的情况,我设置了一个更新表的触发器(自我更新功能)。我在这里得到的是,该函数能够识别出存在更新操作,但是由于列中没有唯一值,因此无法找到要更新的行。
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
答案 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);
如果您想要与原始表格类似的内容,则可以定义视图。