功能/程序更新(ALTER)另一个功能/程序

时间:2013-07-19 13:27:45

标签: function postgresql stored-procedures postgresql-9.2 database-partitioning

我在PostgreSQL 9.2上分区了表,每个表都有一个看起来像这样的分区函数:

CREATE OR REPLACE FUNCTION myPartitionSelectionFunction()
  RETURNS trigger AS
$BODY$
BEGIN
    IF ( NEW.PartitionColumn < DATE '2010-08-08 00:00:00') THEN INSERT INTO MyPartitionedTable_Week_31_2010 VALUES (NEW.*);
    ELSIF ( NEW.PartitionColumn < DATE '2010-08-15 00:00:00' AND NEW.PartitionColumn >=  DATE '2010-08-08 00:00:00') THEN INSERT INTO MyPartitionedTable_Week_32_2010 VALUES (NEW.*);
    ELSE
        RAISE EXCEPTION 'PartitionColumn out of range. Update myPartitionSelectionFunction()';
    END IF;
    RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql

所以,每周都是一个新的分区。问题是每周更新数百个功能。我必须自动化,并且每个插入的触发器都是不可行的。我们的想法是创建一个由cron调用的函数,它更新每个分区函数,在最终的ELSE之前添加另一个ELSIF。但是我找不到一种方法来遍历每个具有“分区”名称的函数,然后检索它的代码(像\ d这样的psql命令在函数中不起作用,对吗?)来添加新的ELSIF和相应地更新(ALTER)每个函数,在过程中创建一个新的分区。

所以,我现在面临的最大问题是:

如果在其上有“分区”名称后,如何通过每个函数迭代(使用游标?),然后检索它的代码,在ELSE之前添加另一个ELSIF并更新(ALTER)它的内容不会有陷入困境的风险无限循环?

非常感谢任何帮助。感谢。

1 个答案:

答案 0 :(得分:2)

虽然您可以从pg_proc检索功能源,但尝试检索它,编辑它并更新功能是一种痛苦和痛苦的方法。

相反,编写一个PL / PgSQL过程,完整地生成函数文本。对information_schemapg_catalog.pg_class使用查询以获取所需的表列表,约束,继承等。循环查询结果,生成函数体,然后将它们全部加入到单个块中文本并将其传递给EXECUTE

这是一个生成另一个函数的玩具示例:

CREATE OR REPLACE FUNCTION very_meta(func_name text, message text) RETURNS void AS 
$$
DECLARE
    func_lines text;
BEGIN
    -- In reality you'd build this iteratively, or preferably use `string_agg` over
    -- a query, but I'm just going to supply a single line function body for this
    -- example:
    func_lines := format($LINE$RAISE NOTICE 'It works, message is %%!','%s';$LINE$, message);
    -- Now, build the function creation statement and execute it:
    EXECUTE format(
    $INNER$
        -- this is the SQL text we're going to execute, with the %%I placeholder
        -- to be replaced by the format(...) function:
        --
        CREATE OR REPLACE FUNCTION %I() RETURNS void AS
        $INNERBODY$
        BEGIN
            -- and this is the body of the function we're generating
            -- in this case it's going to be substituted in as func_lines
            -- by format(...)
            %s
        END;
        $INNERBODY$
        LANGUAGE plpgsql;
    $INNER$, func_name, func_lines);
END;
$$ LANGUAGE plpgsql;

演示:

regress=> SELECT very_meta('lessmeta', 'Secret Message');
 very_meta 
-----------

(1 row)

regress=> SELECT lessmeta();
NOTICE:  It works, message is Secret Message!
 lessmeta 
----------

(1 row)

这可以与针对information_schema和/或系统目录的适当查询相结合,以获取表格列表,创建一系列条件测试等等。This answer I wrote a while ago details how to query the catalogs for inheritance relationships,这可能很有用,但是你' ll还需要识别正在使用的CHECK约束。如果您有一个命名约定,那么依靠它并搜索pg_class可能会更简单。

请记住,PostgreSQL的分区最适用于最多几百个表,如果是这样的话。由于查询计划成本较大,因此性能将显着下降。