問題は、MySQL が文字列比較を行うときに末尾の空白を無視することです。http://dev.mysql.com/doc/refman/5.7/en/char.htmlを参照してください
。
すべての MySQL 照合は PADSPACE 型です。これは、MySQL のすべての CHAR、VARCHAR、および TEXT 値が末尾のスペースに関係なく比較されることを意味します。
...
末尾の埋め込み文字が削除されるか、比較でそれらが無視される場合、列に一意の値を必要とするインデックスがある場合、末尾の埋め込み文字の数だけが異なる値を列に挿入すると、重複キー エラーが発生します。たとえば、テーブルに「a」が含まれている場合、「a」を格納しようとすると、重複キー エラーが発生します。
(この情報は 5.7 用です。8.0 ではこれが変更されました。以下を参照してください)
演算子のセクションでは、like
この動作の例を示します (like
末尾の空白を尊重することを示しています)。
mysql> SELECT 'a' = 'a ', 'a' LIKE 'a ';
+------------+---------------+
| 'a' = 'a ' | 'a' LIKE 'a ' |
+------------+---------------+
| 1 | 0 |
+------------+---------------+
1 row in set (0.00 sec)
残念ながら、UNIQUE
インデックスは標準の文字列比較を使用してそのような値が既に存在するかどうかを確認しているように見えるため、末尾の空白は無視されます。VARCHAR
これは、またはの使用とは無関係ですCHAR
。どちらの場合も、一意のチェックが失敗するため、挿入は拒否されます。like
チェックにセマンティクスを使用する方法がある場合UNIQUE
、私はそれを知りません。
あなたができることは、値を次のように保存することです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)
代わりにバイト値でソートが行われ、それはユーザーが期待するものではないため、この列でアルファベット順にソートするようなことはしたくないでしょう (ほとんどのユーザーはとにかく)。
別の方法として、MySQL にパッチを適用し、タイプ NO PAD の独自の照合順序を記述します。誰かがそれをやりたいかどうかはわかりませんが、もしそうなら、私に知らせてください;)
編集: 一方、MySQL には、 https : //dev.mysql.com/doc/refman/8.0/en/char.html によると、タイプ NO PAD の照合順序があります。
ほとんどの MySQL 照合には、PAD SPACE のパッド属性があります。例外は、UCA 9.0.0 以降に基づく Unicode 照合であり、パッド属性が NO PAD です。
およびhttps://dev.mysql.com/doc/refman/8.0/en/charset-unicode-sets.html
4.0.0 以降の UCA バージョンに基づく Unicode 照合には、照合名にバージョンが含まれます。したがって、utf8mb4_unicode_520_ci は UCA 5.2.0 の重みキーに基づいていますが、utf8mb4_0900_ai_ci は UCA 9.0.0 の重みキーに基づいています。
したがって、試してみると:
create table test_ws ( `value` varbinary(255) UNIQUE )
character set utf8mb4 collate utf8mb4_0900_ai_ci;
末尾の空白の有無にかかわらず値を挿入できます
利用可能なすべての NO PAD 照合は、次のように見つけることができます。
show collation where Pad_attribute='NO PAD';