いずれにせよ、動的 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 つに統合し、number
as 列を追加することを検討してください。そうすれば、動的 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;