Ik heb de tijd genomen om het voor je te laten werken.
Om te beginnen wat informatie over wat er in de code gebeurt.
Uitleg
- functie heeft twee invoerargumenten:kolomnaam en kolomwaarde
- het vereist een gemaakt type dat een set van . zal retourneren
- eerste lus identificeert tabellen waarvoor een kolomnaam is opgegeven als invoerargument
- vervolgens vormt het een query die alle rijen verzamelt die overeenkomen met de invoervoorwaarde in elke tabel uit stap 3 met vergelijking op basis van
ILIKE
- volgens uw voorbeeld - functie gaat alleen naar de tweede lus als er ten minste één rij in de momenteel bezochte tabel is die overeenkomt met de opgegeven voorwaarde (dan is de array niet null)
- tweede lus verwijdert de reeks rijen die overeenkomen met de voorwaarde en plaatst het voor elk element in de functie-uitvoer met
RETURN NEXT rec
clausule
Opmerkingen
-
Zoeken met LIKE is inefficiënt - ik raad aan om nog een invoerargument "kolomtype" toe te voegen en dit in de zoekopdracht te beperken door een join toe te voegen aan
pg_catalog.pg_type
tafel. -
De tweede lus is er, zodat als er meer dan 1 rij wordt gevonden voor een bepaalde tabel, elke rij wordt geretourneerd.
-
Als u op zoek bent naar iets anders, bijvoorbeeld dat u sleutel-waardeparen nodig hebt, niet alleen de waarden, dan moet u de functie uitbreiden. U kunt bijvoorbeeld een json-indeling maken van rijen.
Nu naar de code.
Testcase
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);
Tabel slaat gegevens op:
postgres=# select * From tbl1;
col1 | id
------+----
1 | 5
1 | 33
1 | 25
(3 rows)
Aanmaaktype
CREATE TYPE sometype AS ( schemaname text, tablename text, colname text, entirerow text );
Functiecode
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
$$;
Voorbeeldige oproep en uitvoer
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)