在Postgres触发器中使用tsvector更新触发器

时间:2011-07-21 23:19:35

标签: postgresql triggers

我想要在行更改时更新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 个答案:

答案 0 :(得分:14)

这就是我最终的结果:

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

答案 1 :(得分:2)

替代方案可能与众不同,它确实帮了我几次。但是未经测试的代码。

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

答案 2 :(得分:0)

名称比较逻辑需要进入tsvector_update_trigger过程代码。 类似的东西:

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

然后创建一个在INSERT和UPDATE之前调用的触发器

答案 3 :(得分:0)

当您插入行时,您不必检查此条件,实际上您不能因为没有OLD记录所以:

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