sql >> Databasteknik >  >> RDS >> PostgreSQL

Vänsterkoppling med dynamiskt tabellnamn härlett från kolumn

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:

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;



  1. Ett sätt att se frågan efter att parametrar har tillämpats?

  2. Hur man definierar Oracle Package Procedur i H2 för testning

  3. förberett uttalande med Eloquent ORM / laravel

  4. Hur man gör två MySQL SUM:ar baserat på olika kriterier