Postgresql触发器插入行

时间:2016-08-09 08:37:33

标签: postgresql triggers insert-into


我在Postgresql(以及Mysql)上使用了触发器几天。我只想将新填充的行插入另一个表。原始数据来自外部表单(OpenDataKit)并转到"中间"表。我无法理解为什么一旦创建触发器,表单就不能再发送数据...请注意,当我手动插入时,所有操作都在没有触发器的情况下工作。我非常感谢一些帮助,以了解我做错了什么。
我现在正在使用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查询),我尝试将此行(与其他中间表中的信息结合)插入到表#34中;代替"对于触发器的第一个动作,以及第二个动作的表i_lieu_observation(由双主键组成)。我还测试了仅由第一个动作组成的触发器,但它也不起作用。发送表单的Android应用程序崩溃,直到我删除触发器 提前谢谢!

2 个答案:

答案 0 :(得分:1)

您需要在触发器中使用特殊的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();

因为我不知道哪些字段来自哪些表格,所以我不能完全正确。与我编写new.id_loc的方式相同,您需要为来自formulaire_natobs_repeat_loc表的所有字段添加new.field_name。

HTH

答案 1 :(得分:0)

试试这个

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();

希望它适合你。