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

Postgres findet alle Zeilen in Datenbanktabellen, die den Kriterien einer bestimmten Spalte entsprechen

Ich habe mir die Zeit genommen, damit es für Sie funktioniert.

Für den Anfang einige Informationen darüber, was im Code vor sich geht.

Erklärung

  1. Funktion nimmt zwei Eingabeargumente:Spaltenname und Spaltenwert
  2. es erfordert einen erstellten Typ, von dem es einen Satz zurückgibt
  3. Erste Schleife identifiziert Tabellen, die einen Spaltennamen als Eingabeargument angegeben haben
  4. dann bildet es eine Abfrage, die alle Zeilen aggregiert, die der Eingabebedingung in jeder Tabelle aus Schritt 3 entsprechen, mit einem Vergleich basierend auf ILIKE - nach deinem Beispiel
  5. Funktion geht nur dann in die zweite Schleife, wenn es mindestens eine Zeile in der aktuell besuchten Tabelle gibt, die der angegebenen Bedingung entspricht (dann ist das Array nicht null)
  6. Die
  7. zweite Schleife entschachtelt das Array von Zeilen, die der Bedingung entsprechen, und fügt es für jedes Element in die Funktionsausgabe mit RETURN NEXT rec ein Klausel

Notizen

  • Die Suche mit LIKE ist ineffizient - ich schlage vor, ein weiteres Eingabeargument "Spaltentyp" hinzuzufügen und es in der Suche einzuschränken, indem Sie einen Join zu pg_catalog.pg_type hinzufügen Tabelle.

  • Die zweite Schleife ist da, damit, wenn mehr als eine Zeile für eine bestimmte Tabelle gefunden wird, jede Zeile zurückgegeben wird.

  • Wenn Sie nach etwas anderem suchen, wie Sie Schlüssel-Wert-Paare benötigen, nicht nur die Werte, müssen Sie die Funktion erweitern. Sie könnten zum Beispiel das JSON-Format aus Zeilen erstellen.

Nun zum Code.

Testfall

CREATE TABLE tbl1 (col1 int, id int); -- does contain values
CREATE TABLE tbl2 (col1 int, col2 int); -- doesn't contain column "id"
CREATE TABLE tbl3 (id int, col5 int); -- doesn't contain values

INSERT INTO tbl1 (col1, id)
  VALUES (1, 5), (1, 33), (1, 25);

Tabelle speichert Daten:

postgres=# select * From tbl1;

 col1 | id
------+----
    1 |  5
    1 | 33
    1 | 25
(3 rows)

Typ erstellen

CREATE TYPE sometype AS ( schemaname text, tablename text, colname text, entirerow text );

Funktionscode

CREATE OR REPLACE FUNCTION search_tables_for_column (
    v_column_name text
  , v_column_value text
)
RETURNS SETOF sometype
LANGUAGE plpgsql
STABLE
AS
$$
DECLARE
  rec           sometype%rowtype;
  v_row_array   text[];
  rec2          record;
  arr_el        text;
BEGIN
FOR rec IN
  SELECT 
      nam.nspname AS schemaname
    , cls.relname AS tablename
    , att.attname AS colname
    , null::text AS entirerow
  FROM 
    pg_attribute att
    JOIN pg_class cls ON att.attrelid = cls.oid 
    JOIN pg_namespace nam ON cls.relnamespace = nam.oid 
  WHERE 
    cls.relkind = 'r'
    AND att.attname = v_column_name
LOOP
  EXECUTE format('SELECT ARRAY_AGG(row(tablename.*)::text) FROM %I.%I AS tablename WHERE %I::text ILIKE %s',
    rec.schemaname, rec.tablename, rec.colname, quote_literal(concat('%',v_column_value,'%'))) INTO v_row_array;
  IF v_row_array is not null THEN
    FOR rec2 IN
      SELECT unnest(v_row_array) AS one_row
    LOOP
      rec.entirerow := rec2.one_row;
      RETURN NEXT rec;
    END LOOP;
  END IF;
END LOOP;
END
$$;

Beispielhafter Aufruf &Ausgabe

postgres=# select * from search_tables_for_column('id','5');

 schemaname | tablename | colname | entirerow
------------+-----------+---------+-----------
 public     | tbl1      | id      | (1,5)
 public     | tbl1      | id      | (1,25)
(2 rows)