El problema es que MySQL ignora los espacios en blanco al hacer una comparación de cadenas. Ver http://dev.mysql.com/doc/refman/ 5.7/es/char.html
(Esta información es para 5.7; para 8.0 esto cambió, ver más abajo)
La sección para el like
operador da un ejemplo de este comportamiento (y muestra que like
respeta los espacios en blanco al final):
mysql> SELECT 'a' = 'a ', 'a' LIKE 'a ';
+------------+---------------+
| 'a' = 'a ' | 'a' LIKE 'a ' |
+------------+---------------+
| 1 | 0 |
+------------+---------------+
1 row in set (0.00 sec)
Desafortunadamente, el UNIQUE
index parece usar la comparación de cadenas estándar para verificar si ya existe dicho valor y, por lo tanto, ignora los espacios en blanco finales. Esto es independiente del uso de VARCHAR
o CHAR
, en ambos casos se rechaza la inserción porque falla la comprobación de unicidad. Si hay una forma de usar like
semántica para UNIQUE
comprueba entonces que no lo sé.
Lo que podría hacer es almacenar el valor como 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)
Es mejor que no quiera hacer nada como ordenar alfabéticamente en esta columna, porque la ordenación ocurrirá en los valores de bytes en su lugar, y eso no será lo que los usuarios esperan (la mayoría de los usuarios, de todos modos).
La alternativa es parchear MySQL y escribir su propia intercalación que es del tipo NO PAD. No estoy seguro si alguien quiere hacer eso, pero si lo hace, hágamelo saber;)
Editar:mientras tanto, MySQL tiene intercalaciones que son del tipo NO PAD, de acuerdo con https://dev.mysql.com/doc/refman/8.0/en/char.html :
y https://dev.mysql.com/ doc/refman/8.0/en/charset-unicode-sets.html
Así que si intentas:
create table test_ws ( `value` varbinary(255) UNIQUE )
character set utf8mb4 collate utf8mb4_0900_ai_ci;
puede insertar valores con y sin espacios en blanco al final
Puede encontrar todas las intercalaciones de NO PAD disponibles con:
show collation where Pad_attribute='NO PAD';