MySQL - Come verificare la presenza di un valore in tutte le colonne


11

Sono curioso, c'è un buon modo per cercare in tutte le colonne un determinato valore? Per i miei scopi, non è necessario che sia veloce, è solo una cosa una tantum e non voglio davvero digitare tutti i nomi dei campi. Questo è esattamente quello che farò per ora, ma penso che sicuramente ci sia un modo migliore.

Vorrei trasformare questo:

SELECT * FROM table WHERE col1 = 'val' OR col2 = 'val' OR col3 = 'val';

in questo:

SELECT * FROM table WHERE * = 'val'

... o ancora meglio (anche se ne dubito seriamente ...)

SELECT * FROM table WHERE * like '%val%'

Ho trovato questo , che sembra un po 'non molto vicino, ma non trovo nulla di più vicino:

SELECT whatever WHERE col1,col2 IN ((val1, val2), (val1, val2), ...)

Differenza, che cerca una selezione di colonne per i valori specificati, mentre sto cercando di cercare TUTTE le colonne per un singolo valore.

Non è importante però, come ho detto più di ogni altra cosa sono solo curioso

Risposte:


23

SQL non fornisce un buon modo per farlo perché probabilmente non è una buona progettazione di tabelle avere N colonne che potrebbero avere valori nello stesso dominio. Questo è potenzialmente un caso di "gruppi ripetitivi" come se si dispone di colonne phone1, phone2, phone3, ... phoneN.

Se hai un numero di colonne con lo stesso dominio logico di valori, potrebbe trattarsi di un attributo multivalore (come nell'esempio dei telefoni). Il modo standard di memorizzare attributi a più valori è come più righe in un'altra tabella, con un riferimento alla riga a cui appartengono nella tabella principale.

Se lo fai, devi solo cercare il valore specifico in una colonna della tabella dipendente.

SELECT t.* FROM mytable AS t
JOIN phones AS p ON t.primaryKey = p.refKey 
WHERE p.phone = ?

1
E se per qualsiasi motivo non è possibile modificare il layout della tabella, è possibile scrivere una vista che rappresenti i dati in questo formato, quindi interrogare la vista.
CodeCaster

10
No, basta cambiare il layout della tabella. Questo è tutto. Sono stanco della scusa "Non posso cambiarlo". Non lo accetto più. È tempo di imparare a cambiare le cose.
Bill Karwin,

15

Il più vicino che puoi ottenere è questo, usando IN:

SELECT * FROM table WHERE 'val' IN (col1, col2, ..., colN) ;

Devi ancora scrivere tutte le colonne che vuoi controllare.
E non è diverso ORdall'espressione che hai, non in termini di prestazioni o altro. Questo è solo un modo diverso ed equivalente per scrivere l'espressione, con un po 'meno caratteri.


3

Devi farlo in due passaggi, prima genera il sql come (supponendo che la tua tabella sia chiamata T nello schema S:

select concat(' SELECT * FROM t WHERE ''a'' in ('
             , GROUP_CONCAT(COLUMN_NAME)
             , ')')
from INFORMATION_SCHEMA.columns 
where table_schema = 's' 
  and table_name = 't'
  and DATA_TYPE IN ('char','varchar');

Ora puoi eseguire questa stringa. Nota che devi citare la 'a' con extra '. Se si inserisce questo ad esempio in una procedura, è possibile preparare ed eseguire la stringa generata.

Ho provato con:

create table t (a char(3), b varchar(5), c int);
insert into t(a,b) values ('a','b'),('b','c'),('c','c');    

La query generata dove:

SELECT * FROM t WHERE 'a' in (a,b)

e l'esecuzione che comporta:

a   b   c
---------
a   b   

1

Sembra che sia passato un anno da quando l'ho chiesto, ma mi sono appena imbattuto in quella che sembra essere la cosa esatta che stavo cercando! Non è un'istruzione SQL, come stavo anticipando, ma fa quello che volevo.

In MySQL Workbench, puoi fare clic con il pulsante destro del mouse sulla tabella o sullo schema e scegliere Cerca dati tabella.menu contestuale dello schema


0

Prova questo:

select
    *
from
    _table_
where
    concat('.', col1, '.', col2, '.', col3, '.') like "%.search_value.%";

Questo presuppone che non ci sia .nella tua stringa di ricerca. Se non puoi garantirlo, forse puoi usare un diverso "carattere separatore".


1
Potresti spiegare perché la tua soluzione funziona per favore? Qui solo le risposte al codice non sono considerate una buona risposta.
George.Palacios,

non funziona. ad es. se la ricerca contiene %o _o contiene colonne.
Jasen,

1
@Jasen Puoi sfuggire ai caratteri speciali e usare un separatore diverso.
Anon0012398193,

@ George.Palacios - cosa trovi poco chiaro?
Anon0012398193,

scegliere il separatore corretto potrebbe essere molto difficile. questo approccio è molto difficile da fare nel modo giusto
Jasen,

0

La soluzione più semplice sta facendo

mysqldump ... --skip-extended-insert db table | grep 'val'

A meno che val non sia qualcosa che si verifica comunemente nella sintassi sql.


Spero che tu mi stia prendendo in giro, poiché l'alternativa è che hai pensato che sarebbe stato utile.
donutguy640,

1
Io sicuramente no. È un modo valido per trovare qualcosa se non sai "dove" si trova nel db / table. Grep restituirà tutte le righe (incluso il nome della tabella) in cui è presente il valore. Non è SQL e non è molto utile se si desidera elaborare l'output a livello di codice, ma è semplice e abbastanza veloce.
jkavalik,

-2

Prova questo.

SELECT *
FROM table
WHERE CONCAT(col1,' ',col2,' ',col3)="val val val";

CONCAT () viene utilizzato per separare i valori di colonna come qui è possibile separare la colonna con spazio per specificare il risultato migliore all'interno della funzione e controllare il valore anche separato stringa con spazio e il risultato è nella tua mano.


-3

È possibile utilizzando il database information_schema, fondamentalmente elencheremo solo tutte le colonne di una tabella specifica, quindi utilizzeremo GROUP_CONCAT per elencarle come un'unica riga, quindi inserirle in un'istruzione IN.

select * from db.table where 'value' in (select GROUP_CONCAT(COLUMN_NAME) from INFORMATION_SCHEMA.columns where table_schema = 'db' and table_name = 'table');

Ciò restituirà una riga solo se "valore" è presente in tutte le colonne.


1
Intendi if 'value' is present in any of the columns? Inoltre, puoi aggiungere un predicato per tipi di stringa come: `e DATA_TYPE IN ('char', 'varchar')`
Lennart,

1
Questo lo farà e raggiungerà l'obiettivo di OP di evitare di nominare esplicitamente le colonne. Non è un carattere jolly, ma GROUP_CONCAT rispetto allo schema delle informazioni è valido come un carattere jolly di tutti i nomi di colonna.
tbrookside,

2
Sto avendo problemi a farlo funzionare. Ho sostituito db e table con i miei nomi di schema e tabella, c'è qualcos'altro che deve essere segnaposto per i nomi reali? Inoltre, ho provato da solo l'istruzione interna e mi sto rendendo conto che CONCATTA i nomi delle colonne, anziché i dati di una riga. È quello che avevi voluto?
donutguy640,

4
Con tutto il rispetto, questo è sbagliato. La tua query confronterà 'valore' con i nomi delle colonne, non con il loro contenuto . Devo dare un voto negativo.
Bill Karwin,

4
Più precisamente, questo confronterà la stringa 'valore' con la stringa che è un elenco separato da virgole di nomi di colonne - essenzialmente lo stesso di where 'value' in ('col1,col2,col3…').
Andriy M,
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.