web-dev-qa-db-fra.com

Rechercher dans tous les champs de chaque table d'une base de données MySQL

Je souhaite rechercher dans tous les champs de toutes les tables d'une base de données MySQL une chaîne donnée, en utilisant éventuellement la syntaxe suivante:

SELECT * FROM * WHERE * LIKE '%stuff%'

Est-il possible de faire quelque chose comme ça? 

269
RSilva

Vous pouvez jeter un coup d'œil dans le schéma information_schema. Il contient une liste de toutes les tables et de tous les champs contenus dans une table. Vous pouvez ensuite exécuter des requêtes en utilisant les informations que vous avez obtenues à partir de cette table.

Les tables impliquées sont SCHEMATA, TABLES et COLUMNS. Il existe des clés étrangères permettant de définir exactement comment les tables sont créées dans un schéma. 

74
Milhous

Vous pouvez faire un SQLDump de la base de données (et ses données) puis rechercher ce fichier.

411
Dean Rather

Si vous avez installé phpMyAdmin, utilisez sa fonctionnalité 'Recherche'.

  • Sélectionnez votre base de données
  • Assurez-vous d’avoir sélectionné une base de données (c’est-à-dire pas une table, sinon vous obtiendrez un dialogue de recherche complètement différent)
  • Cliquez sur l'onglet 'Recherche'
  • Choisissez le terme de recherche que vous voulez
  • Choisissez les tables à rechercher

Je l'ai utilisé sur un maximum de 250 bases de données de table/10 Go (sur un serveur rapide) et le temps de réponse est tout simplement incroyable.

181
Greg Lyon

Vous pouvez utiliser ce projet: http://code.google.com/p/anywhereindb

Cela recherchera toutes les données de toutes les tables. 

41
nafis
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()){
                    $colum = $r2[0];
                    $sql_search_fields[] = $colum." 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;
}
41
Olivier

Si vous évitez stored procedures comme le fléau, ou êtes incapable de faire un mysql_dump en raison d'autorisations, ou pour toute autre raison. 

Je suggérerais une approche en trois étapes comme celle-ci:

1) Où cette requête génère un ensemble de requêtes en tant que jeu de résultats. 

# =================
# 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%'
;

Les résultats devraient ressembler à ceci:

 Copy these results into another query window

2) Vous pouvez alors simplement Right Click et utiliser la fonction Copy Row (tab separated) 

 enter image description here

3) Coller les résultats dans une nouvelle fenêtre de requête et les exécuter à votre guise.

Détail: J'exclus les schémas système que vous ne pouvez généralement pas voir dans votre plan de travail, sauf si vous avez coché l'option Show Metadata and Internal Schemas.

Je l’ai fait pour fournir un moyen rapide de ANALYZE un hôte entier ou une base de données si nécessaire, ou pour exécuter des instructions OPTIMIZE afin de prendre en charge les améliorations de performances.

Je suis sûr qu’il existe différentes façons de procéder mais voici ce qui fonctionne pour moi:

-- ========================================== 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';

Testé sur la version MySQL: 5.6.23 

AVERTISSEMENT: NE PAS EXÉCUTER CE SI:

  1. Vous êtes préoccupé par les verrous de table (gardez un œil sur vos connexions client)
  2. Vous ne savez pas ce que vous faites.

  3. Vous essayez de vous mettre en colère, DBA. (vous pouvez avoir des gens à votre bureau avec le quickness.)

A bientôt, Jay;]

11
JayRizzo

J'ai également fait mon propre robot d'exploration mysql pour rechercher une configuration wordpress, j'étais incapable de la trouver dans l'interface et la base de données, et les sauvegardes de la base de données étaient trop lourdes et illisibles. Je dois dire que je ne peux plus m'en passer maintenant.

Cela fonctionne comme celui de @Olivier, mais il gère des noms de bases de données/tables exotiques et est sécurisé avec 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++;
    }
}

L'exécution de ce script peut générer quelque chose comme:

---------------------------------------------------
Table 'customers' contains 1 rows matching '*iemblo'.
---------------------------------------------------
Row #1: email_client: [email protected]
        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: [email protected]
8
Alain Tiemblo

C'est la requête la plus simple pour récupérer toutes les colonnes et tous les tableaux.

SELECT * FROM information_schema.`COLUMNS` C WHERE TABLE_SCHEMA = 'YOUR_DATABASE'

Toutes les tables ou celles avec un nom de chaîne spécifique peuvent être recherchées via l'onglet Recherche de phpMyAdmin. 

Avoir une bonne question ...\^. ^ /

7
aji

Avec MySQL Workbench, il est facile de sélectionner plusieurs tables et d’effectuer une recherche de texte dans toutes les tables de la base de données ;-)

5
Fred Christophe

HeidiSQL est un outil utile et fiable, conçu pour les développeurs Web utilisant le célèbre serveur MySQL.

Dans HeidiSQL, vous pouvez appuyer sur Maj + Ctrl + F et trouver du texte sur le serveur dans tous les tableaux. Cette option est très utile.

5
Lev K.

Voici ma solution pour cela

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;
4
user862010

C’est le moyen le plus simple que je connaisse . Sélectionnez votre base de données dans PHPMyAdmin, allez à l’onglet "Rechercher" et écrivez ce que vous voulez trouver et où vous le souhaitez. Sélectionnez toutes les tables si vous voulez rechercher les mots de toutes les tables. Puis "GO" et regardez le résultat .  I Want to find the Word VCD (backdoor) from my Wordpress DB for deleting

3
ardan7779

Bien que cette question soit ancienne, voici comment vous pouvez le faire si vous utilisez mysql workbench 6.3. (Très probablement, cela fonctionne aussi pour d'autres versions)

Faites un clic droit sur votre schéma et "Rechercher dans la table", entrez votre valeur et cliquez sur "Lancer la recherche". C'est tout.

3
Rpant

Vous pourriez utiliser

SHOW TABLES;

Puis obtenez les colonnes dans ces tables (en boucle) avec

SHOW COLUMNS FROM table;

et puis avec cette information créer beaucoup de nombreuses requêtes que vous pouvez également UNION si vous avez besoin.

Mais c'est extrêmement lourd sur la base de données. Surtout si vous faites une recherche comme.

2
Ólafur Waage

J'ai modifié un peu la réponse PHP d'Olivier à:

  • imprimer les résultats dans lesquels la chaîne a été trouvée
  • omettre les tableaux sans résultats
  • affiche également la sortie si les noms des colonnes correspondent à l'entrée de recherche
  • afficher le nombre total de résultats

    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;
    }
    
2
Flion

Le vidage du fichier SQL était probablement le plus rapide et le plus rapide pour moi. Aussi découvert un autre problème de toute façon ..

2
Chad

Cette solution 
a) n’est que MySQL, aucune autre langue n’est nécessaire, et
b) renvoie les résultats SQL, prêts au traitement!

#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;
2
Chonez

je dois le faire fonctionner. il vous suffit de changer les 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>";
1
Trevor

Je me suis basé sur une réponse précédente et j'ai ceci, un rembourrage supplémentaire juste pour pouvoir joindre facilement toutes les sorties:

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

D'abord, vous exécutez ceci, puis collez et exécutez le résultat (sans modification) et il affichera tous les noms de table et les colonnes où la valeur est utilisée.

1
Jim Björklund

Il y a une belle bibliothèque pour lire toutes les tables, 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

}
0
mirhossein

Je ne sais pas s'il s'agit uniquement des versions récentes, mais un clic droit sur l'option Tables dans le volet Navigator ouvre une option appelée Search Table Data. Cela ouvre une boîte de recherche où vous remplissez la chaîne de recherche et cliquez sur Rechercher.

Vous devez sélectionner la table dans laquelle vous souhaitez effectuer une recherche dans le volet gauche. Mais si vous maintenez la touche shift enfoncée et que vous sélectionnez environ 10 tables à la fois, MySql peut gérer cela et renvoyer les résultats en quelques secondes.

Pour tous ceux qui recherchent de meilleures options! :)

0
Crazy Cucumber

Exportez la base de données complète et recherchez dans le fichier .sql.

0
AllenBooTung

J'ai fait cela en utilisant HeidiSQL. Ce n'est pas facile à trouver, mais en appuyant sur Ctrl + Maj + F, la boîte de dialogue "outils de tableau" s'affiche. Sélectionnez ensuite ce que vous souhaitez rechercher (base de données complète dans une seule table), entrez la valeur "Texte à rechercher" et cliquez sur "Rechercher". Je l'ai trouvé étonnamment rapide (870 Mo en moins d'une minute)

0
R1CHY_RICH

J'ai utilisé Union pour enchaîner des requêtes. Je ne sais pas si c'est le moyen le plus efficace, mais ça marche.

SELECT * FROM table1 WHERE name LIKE '%Bob%' Union
SELCET * FROM table2 WHERE name LIKE '%Bob%';
0
mrmills129