2026年5月19日
2026年5月19日
MySQLで大文字と小文字を区別する方法|utf8mb4_binと照合順序の変更
MySQL では、文字列の比較や並べ替えのルールを「照合順序(collation)」で決めています。MySQL 8.0 以降で utf8mb4 を使うときの既定の照合順序は utf8mb4_0900_ai_ci で、名前の最後の ci(case-insensitive)のとおり、大文字と小文字を区別しません。そのため、WHERE username = 'ALICE' で Alice の行が見つかり、一意(UNIQUE)の列に Alice と alice を両方入れることはできません。
この記事では、大文字と小文字を区別したい列の照合順序を変える方法と、クエリだけで区別する方法を説明します。SQL と結果は 2026年10月時点の MySQL 8.4.13 で確認しています。
大文字と小文字を区別する照合順序
照合順序の名前の最後の部分で、区別のしかたが分かります。
| 接尾辞 | 意味 |
|---|---|
_ci |
大文字と小文字を区別しない(case-insensitive) |
_cs |
大文字と小文字を区別する(case-sensitive) |
_ai / _as |
アクセント記号を区別しない / 区別する(é と e など) |
_bin |
文字コードの値で比べる(バイナリ照合) |
大文字と小文字を区別したいときに使う主な照合順序は、次の2つです。
| 照合順序 | 比較のしかた | 末尾の空白 |
|---|---|---|
utf8mb4_bin |
文字のコードポイントの値で比べる。並べ替えもコードポイント順(大文字が小文字より先) | 無視する(PAD SPACE) |
utf8mb4_0900_as_cs |
Unicode の規則で比べ、大文字と小文字、アクセント記号を区別する | 区別する(NO PAD) |
「末尾の空白」は、'a' と 'a '(最後に空白あり)を同じとみなすかどうかです。手元の MySQL 8.4 で確かめた結果は次のとおりです。
SELECT 'Alice' = 'alice' AS default_cmp, -- 1(同じとみなす)
'Alice' = 'alice' COLLATE utf8mb4_bin AS bin_cmp, -- 0(区別する)
'Alice' = 'alice' COLLATE utf8mb4_0900_as_cs AS as_cs_cmp, -- 0(区別する)
'a' = 'a ' COLLATE utf8mb4_bin AS bin_pad, -- 1(末尾の空白を無視)
'a' = 'a ' COLLATE utf8mb4_0900_as_cs AS as_cs_pad; -- 0(末尾の空白も区別)
照合順序ごとの PAD 属性は、次の SQL で確認できます。
SELECT COLLATION_NAME, PAD_ATTRIBUTE
FROM information_schema.COLLATIONS
WHERE COLLATION_NAME IN ('utf8mb4_0900_ai_ci', 'utf8mb4_0900_as_cs', 'utf8mb4_bin', 'utf8mb4_0900_bin');
MariaDB では照合順序の名前と既定値が違います。2026年10月時点の MariaDB 11.8 では、utf8mb4 の既定の照合順序は utf8mb4_uca1400_ai_ci です。utf8mb4_bin は MariaDB でも使え、大文字と小文字を区別します。
新しくテーブルを作るときに指定する
区別したい列にだけ、照合順序を指定します。
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
email VARCHAR(255) NOT NULL,
UNIQUE KEY uk_username (username)
);
この例では username だけ大文字と小文字を区別し、email はテーブルの既定(大文字と小文字を区別しない)のままにしています。メールアドレスは大文字と小文字を区別せずに扱われるのが一般的で、User@example.com と user@example.com を別のユーザーとして登録できてしまうと、重複登録の原因になります。区別するかどうかは、列ごとに目的に合わせて決めます。
データベース全体の既定を変えることもできます。この場合、後から作るテーブルで照合順序を指定しなかった列は、すべて大文字と小文字を区別するようになります。
CREATE DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
既存の列の照合順序を変える
特定の列だけを変えるには、ALTER TABLE ... MODIFY で列の定義を書き直します。NOT NULL などの既存の属性も書き直す必要があるので、先に SHOW CREATE TABLE で今の定義を確認してください。
SHOW CREATE TABLE users;
ALTER TABLE users
MODIFY username VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;
ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin; を使うと、テーブルにある文字列の列がすべて変わります。区別したくない列(メールアドレスなど)まで変わるので、目的の列だけを変えるときは MODIFY を使います。
変更後は次のどちらかで確認します。
SHOW FULL COLUMNS FROM users;
SELECT COLUMN_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users';
一意キーへの影響
UNIQUE キーのある列では、照合順序を変えると重複の判定も変わります。
- 区別しない(
_ci)→ 区別する(_bin)への変更は、今あるデータがそのまま入ります。変更後はAliceとaliceを両方登録できるようになります - 区別する → 区別しない への変更は、
Aliceとaliceが両方あるとERROR 1062 (23000): Duplicate entryで失敗します
実際に、区別しない照合順序の列に Alice を入れた後で alice を入れると、次のエラーになりました。
ERROR 1062 (23000): Duplicate entry 'alice' for key 'users.uk_username'
ALTER TABLE はテーブルを作り直すことがあり、大きなテーブルでは時間がかかります。本番では、バックアップを取ってから、アクセスの少ない時間に実行してください。
列を変えずにクエリだけで区別する
列の照合順序は変えずに、特定のクエリだけ大文字と小文字を区別したい場合は、COLLATE で比較に使う照合順序を指定します。
SELECT * FROM users WHERE username = 'Alice' COLLATE utf8mb4_bin;
ただし、列と違う照合順序で比べると、その列のインデックスを使った絞り込みができず、インデックス全体を読むことになります。手元で EXPLAIN を実行すると、type は index(インデックス全体を読む)でした。行が多いテーブルでは、次のように通常の比較でインデックスを使って候補を絞り、COLLATE で最終的に区別する書き方にすると、type が const になり、インデックスを使った検索になりました。
SELECT * FROM users
WHERE username = 'Alice'
AND username = 'Alice' COLLATE utf8mb4_bin;
WHERE BINARY username = 'Alice' という書き方も動きますが、MySQL 8.0.27 以降では非推奨で、実行すると 'BINARY expr' is deprecated という警告が出ます。新しく書く SQL では COLLATE を使ってください。
照合順序を変えると変わること
- 検索:
=だけでなくLIKEも大文字と小文字を区別するようになります。WHERE username LIKE 'a%'でAliceは見つからなくなります - 並べ替え:
utf8mb4_binではORDER BYがコードポイント順になり、Aliceがaliceより先、Bがaより先に並びます - アプリケーション:ログイン名などを区別するようにした場合、利用者が大文字と小文字を間違えるとログインできなくなります。画面の案内や入力時の扱い(小文字にそろえるかどうか)も合わせて決めてください
WordPressのテーブルについて
WordPress のテーブルは、wp-config.php の DB_CHARSET・DB_COLLATE とデータベースの設定に従って作られ、通常は大文字と小文字を区別しない照合順序(utf8mb4_unicode_520_ci など)になっています。WordPress 本体のテーブル(wp_users など)の照合順序を変えると、ユーザー名の検索や重複チェックの動きが変わるので、変更しないでください。この記事の方法は、プラグインや独自アプリケーションで自分が作ったテーブルに使います。
まとめ
- MySQL 8.0 以降の既定の照合順序
utf8mb4_0900_ai_ciは、大文字と小文字を区別しない - 区別したい列は
utf8mb4_binかutf8mb4_0900_as_csにする。utf8mb4_binは末尾の空白を無視し、utf8mb4_0900_as_csは区別する - 既存の列は
ALTER TABLE ... MODIFYで変える。CONVERT TOはすべての文字列の列が変わる - クエリだけで区別するなら
COLLATE utf8mb4_binを使い、インデックスを使うために通常の比較と組み合わせる BINARY演算子は MySQL 8.0.27 以降で非推奨
関連記事: