7

私はPostgreSQLが初めてで、numberfrom tabletbcを left join のテーブル名の一部として使用できるかどうか疑問に思っています'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)

また、たとえば PHP の追加コードではなく、PostgreSQL のみを使用したいと考えています。

4

1 に答える 1

8

いずれにせよ、動的 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必要のない動的入力だけで。この関連する回答の詳細とリンク:
INSERT with dynamic table name in trigger function

データ・モデル

データモデルには正当な理由があるかもしれません。パーティショニング/シャーディングまたは個別の権限
のように... よほどの理由がない場合は、同一のスキーマを持つ複数のテーブルを 1 つに統合し、numberas 列を追加することを検討してください。そうすれば、動的 SQL は必要ありません。

継承を検討してください。次に、条件を追加してtableoid、特定の子テーブルからのみ行を取得できます。

SELECT * FROM parent_table
WHERE  tableoid = 'pa456887'::regclass

ただし、継承の制限に注意してください。関連する回答:

1 番目のテーブルの値に応じた 2 番目のテーブルの名前

最初のテーブルの値から結合テーブルの名前を導出すると、動的に複雑になります。

ほんの数テーブルの場合

LEFT JOIN各上にtableoid。行ごとに 1 つの一致しかないため、 を使用します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;
于 2014-07-16T14:19:19.077 に答える