J'ai pris le temps de le faire fonctionner pour vous.
Pour commencer, quelques informations sur ce qui se passe dans le code.
Explication
- la fonction prend deux arguments d'entrée :le nom de la colonne et la valeur de la colonne
- il nécessite un type créé qui renverra un ensemble de
- la première boucle identifie les tables qui ont un nom de colonne spécifié comme argument d'entrée
- 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 - 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)
- 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)