PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Postgres намира всички редове в таблиците на базата данни, отговарящи на критерии за дадена колона

Отделих време, за да го накарам да работи за вас.

Като за начало, малко информация за това какво се случва вътре в кода.

Обяснение

  1. функцията приема два входни аргумента:име на колона и стойност на колона
  2. изисква създаден тип, който ще връща набор от
  3. първият цикъл идентифицира таблици, които имат име на колона, указано като входен аргумент
  4. след това формира заявка, която агрегира всички редове, които отговарят на входното условие във всяка таблица, взета от стъпка 3, със сравнение на базата на ILIKE - според вашия пример
  5. функцията влиза във втория цикъл само ако има поне един ред в текущо посетената таблица, който отговаря на определено условие (тогава масивът не е нула)
  6. вторият цикъл премахва масива от редове, които отговарят на условието, и за всеки елемент го поставя в изхода на функцията с RETURN NEXT rec клауза

Бележки

  • Търсенето с LIKE е неефективно - предлагам да добавите друг входен аргумент "тип колона" и да го ограничите при търсенето, като добавите съединение към pg_catalog.pg_type таблица.

  • Вторият цикъл е там, така че ако се намери повече от 1 ред за определена таблица, всеки ред се връща.

  • Ако търсите нещо друго, като имате нужда от двойки ключ-стойност, а не само от стойностите, тогава трябва да разширите функцията. Можете например да изградите json формат от редове.

Сега към кода.

Тестов случай

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

Таблицата съхранява данни:

postgres=# select * From tbl1;

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

Създаване на тип

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

Функционален код

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

Примерно повикване и изход

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. Да изпратите SQLite база данни към Heroku с кранове?

  2. Как да изброите таблици в текущата база данни с помощта на PostgreSQL

  3. Как да напиша съхранена процедура на postgres, която не връща нищо?

  4. PostgreSQL разстояние между 2 точки, съхранени в таблица

  5. Oracle към PostgreSQL — Курсори и ltrees