Problem polega na tym, że MySQL ignoruje końcowe białe znaki podczas porównywania ciągów. Zobaczhttp://dev.mysql.com/doc/refman/ 5.7/pl/znak.html
(Te informacje dotyczą wersji 5.7; dla wersji 8.0 to się zmieniło, patrz poniżej)
Sekcja dla like
operator podaje przykład tego zachowania (i pokazuje, że like
uwzględnia końcowe białe znaki):
mysql> SELECT 'a' = 'a ', 'a' LIKE 'a ';
+------------+---------------+
| 'a' = 'a ' | 'a' LIKE 'a ' |
+------------+---------------+
| 1 | 0 |
+------------+---------------+
1 row in set (0.00 sec)
Niestety UNIQUE
index wydaje się używać standardowego porównywania ciągów znaków, aby sprawdzić, czy istnieje już taka wartość, a zatem ignoruje końcowe białe znaki. Jest to niezależne od użycia VARCHAR
lub CHAR
, w obu przypadkach wstawienie jest odrzucane, ponieważ sprawdzanie unikatowe kończy się niepowodzeniem. Jeśli istnieje sposób na użycie like
semantyka dla UNIQUE
sprawdź to nie wiem.
Możesz zapisać wartość jako 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)
Lepiej nie chcieć robić nic takiego jak sortowanie alfabetyczne w tej kolumnie, ponieważ zamiast tego sortowanie nastąpi na wartościach bajtów, a to nie będzie to, czego oczekują użytkownicy (w każdym razie większość użytkowników).
Alternatywą jest załatanie MySQL i napisanie własnego zestawienia typu NO PAD. Nie jestem pewien, czy ktoś chce to zrobić, ale jeśli tak, daj mi znać;)
Edycja:w międzyczasie MySQL ma zestawienia typu NO PAD, zgodnie z https://dev.mysql.com/doc/refman/8.0/en/char.html :
i https://dev.mysql.com/ doc/refman/8.0/en/charset-unicode-sets.html
Więc jeśli spróbujesz:
create table test_ws ( `value` varbinary(255) UNIQUE )
character set utf8mb4 collate utf8mb4_0900_ai_ci;
możesz wstawiać wartości z końcowymi białymi znakami i bez
Możesz znaleźć wszystkie dostępne zestawienia NO PAD z:
show collation where Pad_attribute='NO PAD';