Search text in fields in every table of a MySQL database

前端 未结 24 1598
梦谈多话
梦谈多话 2020-11-22 06:23

I want to search in all fields from all tables of a MySQL database a given string, possibly using syntax as:

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


        
相关标签:
24条回答
  • 2020-11-22 06:51

    MySQL Workbench

    Here are some instructions.

    Download and install MSQL Workbench.

    https://www.mysql.com/products/workbench/

    When installing, it might require you to install Visual Studio C++ Redistributable. You can get it here:

    https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads

    x64: vc_redist.x64.exe (for 64 bit Windows)

    When you open MySQL Workbench, you will have to enter your host name, user and password.

    There is a Schemas tab on the side menu bar, click on the Schemas tab, then double click on a database to select the database you want to search.

    Then go to menu Database - Search Data, and enter the text you are searching for, click on Start Search.

    HeidiSql

    Download and install HeidiSql https://www.heidisql.com/download.php

    Enter your hostname, user and password.

    Hit Ctrl+Shift+F to search text.

    0 讨论(0)
  • 2020-11-22 06:54

    You could do an SQLDump of the database (and its data) then search that file.

    0 讨论(0)
  • 2020-11-22 06:55

    There is a nice library for reading all 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 讨论(0)
  • 2020-11-22 06:55

    Even if the following proposal should not be considered as a final solution you can achieve the goal by doing something like this:

    SET SESSION group_concat_max_len = 1000000;
    SET @search = 'Text_To_Search';
    
    DROP table IF EXISTS table1;
    CREATE TEMPORARY TABLE table1 AS 
    (SELECT 
        CONCAT('SELECT \'',TABLE_NAME,'\' as \'table_name\',\'',COLUMN_NAME,'\' as \'column_name\',CONVERT(count(*),char) as \'matches\' FROM `',
        TABLE_NAME,'` where `',COLUMN_NAME,'` like \'%',@search,'%\' UNION ') as 'query'
    FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'db_name' limit 1000000);
    
    set @query = (SELECT GROUP_CONCAT(t1.`query` SEPARATOR '') as 'final_query' from table1 t1 limit 1);
    set @query = (SELECT SUBSTRING(@query, 1, length(@query) - 7));
    
    PREPARE stmt FROM @query;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    

    Please remember that:

    1. Options: group_concat_max_len and limit 1000000 not always are needed, it will depends of your server/IDE configuration. Just in case I added them.

    2. After executing this you will get a 3 column response: [table_name], [column_name], [matches]

    3. Column 'matches' is the number of occurrences in the given table/column.

    4. This query is very fast.

    DISCLAIMER: It would be useful only for personal use, in other words please don't use it in a production system, because it is sensitive to SQL Injection attacks given that the search parameter is concatenated with other strings. If you want to create a prod. ready function, then you will need to create a store procedure with a LOOP.

    0 讨论(0)
  • 2020-11-22 06:56

    I also did my own mysql crawler to search some wordpress configuration, was unable to find it in both the interface and database, and database dumps were too heavy and unreadable. I must say I can't do without it now.

    It works like the one from @Olivier, but it manages exotic database / table names and is LIKE-joker safe.

    <?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++;
        }
    }
    

    Running this script could output something like:

    ---------------------------------------------------
    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
    
    0 讨论(0)
  • 2020-11-22 06:57

    If you are avoiding stored procedures like the plague, or are unable to do a mysql_dump due to permissions, or running into other various reasons.

    I would suggest a three-step approach like this:

    1) Where this query builds a bunch of queries as a result set.

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

    Results should look like this:

    2) You can then just Right Click and use the Copy Row (tab-separated)

    3) Paste results in a new query window and run to your heart's content.

    Detail: I exclude system schema's that you may not usually see in your workbench unless you have the option Show Metadata and Internal Schemas checked.

    I did this to provide a quick way to ANALYZE an entire HOST or DB if needed or to run OPTIMIZE statements to support performance improvements.

    I'm sure there are different ways you may go about doing this but here’s what works for me:

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

    Tested On MySQL Version: 5.6.23

    WARNING: DO NOT RUN THIS IF:

    1. You are concerned with causing Table-locks (keep an eye on your client-connections)
    2. You are unsure about what you are doing.

    3. You are trying to anger you DBA. (you may have people at your desk with the quickness.)

    Cheers, Jay ;-]

    0 讨论(0)
提交回复
热议问题