我在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)它的内容不会有陷入困境的风险无限循环?
非常感谢任何帮助。感谢。
答案 0 :(得分:2)
虽然您可以从pg_proc
检索功能源,但尝试检索它,编辑它并更新功能是一种痛苦和痛苦的方法。
相反,编写一个PL / PgSQL过程,完整地生成函数文本。对information_schema
或pg_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的分区最适用于最多几百个表,如果是这样的话。由于查询计划成本较大,因此性能将显着下降。