Mysql
 sql >> Database >  >> RDS >> Mysql

Il database MySQL con campi univoci ha ignorato gli spazi finali

Il problema è che MySQL ignora gli spazi bianchi finali durante il confronto delle stringhe. Vedihttp://dev.mysql.com/doc/refman/ 5.7/en/char.html

(Questa informazione è per 5.7; per 8.0 questo è cambiato, vedi sotto)

La sezione per i like operatore fornisce un esempio per questo comportamento (e mostra che like rispetta gli spazi bianchi finali):

mysql> SELECT 'a' = 'a ', 'a' LIKE 'a ';
+------------+---------------+
| 'a' = 'a ' | 'a' LIKE 'a ' |
+------------+---------------+
|          1 |             0 |
+------------+---------------+
1 row in set (0.00 sec)

Purtroppo il UNIQUE index sembra utilizzare il confronto di stringhe standard per verificare se esiste già un tale valore, e quindi ignora gli spazi vuoti finali. Questo è indipendente dall'utilizzo di VARCHAR o CHAR , in entrambi i casi l'inserimento viene rifiutato, perché il controllo univoco fallisce. Se c'è un modo per usare like semantica per UNIQUE controlla allora non lo so.

Quello che potresti fare è memorizzare il valore come VARBINARY :

mysql> create table test_ws ( `value` varbinary(255) UNIQUE );
Query OK, 0 rows affected (0.13 sec)

mysql> insert into test_ws (`value`) VALUES ('a');
Query OK, 1 row affected (0.08 sec)

mysql> insert into test_ws (`value`) VALUES ('a ');
Query OK, 1 row affected (0.06 sec)

mysql> SELECT CONCAT( '(', value, ')' ) FROM test_ws;
+---------------------------+
| CONCAT( '(', value, ')' ) |
+---------------------------+
| (a)                       |
| (a )                      |
+---------------------------+
2 rows in set (0.00 sec)

È meglio non fare nulla come l'ordinamento alfabetico su questa colonna, perché l'ordinamento avverrà invece sui valori dei byte e non sarà quello che gli utenti si aspettano (la maggior parte degli utenti, comunque).

L'alternativa è applicare una patch a MySQL e scrivere le proprie regole di confronto che sono di tipo NO PAD. Non sono sicuro che qualcuno voglia farlo, ma se lo fai, fammi sapere;)

Modifica:nel frattempo MySQL ha regole di confronto di tipo NO PAD, secondo https://dev.mysql.com/doc/refman/8.0/en/char.html :

e https://dev.mysql.com/ doc/refman/8.0/en/charset-unicode-sets.html

Quindi se provi:

  create table test_ws ( `value` varbinary(255) UNIQUE )
    character set utf8mb4 collate utf8mb4_0900_ai_ci;

puoi inserire valori con e senza spazi vuoti finali

Puoi trovare tutte le collazioni NO PAD disponibili con:

 show collation where Pad_attribute='NO PAD';