无论哪种方式,您都需要动态SQL。
将表名作为给定参数
CREATE OR REPLACE FUNCTION foo(_number int)
RETURNS TABLE (cpa int, nr text, vym text) AS
$func$
BEGIN
RETURN QUERY EXECUTE format(
'SELECT t.cpa, substring(t.ku,'[0-9]+'), p.vym
FROM public."table_data_C" t
LEFT JOIN %s p USING (cpa)'
, 'pa' || _number
);
END
$func$ LANGUAGE plpgsql;
呼叫:
SELECT * FROM foo(456887)
一般情况下,您需要使用format ( %I )
来对表名进行清理以避免 SQL 注入。但如果只有一个作为动态输入的integer
,这是不必要的。更多细节和相关链接请参见此答案:
INSERT with dynamic table name in trigger function
数据模型
可能存在数据模型的良好原因,例如分区/分片或单独的特权...
如果您没有这样一个很好的原因,请考虑将具有相同模式的多个表合并为一个表,并添加number
作为列。然后您就不需要动态 SQL。
考虑 inheritance。然后您可以在tableoid
上添加条件,仅从给定的子表中检索行:
SELECT * FROM parent_table
WHERE tableoid = 'pa456887'::regclass
请注意继承的限制。 相关答案:
根据第一张表中的值获取第二张表的名称
从第一张表中的值动态派生联接表的名称会使事情变得复杂。
对于只有几个表
LEFT JOIN
每个表到tableoid
上。每行只有一个匹配项,因此使用COALESCE
。
SELECT t.*, t.tbl, COALESCE(p1.vym, p2.vym, p3.vym) AS vym
FROM (
SELECT cpa, ('pa' || substring(ku,'[0-9]+'))::regclass AS tbl
FROM public."table_data_C"
) t
LEFT JOIN pa456887 p1 ON p1.cpa = t.cpa AND p1.tableoid = t.tbl
LEFT JOIN pa456888 p2 ON p2.cpa = t.cpa AND p2.tableoid = t.tbl
LEFT JOIN pa456889 p3 ON p3.cpa = t.cpa AND p3.tableoid = t.tbl
对于许多表格
将循环与动态查询结合使用:
CREATE OR REPLACE FUNCTION foo(_number int)
RETURNS TABLE (cpa int, nr text, vym text) AS
$func$
DECLARE
_nr text;
BEGIN
FOR _nr IN
SELECT DISTINCT substring(ku,'[0-9]+')
FROM public."table_data_C"
LOOP
RETURN QUERY EXECUTE format(
'SELECT t.cpa, _nr, p.vym
FROM public."table_data_C" t
LEFT JOIN %I p USING (cpa)
WHERE t.ku LIKE (_nr || '%')'
, 'pa' || _nr
);
END LOOP;
END
$func$ LANGUAGE plpgsql;