PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Linker Join mit dynamischem Tabellennamen, der von der Spalte abgeleitet ist

In jedem Fall benötigen Sie dynamisches SQL.

Tabellenname als gegebener 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;

Aufruf:

SELECT * FROM foo(456887)

Im Allgemeinen würden Sie Tabellennamen im format ( %I ) bereinigen um SQL-Injection zu vermeiden. Mit nur einer integer als dynamische Eingabe ist das nicht notwendig. Weitere Details und Links in dieser verwandten Antwort:
INSERT mit dynamischem Tabellennamen in Triggerfunktion

Datenmodell

Für das Datenmodell mag es gute Gründe geben. Wie Partitionierung / Sharding oder separate Privilegien ...
Wenn Sie keinen so guten Grund haben, ziehen Sie in Betracht, mehrere Tabellen mit identischem Schema zu einer zu konsolidieren und die number hinzuzufügen als Säule. Dann brauchen Sie kein dynamisches SQL.

Betrachten Sie Vererbung . Dann können Sie tableoid eine Bedingung hinzufügen um nur Zeilen aus einer bestimmten untergeordneten Tabelle abzurufen:

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

Beachten Sie jedoch die Einschränkungen für die Vererbung. Verwandte Antworten:

Name der 2. Tabelle abhängig vom Wert in der 1. Tabelle

Das Ableiten des Namens der Join-Tabelle aus Werten in der ersten Tabelle macht die Dinge dynamisch komplizierter.

Für nur ein paar Tische

LEFT JOIN jeweils auf tableoid . Es gibt nur eine Übereinstimmung pro Zeile, also verwenden Sie 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 viele Tabellen

Kombinieren Sie eine Schleife mit dynamischen Abfragen:

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;