web-dev-qa-db-ger.com

Wie kann ich unter MySQL einen SQL-Stringvergleich durchführen, bei dem zwischen Groß- und Kleinschreibung unterschieden wird?

Ich habe eine Funktion, die fünf Zeichen mit Groß-/Kleinschreibung zurückgibt. Wenn ich eine Abfrage für diese Zeichenfolge durchführe, wird der Wert unabhängig von Groß- und Kleinschreibung zurückgegeben.

Wie kann ich MySQL-String-Abfragen zwischen Groß- und Kleinschreibung unterscheiden lassen?

252
StevenB

http://dev.mysql.com/doc/refman/5.0/de/case-sensitivity.html

Der Standardzeichensatz und die Standardkollatierung sind latin1 und latin1_swedish_ci. Daher wird beim Vergleich von nichtbinären Zeichenfolgen standardmäßig die Groß- und Kleinschreibung nicht berücksichtigt. Das heißt, wenn Sie mit col_name LIKE 'a%' suchen, erhalten Sie alle Spaltenwerte, die mit A oder a beginnen. Um diese Suche zwischen Groß- und Kleinschreibung zu unterscheiden, stellen Sie sicher, dass einer der Operanden eine Sortierung zwischen Groß- und Kleinschreibung oder eine binäre Sortierung aufweist. Wenn Sie beispielsweise eine Spalte und eine Zeichenfolge vergleichen, die beide den Zeichensatz latin1 haben, können Sie mit dem Operator COLLATE bewirken, dass einer der Operanden die Sortierung latin1_general_cs oder latin1_bin hat:

col_name COLLATE latin1_general_cs LIKE 'a%'
col_name LIKE 'a%' COLLATE latin1_general_cs
col_name COLLATE latin1_bin LIKE 'a%'
col_name LIKE 'a%' COLLATE latin1_bin

Wenn eine Spalte immer zwischen Groß- und Kleinschreibung unterschieden werden soll, deklarieren Sie sie mit einer Sortierung zwischen Groß- und Kleinschreibung oder einer binären Sortierung.

139
drudge

Die gute Nachricht ist, dass es sehr einfach ist, bei der Abfrage zwischen Groß- und Kleinschreibung zu unterscheiden:

SELECT *  FROM `table` WHERE BINARY `column` = 'value'
659
Craig White

Anstelle des Operators = können Sie auch LIKE oder LIKE BINARY verwenden

// this returns 1 (true)
select 'A' like 'a'

// this returns 0 (false)
select 'A' like binary 'a'


select * from user where username like binary 'a'

Es wird 'a' und nicht 'A' in seinem Zustand annehmen

35
insoftservice

Antwort gepostet Craig White, hat große Leistungsstrafe

SELECT *  FROM `table` WHERE BINARY `column` = 'value'

weil es keine Indizes verwendet. Entweder müssen Sie die Tabellensortierung ändern, wie hier erwähnt https://dev.mysql.com/doc/refman/5.7/en/case-sensitivity.html .

OR

Am einfachsten ist es, einen BINARY-Wert zu verwenden.

SELECT *  FROM `table` WHERE `column` = BINARY 'value'

Z.B.

mysql> EXPLAIN SELECT * FROM temp1 WHERE BINARY col1 = "ABC" AND col2 = "DEF" ;
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | temp1  | ALL  | NULL          | NULL | NULL    | NULL | 190543 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+

VS

mysql> EXPLAIN SELECT * FROM temp1 WHERE col1 = BINARY "ABC" AND col2 = "DEF" ;
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
| id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra                              |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
|  1 | SIMPLE      | temp1 | range | col1_2e9e898e | col1_2e9e898e | 93      | NULL |    2 | Using index condition; Using where |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
enter code here

1 Reihe im Satz (0,00 Sek.)

35
Nitesh

Um einen Index zu verwenden, bevor Sie das BINARY verwenden, können Sie bei großen Tabellen so etwas tun.

SELECT
   *
FROM
   (SELECT * FROM `table` WHERE `column` = 'value') as firstresult
WHERE
   BINARY `column` = 'value'

Die Unterabfrage würde zu einer sehr kleinen Teilmenge führen, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird.

13
Eric

Das Folgende gilt für MySQL-Versionen ab 5.5.

Fügen Sie /etc/mysql/my.cnf hinzu

  [mysqld]
  ...
  character-set-server=utf8
  collation-server=utf8_bin
  ...

Alle anderen Kollatierungen, die ich versuchte, schienen ohne Berücksichtigung der Groß- und Kleinschreibung zu sein, nur "utf8_bin" funktionierte.

Vergiss nicht, mysql danach neu zu starten:

   Sudo service mysql restart

Laut http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html gibt es auch ein "latin1_bin".

"Utf8_general_cs" wurde vom Start von mysql nicht akzeptiert. (Ich lese "_cs" als "case-sensitive" - ​​???).

7
fritzthecat

Sie können BINARY verwenden, um Groß- und Kleinschreibung zu berücksichtigen

select * from tb_app where BINARY Android_package='com.Mtime';

leider kann dieser SQL-Code keinen Index verwenden. Bei Abfragen, die auf diesen Index angewiesen sind, wird die Leistung beeinträchtigt

mysql> explain select * from tb_app where BINARY Android_package='com.Mtime';
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra       |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
|  1 | SIMPLE      | tb_app | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 1590351 |   100.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+

Zum Glück habe ich ein paar Tricks, um dieses Problem zu lösen

mysql> explain select * from tb_app where Android_package='com.Mtime' and BINARY Android_package='com.Mtime';
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
| id | select_type | table  | partitions | type | possible_keys             | key                       | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | tb_app | NULL       | ref  | idx_Android_pkg           | idx_Android_pkg           | 771     | const |    1 |   100.00 | Using index condition |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+  
5
xiezefan

Die korrekteste Methode zum Vergleichen von Zeichenfolgen, bei der die Groß- und Kleinschreibung beachtet wird, ohne die Sortierung der abgefragten Spalte zu ändern, besteht darin, explizit einen Zeichensatz und eine Sortierung für den Wert anzugeben, mit dem die Spalte verglichen wird.

select * from `table` where `column` = convert('value' using utf8mb4) collate utf8mb4_bin;

Warum nicht binary verwenden?

Die Verwendung des Operators binary wird nicht empfohlen, da er die tatsächlichen Bytes der codierten Zeichenfolgen vergleicht. Wenn Sie die tatsächlichen Bytes von zwei Zeichenfolgen vergleichen, die mit den verschiedenen Zeichensätzen codiert wurden, sind zwei Zeichenfolgen möglicherweise nicht gleich. Wenn Sie beispielsweise eine Spalte haben, die den Zeichensatz latin1 Verwendet, und Ihr Server-/Sitzungszeichensatz utf8mb4 Ist, vergleichen Sie die Spalte mit einer Zeichenfolge mit einem Akzent wie 'café 'es wird nicht mit Zeilen übereinstimmen, die dieselbe Zeichenkette enthalten! Dies liegt daran, dass in latin1 É als Byte 0xE9 Codiert ist, in utf8 Jedoch zwei Bytes: 0xC3A9.

Warum convert sowie collate verwenden?

Kollatierungen müssen mit dem Zeichensatz übereinstimmen. Wenn Ihr Server oder Ihre Sitzung für die Verwendung des Zeichensatzes latin1 Eingerichtet ist, müssen Sie collate latin1_bin Verwenden. Wenn Ihr Zeichensatz jedoch utf8mb4 Lautet, müssen Sie collate utf8mb4_bin Verwenden. Daher besteht die robusteste Lösung darin, den Wert immer in den flexibelsten Zeichensatz zu konvertieren und die binäre Kollatierung für diesen Zeichensatz zu verwenden.

Warum die convert und collate auf den Wert und nicht auf die Spalte anwenden?

Wenn Sie eine Transformationsfunktion auf eine Spalte anwenden, bevor Sie einen Vergleich durchführen, verhindert dies, dass das Abfragemodul einen Index verwendet, falls für die Spalte ein Index vorhanden ist. Dies kann Ihre Abfrage erheblich verlangsamen. Daher ist es immer besser, den Wert zu transformieren, wo dies möglich ist. Wenn ein Vergleich zwischen zwei Zeichenfolgenwerten durchgeführt wird und einer davon eine explizit angegebene Sortierung aufweist, verwendet das Abfragemodul die explizite Sortierung, unabhängig davon, auf welchen Wert er angewendet wird.

Akzentempfindlichkeit

Es ist wichtig zu beachten, dass MySql nicht nur bei Spalten mit einer Kollatierung von _ci (Was normalerweise der Standard ist) die Groß- und Kleinschreibung berücksichtigt, sondern auch accent unempfindlich ist. Dies bedeutet, dass 'é' = 'e'. Die Verwendung einer binären Kollatierung (oder des Operators binary) unterscheidet zwischen Groß- und Kleinschreibung.

Was ist utf8mb4?

Der Zeichensatz utf8 In MySql ist ein Alias ​​für utf8mb3, Der in neueren Versionen veraltet ist, da er keine 4-Byte-Zeichen unterstützt (was für die Codierung von Zeichenfolgen wichtig ist) mögen ????). Wenn Sie TF8-Zeichencodierung mit MySql verwenden möchten, sollten Sie den Zeichensatz utf8mb4 Verwenden.

3
Paul Wheeler

Es ist nicht erforderlich, Änderungen auf DB-Ebene vorzunehmen. Sie müssen lediglich Änderungen in SQL Query vornehmen, damit dies funktioniert.

Beispiel -

"SELECT * FROM <TABLE> where userId = '" + iv_userId + "' AND password = BINARY '" + iv_password + "'";

Bei einem binären Schlüsselwort wird die Groß- und Kleinschreibung berücksichtigt.

2
Pappu Mehta

Ausgezeichnet!

Ich teile mit Ihnen Code aus einer Funktion, die Passwörter vergleicht:

SET pSignal =
(SELECT DECODE(r.usignal,'YOURSTRINGKEY') FROM rsw_uds r WHERE r.uname =
in_usdname AND r.uvige = 1);

SET pSuccess =(SELECT in_usdsignal LIKE BINARY pSignal);

IF pSuccess = 1 THEN
      /*Your code if match*/
ELSE
      /*Your code if don't match*/

END IF;
1
Victor Enrique

bei mysql wird standardmäßig nicht zwischen Groß- und Kleinschreibung unterschieden. Ändern Sie die Sprachsortierung in latin1_general_cs

0
ohmusama