Hur som helst behöver du dynamisk SQL.
Tabellnamn som given 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:
SELECT * FROM foo(456887)
I allmänhet skulle du rensa tabellnamn med format ( %I )
för att undvika SQL-injektion. Med bara ett integer
som dynamisk ingång som inte är nödvändig. Mer detaljer och länkar i detta relaterade svar:
INSERT med dynamiskt tabellnamn i triggerfunktionen
Datamodell
Det kan finnas goda skäl för datamodellen. Som partitionering / sharding eller separata privilegier ...
Om du inte har en så bra anledning, överväg att konsolidera flera tabeller med identiskt schema till en och lägg till number
som kolumn. Då behöver du inte dynamisk SQL.
Överväg arv
. Sedan kan du lägga till ett villkor på tableoid
för att bara hämta rader från en given underordnad tabell:
SELECT * FROM parent_table
WHERE tableoid = 'pa456887'::regclass
Var dock medveten om begränsningar för arv. Relaterade svar:
- Hämta namnet på en rads källtabell när du frågar vilken förälder den ärver från
- Välj (hämta) alla poster från flera scheman med Postgres
Namn på 2:a tabellen beroende på värdet i 1:a tabell
Att härleda namnet på join-tabellen från värden i den första tabellen komplicerar dynamiskt saker och ting.
För endast ett fåtal bord
LEFT JOIN
var och en på tableoid
. Det finns bara en matchning per rad, så använd 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
För många bord
Kombinera en loop med dynamiska frågor:
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;