Использование триггера обновления tsvector в триггере Postgres
У меня есть столбец 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. Поэтому я пытаюсь использовать синтаксис all-in-one-trigger+procedure...
Есть идеи?
4 ответов:
Вот что у меня получилось:
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();
Альтернативой может быть что-то вроде отличного от, это действительно помогло мне несколько раз. Однако непроверенный код.
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);
Логика сравнения имен должна входить в код процедуры tsvector_update_trigger. что-то вроде:
IF TG_OP = 'UPDATE' THEN IF NEW.name <> OLD.name THEN -- Do tsvector update END IF; END IF;Затем создайте триггер, который вызывается перед INSERT и UPDATE
Когда вы вставляете строку, вам не нужно проверять это условие, на самом деле вы не можете, так как нет старой записи, поэтому:
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);
Comments