更新 (ALTER) 另一个函数/过程的函数/过程

标签 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)它的内容不会有陷入困境的风险无限循环?

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

最佳答案

虽然您可以从 pg_proc 检索函数源代码,但尝试检索它、编辑它并更新函数是痛苦和折磨的良方。

相反,编写一个 PL/PgSQL 过程来生成完整的函数文本。使用对 information_schemapg_catalog.pg_class 的查询来获取所需的表列表、约束、继承等。循环查询结果,生成函数的主体,然后将它们全部合并为一个文本 block 并将其传递给 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 ,这可能会有用,但您还需要确定正在使用的 CHECK 约束。如果您有命名约定,那么仅依赖它并搜索 pg_class 可能会更简单。

请记住,如果有的话,PostgreSQL 的分区最多只能处理几百个表。由于表数较大时的查询计划成本,性能将显着下降。

关于更新 (ALTER) 另一个函数/过程的函数/过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17747317/

相关文章:

java - 亚马逊 RDS : is there java API for PostgreSQL?

来自多列和空值的每行 SQL 平均值

PostgreSQL、Pl/pgsql - 如何访问执行我所在的存储过程的查询字符串?

C语言原型(prototype)创建

javascript - 比较if语句javascript中的两个变量

c++ - 将 lambda 作为参数传递 - 通过引用或值?

javascript - 行查询中的单引号( Sequelize )

sql - 合并存储过程的结果集

sql - 如何不插入具有空值的双记录

function - 无法使用powershell函数在数组中添加元素