PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Postgres znajduje wszystkie wiersze w tabelach bazy danych spełniające kryteria w danej kolumnie

Poświęciłem czas, aby to zadziałało dla Ciebie.

Na początek kilka informacji o tym, co dzieje się w kodzie.

Wyjaśnienie

  1. funkcja przyjmuje dwa argumenty wejściowe:nazwę kolumny i wartość kolumny
  2. wymaga utworzonego typu, który będzie zwracał zestaw
  3. pierwsza pętla identyfikuje tabele, które mają nazwę kolumny określoną jako argument wejściowy
  4. następnie tworzy zapytanie, które agreguje wszystkie wiersze pasujące do warunku wejściowego w każdej tabeli pobranej z kroku 3 z porównaniem opartym na ILIKE - jak na twoim przykładzie
  5. funkcja przechodzi do drugiej pętli tylko wtedy, gdy w aktualnie odwiedzanej tabeli znajduje się przynajmniej jeden wiersz, który spełnia określony warunek (wtedy tablica nie jest pusta)
  6. druga pętla rozpakowuje tablicę wierszy spełniających warunek i dla każdego elementu umieszcza ją w wyjściu funkcji za pomocą RETURN NEXT rec klauzula

Notatki

  • Wyszukiwanie za pomocą LIKE jest nieefektywne - proponuję dodać kolejny argument wejściowy "typ kolumny" i ograniczyć go w wyszukiwaniu, dodając sprzężenie do pg_catalog.pg_type tabela.

  • Druga pętla działa tak, że jeśli dla danej tabeli zostanie znaleziony więcej niż 1 wiersz, to każdy wiersz zostanie zwrócony.

  • Jeśli szukasz czegoś innego, na przykład potrzebujesz par klucz-wartość, a nie tylko wartości, musisz rozszerzyć funkcję. Możesz na przykład zbudować format json z wierszy.

Teraz przejdźmy do kodu.

Przypadek testowy

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

Tabela przechowuje dane:

postgres=# select * From tbl1;

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

Tworzenie typu

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

Kod funkcji

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

Przykładowe połączenie i wyjście

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy ograniczenie Postgres UNIQUE implikuje indeks?

  2. Jak wybrać za pomocą klauzuli WITH RECURSIVE

  3. Łączenie dwóch oddzielnych zapytań w postgresql ...query... (możliwe lub niemożliwe)

  4. Zresetuj wartość sekwencji jako 1

  5. Uzyskaj wartości z pierwszego i ostatniego wiersza na grupę