MySQL - So überprüfen Sie alle Spalten auf einen Wert

11

Ich bin neugierig, gibt es eine gute Möglichkeit, alle Spalten nach einem bestimmten Wert zu durchsuchen? Für meine Zwecke muss es überhaupt nicht schnell sein, es ist nur eine einmalige Sache, und ich möchte nicht wirklich jeden Feldnamen eingeben müssen. Genau das werde ich jetzt tun, aber ich denke, es gibt sicherlich einen besseren Weg.

Ich möchte dies umdrehen:

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

das mögen:

SELECT * FROM table WHERE * = 'val'

... oder noch besser (obwohl ich es ernsthaft bezweifle ...)

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

Ich fand das , was scheint irgendwie-nicht-ganz in der Nähe, aber ich finde nichts näher:

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

Der Unterschied besteht darin, dass eine Auswahl von Spalten nach den angegebenen Werten durchsucht wird, während ich versuche, ALLE Spalten nach einem einzelnen Wert zu durchsuchen.

Es ist jedoch nicht wichtig, wie ich mehr als alles andere sagte, ich bin nur neugierig

donutguy640
quelle

Antworten:

23

SQL bietet hierfür keine gute Möglichkeit, da es wahrscheinlich kein gutes Tabellendesign ist, N Spalten zu haben, die möglicherweise Werte in derselben Domäne haben. Dies ist möglicherweise ein Fall von „Wiederholungsgruppen“ wie wenn Sie Spalten haben phone1, phone2, phone3, ... phoneN.

Wenn Sie mehrere Spalten haben, die dieselbe logische Wertedomäne haben, kann es sich um ein mehrwertiges Attribut handeln (wie im Beispiel des Telefons). Die Standardmethode zum Speichern mehrwertiger Attribute besteht darin, mehrere Zeilen in einer anderen Tabelle mit einem Verweis auf die Zeile zu speichern, zu der sie in der Primärtabelle gehören.

Wenn Sie dies tun, müssen Sie nur in einer Spalte der abhängigen Tabelle nach dem bestimmten Wert suchen.

SELECT t.* FROM mytable AS t
JOIN phones AS p ON t.primaryKey = p.refKey 
WHERE p.phone = ?
Bill Karwin
quelle
1
Wenn Sie das Tabellenlayout aus irgendeinem Grund nicht ändern können, können Sie eine Ansicht schreiben, die die Daten in diesem Format darstellt, und dann die Ansicht abfragen.
CodeCaster
10
Nein, ändern Sie einfach das Tabellenlayout. Das ist es. Ich habe die Ausrede satt "Ich kann es nicht ändern." Das akzeptiere ich nicht mehr. Es ist Zeit zu lernen, wie man Dinge ändert.
Bill Karwin
15

Je näher Sie kommen können, desto folgender ist Folgendes IN:

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

Sie müssen noch alle Spalten schreiben, die Sie überprüfen möchten.
Und es ist nicht anders als der ORAusdruck, den Sie haben, weder in der Leistung noch auf andere Weise. Dies ist nur eine andere, äquivalente Art, den Ausdruck mit etwas weniger Zeichen zu schreiben.

ypercubeᵀᴹ
quelle
3

Sie müssen dies in zwei Schritten tun. Generieren Sie zuerst die SQL-Datei (vorausgesetzt, Ihre Tabelle heißt im Schema S T:

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

Jetzt können Sie diese Zeichenfolge ausführen. Beachten Sie, dass Sie das 'a' mit extra 'zitieren müssen. Wenn Sie dies beispielsweise in eine Prozedur einfügen, können Sie die generierte Zeichenfolge vorbereiten und ausführen.

Ich habe getestet mit:

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

Die Abfrage wurde generiert, wo:

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

und das Ausführen führt zu:

a   b   c
---------
a   b   
Lennart
quelle
1

Es fühlt sich an, als wäre es ein Jahr her, seit ich das gefragt habe, aber ich bin nur auf das gestoßen, was genau das zu sein scheint, wonach ich gesucht habe! Es ist keine SQL-Anweisung, wie ich es erwartet hatte, aber sie macht das, was ich wollte.

In MySQL Workbench können Sie mit der rechten Maustaste auf die Tabelle oder das Schema klicken und Tabellendaten durchsuchen auswählen.Schema-Kontextmenü

donutguy640
quelle
0

Probier diese:

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

Dies setzt voraus, dass .Ihre Suchzeichenfolge keine enthält . Wenn Sie dies nicht garantieren können, können Sie möglicherweise ein anderes "Trennzeichen" verwenden.

Anon0012398193
quelle
1
Können Sie bitte erklären, warum Ihre Lösung funktioniert? Nur-Code-Antworten werden hier nicht als gute Antwort angesehen.
George.Palacios
es funktioniert nicht zB wenn die Suche enthält %oder _oder eine Spalte enthält.
Jasen
1
@Jasen Sie können den Sonderzeichen entkommen und ein anderes Trennzeichen verwenden.
Anon0012398193
@ George.Palacios - was findest du unklar?
Anon0012398193
Die Auswahl des richtigen Separators kann sehr schwierig sein. Dieser Ansatz ist sehr schwer richtig zu machen
Jasen
0

Die einfachste Lösung ist zu tun

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

Es sei denn, der Wert ist etwas, das in der SQL-Syntax häufig vorkommt.

jkavalik
quelle
Ich hoffe, Sie verspotten mich, da die Alternative darin besteht, dass Sie dachten, dies wäre hilfreich.
Donutguy640
1
Ich bin definitiv nicht. Es ist ein gültiger Weg, um etwas zu finden, wenn Sie nicht wissen, "wo" es sich in der Datenbank / Tabelle befindet. Das grep gibt die gesamten Zeilen (einschließlich des Tabellennamens) zurück, in denen der Wert vorhanden ist. Es ist kein SQL und nicht sehr nützlich, wenn Sie die Ausgabe programmgesteuert verarbeiten möchten, aber es ist einfach und recht schnell.
Jkavalik
-2

Versuche dies.

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

CONCAT () wird verwendet, um Spaltenwerte wie hier zu trennen. Sie können Ihre Spalte durch Leerzeichen trennen, um das bessere Ergebnis innerhalb der Funktion anzugeben, und überprüfen, ob der Wert auch durch Leerzeichen getrennt ist, und das Ergebnis liegt in Ihrer Hand.

Deepak
quelle
-3

Mithilfe der Datenbank information_schema können wir im Grunde nur alle Spalten einer bestimmten Tabelle auflisten und sie dann mit GROUP_CONCAT als eine Zeile auflisten und dann in eine IN-Anweisung einspeisen.

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

Dies gibt nur dann eine Zeile zurück, wenn 'value' in allen Spalten vorhanden ist.

Rodie
quelle
1
Meinst du if 'value' is present in any of the columns? Außerdem können Sie ein Prädikat für Zeichenfolgentypen wie "und DATA_TYPE IN (" char "," varchar ")" hinzufügen
Lennart
1
Dies wird es tun und das Ziel von OP erreichen, die explizite Benennung der Spalten zu vermeiden. Es ist kein Platzhalter, aber GROUP_CONCAT für das Informationsschema ist so gut wie ein Platzhalter aller Spaltennamen.
Tbrookside
2
Ich habe Probleme damit. Ich habe db und table durch meine Schema- und Tabellennamen ersetzt. Gibt es noch etwas, das Platzhalter für tatsächliche Namen sein soll? Außerdem habe ich die innere Anweisung selbst ausprobiert und stelle fest, dass sie die Spaltennamen und nicht die Daten einer Zeile enthält. Hast du das beabsichtigt?
Donutguy640
4
Bei allem Respekt ist das falsch. Ihre Abfrage vergleicht den Wert mit den Namen der Spalten, nicht mit deren Inhalt . Ich muss dies ablehnen.
Bill Karwin
4
Genauer gesagt vergleicht dies den Wert der Zeichenfolge mit der Zeichenfolge, bei der es sich um eine durch Kommas getrennte Liste von Spaltennamen handelt - im Wesentlichen dieselbe wie where 'value' in ('col1,col2,col3…').
Andriy M