sql >> Database >  >> RDS >> PostgreSQL

Postgres vindt alle rijen in databasetabellen die overeenkomen met criteria in een bepaalde kolom

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

  1. functie heeft twee invoerargumenten:kolomnaam en kolomwaarde
  2. het vereist een gemaakt type dat een set van
  3. . zal retourneren
  4. eerste lus identificeert tabellen waarvoor een kolomnaam is opgegeven als invoerargument
  5. 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
  6. 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)
  7. 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)



  1. Hoe records te matchen die zijn gekoppeld aan een specifieke set andere records?

  2. MariaDB RONDE() vs TRUNCATE()

  3. Hoe kan ik de SQL-query afdrukken die wordt uitgevoerd nadat Perl's DBI de tijdelijke aanduidingen heeft ingevuld?

  4. MariaDB JSON_VALUE() uitgelegd