2015-08-02 5 views
2

Эта тема является частью этой проблемы thread, на которую я ищу лучшее решение для одной части от TRIGGER. Я просто хочу запустить триггер для преобразования в правильные скобки. Я думаю, должен ли я возвращаться с триггера NULL или что-то еще до запуска.Чтобы проигнорировать результат в TRIGGER PostgreSQL?

Код

CREATE OR REPLACE FUNCTION insbef_events_function() 
    RETURNS TRIGGER AS 
$func$ 
DECLARE 
    m int[]; 
BEGIN 
    FOREACH m SLICE 1 IN ARRAY TG_ARGV[0]::int[] 
    LOOP 
     INSERT INTO events (measurement_id, event_index_start, event_index_end) 
     SELECT NEW.measurement_id, m[1], m[2]; -- Postgres array starts with 1 ! 
    END LOOP; 

     -- do something with _result ... 

RETURN NULL; -- result ignored since this is an BEFORE trigger TODO right? 
END 
$func$ LANGUAGE plpgsql; 

, который я использую в функции

CREATE OR REPLACE FUNCTION f_create_my_trigger_events(_arg1 int, _arg2 text, _arg3 text) 
    RETURNS void AS 
$func$ 
BEGIN 

EXECUTE format($$ 
    DROP TRIGGER IF EXISTS insbef_ids ON events 
    CREATE TRIGGER insbef_ids 
    BEFORE INSERT ON events 
    FOR EACH ROW EXECUTE PROCEDURE insbef_events_function(%1$L)$$ 
    , translate(_arg2, '[]', '{}'), translate(_arg3, '[]', '{}') 
); 

END 
$func$ LANGUAGE plpgsql; 

Я не уверен насчет этой линии: RETURN NULL; -- result ignored since this is an ДО trigger TODO right?, так как я думаю, что это имеет место в AFTER триггером, но не в перед триггером.
Я просто хочу запустить триггер для преобразования правильных скобок.

Тестовая команда sudo -u postgres psql detector -c "SELECT f_create_my_trigger_events(1,'[112]','[113]');", получив следующую ошибку из-за непонимания возвращающейся-вещи, я думаю.

LINE 3:  CREATE TRIGGER insbef_ids 
      ^
QUERY: 
    DROP TRIGGER IF EXISTS insbef_ids ON events 
    CREATE TRIGGER insbef_ids 
    BEFORE INSERT ON events 
    FOR EACH ROW EXECUTE PROCEDURE insbef_events_function('{112}') 
CONTEXT: PL/pgSQL function f_create_my_trigger_events(integer,text,text) line 4 at EXECUTE statement 

Как вы можете управлять BEFORE триггеры в PostgreSQL 9.4?

+0

@ErwinBrandstetter Да, ваш!Я потратил несколько дней на тестирование ваших предложений в разных условиях, и они работали, но забыли принять ваш ответ. –

ответ

2

Прежде всего, вам необходимо передать переменную строки в BEFORE триггер. Передача NULL отменяет операцию для строки:

CREATE OR REPLACE FUNCTION insbef_events_function() 
    RETURNS TRIGGER AS 
$func$ 
DECLARE 
    m int[]; 
BEGIN 
    FOREACH m SLICE 1 IN ARRAY TG_ARGV[0]::int[] 
    LOOP 
     INSERT INTO events (measurement_id, event_index_start, event_index_end) 
     SELECT NEW.measurement_id, m[1], m[2]; -- Postgres array starts with 1 ! 
    END LOOP; 

     -- do something with _result ... 

RETURN NEW; -- NULL would cancel operation in BEFORE trigger! 
END 
$func$ LANGUAGE plpgsql;

я продемонстрировал использование RETRUN NULL в качестве триггера AFTERin my previous answer. Вы не можете сделать то же самое для триггера BEFORE. The documentation:

Строчных триггера произвели BEFORE может возвращать нуль, чтобы сигнал на спусковом крючке менеджера, чтобы пропустить остальную часть операции для этой строки (то есть, последующих триггера не выпустили, а INSERT/UPDATE/DELETE делает не встречаются для этой строки). Если возвращается ненулевое значение, то операция будет продолжена с этим значением строки.

Существует больше. Прочтите руководство.

Но поскольку вы передаете две 1-мерные массивов вместо одного 2-мерного массива в настоящее время, необходимо адаптировать спусковую логику:

CREATE OR REPLACE FUNCTION insbef_events_function() 
    RETURNS TRIGGER AS 
$func$ 
DECLARE 
    a1 int[] := TG_ARGV[1]::int[]; 
    a2 int[] := TG_ARGV[2]::int[]; 
BEGIN 
    FOR i in array_lower(a1, 1) .. array_upper(a1, 1) 
    LOOP 
     INSERT INTO events (measurement_id, event_index_start, event_index_end) 
     SELECT NEW.measurement_id -- or TG_ARGV[0]::int instead? 
      , a1[i] 
      , a2[i]; 
    END LOOP; 

    RETURN NEW; -- NULL would cancel operation in BEFORE trigger! 
END 
$func$ LANGUAGE plpgsql; 

Теперь это ваша ответственность, что оба массива имеет одинаковое число элементы.
Функция изменение триггера может выглядеть это сейчас:

CREATE OR REPLACE FUNCTION f_create_my_trigger_events(_arg1 int, _arg2 text, _arg3 text) 
    RETURNS void AS 
$func$ 
BEGIN 

EXECUTE format($$ 
    DROP TRIGGER IF EXISTS insbef_ids ON measurements; -- on measurements .. 
    CREATE TRIGGER insbef_ids 
    BEFORE INSERT ON measurements -- .. according to previous posts!! 
    FOR EACH ROW EXECUTE PROCEDURE insbef_events_function(%s, %L, %L)$$ 
    , _arg1 
    , translate(_arg2, '[]', '{}') 
    , translate(_arg3, '[]', '{}') 
); 

END 
$func$ LANGUAGE plpgsql; 

Вам действительно нужно, чтобы понять основы SQL, plpgsql и запуск функций перед использованием этого передового автоматизированного проектирования.

Смежные вопросы