Ho una funzione che restituisce cinque caratteri con maiuscole e minuscole. Se eseguo una query su questa stringa, verrà restituito il valore indipendentemente dal caso.
Come posso rendere le query stringa MySQL sensibili al maiuscolo / minuscolo?
Ho una funzione che restituisce cinque caratteri con maiuscole e minuscole. Se eseguo una query su questa stringa, verrà restituito il valore indipendentemente dal caso.
Come posso rendere le query stringa MySQL sensibili al maiuscolo / minuscolo?
Risposte:
http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html
Il set di caratteri e le regole di confronto predefiniti sono latin1 e latin1_swedish_ci, pertanto i confronti di stringhe non binari non fanno distinzione tra maiuscole e minuscole per impostazione predefinita. Ciò significa che se si cerca con col_name COME 'a%', si ottengono tutti i valori di colonna che iniziano con A o a. Per rendere sensibile questa distinzione tra maiuscole e minuscole, accertarsi che uno degli operandi abbia una distinzione tra maiuscole e minuscole o binaria. Ad esempio, se si stanno confrontando una colonna e una stringa che hanno entrambi il set di caratteri latin1, è possibile utilizzare l'operatore COLLATE per far sì che l'operando abbia le regole di confronto latin1_general_cs o latin1_bin:
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
Se si desidera che una colonna sia sempre trattata in modo sensibile al maiuscolo / minuscolo, dichiararla con una distinzione tra maiuscole e minuscole o binaria.
SELECT 'email' COLLATE utf8_bin = 'Email'
La buona notizia è che se è necessario effettuare una query con distinzione tra maiuscole e minuscole, è molto semplice:
SELECT * FROM `table` WHERE BINARY `column` = 'value'
convert(char(0x65,0xcc,0x88) using utf8)
(cioè e
con l' ¨
aggiunta) e convert(char(0xc3,0xab) using utf8)
(cioè ë
), ma l'aggiunta BINARY
le renderà disuguali.
La risposta inviata da Craig White, ha un grosso rigore per le prestazioni
SELECT * FROM `table` WHERE BINARY `column` = 'value'
perché non usa gli indici. Quindi, o è necessario modificare le regole di confronto delle tabelle come menzionato qui https://dev.mysql.com/doc/refman/5.7/en/case-sensitivity.html .
O
Correzione più semplice, dovresti usare un BINARY di valore.
SELECT * FROM `table` WHERE `column` = BINARY 'value'
Per esempio.
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 riga nel set (0,00 sec)
Invece di usare l'operatore =, potresti voler usare LIKE o LIKE BINARY
// 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'
Ci vorrà 'a' e non 'A' nelle sue condizioni
Per utilizzare un indice prima di usare il BINARY, puoi fare qualcosa del genere se hai tabelle di grandi dimensioni.
SELECT
*
FROM
(SELECT * FROM `table` WHERE `column` = 'value') as firstresult
WHERE
BINARY `column` = 'value'
La sottoquery comporterebbe un sottoinsieme veramente piccolo senza distinzione tra maiuscole e minuscole, di cui si seleziona l'unica corrispondenza sensibile al maiuscolo / minuscolo.
Il modo più corretto per eseguire un confronto tra maiuscole e minuscole senza modificare le regole di confronto della colonna da interrogare è specificare esplicitamente un set di caratteri e regole di confronto per il valore a cui viene confrontata la colonna.
select * from `table` where `column` = convert('value' using utf8mb4) collate utf8mb4_bin;
binary
?L'uso binary
dell'operatore non è consigliabile perché confronta i byte effettivi delle stringhe codificate. Se si confrontano i byte effettivi di due stringhe codificate utilizzando i diversi set di caratteri, due stringhe che devono essere considerate uguali potrebbero non essere uguali. Ad esempio, se si dispone di una colonna che utilizza il latin1
set di caratteri e il set di caratteri del server / sessione è utf8mb4
, quindi quando si confronta la colonna con una stringa contenente un accento come "café", non corrisponderà alle righe contenenti quella stessa stringa! Questo perché in latin1
E è codificato come il byte 0xE9
ma utf8
è due byte: 0xC3A9
.
convert
così come collate
?Le regole di confronto devono corrispondere al set di caratteri. Pertanto, se il server o la sessione è impostato per utilizzare il latin1
set di caratteri, è necessario utilizzare, collate latin1_bin
ma se è impostato il set di caratteri, è utf8mb4
necessario utilizzare collate utf8mb4_bin
. Pertanto, la soluzione più solida è convertire sempre il valore nel set di caratteri più flessibile e utilizzare le regole di confronto binarie per quel set di caratteri.
convert
e collate
al valore e non la colonna?Quando si applica una funzione di trasformazione a una colonna prima di effettuare un confronto, si impedisce al motore di query di utilizzare un indice se ne esiste uno per la colonna, che potrebbe rallentare notevolmente la query. Pertanto è sempre meglio trasformare il valore invece dove possibile. Quando viene eseguito un confronto tra due valori di stringa e uno di essi ha un confronto esplicitamente specificato, il motore di query utilizzerà il confronto esplicito, indipendentemente dal valore a cui viene applicato.
È importante notare che MySql non è solo sensibile al maiuscolo / minuscolo per le colonne che utilizzano una _ci
fascicolazione (che è in genere l'impostazione predefinita), ma è anche insensibile all'accento . Questo significa che 'é' = 'e'
. L'uso di un confronto binario (o binary
dell'operatore) renderà il confronto delle stringhe sensibile all'accento e al maiuscolo / minuscolo.
utf8mb4
?Il utf8
set di caratteri in MySql è un alias per il utf8mb3
quale è stato deprecato nelle versioni recenti perché non supporta caratteri a 4 byte (che è importante per la codifica di stringhe come 🐈). Se desideri utilizzare la codifica dei caratteri UTF8 con MySql, dovresti utilizzare il utf8mb4
set di caratteri.
Di seguito è riportato per le versioni di MySQL uguali o superiori a 5.5.
Aggiungi a /etc/mysql/my.cnf
[mysqld]
...
character-set-server=utf8
collation-server=utf8_bin
...
Tutte le altre raccolte che ho provato sembravano non distinguere tra maiuscole e minuscole, solo "utf8_bin" ha funzionato.
Non dimenticare di riavviare mysql dopo questo:
sudo service mysql restart
Secondo http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html esiste anche un "latin1_bin".
"Utf8_general_cs" non è stato accettato dall'avvio di mysql. (Ho letto "_cs" come "case sensitive" - ???).
Puoi usare BINARY per maiuscole e minuscole in questo modo
select * from tb_app where BINARY android_package='com.Mtime';
sfortunatamente questo sql non può usare l'indice, subirai un calo delle prestazioni sulle query basate su tale indice
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 |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
Fortunatamente, ho alcuni trucchi per risolvere questo problema
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 |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
Eccellente!
Condivido con te il codice di una funzione che confronta le password:
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;
declare pSuccess BINARY;
Non c'è bisogno di cambiare nulla a livello di DB, devi solo cambiare in SQL Query funzionerà.
Esempio -
"SELECT * FROM <TABLE> where userId = '" + iv_userId + "' AND password = BINARY '" + iv_password + "'";
La parola chiave binaria farà distinzione tra maiuscole e minuscole.