Uanset hvad, har du brug for dynamisk SQL.
Tabelnavn som givet parameter
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;
Ring til:
SELECT * FROM foo(456887)
Generelt ville du rense tabelnavne med format ( %I )
for at undgå SQL-injektion. Med kun et integer
som dynamisk input, der ikke er nødvendigt. Flere detaljer og links i dette relaterede svar:
INSERT med dynamisk tabelnavn i triggerfunktion
Datamodel
Der kan være gode grunde til datamodellen. Som partitionering / sharding eller separate privilegier ...
Hvis du ikke har en sådan god grund, kan du overveje at konsolidere flere tabeller med identisk skema til én og tilføje number
som kolonne. Så behøver du ikke dynamisk SQL.
Overvej arv
. Derefter kan du tilføje en betingelse på tableoid
for kun at hente rækker fra en given undertabel:
SELECT * FROM parent_table
WHERE tableoid = 'pa456887'::regclass
Vær dog opmærksom på begrænsninger for arv. Relaterede svar:
- Få navnet på en rækkes kildetabel, når du forespørger på den forælder, den arver fra
- Vælg (hent) alle poster fra flere skemaer ved hjælp af Postgres
Navn på 2. tabel afhængig af værdi i 1. tabel
At udlede navnet på join-tabellen fra værdier i den første tabel komplicerer tingene dynamisk.
Kun for nogle få borde
LEFT JOIN
hver på tableoid
. Der er kun ét match pr. række, så brug 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
For mange borde
Kombiner en loop med dynamiske forespørgsler:
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;