2008-11-20 123 views
19

我在Postgresql中有這個觸發器,我不能只是開始工作(什麼都不做)。爲了理解,我是這樣定義它的:調試postgresql觸發器

CREATE TABLE documents (
    ... 
    modification_time timestamp with time zone DEFAULT now() 
); 

CREATE FUNCTION documents_update_mod_time() RETURNS trigger 
AS $$ 
    begin 
    new.modification_time := now(); 
    return new; 
    end 
$$ 
    LANGUAGE plpgsql; 

CREATE TRIGGER documents_modification_time 
    BEFORE INSERT OR UPDATE ON documents 
    FOR EACH ROW 
    EXECUTE PROCEDURE documents_update_mod_time(); 

現在讓它更有趣一點..如何調試觸發器?

+0

這是不嚴格相關,但你可能會發現它在你的pgsql冒險有用反正:http://stackoverflow.com/questions/430123/how-do-i-enable-the-postgresql-function -profiler – Kev 2009-01-09 23:34:18

回答

41
  1. 使用觸發器功能中下面的代碼,然後看在pgAdmin3的「郵件」選項卡或psql的輸出:

    RAISE NOTICE 'myplpgsqlval is currently %', myplpgsqlval;  -- either this 
    RAISE EXCEPTION 'failed'; -- or that 
    
  2. 要了解哪些觸發實際上被調用,多少時間等,下面的語句是首選的生命保護程序:

    EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers 
    

    請注意,如果您的觸發器不獲取調用,並且使用繼承,這可能是個您只在父表上定義觸發器,而觸發器不會自動由子表繼承。

  3. 要逐步完成該功能,可以使用內置於pgAdmin3中的調試器,該調試器在Windows上默認啓用;您只需要執行... \ 8.3 \ share \ contrib \ pldbgapi.sql中發現的代碼,然後重新啓動pgAdmin3,右鍵單擊您的觸發器函數,點擊'Set Breakpoint',然後執行一個會導致觸發器觸發的語句,例如上面的UPDATE語句。

3

您可以在觸發器函數內使用'raise notice'語句來調試它。調試沒有被調用的觸發器是另一回事。

如果您在觸發器功能中添加「異常提升」,您還可以插入/更新嗎?另外,如果您的更新測試發生在與插入測試相同的事務中,則now()將是相同的(因爲它僅針對每個事務計算一次),因此更新似乎不會執行任何操作。如果是這種情況,可以在單獨的事務中執行它們,或者如果這是單元測試,並且不能這樣做,請使用clock_timestamp()。

我有一個單元測試,要看一段時間的交易之間經過,因此在單元測試的開始,我有類似:

ALTER TABLE documents 
    ALTER COLUMN modification_time SET DEFAULT clock_timestamp(); 

然後在觸發器,使用「設置MODIFICATION_TIME =默認」。

所以通常它不會做額外的計算,但在單元測試期間,這允許我插入pg_sleep來模擬時間傳遞,並且實際上已經將其反映在數據中。

+0

好的提示...所以它似乎函數不會被調用..任何想法爲什麼? – 2008-11-20 19:28:05

+0

你對觸發功能有執行權限嗎? – Kev 2008-11-20 19:45:49

+0

您可能想完全限定(在模式名稱前面)各種對象的名稱,只是爲了安全起見。 此外,您可能會忽略觸發器定義中的「INSERT」部分,默認值會處理這種情況。 – 2008-11-20 20:02:38

2

原來我在上面的問題中使用繼承,忘記提及它。現在對於誰可能會遇到這個問題,以及大家,這裏的一些調試提示:

使用下面的代碼調試什麼是觸發器做:

RAISE NOTICE 'test';  -- either this 
RAISE EXCEPTION 'failed'; -- or that 

要了解哪些觸發實際上被調用,多少次等等,下面的語句是首選的生命保護程序:

EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers 

然後有一兩件事我不知道之前:更新他們定義確切的表時,只觸發了火災。如果你使用繼承,你也必須在子表上定義它們!