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中实现此要求?
您应该看一下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)
编辑:我把数字代替重量而不是两倍,因为我的服务器不支持这种类型。
要使用数组中的项目(表名)动态创建选择查询,您可以使用以下选择语句
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)
| 归档时间: |
|
| 查看次数: |
3964 次 |
| 最近记录: |