sql >> Base de Datos >  >> RDS >> PostgreSQL

Postgres encuentra todas las filas en las tablas de la base de datos que coinciden con los criterios en una columna determinada

Me tomé el tiempo para que funcione para ti.

Para empezar, alguna información sobre lo que sucede dentro del código.

Explicación

  1. la función toma dos argumentos de entrada:nombre de columna y valor de columna
  2. requiere un tipo creado que devolverá un conjunto de
  3. el primer bucle identifica las tablas que tienen un nombre de columna especificado como argumento de entrada
  4. luego forma una consulta que agrega todas las filas que coinciden con la condición de entrada dentro de cada tabla tomada del paso 3 con una comparación basada en ILIKE - según tu ejemplo
  5. la función entra en el segundo ciclo solo si hay al menos una fila en la tabla visitada actualmente que coincide con la condición especificada (entonces la matriz no es nula)
  6. el segundo ciclo anula la matriz de filas que coinciden con la condición y para cada elemento lo coloca en la salida de la función con RETURN NEXT rec cláusula

Notas

  • Buscar con LIKE es ineficiente:sugiero agregar otro argumento de entrada "tipo de columna" y restringirlo en la búsqueda agregando una unión a pg_catalog.pg_type mesa.

  • El segundo bucle está ahí, de modo que si se encuentra más de 1 fila para una tabla en particular, se devuelven todas las filas.

  • Si está buscando algo más, como si necesita pares clave-valor, no solo los valores, entonces necesita extender la función. Por ejemplo, podría crear un formato json a partir de filas.

Ahora, al código.

Caso de prueba

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 tabla almacena datos:

postgres=# select * From tbl1;

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

Creando tipo

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

Código de función

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

Llamada y resultados ejemplares

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)