In ogni caso, hai bisogno di SQL dinamico.
Nome tabella come parametro specificato
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;
Chiama:
SELECT * FROM foo(456887)
In genere, sanificheresti i nomi dei tavoli con format ( %I )
per evitare l'iniezione SQL. Con solo un integer
come input dinamico che non è necessario. Maggiori dettagli e collegamenti in questa risposta correlata:
INSERT con nome tabella dinamica nella funzione trigger
Modello di dati
Potrebbero esserci buone ragioni per il modello di dati. Come il partizionamento/sharding o privilegi separati...
Se non hai una buona ragione, considera di consolidare più tabelle con schema identico in una e aggiungi il number
come colonna. Allora non hai bisogno di SQL dinamico.
Considera ereditarietà
. Quindi puoi aggiungere una condizione su tableoid
per recuperare solo righe da una determinata tabella figlio:
SELECT * FROM parent_table
WHERE tableoid = 'pa456887'::regclass
Siate tuttavia consapevoli delle limitazioni per l'ereditarietà. Risposte correlate:
- Ottieni il nome della tabella di origine di una riga quando esegui una query sul genitore da cui eredita
- Seleziona (recupera) tutti i record da più schemi utilizzando Postgres
Nome della 2a tabella in base al valore nella 1a tabella
Derivare il nome della tabella di join dai valori nella prima tabella complica le cose in modo dinamico.
Solo per pochi tavoli
LEFT JOIN
ciascuno su tableoid
. C'è solo una corrispondenza per riga, quindi usa 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
Per molti tavoli
Combina un ciclo con query dinamiche:
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;