Получить данные нескольких вставленных строк в одном объекте, используя триггер в postgres - PullRequest
0 голосов
/ 16 апреля 2020

Я пытаюсь написать триггер, который получает данные из атрибута таблицы, в который вставлено несколько строк , соответствующих одному actionId за один раз , и сгруппировал все эти данные в один объект:

 Table Schema
 actionId
 key
 value

Я запускаю триггер при вставке строк, ТАК как я могу обработать эту вставку нескольких строк и как я могу собрать все данные.

CREATE TRIGGER attribute_changes
AFTER INSERT
ON attributes
FOR EACH ROW
EXECUTE PROCEDURE log_attribute_changes();

и функцию,

 CREATE OR REPLACE FUNCTION wflowr222.log_task_extendedattribute_changes()
RETURNS trigger AS
$BODY$

        DECLARE
        _message json; 
        _extendedAttributes jsonb;

         BEGIN

                SELECT json_agg(tmp) 
                INTO _extendedAttributes
                FROM (
                -- your subquery goes here, for example:
                SELECT attributes.key, attributes.value
                FROM attributes
                WHERE attributes.actionId=NEW.actionId
                ) tmp;

    _message :=json_build_object('actionId',NEW.actionId,'extendedAttributes',_extendedAttributes);

    INSERT INTO wflowr222.irisevents(message)
       VALUES(_message );

       RETURN NULL;
       END;

        $BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

и формат данных:

actionId    key   value
 2         flag   true
 2         image  http:test.com/image
 2         status New

Я пытался сделать это с помощью триггера вставки, но он запускается на каждой вставленной строке. Если у кого-нибудь есть идеи по этому поводу?

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Учитывая версию postgres, которую вы используете, и, следовательно, помните, что вы не можете использовать триггер, определенный FOR EACH STATEMENT, для своей цели, единственная альтернатива, которую я вижу, это

  • , использующая триггер после вставки для сбора некоторой информации об изменениях в служебной таблице
  • с использованием unix cron, который выполняет pl / sql, который выполняет работу с набором данных

Например:

Ваша служебная таблица

CREATE TABLE utility  (
  actionid integer,
  createtime timestamp
  );

Вы можете определить триггер FOR EACH ROW с телом, которое делает что-то подобное

INSERT INTO utilty values(NEW.actionid, curent_timestamp);

И, наконец, есть crontab UNIX, который выполняет файл или процедуру, например, такую:

SELECT a.* FROM utility u JOIN yourtable a ON a.actionid = u.actionid WHERE u.createtime < current_timestamp;
// do something here with records selected above
TRUNCATE table utility;

Если бы у вас было postgres 9.5, вы могли бы использовать pg_cron вместо unix cron ...

1 голос
/ 16 апреля 2020

Я ожидаю, что проблема в том, что вы используете FOR EACH ROW триггер; скорее всего, вам нужен FOR EACH STATEMENT триггер - ie. который срабатывает только один раз для вашего многострочного оператора INSERT. См. Описание в https://www.postgresql.org/docs/current/sql-createtrigger.html для более подробного объяснения.

AFAICT, вам также необходимо добавить REFERENCING NEW TABLE AS NEW в этом режиме, чтобы сделать ссылку NEW доступной для триггера. функция. Поэтому ваш синтаксис CREATE TRIGGER должен быть таким:

CREATE TRIGGER attribute_changes
AFTER INSERT
ON attributes
REFERENCING NEW TABLE AS NEW
FOR EACH STATEMENT
EXECUTE PROCEDURE log_attribute_changes();

В другом месте я читал, что требуемый синтаксис REFERENCING NEW TABLE ... поддерживается только в PostgreSQL 10 и более поздних версиях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...