I have a postgres database that has several tables (a few hundreds). A subset Foo of the tables in the database have the same schema.
我有一个postgres数据库,它有几个表(几百个)。数据库中表的Foo子集具有相同的模式。
Ideally, I would like to create a stored procedure which can run a query against a single table, or against all tables in subset Foo.
理想情况下,我希望创建一个存储过程,它可以对单个表运行查询,也可以对Foo子集中的所有表运行查询。
Pseudocode:
伪代码:
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;
How could I implement this requirement in Postgresql 9.x ?
我如何在Postgresql 9中实现这个需求。x ?
2 个解决方案
#1
2
You should have a look at table inheritance in PostgreSQL, they allow exactly what you speak about.
您应该看看PostgreSQL中的表继承,它们完全允许您所说的内容。
For example, you could create a table parent_tbl:
例如,可以创建一个parent_tbl表:
CREATE TABLE parent_tbl (id INTEGER, name VARCHAR(32), weight numeric, age INTEGER);
Then link your tables to this parent table:
然后将表链接到父表:
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;
Then a SELECT query over parent_tbl will query all of tbl_x tables, while a query on tbl_x will query only this particular table.
然后,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)
It is also possible to filter data from given children tables. For example, if you are interested in data coming from tables tbl_a and tbl_b, you can do
也可以从给定的子表中过滤数据。例如,如果您对来自表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');
EDIT : I put numeric for weight instead of double as this type is not supported on my server.
编辑:我将数值表示权重,而不是双精度,因为我的服务器不支持这种类型。
#2
2
To create select query dynamically using items(table name) in an array you can use following select statement
要使用数组中的项(表名)动态创建select查询,可以使用以下select语句
SELECT string_agg(q, ' union all ')
FROM (
SELECT 'select * from ' || unnest(array ['tble_a','tble_b']) AS q
) t
Result:
结果:
string_agg
---------------------------------------------------
select * from tble_a union all select * from tble_b
You can create the function that returns table with columns
您可以创建返回带有列的表的函数
id INTEGER
,name VARCHAR(32)
,weight numeric
,age INTEGER
P.S: I am avoiding TYPE person_info
P。S:我在避免键入person_info。
function:
功能:
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
Usage:
用法:
select * from generic_func(array['tbl_a','tbl_b','tbl_c','tbl_d'])
Result:
结果:
id name weight age
-- ---- ------ ---
2 ABC 11 112
2 CBC 11 112
2 BBC 11 112
2 DBC 11 112
and
和
select * from generic_func(array['tbl_a'])
select * from generic_func(array[' tbl_a '])
Result:
id name weight age
-- ---- ------ ---
2 ABC 11 112
#1
2
You should have a look at table inheritance in PostgreSQL, they allow exactly what you speak about.
您应该看看PostgreSQL中的表继承,它们完全允许您所说的内容。
For example, you could create a table parent_tbl:
例如,可以创建一个parent_tbl表:
CREATE TABLE parent_tbl (id INTEGER, name VARCHAR(32), weight numeric, age INTEGER);
Then link your tables to this parent table:
然后将表链接到父表:
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;
Then a SELECT query over parent_tbl will query all of tbl_x tables, while a query on tbl_x will query only this particular table.
然后,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)
It is also possible to filter data from given children tables. For example, if you are interested in data coming from tables tbl_a and tbl_b, you can do
也可以从给定的子表中过滤数据。例如,如果您对来自表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');
EDIT : I put numeric for weight instead of double as this type is not supported on my server.
编辑:我将数值表示权重,而不是双精度,因为我的服务器不支持这种类型。
#2
2
To create select query dynamically using items(table name) in an array you can use following select statement
要使用数组中的项(表名)动态创建select查询,可以使用以下select语句
SELECT string_agg(q, ' union all ')
FROM (
SELECT 'select * from ' || unnest(array ['tble_a','tble_b']) AS q
) t
Result:
结果:
string_agg
---------------------------------------------------
select * from tble_a union all select * from tble_b
You can create the function that returns table with columns
您可以创建返回带有列的表的函数
id INTEGER
,name VARCHAR(32)
,weight numeric
,age INTEGER
P.S: I am avoiding TYPE person_info
P。S:我在避免键入person_info。
function:
功能:
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
Usage:
用法:
select * from generic_func(array['tbl_a','tbl_b','tbl_c','tbl_d'])
Result:
结果:
id name weight age
-- ---- ------ ---
2 ABC 11 112
2 CBC 11 112
2 BBC 11 112
2 DBC 11 112
and
和
select * from generic_func(array['tbl_a'])
select * from generic_func(array[' tbl_a '])
Result:
id name weight age
-- ---- ------ ---
2 ABC 11 112