sql >> Databasteknik >  >> RDS >> PostgreSQL

Postgres hittar alla rader i databastabeller som matchar kriterier i en given kolumn

Jag tog mig tid att få det att fungera för dig.

Till att börja med, lite information om vad som händer i koden.

Förklaring

  1. funktionen tar två inmatningsargument:kolumnnamn och kolumnvärde
  2. det kräver en skapad typ som den kommer att returnera en uppsättning av
  3. första slingan identifierar tabeller som har ett kolumnnamn specificerat som inmatningsargument
  4. då bildar den en fråga som aggregerar alla rader som matchar indatavillkoret i varje tabell från steg 3 med jämförelse baserad på ILIKE - enligt ditt exempel
  5. funktionen går in i den andra slingan endast om det finns minst en rad i den för närvarande besökta tabellen som matchar specificerat villkor (då är arrayen inte null)
  6. den andra slingan avnestar arrayen av rader som matchar villkoret och för varje element lägger den in den i funktionsutgången med RETURN NEXT rec klausul

Anteckningar

  • Att söka med LIKE är ineffektivt - jag föreslår att du lägger till ett annat inmatningsargument "kolumntyp" och begränsar det i sökningen genom att lägga till en koppling till pg_catalog.pg_type bord.

  • Den andra slingan är där så att om mer än en rad hittas för en viss tabell, så returneras varje rad.

  • Om du letar efter något annat, som att du behöver nyckel-värdepar, inte bara värdena, måste du utöka funktionen. Du kan till exempel bygga json-format från rader.

Nu till koden.

Testfall

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

Tabell lagrar data:

postgres=# select * From tbl1;

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

Skapar typ

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

Funktionskod

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

Exemplariskt samtal och utdata

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. Hur jämför jag SQL-tidsstämpel i .NET?

  2. MySQL formatera om mysql-resultatet för att möta json hansontable

  3. MySQL - två beroende viktade medelvärden i en enda fråga

  4. fpdf-fel och visningstabellfel