我是PostgreSQL的新手,我想知道是否可以在左连接中将numberfrom tabletbc用作表名的一部分'pa' || number。因此,例如,如果编号为456887,我想与表pa456887左连接。像这样的东西:
number
tbc
'pa' || number
SELECT tdc.cpa, substring(tdc.ku,'[0-9]+') AS number, paTab.vym FROM public."table_data_C" AS tdc LEFT JOIN concat('pa' || number) AS paTab ON (paTab.cpa = tdc.cpa)
而且我只想使用PostgreSQL,而不要使用PHP中的其他代码。
无论哪种方式,都需要动态SQL。
CREATE OR REPLACE FUNCTION foo(_number int) RETURNS TABLE (cpa int, nr text, vym text) AS -- adapt to actual data types! $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动态输入就没有必要了。
format ( %I )
integer
数据模型可能有充分的理由。例如分区/分片或单独的特权… 如果没有足够的理由,请考虑将具有相同模式的多个表合并到一个表中,然后添加numberas列。这样就不需要动态SQL。
考虑继承。然后,您可以添加条件tableoid以仅从给定的子表中检索行:
tableoid
SELECT * FROM parent_table WHERE tableoid = 'pa456887'::regclass
从第一个表中的值派生联接表的名称会动态地使事情复杂化。
LEFT JOIN每个上tableoid。每行只有一个匹配项,因此请使用COALESCE。
LEFT JOIN
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" -- WHERE <some condition> ) 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;