2015-07-20 118 views
3

我想寫一個pgsql函數來動態地創建觸發器。例如,一個觸發器來計算每個表中的插入次數。我試過這樣的EXECUTE:如何在pgsql中動態創建觸發器函數?

CREATE FUNCTION trigen(tbl text) RETURNS void AS $$ 
BEGIN 
    EXECUTE format(
    'CREATE FUNCTION %s_insertCnt() RETURNS TRIGGER AS $$ 
    BEGIN 
     UPDATE insertions SET n = n + 1 WHERE tablename = %s; 
    END 
    $$ LANGUAGE plpgsql', tbl, quote_nullable(tbl)); 

    EXECUTE format('CREATE TRIGGER %s_inCnt BEFORE INSERT ON %s 
    FOR EACH ROW EXECUTE PROCEDURE %s_insertCnt();', tbl, tbl, tbl); 
END 
$$ LANGUAGE plpgsql 

但是這種方法不起作用。導入此代碼時發生了很多語法錯誤。看來EXECUTE不能執行一個函數的創建。

我還可以做些什麼來動態創建觸發器功能?

+1

我認爲問題是嵌套'$$'。要嵌入美元引用的文字,您需要選擇不同的標籤。有關詳細信息,請參見[docs](http://www.postgresql.org/docs/9.4/static/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING)。 –

+0

你爲什麼要這樣做?爲什麼動態? – Patrick

回答

2

兩個$$部分變得困惑。通過使用$ name $語法,您可以分開這些。

此外,觸發器丟失了一個RETURN。

CREATE OR REPLACE FUNCTION trigen(tbl text) RETURNS void AS $T1$ 
BEGIN 
    EXECUTE format(
    'CREATE FUNCTION %s_insertCnt() RETURNS TRIGGER AS $T2$ 
    BEGIN 
     UPDATE insertions SET n = n + 1 WHERE tablename = %s; 
     RETURN NEW; 
    END 
    $T2$ LANGUAGE plpgsql', tbl, quote_nullable(tbl)); 

    EXECUTE format('CREATE TRIGGER %s_inCnt BEFORE INSERT ON %s 
    FOR EACH ROW EXECUTE PROCEDURE %s_insertCnt();', tbl, tbl, tbl); 
    END 
$T1$ LANGUAGE plpgsql; 
+0

謝謝,這完全解決了我的問題! –

相關問題