CREATE OR REPLACE FUNCTION updatepersonne()
RETURNS trigger AS
$BODY$
DECLARE
IDToInsert numeric;
BEGIN
SELECT "PersonneID" FROM "Personne" p INTO IDToInsert WHERE (p."Prenom"=NEW."Prenom" AND p."Nom"=NEW."Nom" AND p."Adresse"=NEW."Adresse");
IF IDToInsert IS NULL THEN
INSERT INTO "Personne" ("PersonneID","Nom","Prenom","Adresse") VALUES (Default, NEW."Nom",NEW."Prenom",NEW."Adresse") RETURNING "PersonneID" into IDToInsert;
END IF;
NEW."PersonneID":=IDToInsert;
--IF TG_RELNAME="Emprunteur"
--THEN
-- NEW."EmprunteurID":=IDToInsert;
--ELSE
-- NEW."DetenteurID":=IDToInsert;
--END IF;
return new;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION updatepersonne()
OWNER TO postgres;
CREATE TRIGGER updatepersonnefromemprunteur
BEFORE INSERT
ON "Emprunteur"
FOR EACH ROW
EXECUTE PROCEDURE updatepersonne();
我想检查另一个表上是否存在元组,以便获取 ID 并将其用于新元组,或者如果不存在,则将其插入另一个表。它似乎获取了 ID 或将其正确插入到另一个表上(使用 return null 进行测试(,但主插入(在触发该事物的表上(进行了疯狂的无限循环。对不起,我的英语/表达能力很差。有什么提示吗?提前谢谢。
我有一些关于如何改进功能的提示。但是这里没有什么会导致无限循环。原因必须是问题中没有的内容,例如任何涉及表上的其他触发器或规则。
提示:
CREATE OR REPLACE FUNCTION updatepersonne()
RETURNS trigger AS
$func$
BEGIN
WITH sel AS (
SELECT "PersonneID"
FROM "Personne"
WHERE "Prenom" = NEW."Prenom"
AND "Nom" = NEW."Nom"
AND "Adresse" = NEW."Adresse"
)
, ins AS (
INSERT INTO "Personne" ("Nom", "Prenom", "Adresse")
SELECT (NEW."Nom", NEW."Prenom", NEW."Adresse")
WHERE NOT EXISTS (SELECT 1 FROM sel)
RETURNING "PersonneID"
)
SELECT COALESCE(sel."PersonneID", ins."PersonneID")
FROM ins, sel
INTO NEW."PersonneID";
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
CREATE TRIGGER updatepersonnefromemprunteur
BEFORE INSERT
ON "Emprunteur"
FOR EACH ROW
EXECUTE PROCEDURE updatepersonne();
使用数据修改 CTE 最小化 SELECT 和 INSERT 之间的时间窗口,以避免并发负载过重时可能出现的争用情况。更多关于这一点:
函数中的 SELECT 或 INSERT 是否容易出现竞争条件?无需声明其他变量,可以直接选择 into
NEW."PersonneID"
。要将默认值插入新行的列中,只需从
INSERT
中省略该列。