Можно ли в PostgreSQL искать в каждом столбце каждой таблицы определенное значение?
Аналогичный вопрос доступен здесь для Oracle.
postgresql
grep
string-matching
Сандро Мунда
источник
источник
Ответы:
Как насчет того, чтобы выгрузить содержимое базы данных, а затем использовать
grep
?Та же утилита, pg_dump, может включать имена столбцов в вывод. Просто смени
--inserts
на--column-inserts
. Таким образом, вы также можете искать определенные имена столбцов. Но если бы я искал имена столбцов, я бы, вероятно, сбросил схему вместо данных.источник
ALTER DATABASE your_db_name SET bytea_output = 'escape';
добавить их в базу данных (или ее копию), прежде чем сбросить их. (Я не вижу способа указать это только дляpg_dump
команды.)Вот функция pl / pgsql, которая находит записи, в которых любой столбец содержит определенное значение. Он принимает в качестве аргументов значение для поиска в текстовом формате, массив имен таблиц для поиска (по умолчанию для всех таблиц) и массив имен схем (по умолчанию все имена схем).
Он возвращает структуру таблицы со схемой, именем таблицы, именем столбца и псевдостолбцом
ctid
(недолговечное физическое расположение строки в таблице, см. Системные столбцы )Смотрите также версию на github основанную на том же принципе, но с добавлением некоторых улучшений скорости и отчетов.
Примеры использования в тестовой базе данных:
Варианты
Чтобы проверить регулярное выражение вместо строгого равенства, такого как grep, эта часть запроса:
SELECT ctid FROM %I.%I WHERE cast(%I as text)=%L
может быть изменено на:
SELECT ctid FROM %I.%I WHERE cast(%I as text) ~ %L
Для сравнений без учета регистра вы можете написать:
SELECT ctid FROM %I.%I WHERE lower(cast(%I as text)) = lower(%L)
источник
~*
более адекватный, чем lower (). Но в любом случаеt.*
это не часть приведенного выше ответа. Поиск столбец за столбцом - это не то же самое, что поиск строки как значения из-за разделителей столбцов.Это не определяет, как точно соответствовать.
Он также не определяет, что именно возвращать.
Предполагая:
regclass
) и идентификатор кортежа (ctid
), потому что это проще всего.Вот мертвый простой, быстрый и немного грязный способ:
Вызов:
Предоставьте шаблон поиска без заключений
%
.Почему немного грязно?
Если разделители и декораторы для строки в
text
представлении могут быть частью шаблона поиска, могут быть ложные срабатывания:,
по умолчанию()
"
\
может быть добавлен как escape-символИ текстовое представление некоторых столбцов может зависеть от локальных настроек - но эта двусмысленность присуща самому вопросу, а не моему решению.
Каждая соответствующая строка возвращается только один раз , даже если она совпадает несколько раз (в отличие от других ответов здесь).
Выполняется поиск по всей БД, кроме системных каталогов. Обычно на завершение уходит много времени . Возможно, вы захотите ограничиться определенными схемами / таблицами (или даже столбцами), как показано в других ответах. Или добавьте уведомления и индикатор прогресса, что также показано в другом ответе.
Тип
regclass
идентификатора объекта представлен в виде имени таблицы, дополненного схемой, где это необходимо, для устранения неоднозначности в соответствии с текущимsearch_path
:Что такое
ctid
?Вы можете захотеть экранировать символы со специальным значением в шаблоне поиска. Видеть:
источник
И если кто-то думает, это может помочь. Вот функция @Daniel Vérité с другим параметром, принимающим имена столбцов, которые можно использовать в поиске. Таким образом сокращается время обработки. По крайней мере, в моем тесте он сильно уменьшился.
Ниже приведен пример использования функции search_function, созданной выше.
источник
Без сохранения новой процедуры вы можете использовать блок кода и выполнить его для получения таблицы вхождений. Вы можете фильтровать результаты по схеме, таблице или имени столбца.
источник
Есть способ добиться этого без создания функции или использования внешнего инструмента. Используя
query_to_xml()
функцию Postgres, которая может динамически запускать запрос внутри другого запроса, можно искать текст во многих таблицах. Это основано на моем ответе на получение количества строк для всех таблиц :Для поиска строки
foo
во всех таблицах схемы можно использовать следующее:Обратите внимание, что для использования
xmltable
требуется Postgres 10 или новее. Для более старой версии Postgres это также можно сделать с помощью xpath ().Общее табличное выражение (
WITH ...
) используется только для удобства. Он просматривает все таблицы вpublic
схеме. Для каждой таблицы черезquery_to_xml()
функцию выполняется следующий запрос :Предложение where используется, чтобы гарантировать, что дорогостоящая генерация XML-контента выполняется только для строк, содержащих строку поиска. Это может вернуть что-то вроде этого:
Преобразование всей строки в
jsonb
выполнено, чтобы в результате можно было увидеть, какое значение принадлежит какому столбцу.Вышеупомянутое может вернуть что-то вроде этого:
Онлайн-пример для Postgres 10+
Онлайн-пример для более старых версий Postgres
источник
ERROR: 42883: function format("unknown", information_schema.sql_identifier, information_schema.sql_identifier) does not exist
format('%I.%I', table_schema::text, table_name::text)
ERROR: 42883: function format("unknown", character varying, character varying) does not exist
format()
функцииВот функция @Daniel Vérité с функцией отчета о прогрессе. Он сообщает о прогрессе тремя способами:
_
источник
- Ниже функция перечислит все таблицы, которые содержат определенную строку в базе данных
- Перебирает все таблицы в базе данных
- Возвращает количество таблиц, для которых выполнено условие. - Например, если предполагаемый текст существует в любом из полей таблицы, - тогда счетчик будет больше нуля. Мы можем найти уведомления - в разделе «Сообщения» программы просмотра результатов в базе данных postgres.
--Получить поля каждой таблицы. Создает предложение where со всеми столбцами таблицы.
источник