sql >> Database >  >> RDS >> PostgreSQL

Linker join met dynamische tabelnaam afgeleid van kolom

Hoe dan ook, je hebt dynamische SQL nodig.

Tabelnaam als opgegeven 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;

Bel:

SELECT * FROM foo(456887)

Over het algemeen zou u tabelnamen opschonen met format ( %I ) om SQL-injectie te voorkomen. Met slechts een integer als dynamische input is dat niet nodig. Meer details en links in dit gerelateerde antwoord:
INSERT met dynamische tabelnaam in triggerfunctie

Gegevensmodel

Er kunnen goede redenen zijn voor het datamodel. Zoals partitionering / sharding of aparte privileges ...
Als je niet zo'n goede reden hebt, overweeg dan om meerdere tabellen met een identiek schema samen te voegen tot één en voeg het number toe als kolom. Dan heb je geen dynamische SQL nodig.

Overweeg erfenis . Dan kun je een voorwaarde toevoegen aan tableoid om alleen rijen uit een bepaalde onderliggende tabel op te halen:

SELECT * FROM parent_table
WHERE  tableoid = 'pa456887'::regclass

Houd echter rekening met beperkingen voor overerving. Gerelateerde antwoorden:

Naam van 2e tafel afhankelijk van waarde in 1e tabel

Het afleiden van de naam van de join-tabel van waarden in de eerste tabel maakt de zaken dynamisch ingewikkelder.

Voor slechts een paar tafels

LEFT JOIN elk op tableoid . Er is slechts één overeenkomst per rij, dus gebruik 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

Voor veel tafels

Combineer een lus met dynamische zoekopdrachten:

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. Hoe kan ik een Profiled DataAdapter instantiëren om te gebruiken met MVC MINI PROFILER?

  2. Flask SQLAlchemy sluit MySQL-databaseverbindingen niet

  3. MariaDB JSON_SEARCH() uitgelegd

  4. BLOB of VARBINARY gebruiken voor versleutelde gegevens in MySQL?