Come cercare un intero database MySQL per una stringa particolare


19

è possibile cercare un intero database (righe e colonne) per scoprire una stringa particolare.

Sto avendo un database chiamato A con circa 35 tabelle, devo cercare la stringa denominata "ciao" e non so su quale tabella questa stringa viene salvata. È possibile?

Usando MySQL

sono un amministratore linux e non ho familiarità con i database, sarebbe davvero utile se tu potessi anche spiegare la query.


Risposte:



7

Nel luglio 2012 ho scritto questo post

Esegui query per trovare e sostituire il testo in tutte le tabelle e i campi di un db mysql

Utilizza la tabella information_schema.columns per raccogliere tutti i campi CHAR, VARCHAR e TEXT ed eseguire un REPLACE testuale .

Per favore, guarda il mio vecchio link e usa il suo paradigma per fare una ricerca.

Ad esempio, questo creerà un SELECT separato per ogni colonna di testo in ogni tabella

SELECT
    CONCAT('SELECT ',QUOTE(db),',',QUOTE(tb),',',QUOTE(col),',COUNT(1) FieldHasIt
    FROM ',db,'.',tb,' WHERE \`',col,'\`=''',SearchString,''';') SearchSQL
FROM
(
    SELECT table_schema db,table_name tb,column_name col FROM information_schema.columns
    WHERE table_schema = 'mydb' AND
    (column_type LIKE 'char(%' OR column_type LIKE 'varchar(%' OR column_type LIKE '%text')
) A,(SELECT 'Hello' SearchString) B;

Crea un file di testo SQL gigante con esso. Quindi, esegui quello script Giant SQL:

SQL="SELECT CONCAT('SELECT ',QUOTE(db),',',QUOTE(tb),',',"
SQL="${SQL} QUOTE(col),',COUNT(1) FieldHasIt FROM ',db,'.',tb,'"
SQL="${SQL} WHERE \`',col,'\`=''',SearchString,''';') SearchSQL FROM"
SQL="${SQL} (SELECT table_schema db,table_name tb,column_name col FROM"
SQL="${SQL} information_schema.columns WHERE table_schema='store_qa'"
SQL="${SQL} AND (column_type LIKE 'char(%' OR column_type LIKE 'varchar(%'"
SQL="${SQL} OR column_type LIKE '%text')) A,(SELECT 'Hello' SearchString) B;"

mysql -uroot -p... -ANe"${SQL}" > MegaSearch.sql
mysql -uroot -p... -AN < MegaSearch.sql > MegaSearchResults.txt
RESULTS_FOUND=`grep -c "1$" < MegaSearchResults.txt`
echo ${RESULTS_FOUND}
if [ ${RESULTS_FOUND} -gt 0 ] ; then grep "1$" < MegaSearchResults.txt ; fi

L'output indica il database, la tabella e la colonna in cui vengono visualizzati i dati.

Provaci !!!.

MODIFICARE:

CONCAT('SELECT ',QUOTE(db),',',QUOTE(tb),',',QUOTE(col),',COUNT(1) FieldHasIt
        FROM ',db,'.',tb,' WHERE \`',col,'\`=''',SearchString,''';')

DOVREBBE: aggiungere i due segni di spunta mostrati di seguito per le tabelle che hanno uno spazio nel nome.

db,'.`',tb,'`',' WHERE

Questa soluzione ha funzionato molto bene! È necessario copiare manualmente la query iniziale in una variabile di ambiente riga per riga? Sono stato in grado di incollare ed eseguire la query all'interno di una sessione mysql, ma sicuramente è anche possibile incollare quella query in un file?
John T,

@JohnT II fai riga per riga per evitare di dover scorrere verticalmente la mia risposta. Puoi fare qualunque sia il modo più semplice.
RolandoMySQLDBA

2

Adottando un altro approccio che non richiede la creazione di query SQL, ho sviluppato CRGREP come uno strumento da riga di comando open source gratuito che eseguirà grep database (incluso MySQL) e supporterà entrambe le semplici ricerche "fred customer.name" per "fred" nel "nome" "colonna della tabella" cliente "per una corrispondenza più complessa come" fr? d * .author "per la corrispondenza dei modelli con tutte le colonne" autore "su tutte le tabelle.


2

Puoi restituire tutte le colonne da tutte le tabelle che corrispondono a tutti i valori che stai cercando in una sola volta, basandoti sulla risposta di RolandoMySQLDBA e utilizzando PREPAREe EXECUTEper eseguire la query .

-- Your values
SET @table_schema = 'your_table_name';
SET @condition = "LIKE '%your string to search%'";
SET @column_types_regexp = '^((var)?char|(var)?binary|blob|text|enum|set)\\(';

-- Reset @sql_query in case it was used previously
SET @sql_query = '';

-- Build query for each table and merge with previous queries with UNION
SELECT
    -- Use `DISTINCT IF(QUERYBUILDING, NULL, NULL)`
    -- to only select a single null value
    -- instead of selecting the query over and over again as it's built
    DISTINCT IF(@sql_query := CONCAT(
        IF(LENGTH(@sql_query), CONCAT(@sql_query, " UNION "), ""),
        'SELECT ',
            QUOTE(CONCAT('`', `table_name`, '`.`', `column_name`, '`')), ' AS `column`, ',
            'COUNT(*) AS `occurrences` ',
        'FROM `', `table_schema`, '`.`', `table_name`, '` ',
        'WHERE `', `column_name`, '` ', @condition
    ), NULL, NULL) `query`
FROM (
    SELECT
        `table_schema`,
        `table_name`,
        `column_name`
    FROM `information_schema`.`columns`
    WHERE `table_schema` = @table_schema
    AND `column_type` REGEXP @column_types_regexp
) `results`;
select @sql_query;

-- Only return results with at least one occurrence
SET @sql_query = CONCAT("SELECT * FROM (", @sql_query, ") `results` WHERE `occurrences` > 0");

-- Run built query
PREPARE statement FROM @sql_query;
EXECUTE statement;
DEALLOCATE PREPARE statement;

1

Se puoi usare un bash - ecco uno script: ha bisogno di un dbread utente con pass dbread sul database.

#!/bin/bash
IFS='
'
DBUSER=dbread
DBPASS=dbread
echo -n "Which database do you want to search in (press 0 to see all databases): " 
read DB
echo -n "Which string do you want to search: " 
read SEARCHSTRING
for i in `mysql $DB -u$DBUSER -p$DBPASS -e "show tables" | grep -v \`mysql $DB -u$DBUSER -p$DBPASS -e "show tables" | head -1\``
do
for k in `mysql $DB -u$DBUSER -p$DBPASS -e "desc $i" | grep -v \`mysql $DB -u$DBUSER -p$DBPASS -e "desc $i" | head -1\` | grep -v int | awk '{print $1}'`
do
if [ `mysql $DB -u$DBUSER -p$DBPASS -e "Select * from $i where $k='$SEARCHSTRING'" | wc -l` -gt 1 ]
then
echo " Your searchstring was found in table $i, column $k"
fi
done
done

Se qualcuno vuole una spiegazione: http://infofreund.de/?p=1670


1

Se sei un amministratore Linux, dovresti avere familiarità con la riga di comando, quindi questo sarebbe utile:

$ mysqldump -u root -proot --skip-extended-insert db_name | grep --color=auto -w foo

Cambia root/ rootalle tue credenziali mysql (o usa ~/.my.cnf), db_nameal nome del tuo database e fooper il tuo testo di ricerca. Il parametro --skip-extended-insertper mysqldumpvisualizzerà ogni query in righe separate. Il parametro --color=autoper grepevidenzierà la stringa e -wcorrisponderà all'intera parola.


0

Hai accesso a phpMyAdmin? Ha una funzione di ricerca per ogni database.

o usa gli script di tua scelta sul risultato di (cambia dbname):

$string = 'mysqldump --compact --skip-extended-insert -u ' . $db_user . ' -p' . $db_password . ' dbname 2>&1 | grep "particular string" 2>&1';
$result = shell_exec ( $string );

0

Mi concentro su una soluzione modello semplice per la tua domanda implementata nel database plsql per Oracle , spero di personalizzarla su MySql, essendo semplice googleing. tutto ciò che serve è investigare lo schema informativo su MySql e sostituire alcuni nomi e colonne di tabelle.

Nello script: ALL_TAB_COLUMNSè una tabella dello schema di informazioni contenente tutte le colonne della tabella 'VARCHAR2', 'NVARCHAR2', 'NCHAR', 'CHAR' si riferisce ai tipi di colonna stringa in Oracle, devi sostituirli con nomi di tipo equivalenti di MySql
% hello% è la parola chiave di ricerca sostituirlo con qualsiasi stringa.

Il risultato sarà uno o più script sql (basati sui tipi di colonna delle tabelle) e la loro esecuzione darà la risposta.
Anche le prestazioni e il consumo di tempo saranno un'altra questione.
spero che questo sia utile

SELECT 
'SELECT ' || ALL_TAB_COLUMNS.COLUMN_NAME  || ' AS RESULT_FOUND, ' 
|| '''' || ALL_TAB_COLUMNS.TABLE_NAME ||''''|| ' AS TABLE_NAME, '
|| '''' || ALL_TAB_COLUMNS.COLUMN_NAME ||''''|| ' AS COLUMN_NAME '
|| 'FROM ' || ALL_TAB_COLUMNS.OWNER ||'.'||ALL_TAB_COLUMNS.TABLE_NAME  
|| ' WHERE ' || ALL_TAB_COLUMNS.COLUMN_NAME || ' LIKE ''%hello%''' || ';'
FROM ALL_TAB_COLUMNS 
WHERE 
ALL_TAB_COLUMNS.OWNER = 'SCOTT'
AND 
ALL_TAB_COLUMNS.DATA_TYPE IN ('VARCHAR2','NVARCHAR2','NCHAR','CHAR')

0

C'è una bella biblioteca per leggere tutti i tavoli, ridona

$database = new ridona\Database('mysql:dbname=database_name;host=127.0.0.1', 'db_user','db_pass');

foreach ($database->tables(['table_name1','table_name2'])->by_entire() as $row) {

  do...

}

0

Usa questo trucco con una riga di codice

SELECT * FROM `table_name1`,`table_name2` 
WHERE '$data' IN (`column_name1`,`column_name2`,`column_name3`,`column_name4`);

nome_colonna: digitare il nome di tutte le colonne in cui si cerca.

table_name: digitare tutto il nome della tabella in cui si cerca.


Questo può essere pratico in database molto piccoli: lo è di meno se stai cercando di individuare un valore su centinaia di tabelle e migliaia di colonne. Sulla base della dicitura "intero database" nella domanda originale, suppongo che questo dovrebbe occuparsi di tutte le tabelle nel DB.
RDFozz,

0

Se stai utilizzando MySQL Workbench, fai clic con il pulsante destro del mouse sullo schema del database e seleziona "Cerca dati tabella ...", quindi compila il modulo. Questo cercherà l'intero database. Quando (o se) vengono visualizzati i risultati, fare clic sulla freccia per espandere. Mostrerà lo schema, la tabella, i dati della chiave primaria, il nome della colonna e i dati effettivi che corrispondono alla tua ricerca.
Suggerimento: se non viene visualizzato nulla, prova ad ampliare la ricerca.
Si prega di notare che questa è realmente utile solo per la ricerca di testo ( char, varchare text) i tipi di dati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.