Postgresql - 如何在具有相同模式的多个表上运行查询

时间:2017-01-05 09:17:57

标签: sql postgresql stored-procedures dynamic-sql

我有一个postgres数据库,有几个表(几百个)。数据库中表的子集 Foo 具有相同的架构。

理想情况下,我想创建一个存储过程,该存储过程可以针对单个表运行查询,也可以针对子集 Foo 中的所有表运行。

伪代码:

from_date = Date.new(2016, 1, 1)
to_date = Date.today

Sidekiq.redis do |redis|
  redis.del("stat:processed")
  redis.del("stat:failed")

  (from_date..to_date).each do |date|
    redis.del("stat:processed:#{date}")
    redis.del("stat:failed:#{date}")
  end
end

我如何在Postgresql 9.x中实现此要求?

2 个答案:

答案 0 :(得分:6)

你应该看一下PostgreSQL中的table inheritance,它们完全允许你说的话。

例如,您可以创建表parent_tbl:

CREATE TABLE parent_tbl (id INTEGER, name VARCHAR(32), weight numeric, age INTEGER);

然后将您的表链接到此父表:

ALTER TABLE tbl_a INHERIT parent_tbl;
ALTER TABLE tbl_b INHERIT parent_tbl;
ALTER TABLE tbl_c INHERIT parent_tbl;
ALTER TABLE tbl_d INHERIT parent_tbl;

然后,通过parent_tbl的SELECT查询将查询所有tbl_x表,而对tbl_x的查询将仅查询此特定表。

INSERT INTO tbl_a VALUES (1, 'coucou', 42, 42);

SELECT * FROM tbl_a;
 id |  name  | weight | age 
----+--------+--------+-----
  1 | coucou |     42 |  42
(1 row)

SELECT * FROM parent_tbl;
 id |  name  | weight | age 
----+--------+--------+-----
  1 | coucou |     42 |  42
(1 row)

SELECT * FROM tbl_b;
 id |  name  | weight | age 
----+--------+--------+-----
(0 rows)

也可以从给定的子表中过滤数据。例如,如果您对来自表tbl_a和tbl_b的数据感兴趣,可以这样做

select id, name, weight, age
from parent_tbl
left join pg_class on oid = parent_tbl.tableoid
where relname in ('tbl_a', 'tbl_b');

编辑:我把数字用于重量而不是双倍,因为我的服务器不支持此类型。

答案 1 :(得分:4)

要使用数组中的项(表名)动态创建选择查询,可以使用以下select语句

SELECT string_agg(q, ' union all ')
FROM  (
    SELECT 'select * from ' || unnest(array ['tble_a','tble_b']) AS q
    ) t

结果:

string_agg                                          
--------------------------------------------------- 
select * from tble_a union all select * from tble_b 

您可以创建返回带列

的表的函数
 id INTEGER
,name VARCHAR(32)
,weight numeric
,age INTEGER

P.S:我在避免TYPE person_info

功能:

CREATE
    OR REPLACE FUNCTION generic_func (tbl varchar [])
RETURNS TABLE (         -- To store the output
        id INTEGER
        ,name VARCHAR(32)
        ,weight numeric
        ,age INTEGER
        ) AS $BODY$

DECLARE qry text;

BEGIN
    SELECT string_agg(q, ' union all ')  --To create select query dynamically
    INTO qry
    FROM (
        SELECT 'select * from ' || unnest(tbl) AS q
        ) t;

    RAISE NOTICE 'qry %',qry; --optional

    RETURN query --Executes the query to the defined table

    EXECUTE qry;
END;$BODY$

LANGUAGE plpgsql VOLATILE

用法:

select * from generic_func(array['tbl_a','tbl_b','tbl_c','tbl_d'])

结果:

id name weight age 
-- ---- ------ --- 
2  ABC  11     112 
2  CBC  11     112 
2  BBC  11     112 
2  DBC  11     112 

select * from generic_func(array['tbl_a'])

Result:
id name weight age 
-- ---- ------ --- 
2  ABC  11     112