Quero pesquisar em todos os campos de todas as tabelas de um banco de dados MySQL uma determinada string, possivelmente usando a sintaxe como:
SELECT * FROM * WHERE * LIKE '%stuff%'
É possível fazer algo assim?
Quero pesquisar em todos os campos de todas as tabelas de um banco de dados MySQL uma determinada string, possivelmente usando a sintaxe como:
SELECT * FROM * WHERE * LIKE '%stuff%'
É possível fazer algo assim?
Respostas:
Você pode espiar o information_schema
esquema. Ele tem uma lista de todas as tabelas e todos os campos que estão em uma tabela. Em seguida, você pode executar consultas usando as informações obtidas dessa tabela.
As tabelas envolvidas são ESQUEMA, TABELAS e COLUNAS. Existem chaves estrangeiras para que você possa criar exatamente como as tabelas são criadas em um esquema.
information_schema
é um banco de dados, não uma tabela. Alguns esclarecimentos sobre qual tabela pesquisar dentro information_schema
seriam bons!
Você pode fazer um SQLDump
banco de dados (e seus dados) e pesquisar nesse arquivo.
mysqldump -T
que cria dois arquivos por tabela em um diretório especificado. Eu então grep <search> *
no dir, e o que é retornado é o arquivo tablename.txt ou .sql. O arquivo txt mantém os dados da tabela (delimitado por tabulação, renomeie para csv para abrir no Excel) e o sql mantém a definição da tabela, você adivinhou: SQL. Dessa forma, você está pesquisando tudo e é fácil restringir onde estão seus dados. Esse método pode ser bastante difícil de trabalhar em determinados ambientes. O estouro de pilha é muito útil aqui.
Se você possui o phpMyAdmin instalado, use o recurso 'Pesquisar'.
Eu usei isso em bancos de dados de até 250 tabelas / 10 GB (em um servidor rápido) e o tempo de resposta é incrível.
Função 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
assim:$mysqli = new mysqli('localhost', 'root', 'hunter2', 'my_database');
$colum
por, "`$colum`"
para que os campos que são palavras reservadas não causem problemas
Você pode usar este projeto: http://code.google.com/p/anywhereindb
Isso pesquisará todos os dados em todas as tabelas.
Se você está evitando stored procedures
como uma praga, ou não consegue fazer um mysql_dump
devido a permissões, ou se deparar com outros motivos diversos.
Eu sugeriria uma abordagem em três etapas como esta:
1) Onde esta consulta cria um monte 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%'
;
Os resultados devem ficar assim:
2) Você pode então apenas Right Click
usar oCopy Row (tab-separated)
3) Cole os resultados em uma nova janela de consulta e execute o conteúdo do seu coração.
Detalhe: excluo os esquemas do sistema que você normalmente não vê no seu ambiente de trabalho, a menos que tenha a opção Show Metadata and Internal Schemas
marcada.
Fiz isso para fornecer uma maneira rápida de ANALYZE
um HOST ou banco de dados inteiro, se necessário, ou para executar OPTIMIZE
instruções para dar suporte a melhorias de desempenho.
Tenho certeza de que existem maneiras diferentes de você fazer isso, mas eis o que funciona para mim:
-- ========================================== 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';
Testado na versão MySQL: 5.6.23
AVISO: NÃO EXECUTAR ISTO SE:
- Você está preocupado em causar bloqueios de tabela (fique de olho nas conexões do cliente)
Você não tem certeza do que está fazendo.
Você está tentando irritar seu DBA. (você pode ter pessoas em sua mesa com a rapidez .)
Saúde, Jay; -]
Também fiz meu próprio rastreador mysql para pesquisar alguma configuração do wordpress, não consegui encontrá-la na interface nem no banco de dados, e os despejos de banco de dados eram muito pesados e ilegíveis. Devo dizer que não posso ficar sem isso agora.
Ele funciona como o do @Olivier, mas gerencia nomes de bancos de dados / tabelas exóticos e é seguro para o 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++;
}
}
A execução desse script pode gerar 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 é a consulta mais simples para recuperar todas as colunas e tabelas
SELECT * FROM information_schema.`COLUMNS` C WHERE TABLE_SCHEMA = 'YOUR_DATABASE'
Todas as tabelas ou aquelas com string específica no nome podem ser pesquisadas na guia Pesquisar no phpMyAdmin.
Tenha uma Consulta Agradável ... \ ^. ^ /
Usando o MySQL Workbench, é fácil selecionar várias tabelas e executar uma pesquisa por texto em todas as tabelas do banco de dados ;-)
Embora essa questão seja antiga, veja como você pode fazê-lo se estiver usando o mysql workbench 6.3. (Muito provavelmente também funciona para outras versões)
Clique com o botão direito do mouse em seu esquema e em "Pesquisar dados da tabela", insira seu valor e pressione "Iniciar pesquisa". É isso aí.
Aqui está a minha solução para isso
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')
, sinto falta deste erro: # 1267 - Mistura ilegal de agrupamentos (utf8_general_ci, IMPLICIT) e (utf8_unicode_ci, IMPLICIT) para operation '=' Consegue corrigi-lo? Obrigado!
Eu estou usando HeidiSQL é uma ferramenta útil e confiável projetada para desenvolvedores web usando o popular servidor MySQL.
No HeidiSQL, você pode pressionar shift + ctrl + f e pode encontrar texto no servidor em todas as tabelas. Esta opção é muito útil.
Você poderia usar
SHOW TABLES;
Em seguida, obtenha as colunas nessas tabelas (em um loop) com
SHOW COLUMNS FROM table;
e, com essas informações, crie muitas consultas, que você também poderá unir, se precisar.
Mas isso é extremamente pesado no banco de dados. Especialmente se você estiver fazendo uma pesquisa COMO.
SHOW TABLES FROM <db_name>
é mais preciso
Esta solução
a) é apenas MySQL, nenhuma outra linguagem é necessária
eb) retorna resultados SQL, prontos para processamento!
#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
quando eu executar a consulta no phpMyAdmin para pesquisar no banco de dados inteiro
Modifiquei a resposta PHP de Olivier um pouco para:
mostra o 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;
}
Eu construí uma resposta anterior e tenho isso, algum preenchimento extra apenas para poder juntar convenientemente toda a saída:
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
Primeiro você executa isso, depois cola e executa o resultado (sem edição) e ele exibirá todos os nomes de tabelas e colunas em que o valor é usado.
WHERE NOT A.TABLE_SCHEMA IN ('mysql', 'innodb', 'performance_schema', 'information_schema')
ou, melhor ainda, executá-lo, verificar os esquemas usados e definir o esquema usado no local, excluindo todos os outros.
Eu tenho que trabalhar. você só precisa alterar as variáveis
$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>";
Eu fiz isso usando o HeidiSQL. Não é fácil encontrar, mas pressionando Ctrl + Shift + F ele exibe a caixa de diálogo "table tools". Em seguida, selecione o que deseja pesquisar (banco de dados completo em tabela única) e digite o valor "Texto a encontrar" e clique em "Localizar". Achei surpreendentemente rápido (870MiB db em menos de um minuto)
Eu usei o Union para encadear consultas. Não sei se é a maneira mais eficiente, mas funciona.
SELECT * FROM table1 WHERE name LIKE '%Bob%' Union
SELCET * FROM table2 WHERE name LIKE '%Bob%';
Existe uma boa biblioteca para ler todas as tabelas, 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
}
Não sei se isso é apenas nas versões recentes, mas clicar com o botão direito do mouse na Tables
opção no Navigator
painel exibe uma opção chamadaSearch Table Data
. Isso abre uma caixa de pesquisa onde você preenche a sequência de pesquisa e pressiona a pesquisa.
Você precisa selecionar a tabela que deseja pesquisar no painel esquerdo. Mas se você mantiver a tecla shift pressionada e selecionar 10 tabelas por vez, o MySql poderá lidar com isso e retornar os resultados em segundos.
Para quem procura melhores opções! :)