循环遍历模式中的表格

时间:2014-01-15 17:42:37

标签: sql postgresql plpgsql partitioning dynamic-sql

Postgres 9.1 - 我有一个模式,按月“分区”表(每个月创建一个新表,所有列都相同)。它未设置为具有“主”表的正常分区。我目前正在编写一个相当大的查询,我每个月都要运行几次。

架构:augmented_events
表:
p201301(2013年1月)
p201302(2013年2月)
p201303(2013年3月)
 ...
p201312(2013年12月)
p201401(2014年1月)

现在我必须将我的(简化)查询编写为:

select *    
from augmented_events.p201301  
union   
select *      
from augmented_events.p201302  
union  
select *      
from augmented_events.p201303  
union  
select *      
from augmented_events.p201312  
union  
select *      
from augmented_events.p201401 

每个月我都需要在新月加入。我想让它更具可扩展性,而不必每个月重新访问它。是否有一个我可以创建的函数(或者一个存在的函数)循环遍历augmented_events模式中的每个表,并将其视为我将这些表联合起来?

2 个答案:

答案 0 :(得分:0)

我怀疑在直接SQL中可能有这样的东西,但你可以使用外部代码(PHP,Perl,.NET;你熟悉的任何东西)。它将查询模式,删除旧视图,并创建新模式。安排它每天运行,你将能够使用视图而不考虑包含哪些表。

这是一个创可贴:更好的方法是纠正这种伪分区。

答案 1 :(得分:0)

正确的解决方案

...将通过INHERITANCE进行分区。实际上它很简单。考虑这个相关的答案:
Select (retrieve) all records from multiple schemas using Postgres

目前

虽然您遇到了不幸的设计,但您可以在EXECUTE的plpgsql函数中使用动态SQL。

创建此功能一次

CREATE OR REPLACE FUNCTION f_all_in_schema_foo()
  RETURNS SETOF t AS
$func$
BEGIN
RETURN QUERY EXECUTE (
   SELECT string_agg(format('SELECT * FROM %s', c.oid ::regclass)
                    ,E'\nUNION ALL\n'
                     ORDER BY relname)
   FROM   pg_namespace n
   JOIN   pg_class c ON c.relnamespace = n.oid
   WHERE  n.nspname = 'foo'
   AND    c.relkind = 'r'
   );
END
$func$  LANGUAGE plpgsql;

请注意我如何小心避免 SQL注入的任何可能性(表名必须被视为“用户输入”!)。在这个相关答案中考虑详细的建议:
Table name as a PostgreSQL function parameter
生成并执行以下形式的查询:

SELECT * FROM foo.p201301 
UNION ALL
SELECT * FROM foo.p201302 
UNION ALL
SELECT * FROM foo.p201303 
UNION ALL
...

由于string_agg()中的ORDER BY子句,表按名称排序。

您可以像表一样使用此表函数。拨打:

SELECT * FROM f_all_in_schema_foo();

表现应该不错。

您可以在SO with this search找到类似的解释和链接示例。

相关问题