sql >> Base de Datos >  >> RDS >> Mysql

Base de datos MySQL con campos únicos ignorados espacios finales

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';