Postgresql 触发器插入行

Postgresql Trigger to insert rows


我在 Postgresql 触发器(以及 Mysql )上被困了好几天。我只想将新填充的行插入另一个 table。原始数据来自外部表单(OpenDataKit)并转到"intermediate" tables。我不明白为什么一旦创建了触发器,表单就不能再发送数据了……请注意,当我手动插入时,所有操作都可以在没有触发器的情况下工作。如果能帮助我理解我做错了什么,我将不胜感激。
我现在正在使用 Postgresql 9.5 进行测试,但我在使用 MySQL 5.1 时遇到了类似的问题。

-- CREATE procedure: 
CREATE OR REPLACE FUNCTION proc_natobs() RETURNS TRIGGER AS
$BODY$
DECLARE
BEGIN
INSERT INTO lieu (id_lieu, wgs_lat, wgs_lon, date_obs, geom)    
    SELECT  id_loc,"GPS_TEL_LAT", "GPS_TEL_LNG", "DATE_OBS", ST_SetSRID(ST_POINT("GPS_TEL_LNG","GPS_TEL_LAT"), 4326)
    FROM "FORMULAIRE_NATOBS_REPEAT_LOC", "FORMULAIRE_NATOBS_CORE"
    WHERE "FORMULAIRE_NATOBS_CORE"."_URI" = "FORMULAIRE_NATOBS_REPEAT_LOC"."_TOP_LEVEL_AURI"
    AND "FORMULAIRE_NATOBS_REPEAT_LOC".id_loc IN (SELECT max(id_loc) FROM "FORMULAIRE_NATOBS_REPEAT_LOC");

INSERT INTO i_lieu_observateurs (id_lieu, id_auteur)
    SELECT id_loc, CAST("AUTEUR" AS integer) 
    FROM "FORMULAIRE_NATOBS_CORE", "FORMULAIRE_NATOBS_REPEAT_LOC"
    WHERE "FORMULAIRE_NATOBS_REPEAT_LOC"."_TOP_LEVEL_AURI" = "FORMULAIRE_NATOBS_CORE"."_URI"
     AND id_loc IN (SELECT max(id_loc) FROM "FORMULAIRE_NATOBS_REPEAT_LOC")
    UNION 
    SELECT id_loc, CAST("OBSERVATEURS" AS integer) 
    FROM "FORMULAIRE_NATOBS_REPEAT_LOC", "FORMULAIRE_NATOBS_REPEAT_OBSERVATEUR"
    WHERE "FORMULAIRE_NATOBS_REPEAT_LOC"."_TOP_LEVEL_AURI" = "FORMULAIRE_NATOBS_REPEAT_OBSERVATEUR"."_TOP_LEVEL_AURI"
    AND id_loc IN (SELECT max(id_loc) FROM "FORMULAIRE_NATOBS_REPEAT_LOC")
    ;
END;
$BODY$
LANGUAGE 'plpgsql';

-- CREATE the trigger:
CREATE TRIGGER trigger_natobs AFTER INSERT
ON "FORMULAIRE_NATOBS_REPEAT_LOC"
FOR EACH ROW
EXECUTE PROCEDURE proc_natobs();

因此,当 ODK 表单在 FORMULAIRE_NATOBS_REPEAT_LOC 中插入新行时(我为此创建了一个序列 ID 以方便 SQL 查询),我尝试插入这一行(结合信息从其他中间 tables) 进入 table "lieu" 用于触发器的第一个动作,并进入 table i_lieu_observation (由双主键组成)用于第二个动作。我也用仅由第一个动作组成的触发器进行了测试,但它也不起作用。发送表单的 Android 应用程序崩溃,直到我删除触发器。
提前致谢!

您需要在触发器中使用特殊的NEW 变量来访问新插入的数据。所以你需要这样的东西:

CREATE OR REPLACE FUNCTION proc_natobs() RETURNS TRIGGER AS
$BODY$
DECLARE
BEGIN
INSERT INTO lieu (id_lieu, wgs_lat, wgs_lon, date_obs, geom)    
    SELECT  new.id_loc,"GPS_TEL_LAT", "GPS_TEL_LNG", "DATE_OBS", ST_SetSRID(ST_POINT("GPS_TEL_LNG","GPS_TEL_LAT"), 4326)
    FROM "FORMULAIRE_NATOBS_CORE"
    WHERE "FORMULAIRE_NATOBS_CORE"."_URI" = new."_TOP_LEVEL_AURI";

INSERT INTO i_lieu_observateurs (id_lieu, id_auteur)
    SELECT new.id_loc, CAST("AUTEUR" AS integer) 
    FROM "FORMULAIRE_NATOBS_CORE"
WHERE new."_TOP_LEVEL_AURI" = "FORMULAIRE_NATOBS_CORE"."_URI"
    UNION 
    SELECT new.id_loc, CAST("OBSERVATEURS" AS integer) 
    FROM "FORMULAIRE_NATOBS_REPEAT_OBSERVATEUR"
    WHERE new."_TOP_LEVEL_AURI" = "FORMULAIRE_NATOBS_REPEAT_OBSERVATEUR"."_TOP_LEVEL_AURI";
RETURN new;
END;
$BODY$
LANGUAGE 'plpgsql';

-- CREATE the trigger:
CREATE TRIGGER trigger_natobs AFTER INSERT
ON "FORMULAIRE_NATOBS_REPEAT_LOC"
FOR EACH ROW
EXECUTE PROCEDURE proc_natobs();

因为我不知道哪些字段来自哪些 tables,所以我无法使上述内容完全正确。就像我写 new.id_loc 一样,您需要为来自 formulaire_natobs_repeat_loc table.

的所有字段添加 new.field_name

HTH

试试这个

CREATE OR REPLACE FUNCTION proc_natobs() RETURNS TRIGGER AS
$BODY$

BEGIN

IF(TG_OP = 'INSERT') THEN

INSERT INTO lieu (id_lieu, wgs_lat, wgs_lon, date_obs, geom)    
    SELECT  id_loc,"GPS_TEL_LAT", "GPS_TEL_LNG", "DATE_OBS", ST_SetSRID(ST_POINT("GPS_TEL_LNG","GPS_TEL_LAT"), 4326)
    FROM "FORMULAIRE_NATOBS_REPEAT_LOC" loc, "FORMULAIRE_NATOBS_CORE" core
    WHERE core."_URI" = loc."_TOP_LEVEL_AURI"
    AND loc.id_loc =new.id_loc;

INSERT INTO i_lieu_observateurs (id_lieu, id_auteur)
    SELECT id_loc as id, 
    CAST("AUTEUR" AS integer)  as auteur
    FROM "FORMULAIRE_NATOBS_CORE" core, "FORMULAIRE_NATOBS_REPEAT_LOC" loc
    WHERE loc."_TOP_LEVEL_AURI" = core."_URI"
     AND loc.id_loc =new.id_loc;
    UNION 
    SELECT id_loc as id, 
    CAST("OBSERVATEURS" AS integer) as auteur
    FROM "FORMULAIRE_NATOBS_REPEAT_LOC" loc, "FORMULAIRE_NATOBS_REPEAT_OBSERVATEUR" obs
    WHERE loc."_TOP_LEVEL_AURI" = obs."_TOP_LEVEL_AURI"
    AND loc.id_loc =new.id_loc;
    END IF;

   Return new;  
END;
$BODY$
LANGUAGE 'plpgsql';

-- CREATE the trigger:
CREATE TRIGGER trigger_natobs AFTER INSERT
ON "FORMULAIRE_NATOBS_REPEAT_LOC"
FOR EACH ROW
EXECUTE PROCEDURE proc_natobs();

希望对你有用。