左连接,从列派生的动态表名

Lub*_* K. 6 sql postgresql dynamic dynamic-sql tablename

我是PostgreSQL的新手,我想知道是否可以使用numbertable tbc作为左连接中表名的一部分'pa' || number.因此,例如,如果数字是456887,我想要与表pa456887左连接.像这样的东西:

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)
Run Code Online (Sandbox Code Playgroud)

我只想使用PostgreSQL,而不是PHP中的其他代码.

Erw*_*ter 5

无论哪种方式,您都需要动态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;
Run Code Online (Sandbox Code Playgroud)

呼叫:

SELECT * FROM foo(456887)
Run Code Online (Sandbox Code Playgroud)

通常,您将清理表名format ( %I )以避免SQL注入.只需一个integer不必要的动态输入.此相关答案中的更多详细信息和链接:
在触发器功能中使用动态表名INSERT

数据模型

数据模型可能有充分的理由.就像分区/分片或单独的权限一样......
如果没有这么好的理由,可以考虑将具有相同模式的多个表合并为一个并添加numberas列.那你就不需要动态SQL了.

考虑继承.然后,您可以添加条件tableoid以仅检索给定子表中的行:

SELECT * FROM parent_table
WHERE  tableoid = 'pa456887'::regclass
Run Code Online (Sandbox Code Playgroud)

但是要注意继承的限制.相关答案:

第2表的名称取决于第1表中的值

从第一个表中的值派生连接表的名称会使事情变得复杂.

只有几张桌子

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"
   -- 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
Run Code Online (Sandbox Code Playgroud)

对于许多表

将循环与动态查询结合使用:

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;
Run Code Online (Sandbox Code Playgroud)