2015-07-20 121 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

谢谢,这完全解决了我的问题! –

相关问题