2011-07-21 180 views
5

我有一個tsvector列,當行更改時,我想更新該列。對於INSERT我用這觸發:在Postgres觸發器中使用tsvector更新觸發器

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 
      ^

從我的理解,如果我使用觸發程序的語法,鼻翼:

CREATE OR REPLACE FUNCTION something() RETURNS TRIGGER

然後我的函數觸發關聯,那麼我將無法使用內置的tsvector_update_trigger功能,將需要處理ts_vector操縱自己。因此,我嘗試使用all-in-one-trigger +過程語法...

任何想法?

回答

12

這是我結束了:

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

代碼中存在拼寫錯誤。你應該有一個BEFORE INSERT OR UPDATE觸發器,因爲NEW在AFTER觸發器上被忽略。 –

+0

@omatrot是的,你是對的!我修好了 - 謝謝你的提示。 –

0

名稱比較邏輯需要進入tsvector_update_trigger過程代碼。 類似:

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

然後創建一個是INSERT之前稱爲觸發器和更新

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