sql >> Databáze >  >> RDS >> PostgreSQL

Postgres najde všechny řádky v databázových tabulkách odpovídajících kritériím v daném sloupci

Dal jsem si čas, aby to fungovalo pro vás.

Pro začátek nějaké informace o tom, co se děje uvnitř kódu.

Vysvětlení

  1. funkce přebírá dva vstupní argumenty:název sloupce a hodnotu sloupce
  2. vyžaduje vytvořený typ, jehož sadu bude vracet
  3. první smyčka identifikuje tabulky, které mají jako vstupní argument zadaný název sloupce
  4. pak vytvoří dotaz, který agreguje všechny řádky, které odpovídají vstupní podmínce v každé tabulce převzaté z kroku 3, s porovnáním na základě ILIKE - podle vašeho příkladu
  5. funkce přejde do druhého cyklu pouze v případě, že v aktuálně navštívené tabulce existuje alespoň jeden řádek, který odpovídá zadané podmínce (pole pak není null)
  6. druhá smyčka rozloží pole řádků, které vyhovují podmínce, a pro každý prvek jej vloží do výstupu funkce pomocí RETURN NEXT rec doložka

Poznámky

  • Vyhledávání pomocí LIKE je neefektivní – doporučuji přidat další vstupní argument „typ sloupce“ a omezit jej ve vyhledávání přidáním spojení do pg_catalog.pg_type tabulka.

  • Druhá smyčka je zde proto, že pokud je pro konkrétní tabulku nalezen více než 1 řádek, vrátí se každý řádek.

  • Pokud hledáte něco jiného, ​​například potřebujete páry klíč-hodnota, nejen hodnoty, musíte funkci rozšířit. Můžete například vytvořit formát json z řádků.

Nyní ke kódu.

Testovací případ

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

Tabulka ukládá data:

postgres=# select * From tbl1;

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

Vytváření typu

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

Kód funkce

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

Příkladné volání a výstup

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. Existuje způsob, jak skrýt všechny informace o databázi, jako je heslo, uživatelské jméno atd.?

  2. Mohu počítat návštěvy, abych určil počet lidí online?

  3. Rails 3.0.3 - Oracle_enhanced nefunguje

  4. Jak převést na velká písmena v SQLite