Blogブログ

[MySQL] 大文字と小文字、濁点の有無で文字を区別させる

こんにちはHLCの掛橋です👨‍💻
HLCに入社して半年、Laravelって何?ってとこから徐々に理解を深めていき、
気づけばAPIなどピャピャッと作れる身体になりました。慣れってすごいや。

とあるテーブルにて

id(連番) name(※ユニークキー制約)
1

id:2、name:う
のデータをINSERTしようとしたら、、、
Duplicate entry ‘う’ for key ‘name_unique’
ユニークキー制約でエラーが返ってくる。
現在のデータは「ゔ」の一件だけやのに、なんで怒られるんやろう、、?

試しに、
SELECT * FROM HOGE_TABLE WHERE name = ‘う’
と検索すると、、検索結果は↓

id name
1

ンンンンん!????
なんで「う」で検索かけたのに濁点ありの「ゔ」のデータが返ってくるんや??

テーブル定義をみてみる

nameのcollationの設定が「utf8mb4_0900_ai_ci」と判明。

「utf8mb4_0900_ai_ci」is 何?

utf8mb4は4バイトのUTF-8 Unicode エンコーディング
utf8≠utf8mb4です。
utf8は1~3バイトまで対応
utf8mb4は4バイトまで対応→絵文字やutf8で対応できなかった漢字などを表現できるようになったそうな

_0900はUnicodeのバージョン9.0.0
ユニコードってそんなにもバージョンがあったんですね。知らなかった。

_aiは Accent Insensitive
アクセント違いのものは無視する設定。
「ゔ」と「う」や、「は」「ば」「ぱ」など、濁点、半濁点は同じ扱いになる。

_ci は Case Insensitive
大文字小文字の違いは無視する設定。
「う」と「ぅ」や、「A」と「a」などは同じ扱いになる。

どうやら_aiと_ciの設定のせいで、データの挿入や検索などがうまくいってなかったようだ。

解決策

文字を大文字小文字、濁点等で区別させるためにはBINARYオプションを使うことで解決します。

テーブル定義を変更しましょう。

ALTER TABLE テーブル名 MODIFY 列名 VARCHAR BINARY

テーブル定義を修正後
「ヴ」をInsertしてみると

id(連番) name(※ユニークキー制約)
1

無事にデータを入れることができました。

また、「う」と検索をかけると「う」をもつデータが、
「ゔ」と検索をかけると「ゔ」をもつデータが表示されるようになりました。

文字コードは奥が深いなぁ~👀