Mysql
 sql >> Base de données >  >> RDS >> Mysql

Base de données MySQL avec des champs uniques ignorés des espaces de fin

Le problème est que MySQL ignore les espaces de fin lors de la comparaison de chaînes. Voirhttp://dev.mysql.com/doc/refman/ 5.7/fr/char.html

(Cette information est pour 5.7 ; pour 8.0, cela a changé, voir ci-dessous)

La section pour le like L'opérateur donne un exemple de ce comportement (et montre que like respecte les espaces de fin):

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

Malheureusement le UNIQUE index semble utiliser la comparaison de chaînes standard pour vérifier s'il existe déjà une telle valeur, et ignore donc les espaces de fin. Ceci est indépendant de l'utilisation de VARCHAR ou CHAR , dans les deux cas, l'insertion est rejetée, car la vérification unique échoue. S'il existe un moyen d'utiliser like sémantique pour le UNIQUE vérifier alors je ne le sais pas.

Ce que vous pourriez faire est de stocker la valeur sous 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)

Vous feriez mieux de ne pas faire quoi que ce soit comme trier par ordre alphabétique sur cette colonne, car le tri se fera plutôt sur les valeurs d'octets, et ce ne sera pas ce que les utilisateurs attendent (la plupart des utilisateurs, de toute façon).

L'alternative est de patcher MySQL et d'écrire votre propre classement de type NO PAD. Je ne sais pas si quelqu'un veut le faire, mais si c'est le cas, faites-le moi savoir ;)

Edit :pendant ce temps, MySQL a des classements de type NO PAD, selon https://dev.mysql.com/doc/refman/8.0/en/char.html :

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

Donc, si vous essayez :

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

vous pouvez insérer des valeurs avec et sans espace de fin

Vous pouvez trouver tous les classements NO PAD disponibles avec :

 show collation where Pad_attribute='NO PAD';