Использование триггера обновления tsvector в триггере Postgres - PullRequest
10 голосов
/ 22 июля 2011

У меня есть столбец tsvector, который я хочу обновить при изменении строки. Для INSERT я использую этот триггер:

CREATE TRIGGER albums_vector_insert BEFORE INSERT
ON albums
FOR EACH ROW EXECUTE PROCEDURE
 tsvector_update_trigger('search_vector', 'pg_catalog.english', 'name')

Что, похоже, работает нормально Я хотел бы использовать другой триггер в предложениях UPDATE, но я хочу, чтобы он срабатывал только тогда, когда имя действительно меняется, поэтому я не теряю циклы обновления вектора поиска без необходимости. Я пробовал это:

CREATE TRIGGER albums_vector_update BEFORE UPDATE ON albums
FOR EACH ROW EXECUTE PROCEDURE
    IF NEW.name <> OLD.name THEN
        tsvector_update_trigger(search_vector, 'pg_catalog.english', name);
    END IF;

Но при попытке создать триггер выдается 2 ошибки:

Error : ERROR:  syntax error at or near "NEW"
LINE 3:  IF NEW.name <> OLD.name THEN
            ^
Error : ERROR:  syntax error at or near "IF"
LINE 1: END IF
            ^

Насколько я понимаю, если я использую синтаксис триггерной процедуры, ala:

CREATE OR REPLACE FUNCTION something() RETURNS TRIGGER

затем свяжите мою функцию с триггером, тогда я не смогу использовать встроенную функцию tsvector_update_trigger, и мне придется самостоятельно обрабатывать манипуляции с ts_vector. Поэтому я пытаюсь использовать синтаксис «все в одном триггере +» ...

Есть идеи?

Ответы [ 4 ]

14 голосов
/ 23 июля 2011

Вот что я закончил:

CREATE FUNCTION albums_vector_update() RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' THEN
        new.search_vector = to_tsvector('pg_catalog.english', COALESCE(NEW.name, ''));
    END IF;
    IF TG_OP = 'UPDATE' THEN
        IF NEW.name <> OLD.name THEN
            new.search_vector = to_tsvector('pg_catalog.english', COALESCE(NEW.name, ''));
        END IF;
    END IF;
    RETURN NEW;
END
$$ LANGUAGE 'plpgsql';


CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON albums
FOR EACH ROW EXECUTE PROCEDURE albums_vector_update();
2 голосов
/ 27 июня 2013

Альтернатива может отличаться от той, что действительно мне несколько раз помогала.Хотя непроверенный код.

CREATE TRIGGER albums_vector_update 
BEFORE INSERT OR UPDATE ON albums
FOR EACH ROW 
WHEN (OLD.name IS DISTINCT FROM NEW.name)
EXECUTE PROCEDURE tsvector_update_trigger(search_vector, 'pg_catalog.english', NEW.name);
0 голосов
/ 13 июня 2018

Когда вы вставляете строку, вам не нужно проверять это условие, на самом деле вы не можете этого сделать, поскольку нет старой записи, поэтому:

CREATE TRIGGER albums_vector_insert 
BEFORE INSERT ON albums
FOR EACH ROW 
EXECUTE PROCEDURE tsvector_update_trigger(search_vector, 'pg_catalog.english', name);

Для обновления:

CREATE TRIGGER albums_vector_update 
BEFORE UPDATE ON albums
FOR EACH ROW 
WHEN (OLD.name IS DISTINCT FROM NEW.name)
EXECUTE PROCEDURE tsvector_update_trigger(search_vector, 'pg_catalog.english', name);
0 голосов
/ 22 июля 2011

Логика сравнения имен должна входить в код процедуры tsvector_update_trigger. что-то вроде:

IF TG_OP = 'UPDATE' THEN
    IF NEW.name <> OLD.name THEN
       -- Do tsvector update
    END IF;
END IF;

Затем создайте триггер, который вызывается перед INSERT и UPDATE

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