¿Es posible buscar en cada columna de cada tabla un valor particular en PostgreSQL?
Una pregunta similar está disponible aquí para Oracle.
postgresql
grep
string-matching
Sandro Munda
fuente
fuente
Respuestas:
¿Qué hay de tirar el contenido de la base de datos y luego usarlo
grep
?La misma utilidad, pg_dump, puede incluir nombres de columna en la salida. Simplemente cambie
--inserts
a--column-inserts
. De esa forma, también puede buscar nombres de columnas específicos. Pero si estuviera buscando nombres de columnas, probablemente volcaría el esquema en lugar de los datos.fuente
ALTER DATABASE your_db_name SET bytea_output = 'escape';
en la base de datos (o una copia de los mismos) antes de descargarlos. (No veo una forma de especificar esto solo para unpg_dump
comando.)Aquí hay una función pl / pgsql que ubica registros donde cualquier columna contiene un valor específico. Toma como argumentos el valor para buscar en formato de texto, una matriz de nombres de tablas para buscar (por defecto todas las tablas) y una matriz de nombres de esquema (por defecto todos los nombres de esquema).
Devuelve una estructura de tabla con esquema, nombre de tabla, nombre de columna y pseudocolumna
ctid
(ubicación física no duradera de la fila en la tabla, consulte Columnas del sistema )Consulte también la versión en github basada en el mismo principio, pero agregando algunas mejoras de velocidad y generación de informes.
Ejemplos de uso en una base de datos de prueba:
Variantes
Para probar con una expresión regular en lugar de una igualdad estricta, como grep, esta parte de la consulta:
SELECT ctid FROM %I.%I WHERE cast(%I as text)=%L
puede cambiarse a:
SELECT ctid FROM %I.%I WHERE cast(%I as text) ~ %L
Para comparaciones que no distinguen entre mayúsculas y minúsculas, puede escribir:
SELECT ctid FROM %I.%I WHERE lower(cast(%I as text)) = lower(%L)
fuente
~*
más adecuada que lower (). Pero de todos modos,t.*
no es parte de la respuesta anterior. Buscar columna por columna no es lo mismo que buscar la fila como valor debido a los separadores de columna.Esto no define cómo coincidir exactamente.
Tampoco define qué devolver exactamente.
Asumiendo:
regclass
) y el ID de tupla (ctid
), porque eso es lo más simple.Aquí hay una forma sencilla, rápida y ligeramente sucia:
Llamada:
Proporcione el patrón de búsqueda sin adjuntar
%
.¿Por qué un poco sucio?
Si los separadores y decoradores de la fila en la
text
representación pueden ser parte del patrón de búsqueda, puede haber falsos positivos:,
por defecto()
"
\
se puede agregar como carácter de escapeY la representación del texto de algunas columnas puede depender de la configuración local, pero esa ambigüedad es inherente a la pregunta, no a mi solución.
Cada fila de calificación se devuelve solo una vez , incluso cuando coincide varias veces (a diferencia de otras respuestas aquí).
Esto busca en toda la base de datos excepto en los catálogos del sistema. Por lo general, tardará mucho en terminar . Es posible que desee restringirse a ciertos esquemas / tablas (o incluso columnas) como se muestra en otras respuestas. O agregue avisos y un indicador de progreso, también demostrado en otra respuesta.
El
regclass
tipo de identificador de objeto se representa como el nombre de la tabla, calificado por esquema cuando sea necesario para eliminar la ambigüedad de acuerdo con el actualsearch_path
:¿Qué es el
ctid
?Es posible que desee escapar de los caracteres con un significado especial en el patrón de búsqueda. Ver:
fuente
Y si alguien piensa que podría ayudar. Aquí está la función de @Daniel Vérité, con otro parámetro que acepta nombres de columnas que se pueden usar en la búsqueda. De esta forma disminuye el tiempo de procesamiento. Al menos en mi prueba se redujo mucho.
A continuación se muestra un ejemplo del uso de la función de búsqueda creada anteriormente.
fuente
Sin almacenar un nuevo procedimiento, puede usar un bloque de código y ejecutarlo para obtener una tabla de ocurrencias. Puede filtrar los resultados por esquema, tabla o nombre de columna.
fuente
Hay una manera de lograr esto sin crear una función o usar una herramienta externa. Al usar la
query_to_xml()
función de Postgres que puede ejecutar dinámicamente una consulta dentro de otra consulta, es posible buscar un texto en muchas tablas. Esto se basa en mi respuesta para recuperar el recuento de filas para todas las tablas :Para buscar la cadena
foo
en todas las tablas de un esquema, se puede utilizar lo siguiente:Tenga en cuenta que el uso de
xmltable
requiere Postgres 10 o más reciente. Para la versión anterior de Postgres, esto también se puede hacer usando xpath ().La expresión de tabla común (
WITH ...
) solo se usa por conveniencia. Recorre todas las tablas delpublic
esquema. Para cada tabla, se ejecuta la siguiente consulta a través de laquery_to_xml()
función:La cláusula where se utiliza para asegurarse de que la generación costosa de contenido XML solo se realice para las filas que contienen la cadena de búsqueda. Esto podría devolver algo como esto:
Se realiza la conversión de la fila completa a
jsonb
, de modo que en el resultado se pueda ver qué valor pertenece a qué columna.Lo anterior podría devolver algo como esto:
Ejemplo en línea para Postgres 10+
Ejemplo en línea para versiones anteriores de Postgres
fuente
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()
funciónAquí está la función de @Daniel Vérité con funcionalidad de informes de progreso. Informa el progreso de tres formas:
_
fuente
- La siguiente función enumerará todas las tablas que contienen una cadena específica en la base de datos
--Itera a través de todas las tablas de la base de datos
- Devuelve el recuento de tablas para las que se cumple la condición. - Por ejemplo, si el texto deseado existe en cualquiera de los campos de la tabla, - entonces el recuento será mayor que 0. Podemos encontrar las notificaciones - en la sección Mensajes del visor de resultados en la base de datos de Postgres.
- Obtener los campos de cada tabla. Crea la cláusula where con todas las columnas de una tabla.
fuente