2016-08-09 4 views
0


Я застрял в течение нескольких дней с триггерами на Postgresql (и Mysql также). Я просто хочу вставить вновь заполненные строки в другую таблицу. Исходные данные поступают из внешней формы (OpenDataKit) и переходят в «промежуточные» таблицы. Я не могу понять, почему форма больше не может отправлять данные после создания триггера ... Обратите внимание, что все действия работают без триггера, когда я делаю вставки вручную. Я был бы очень признателен за помощь в понимании того, что я делаю неправильно.
Теперь я тестирую Postgresql 9.5, но у меня возникла аналогичная проблема с MySQL 5.1.Postgresql Триггер для вставки строк

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

Итак, когда форма ОКА вставляет новые строки в FORMULAIRE_NATOBS_REPEAT_LOC (для которого я создал серийный номер для облегчения запросов SQL), я пытаюсь вставить эту строку (в сочетании с информацией из других промежуточных таблиц) в таблицу «lieu» для первого действия триггера и в таблицу i_lieu_observation (состоящую из двойного первичного ключа) для второго действия. Я тестировал также триггер, состоящий только из первого действия, но он тоже не работает. Приложение Android, которое отправляет форму, падает до тех пор, пока я не удалю триггер.
Заранее благодарим!

+1

Вместо использования 'MAX (id_loc) FROM FORMULAIRE _...' вы должны использовать 'new.xxx' для проверки строки, которая запускает триггер. – joop

+0

Это поможет, если вы добавите определения для всех упомянутых таблиц в вопрос. Для меня это похоже на соотношение 1: N между двумя таблицами lieu и i_lieu_observateurs. И это, безусловно, поможет, если вы использовали синтаксис JOIN. – wildplasser

ответ

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, вам нужно будет поместить new.field_name для всех полей, исходящих из таблицы formulaire_natobs_repeat_loc.

НТН

+0

Спасибо, но это не сработало. Но см. Мой комментарий к @Paarth – RemiC

+0

Я только что редактировал свой код. Я забыл вернуться! –

+0

Я полагаю, что FORMULAIRE_NATOBS_CORE и FORMULAIRE_NATOBS_REPEAT_OBSERVATEUR имеют значения, которые приравниваются к новому. TOP_LEVEL_AURI? –

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

Надеется, что это работает для вас.

+0

Спасибо! Это будет лучше в том смысле, что форма теперь заполняет таблицы ODK «FORMULAIRE_xx», но триггер ничего не возвращает. Таблицы «lieu» и «i_lieu_observateurs» по-прежнему пусты ... У вас есть дополнительные советы? – RemiC

+0

Включен Check Trigger. Если триггер включен и есть ошибка в триггере, таблица «FORMULAIRE_NATOBS_REPEAT_LOC» также не будет заполнена. проверьте триггер. – Paarth

+0

Если триггер в порядке, попробуйте вставить запрос с некоторыми фиктивными данными для таблиц «lieu» и «i_lieu_observateurs». Работает ли вставка или нет для данных таблиц. – Paarth