像@Igor desrcibes 这样的视图 是一种选择。
如果性能至关重要并且您没有很多写入操作,则可以使用该视图来(重新)创建物化视图。
或者,对于更短的语法和源表的动态选择,您可以使用这样的plpgsql 函数:
CREATE OR REPLACE FUNCTION f_select_from_tbls(tables text[], cond int)
RETURNS TABLE (this int, that text) AS
$BODY$
DECLARE
tbl text; -- automatically avoids SQLi
BEGIN
FOREACH tbl IN ARRAY tables LOOP
RETURN QUERY EXECUTE format('
SELECT this, that
FROM %I
WHERE this = $1', tbl)
USING cond;
END LOOP;
END
$BODY$
LANGUAGE plpgsql;
称呼:
SELECT * FROM f_select_from_tbls('{t1,t2,nonStandard tablename}', 4);
我假设许多表共享相同名称和类型的列(this int, that text)
(您没有在问题中定义数据类型。)该函数将一个array of text
作为表名和一个integer
值作为条件。
手册中有关循环数组的更多信息。手册中有关从函数返回的
更多信息。
使用动态 SQL,您必须警惕SQL 注入。这种威胁在这里通过两种方式消除:
- 数组中的表名
tables
被注入了format()
正确引用任何非标准表名的函数
- 参数中的值按
cond
原样通过 via 传递USING
,从而使 SQLi 不可能。
目的是使函数调用更简单。您可以提交一个文本变量列表,而不是从它们构建一个数组(数组是从参数内部构建的)。就这样。
CREATE OR REPLACE FUNCTION f_select_from_tbls2(cond int, VARIADIC tables text[])
RETURNS TABLE (this int, that text) AS
$BODY$
DECLARE
tbl text; -- automatically avoids SQLi
BEGIN
FOREACH tbl IN ARRAY tables LOOP
RETURN QUERY EXECUTE format('
SELECT this, that
FROM %I
WHERE this = $1', tbl)
USING cond;
END LOOP;
END
$BODY$
LANGUAGE plpgsql;
在这种情况下,我放在tables
最后一个VARIADIC
参数是开放的。称呼:
SELECT * FROM f_select_from_tbls2(4, 't1','t2','iLLegal name')