触发器返回新的无限循环

时间:2013-11-29 10:57:53

标签: postgresql triggers infinite-loop plpgsql sql-insert

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进行测试)但是主插入(在触发该事物的表上)继续进行疯狂的无限循环。 抱歉我的英语/表达能力差。 任何提示?事先确定。

1 个答案:

答案 0 :(得分:1)

我有一些关于如何改进功能的提示。但这里没有什么会导致无限循环。原因必须是问题中不存在的问题,例如任何相关表格上的其他触发器或规则。

提示:

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之间的时间窗口,以避免可能的竞争条件和大量并发负载。更多内容:
    Is SELECT or INSERT in a function prone to race conditions?

  • 您无需声明其他变量,可以直接选择NEW."PersonneID"

  • 要将默认值插入新行的列中,只需忽略INSERT中的列。