PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Postgres trova tutte le righe nelle tabelle del database che corrispondono a criteri su una determinata colonna

Mi sono preso il tempo per farlo funzionare per te.

Per cominciare, alcune informazioni su cosa sta succedendo all'interno del codice.

Spiegazione

  1. La funzione accetta due argomenti di input:il nome della colonna e il valore della colonna
  2. richiede un tipo creato di cui restituirà un set di
  3. first loop identifica le tabelle che hanno un nome di colonna specificato come argomento di input
  4. quindi forma una query che aggrega tutte le righe che corrispondono alla condizione di input all'interno di ogni tabella tratta dal passaggio 3 con confronto basato su ILIKE - come nel tuo esempio
  5. La funzione entra nel secondo ciclo solo se c'è almeno una riga nella tabella attualmente visitata che soddisfa la condizione specificata (quindi l'array non è nullo)
  6. secondo ciclo snida l'array di righe che soddisfano la condizione e per ogni elemento lo inserisce nell'output della funzione con RETURN NEXT rec clausola

Note

  • La ricerca con LIKE è inefficiente:suggerisco di aggiungere un altro argomento di input "tipo di colonna" e di limitarlo nella ricerca aggiungendo un join a pg_catalog.pg_type tabella.

  • Il secondo ciclo è presente in modo che se viene trovata più di 1 riga per una determinata tabella, ogni riga viene restituita.

  • Se stai cercando qualcos'altro, ad esempio hai bisogno di coppie chiave-valore, non solo di valori, allora devi estendere la funzione. Ad esempio, potresti creare il formato json dalle righe.

Ora, al codice.

Caso di prova

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);

La tabella memorizza i dati:

postgres=# select * From tbl1;

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

Tipo di creazione

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

Codice funzione

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
$$;

Chiamata e output esemplari

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)