PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Postgres trouve toutes les lignes dans les tables de base de données correspondant aux critères d'une colonne donnée

J'ai pris le temps de le faire fonctionner pour vous.

Pour commencer, quelques informations sur ce qui se passe dans le code.

Explication

  1. la fonction prend deux arguments d'entrée :le nom de la colonne et la valeur de la colonne
  2. il nécessite un type créé qui renverra un ensemble de
  3. la première boucle identifie les tables qui ont un nom de colonne spécifié comme argument d'entrée
  4. il forme ensuite une requête qui agrège toutes les lignes qui correspondent à la condition d'entrée dans chaque table extraite de l'étape 3 avec une comparaison basée sur ILIKE - selon votre exemple
  5. la fonction passe dans la deuxième boucle uniquement s'il y a au moins une ligne dans la table actuellement visitée qui correspond à la condition spécifiée (le tableau n'est alors pas nul)
  6. la deuxième boucle désimbrique le tableau de lignes qui correspondent à la condition et pour chaque élément, elle le place dans la sortie de la fonction avec RETURN NEXT rec clause

Remarques

  • La recherche avec LIKE est inefficace - je suggère d'ajouter un autre argument d'entrée "type de colonne" et de le restreindre dans la recherche en ajoutant une jointure à pg_catalog.pg_type tableau.

  • La deuxième boucle est là pour que si plus d'une ligne est trouvée pour une table particulière, chaque ligne est renvoyée.

  • Si vous recherchez autre chose, comme si vous aviez besoin de paires clé-valeur, pas seulement de valeurs, vous devez étendre la fonction. Vous pouvez par exemple créer le format json à partir de lignes.

Passons maintenant au code.

Cas de test

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 table stocke les données :

postgres=# select * From tbl1;

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

Type de création

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

Code de fonction

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

Appel et sortie exemplaires

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)