MySQL - Comment vérifier une valeur dans toutes les colonnes

11

Je suis curieux, existe-t-il un bon moyen de rechercher toutes les colonnes pour une valeur donnée? Pour mes besoins, il n'a pas besoin d'être rapide du tout, c'est juste une chose unique, et je ne veux pas vraiment avoir à taper chaque nom de champ. C'est précisément ce que je vais faire pour l'instant, mais je pense qu'il y a sûrement une meilleure façon.

Je voudrais tourner ceci:

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

en cela:

SELECT * FROM table WHERE * = 'val'

... ou encore mieux (même si j'en doute sérieusement ...)

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

J'ai trouvé cela , qui semble un peu proche, mais je ne trouve rien de plus proche:

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

La différence étant, qui recherche une sélection de colonnes pour les valeurs spécifiées, alors que j'essaie de rechercher TOUTES les colonnes pour une seule valeur.

Ce n'est pas important cependant, comme je l'ai dit plus que tout, je suis juste curieux

donutguy640
la source

Réponses:

23

SQL ne fournit pas un bon moyen de le faire, car ce n'est probablement pas une bonne conception de table d'avoir N colonnes qui pourraient avoir des valeurs dans le même domaine. C'est potentiellement un cas de « groupes répétitifs » comme si vous avez des colonnes phone1, phone2, phone3, ... phoneN.

Si vous avez un certain nombre de colonnes qui ont le même domaine logique de valeurs, il peut s'agir d'un attribut à valeurs multiples (comme l'exemple des téléphones). La méthode standard de stockage des attributs à valeurs multiples consiste en plusieurs lignes dans une autre table, avec une référence à la ligne à laquelle elles appartiennent dans la table principale.

Si vous le faites, il vous suffit de rechercher la valeur spécifique dans une colonne de la table dépendante.

SELECT t.* FROM mytable AS t
JOIN phones AS p ON t.primaryKey = p.refKey 
WHERE p.phone = ?
Bill Karwin
la source
1
Et si, pour une raison quelconque, vous ne pouvez pas modifier la disposition du tableau, vous pouvez écrire une vue qui représente les données dans ce format, puis interroger la vue.
CodeCaster
10
Non, changez simplement la disposition du tableau. C'est tout. Je suis fatigué de l'excuse "je ne peux pas le changer." Je n'accepte plus ça. Il est temps d'apprendre à changer les choses.
Bill Karwin
15

Le plus vous pouvez vous rapprocher, en utilisant IN:

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

Vous devez encore écrire toutes les colonnes que vous souhaitez vérifier.
Et ce n'est pas différent de l' ORexpression que vous avez, pas en performance ou autrement. C'est juste une manière différente et équivalente d'écrire l'expression, avec un peu moins de caractères.

ypercubeᵀᴹ
la source
3

Vous devez le faire en deux étapes, générez d'abord le SQL comme (en supposant que votre table est nommée T dans le schéma 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');

Vous pouvez maintenant exécuter cette chaîne. Notez que vous devez citer le «a» avec extra ». Si vous mettez cela par exemple dans une procédure, vous pouvez préparer et exécuter la chaîne qui a été générée.

J'ai testé avec:

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

La requête générée où:

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

et une exécution qui se traduit par:

a   b   c
---------
a   b   
Lennart
la source
1

J'ai l'impression que ça fait un an que j'ai posé cette question, mais je suis juste tombé sur ce qui semble être exactement la chose que je cherchais! Ce n'est pas une instruction SQL, comme je l'avais prévu, mais elle fait ce que je voulais.

Dans MySQL Workbench, vous pouvez cliquer avec le bouton droit sur la table ou le schéma et choisir Rechercher les données de la table.menu contextuel du schéma

donutguy640
la source
0

Essaye celui-là:

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

Cela suppose qu'il n'y en a pas .dans votre chaîne de recherche. Si vous ne pouvez pas garantir cela, vous pouvez peut-être utiliser un «caractère de séparation» différent.

Anon0012398193
la source
1
Pourriez-vous expliquer pourquoi votre solution fonctionne s'il vous plaît? Les réponses codées uniquement ne sont pas considérées comme une bonne réponse ici.
George.Palacios
ça ne marche pas. Par exemple, si la recherche contient %ou _ou une colonne contient.
Jasen
1
@Jasen Vous pouvez échapper aux caractères spéciaux et utiliser un séparateur différent.
Anon0012398193
@ George.Palacios - qu'est-ce que vous trouvez peu clair?
Anon0012398193
choisir le bon séparateur peut être très difficile. cette approche est très difficile à faire correctement
Jasen
0

La solution la plus simple consiste à

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

Sauf si la valeur val est quelque chose qui est une occurrence courante dans la syntaxe sql.

jkavalik
la source
J'espère que vous vous moquez de moi, car l'alternative est que vous pensiez que ce serait utile.
donutguy640
1
Je ne le suis certainement pas. C'est un moyen valide de trouver quelque chose si vous ne savez pas "où" il se trouve dans la base de données / table. Le grep retournera les lignes entières (y compris le nom de la table) où la valeur est présente. Ce n'est pas du SQL et ce n'est pas très utile si vous voulez traiter la sortie par programmation, mais c'est simple et assez rapide.
jkavalik
-2

Essaye ça.

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

CONCAT () est utilisé pour séparer les valeurs de colonne comme ici, vous pouvez séparer votre colonne avec un espace pour spécifier le meilleur résultat à l'intérieur de la fonction et vérifier la valeur également la chaîne séparée avec de l'espace et le résultat est entre vos mains.

Deepak
la source
-3

C'est possible en utilisant la base de données information_schema, nous allons simplement lister toutes les colonnes d'une table spécifique puis utiliser GROUP_CONCAT pour les lister en une seule ligne puis les alimenter dans une instruction 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');

Cela ne retournera une ligne que si «valeur» est présente dans toutes les colonnes.

Rodie
la source
1
Tu veux dire if 'value' is present in any of the columns? De plus, vous pouvez ajouter un prédicat pour les types de chaînes comme: `et DATA_TYPE IN ('char', 'varchar')`
Lennart
1
Cela le fera et accomplira l'objectif d'OP d'éviter de nommer explicitement les colonnes. Ce n'est pas un caractère générique, mais le GROUP_CONCAT par rapport au schéma d'information est aussi bon qu'un caractère générique de tous les noms de colonne.
tbrookside
2
J'ai du mal à faire fonctionner ça. J'ai remplacé db et table par mes noms de schéma et de table, y a-t-il autre chose destiné à être des espaces réservés pour des noms réels? En outre, j'ai essayé la déclaration interne seule et je me rends compte qu'elle CONCATTE les noms de colonne, plutôt que les données d'une ligne. C'est bien ce que vous vouliez?
donutguy640
4
Avec tout le respect que je vous dois, c'est faux. Votre requête comparera «valeur» aux noms des colonnes, et non à leur contenu . Je dois lui donner un downvote.
Bill Karwin
4
Plus précisément, cela comparera la chaîne «valeur» à la chaîne qui est une liste de noms de colonnes séparés par des virgules - essentiellement identique à where 'value' in ('col1,col2,col3…').
Andriy M