V každém případě potřebujete dynamické SQL.
Název tabulky jako daný parametr
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;
Volejte:
SELECT * FROM foo(456887)
Obecně byste názvy tabulek dezinfikovali pomocí format ( %I )
abyste se vyhnuli SQL injection. Pouze s integer
jako dynamický vstup, který není nutný. Další podrobnosti a odkazy v této související odpovědi:
INSERT s názvem dynamické tabulky ve funkci spouštění
Datový model
Datový model může mít dobré důvody. Jako rozdělení/sharding nebo samostatná oprávnění...
Pokud nemáte tak dobrý důvod, zvažte konsolidaci více tabulek se stejným schématem do jedné a přidejte number
jako sloupec. Pak nepotřebujete dynamické SQL.
Zvažte dědění
. Potom můžete přidat podmínku na tableoid
načíst pouze řádky z dané podřízené tabulky:
SELECT * FROM parent_table
WHERE tableoid = 'pa456887'::regclass
Uvědomte si však omezení dědičnosti. Související odpovědi:
- Získat název zdrojové tabulky řádku při dotazu na nadřazený řádek, od kterého zdědí
- Vyberte (načtěte) všechny záznamy z více schémat pomocí Postgres
Název 2. tabulky v závislosti na hodnotě v 1. tabulce
Odvozování názvu spojovací tabulky z hodnot v první tabulce věci dynamicky komplikuje.
Pouze pro několik stolů
LEFT JOIN
každý na tableoid
. Na každý řádek existuje pouze jedna shoda, proto použijte 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
Pro mnoho tabulek
Zkombinujte smyčku s dynamickými dotazy:
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;