Quiero buscar en todos los campos de todas las tablas de una base de datos MySQL una cadena dada, posiblemente usando la sintaxis como:
SELECT * FROM * WHERE * LIKE '%stuff%'
¿Es posible hacer algo como esto?
Quiero buscar en todos los campos de todas las tablas de una base de datos MySQL una cadena dada, posiblemente usando la sintaxis como:
SELECT * FROM * WHERE * LIKE '%stuff%'
¿Es posible hacer algo como esto?
Respuestas:
Puedes echar un vistazo al information_schema
esquema. Tiene una lista de todas las tablas y todos los campos que están en una tabla. Luego puede ejecutar consultas utilizando la información que obtuvo de esta tabla.
Las tablas involucradas son SCHEMATA, TABLES y COLUMNS. Hay claves foráneas para que pueda crear exactamente cómo se crean las tablas en un esquema.
information_schema
es una base de datos, no una tabla. ¡Alguna aclaración sobre qué tabla buscar information_schema
sería buena!
Puede hacer una SQLDump
de la base de datos (y sus datos) y luego buscar ese archivo.
mysqldump -T
que crea dos archivos por tabla en un directorio especificado. Luego grep <search> *
en el directorio, y lo que se devuelve es el archivo tablename.txt o .sql. El archivo txt contiene los datos de la tabla (delimitado por tabuladores, renombra a csv para abrir en Excel), y el sql contiene la definición de la tabla, lo has adivinado: SQL. De esta manera, está buscando todo y es fácil limitar dónde están sus datos. Sin embargo, este método puede ser bastante difícil de conseguir en ciertos entornos. Stack Overflow es muy útil aquí.
Si tiene instalado phpMyAdmin, use su función 'Buscar'.
He usado esto en hasta 250 tablas / bases de datos de 10GB (en un servidor rápido) y el tiempo de respuesta es sorprendente.
Función PHP:
function searchAllDB($search){
global $mysqli;
$out = "";
$sql = "show tables";
$rs = $mysqli->query($sql);
if($rs->num_rows > 0){
while($r = $rs->fetch_array()){
$table = $r[0];
$out .= $table.";";
$sql_search = "select * from ".$table." where ";
$sql_search_fields = Array();
$sql2 = "SHOW COLUMNS FROM ".$table;
$rs2 = $mysqli->query($sql2);
if($rs2->num_rows > 0){
while($r2 = $rs2->fetch_array()){
$column = $r2[0];
$sql_search_fields[] = $column." like('%".$search."%')";
}
$rs2->close();
}
$sql_search .= implode(" OR ", $sql_search_fields);
$rs3 = $mysqli->query($sql_search);
$out .= $rs3->num_rows."\n";
if($rs3->num_rows > 0){
$rs3->close();
}
}
$rs->close();
}
return $out;
}
$mysqli
así:$mysqli = new mysqli('localhost', 'root', 'hunter2', 'my_database');
$colum
con "`$colum`"
por lo que los campos que son palabras reservadas no causará problemas
Puedes usar este proyecto: http://code.google.com/p/anywhereindb
Esto buscará todos los datos en todas las tablas.
Si está evitando stored procedures
como la peste, o no puede hacerlo mysql_dump
debido a los permisos, o se encuentra con otras razones.
Sugeriría un enfoque de tres pasos como este:
1) Donde esta consulta genera un montón de consultas como conjunto de resultados.
# =================
# VAR/CHAR SEARCH
# =================
# BE ADVISED USE ANY OF THESE WITH CAUTION
# DON'T RUN ON YOUR PRODUCTION SERVER
# ** USE AN ALTERNATE BACKUP **
SELECT
CONCAT('SELECT * FROM ', A.TABLE_SCHEMA, '.', A.TABLE_NAME,
' WHERE ', A.COLUMN_NAME, ' LIKE \'%stuff%\';')
FROM INFORMATION_SCHEMA.COLUMNS A
WHERE
A.TABLE_SCHEMA != 'mysql'
AND A.TABLE_SCHEMA != 'innodb'
AND A.TABLE_SCHEMA != 'performance_schema'
AND A.TABLE_SCHEMA != 'information_schema'
AND
(
A.DATA_TYPE LIKE '%text%'
OR
A.DATA_TYPE LIKE '%char%'
)
;
.
# =================
# NUMBER SEARCH
# =================
# BE ADVISED USE WITH CAUTION
SELECT
CONCAT('SELECT * FROM ', A.TABLE_SCHEMA, '.', A.TABLE_NAME,
' WHERE ', A.COLUMN_NAME, ' IN (\'%1234567890%\');')
FROM INFORMATION_SCHEMA.COLUMNS A
WHERE
A.TABLE_SCHEMA != 'mysql'
AND A.TABLE_SCHEMA != 'innodb'
AND A.TABLE_SCHEMA != 'performance_schema'
AND A.TABLE_SCHEMA != 'information_schema'
AND A.DATA_TYPE IN ('bigint','int','smallint','tinyint','decimal','double')
;
.
# =================
# BLOB SEARCH
# =================
# BE ADVISED THIS IS CAN END HORRIFICALLY IF YOU DONT KNOW WHAT YOU ARE DOING
# YOU SHOULD KNOW IF YOU HAVE FULL TEXT INDEX ON OR NOT
# MISUSE AND YOU COULD CRASH A LARGE SERVER
SELECT
CONCAT('SELECT CONVERT(',A.COLUMN_NAME, ' USING utf8) FROM ', A.TABLE_SCHEMA, '.', A.TABLE_NAME,
' WHERE CONVERT(',A.COLUMN_NAME, ' USING utf8) IN (\'%someText%\');')
FROM INFORMATION_SCHEMA.COLUMNS A
WHERE
A.TABLE_SCHEMA != 'mysql'
AND A.TABLE_SCHEMA != 'innodb'
AND A.TABLE_SCHEMA != 'performance_schema'
AND A.TABLE_SCHEMA != 'information_schema'
AND A.DATA_TYPE LIKE '%blob%'
;
Los resultados deberían verse así:
2) Entonces puedes simplemente Right Click
y usar elCopy Row (tab-separated)
3) Pegue los resultados en una nueva ventana de consulta y ejecute el contenido de su corazón.
Detalle: excluyo los esquemas del sistema que normalmente no puede ver en su banco de trabajo a menos que tenga la opción Show Metadata and Internal Schemas
marcada.
Hice esto para proporcionar una manera rápida a ANALYZE
un HOST o DB completo si es necesario o para ejecutar OPTIMIZE
declaraciones para apoyar las mejoras de rendimiento.
Estoy seguro de que hay diferentes maneras de hacerlo, pero esto es lo que funciona para mí:
-- ========================================== DYNAMICALLY FIND TABLES AND CREATE A LIST OF QUERIES IN THE RESULTS TO ANALYZE THEM
SELECT CONCAT('ANALYZE TABLE ', TABLE_SCHEMA, '.', TABLE_NAME, ';') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbname';
-- ========================================== DYNAMICALLY FIND TABLES AND CREATE A LIST OF QUERIES IN THE RESULTS TO OPTIMIZE THEM
SELECT CONCAT('OPTIMIZE TABLE ', TABLE_SCHEMA, '.', TABLE_NAME, ';') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbname';
Probado en la versión de MySQL: 5.6.23
ADVERTENCIA: NO EJECUTE ESTO SI:
- Le preocupa causar bloqueos de tabla (vigile las conexiones de sus clientes)
No estás seguro de lo que estás haciendo.
Estás tratando de enojarte DBA. (puede tener personas en su escritorio con la rapidez ).
Saludos, Jay; -]
También hice mi propio rastreador mysql para buscar alguna configuración de wordpress, no pude encontrarla tanto en la interfaz como en la base de datos, y los volcados de la base de datos eran demasiado pesados e ilegibles. Debo decir que no puedo prescindir de él ahora.
Funciona como el de @Olivier, pero gestiona nombres de tablas / bases de datos exóticos y es seguro como LIKE-joker.
<?php
$database = 'database';
$criteria = '*iemblo'; // you can use * and ? as jokers
$dbh = new PDO("mysql:host=127.0.0.1;dbname={$database};charset=utf8", 'root', '');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$tables = $dbh->query("SHOW TABLES");
while (($table = $tables->fetch(PDO::FETCH_NUM)) !== false)
{
$fields = $dbh->prepare("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?");
$fields->execute(array ($database, $table[0]));
$ors = array ();
while (($field = $fields->fetch(PDO::FETCH_NUM)) !== false)
{
$ors[] = str_replace("`", "``", $field[0]) . " LIKE REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(:search, '\\\\', '\\\\\\\\'), '%', '\\%'), '_', '\\_'), '*', '%'), '?', '_')";
}
$request = 'SELECT * FROM ';
$request .= str_replace("`", "``", $table[0]);
$request .= ' WHERE ';
$request .= implode(' OR ', $ors);
$rows = $dbh->prepare($request);
$rows->execute(array ('search' => $criteria));
$count = $rows->rowCount();
if ($count == 0)
{
continue;
}
$str = "Table '{$table[0]}' contains {$count} rows matching '{$criteria}'.";
echo str_repeat('-', strlen($str)), PHP_EOL;
echo $str, PHP_EOL;
echo str_repeat('-', strlen($str)), PHP_EOL;
$counter = 1;
while (($row = $rows->fetch(PDO::FETCH_ASSOC)) !== false)
{
$col = 0;
$title = "Row #{$counter}:";
echo $title;
foreach ($row as $column => $value)
{
echo
(($col++ > 0) ? str_repeat(' ', strlen($title) + 1) : ' '),
$column, ': ',
trim(preg_replace('!\s+!', ' ', str_replace(array ("\r", "\t", "\n"), array ("", "", " "), $value))),
PHP_EOL;
}
echo PHP_EOL;
$counter++;
}
}
Ejecutar este script podría generar algo como:
---------------------------------------------------
Table 'customers' contains 1 rows matching '*iemblo'.
---------------------------------------------------
Row #1: email_client: my@email.com
numero_client_compta: C05135
nom_client: Tiemblo
adresse_facturation_1: 151, My Street
adresse_facturation_2:
ville_facturation: Nantes
code_postal_facturation: 44300
pays_facturation: FR
numero_tva_client:
zone_geographique: UE
prenom_client: Alain
commentaires:
nom_societe:
email_facturation: my@email.com
Esta es la consulta más simple para recuperar todas las columnas y tablas
SELECT * FROM information_schema.`COLUMNS` C WHERE TABLE_SCHEMA = 'YOUR_DATABASE'
Todas las tablas o aquellas con una cadena específica en el nombre se pueden buscar a través de la pestaña Buscar en phpMyAdmin.
Que tengas una buena consulta ... \ ^. ^ /
Con MySQL Workbench es fácil seleccionar varias tablas y ejecutar una búsqueda de texto en todas esas tablas de la base de datos ;-)
Aquí está mi solución para esto
DROP PROCEDURE IF EXISTS findAll;
CREATE PROCEDURE `findAll`( IN `tableName` VARCHAR( 28 ) , IN `search` TEXT )
BEGIN
DECLARE finished INT DEFAULT FALSE ;
DECLARE columnName VARCHAR ( 28 ) ;
DECLARE stmtFields TEXT ;
DECLARE columnNames CURSOR FOR
SELECT DISTINCT `COLUMN_NAME` FROM `information_schema`.`COLUMNS`
WHERE `TABLE_NAME` = tableName ORDER BY `ORDINAL_POSITION` ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = TRUE;
SET stmtFields = '' ;
OPEN columnNames ;
readColumns: LOOP
FETCH columnNames INTO columnName ;
IF finished THEN
LEAVE readColumns ;
END IF;
SET stmtFields = CONCAT(
stmtFields , IF ( LENGTH( stmtFields ) > 0 , ' OR' , '' ) ,
' `', tableName ,'`.`' , columnName , '` REGEXP "' , search , '"'
) ;
END LOOP;
SET @stmtQuery := CONCAT ( 'SELECT * FROM `' , tableName , '` WHERE ' , stmtFields ) ;
PREPARE stmt FROM @stmtQuery ;
EXECUTE stmt ;
CLOSE columnNames ;
END;
CALL findAll('tbl_test','abb')
, extraño este error: # 1267 - Mezcla ilegal de intercalaciones (utf8_general_ci, IMPLICIT) y (utf8_unicode_ci, IMPLICIT) para la operación '=' ¿Puede solucionarlo? ¡Gracias!
Estoy usando HeidiSQL es una herramienta útil y confiable diseñada para desarrolladores web que utilizan el popular servidor MySQL.
En HeidiSQL puede presionar shift + ctrl + f y puede encontrar texto en el servidor en todas las tablas. Esta opción es muy útil.
Podrías usar
SHOW TABLES;
Luego obtenga las columnas en esas tablas (en un bucle) con
SHOW COLUMNS FROM table;
y luego con esa información crea muchas consultas que también puedes UNIR si lo necesitas.
Pero esto es extremadamente pesado en la base de datos. Especialmente si estás haciendo una búsqueda ME GUSTA.
SHOW TABLES FROM <db_name>
es más preciso
Esta solución
a) es solo MySQL, no se necesita otro lenguaje,
yb) devuelve resultados SQL, ¡listos para procesar!
#Search multiple database tables and/or columns
#Version 0.1 - JK 2014-01
#USAGE: 1. set the search term @search, 2. set the scope by adapting the WHERE clause of the `information_schema`.`columns` query
#NOTE: This is a usage example and might be advanced by setting the scope through a variable, putting it all in a function, and so on...
#define the search term here (using rules for the LIKE command, e.g % as a wildcard)
SET @search = '%needle%';
#settings
SET SESSION group_concat_max_len := @@max_allowed_packet;
#ini variable
SET @sql = NULL;
#query for prepared statement
SELECT
GROUP_CONCAT("SELECT '",`TABLE_NAME`,"' AS `table`, '",`COLUMN_NAME`,"' AS `column`, `",`COLUMN_NAME`,"` AS `value` FROM `",TABLE_NAME,"` WHERE `",COLUMN_NAME,"` LIKE '",@search,"'" SEPARATOR "\nUNION\n") AS col
INTO @sql
FROM `information_schema`.`columns`
WHERE TABLE_NAME IN
(
SELECT TABLE_NAME FROM `information_schema`.`columns`
WHERE
TABLE_SCHEMA IN ("my_database")
&& TABLE_NAME IN ("my_table1", "my_table2") || TABLE_NAME LIKE "my_prefix_%"
);
#prepare and execute the statement
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
#1243 - Unknown prepared statement handler (stmt) given to EXECUTE
cuando ejecuto su consulta en Phpmyadmin para buscar en toda la base de datos
Modifiqué un poco la respuesta PHP de Olivier a:
muestra el número total de resultados
function searchAllDB($search){
global $mysqli;
$out = "";
$total = 0;
$sql = "SHOW TABLES";
$rs = $mysqli->query($sql);
if($rs->num_rows > 0){
while($r = $rs->fetch_array()){
$table = $r[0];
$sql_search = "select * from ".$table." where ";
$sql_search_fields = Array();
$sql2 = "SHOW COLUMNS FROM ".$table;
$rs2 = $mysqli->query($sql2);
if($rs2->num_rows > 0){
while($r2 = $rs2->fetch_array()){
$colum = $r2[0];
$sql_search_fields[] = $colum." like('%".$search."%')";
if(strpos($colum,$search))
{
echo "FIELD NAME: ".$colum."\n";
}
}
$rs2->close();
}
$sql_search .= implode(" OR ", $sql_search_fields);
$rs3 = $mysqli->query($sql_search);
if($rs3 && $rs3->num_rows > 0)
{
$out .= $table.": ".$rs3->num_rows."\n";
if($rs3->num_rows > 0){
$total += $rs3->num_rows;
$out.= print_r($rs3->fetch_all(),1);
$rs3->close();
}
}
}
$out .= "\n\nTotal results:".$total;
$rs->close();
}
return $out;
}
Me basé en una respuesta anterior y tengo esto, algo de relleno adicional solo para poder unir cómodamente toda la salida:
SELECT
CONCAT('SELECT ''',A.TABLE_NAME, '-' ,A.COLUMN_NAME,''' FROM ', A.TABLE_SCHEMA, '.', A.TABLE_NAME,
' WHERE ', A.COLUMN_NAME, ' LIKE \'%Value%\' UNION')
FROM INFORMATION_SCHEMA.COLUMNS A
WHERE
A.TABLE_SCHEMA != 'mysql'
AND A.TABLE_SCHEMA != 'innodb'
AND A.TABLE_SCHEMA != 'performance_schema'
AND A.TABLE_SCHEMA != 'information_schema'
UNION SELECT 'SELECT '''
-- for exact match use: A.COLUMN_NAME, ' LIKE \'Value\' instead
Primero ejecuta esto, luego pega y ejecuta el resultado (sin edición) y mostrará todos los nombres de tabla y columnas donde se usa el valor.
WHERE NOT A.TABLE_SCHEMA IN ('mysql', 'innodb', 'performance_schema', 'information_schema')
o incluso mejor, ejecutarlo, verificar los esquemas utilizados y establecer el esquema utilizado en el lugar en lugar de excluir a todos los demás.
Tengo esto para trabajar. solo necesitas cambiar las variables
$query ="SELECT `column_name` FROM `information_schema`.`columns` WHERE `table_schema`='" . $_SESSION['db'] . "' AND `table_name`='" . $table . "' ";
$stmt = $dbh->prepare($query);
$stmt->execute();
$columns = $stmt->fetchAll(PDO::FETCH_ASSOC);
$query="SELECT name FROM `" . $database . "`.`" . $table . "` WHERE ( ";
foreach ( $columns as $column ) {
$query .=" CONVERT( `" . $column['column_name'] . "` USING utf8 ) LIKE '%" . $search . "%' OR ";
}
$query = substr($query, 0, -3);
$query .= ")";
echo $query . "<br>";
$stmt=$dbh->prepare($query);
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo "<pre>";
print_r ($results );
echo "</pre>";
He hecho esto usando HeidiSQL. No es fácil de encontrar, pero al presionar Ctrl + Shift + F se muestra el cuadro de diálogo "herramientas de tabla". Luego seleccione lo que desea buscar (base de datos completa en una sola tabla) e ingrese el valor "Texto para buscar" y haga clic en "Buscar". Lo encontré sorprendentemente rápido (870MiB db en menos de un minuto)
Usé Union para unir consultas. No sé si es la forma más eficiente, pero funciona.
SELECT * FROM table1 WHERE name LIKE '%Bob%' Union
SELCET * FROM table2 WHERE name LIKE '%Bob%';
Hay una buena biblioteca para leer todas las tablas, ridona
$database = new ridona\Database('mysql:dbname=database_name;host=127.0.0.1', 'db_user','db_pass');
foreach ($database->tables()->by_entire() as $row) {
....do
}
No sé si esto es solo en las versiones recientes, pero al hacer clic derecho en la Tables
opción en el Navigator
panel aparece una opción llamada Search Table Data
. Esto abre un cuadro de búsqueda donde completa la cadena de búsqueda y presiona buscar.
Debe seleccionar la tabla en la que desea buscar en el panel izquierdo. Pero si mantiene presionada la tecla Mayús y selecciona como 10 tablas a la vez, MySql puede manejar eso y devolver los resultados en segundos.
¡Para cualquiera que esté buscando mejores opciones! :)