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

Hom*_*lli 7 sql postgresql stored-procedures dynamic-sql

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

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

伪代码:

CREATE TABLE tbl_a (id INTEGER, name VARCHAR(32), weight double, age INTEGER);
CREATE TABLE tbl_b (id INTEGER, name VARCHAR(32), weight double, age INTEGER);
CREATE TABLE tbl_c (id INTEGER, name VARCHAR(32), weight double, age INTEGER);
CREATE TABLE tbl_d (id INTEGER, name VARCHAR(32), weight double, age INTEGER);

CREATE TYPE person_info AS (id INTEGER, name VARCHAR(32), weight double, age INTEGER);

CREATE FUNCTION generic_func(ARRAY one_or_more_table_names)
    RETURNS person_info 
    -- Run query on table or all specified tables
    AS $$  $$
    LANGUAGE SQL; 
Run Code Online (Sandbox Code Playgroud)

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

Fab*_*cke 8

您应该看一下PostgreSQL 中的表继承,它们完全支持您所说的内容。

例如,您可以创建一个表parent_tbl:

CREATE TABLE parent_tbl (id INTEGER, name VARCHAR(32), weight numeric, age INTEGER);
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

然后,对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)
Run Code Online (Sandbox Code Playgroud)

也可以从给定的子表中过滤数据。例如,如果您对来自表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');
Run Code Online (Sandbox Code Playgroud)

编辑:我把数字代替重量而不是两倍,因为我的服务器不支持这种类型。


Viv*_* S. 5

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

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

结果:

string_agg                                          
--------------------------------------------------- 
select * from tble_a union all select * from tble_b 
Run Code Online (Sandbox Code Playgroud)

您可以创建返回带有列的表的函数

 id INTEGER
,name VARCHAR(32)
,weight numeric
,age INTEGER
Run Code Online (Sandbox Code Playgroud)

PS:我在回避 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
Run Code Online (Sandbox Code Playgroud)

用法:

select * from generic_func(array['tbl_a','tbl_b','tbl_c','tbl_d'])
Run Code Online (Sandbox Code Playgroud)

结果:

id name weight age 
-- ---- ------ --- 
2  ABC  11     112 
2  CBC  11     112 
2  BBC  11     112 
2  DBC  11     112 
Run Code Online (Sandbox Code Playgroud)

和

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

Result:
id name weight age 
-- ---- ------ --- 
2  ABC  11     112 
Run Code Online (Sandbox Code Playgroud)