MySQLのこと。

MySQLのことについてまとめているブログ。他人に見せる用でもなく、自分の勉強備忘録。検索インデックスも外してるので、辿りついた方・・・ようこそ。そんな大した情報ないですよ?!たまにアルゴリズムの練習も

MySQL8.0のCharsetとCollationについて

はじめに

ここではMySQLのCharsetとCollationについて例をまじえてまとめる。そもそもMySQL文字コードは実行環境に依存しないので、LinuxでもWindowsでも同じ結果になる。

Charsetとは

MySQLにおけるCharsetとは、「使用できる文字」と「その文字がどのように扱われるのか」を決めるもの。MySQLのデフォルトのCharsetはutf8mb4です。他にもいくつか代表的なものが下記の表です。

Charset 内容
utf8mb4 utf8エンコーディング。1文字が1~4byteの可変長。
utf8mb3/utf8 utf8エンコーディング。U+10000以上の文字は含まない。1文字が1~3byteの可変長。
utf16 utf16エンコーディング。1文字が2,4byteの可変長。
utf32 utf32エンコーディング。1文字が4byteの固定長。
ascii ASCII
binary バイナリ文字列
latin1 Latin-1(ISO8859-1)
cp932 windows-31J
eucjpms windows-31JEUC-JP表現
ujis EUC-JP
sjis SHIFT-JIS

MySQLから利用可能なCharsetを表示できます。

mysql> SHOW CHARSET;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| armscii8 | ARMSCII-8 Armenian              | armscii8_general_ci |      1 |
| ascii    | US ASCII                        | ascii_general_ci    |      1 |
| big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
| binary   | Binary pseudo charset           | binary              |      1 |
| cp1250   | Windows Central European        | cp1250_general_ci   |      1 |
| cp1251   | Windows Cyrillic                | cp1251_general_ci   |      1 |
| cp1256   | Windows Arabic                  | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic                  | cp1257_general_ci   |      1 |
| cp850    | DOS West European               | cp850_general_ci    |      1 |
| cp852    | DOS Central European            | cp852_general_ci    |      1 |
| cp866    | DOS Russian                     | cp866_general_ci    |      1 |
| cp932    | SJIS for Windows Japanese       | cp932_japanese_ci   |      2 |
| dec8     | DEC West European               | dec8_swedish_ci     |      1 |
| eucjpms  | UJIS for Windows Japanese       | eucjpms_japanese_ci |      3 |
| euckr    | EUC-KR Korean                   | euckr_korean_ci     |      2 |
| gb18030  | China National Standard GB18030 | gb18030_chinese_ci  |      4 |
| gb2312   | GB2312 Simplified Chinese       | gb2312_chinese_ci   |      2 |
| gbk      | GBK Simplified Chinese          | gbk_chinese_ci      |      2 |
| geostd8  | GEOSTD8 Georgian                | geostd8_general_ci  |      1 |
| greek    | ISO 8859-7 Greek                | greek_general_ci    |      1 |
| hebrew   | ISO 8859-8 Hebrew               | hebrew_general_ci   |      1 |
| hp8      | HP West European                | hp8_english_ci      |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak      | keybcs2_general_ci  |      1 |
| koi8r    | KOI8-R Relcom Russian           | koi8r_general_ci    |      1 |
| koi8u    | KOI8-U Ukrainian                | koi8u_general_ci    |      1 |
| latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European     | latin2_general_ci   |      1 |
| latin5   | ISO 8859-9 Turkish              | latin5_turkish_ci   |      1 |
| latin7   | ISO 8859-13 Baltic              | latin7_general_ci   |      1 |
| macce    | Mac Central European            | macce_general_ci    |      1 |
| macroman | Mac West European               | macroman_general_ci |      1 |
| sjis     | Shift-JIS Japanese              | sjis_japanese_ci    |      2 |
| swe7     | 7bit Swedish                    | swe7_swedish_ci     |      1 |
| tis620   | TIS620 Thai                     | tis620_thai_ci      |      1 |
| ucs2     | UCS-2 Unicode                   | ucs2_general_ci     |      2 |
| ujis     | EUC-JP Japanese                 | ujis_japanese_ci    |      3 |
| utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |
| utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
| utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |
| utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_0900_ai_ci  |      4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.01 sec)

Charsetはデータベース、テーブル、カラム単位で個別に設置できますが、普通はすべて統一する。

mysql> CREATE DATABASE charset_db CHARSET utf8mb4;
Query OK, 1 row affected (0.01 sec)

mysql> SHOW CREATE DATABASE charset_db;
+------------+--------------------------------------------------------------------------------------------------------------------------------------+
| Database   | Create Database                                                                                                                      |
+------------+--------------------------------------------------------------------------------------------------------------------------------------+
| charset_db | CREATE DATABASE `charset_db` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+------------+--------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

Collationとは

Collationとは文字をどのように比較するのかを決定する規則のこと。文字列を比較するとき、並び替えを行うときにCollationが関わってくる。例えば、デフォルトの設定では、全角半角は区別されない。大文字、小文字も同じ。

mysql> SELECT "マイエスキューエル" = "マイエスキューエル";
+---------------------------------------------------------------+
| "マイエスキューエル" = "マイエスキューエル"                            |
+---------------------------------------------------------------+
|                                                             1 |
+---------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT "A" = "a";
+-----------+
| "A" = "a" |
+-----------+
|         1 |
+-----------+
1 row in set (0.00 sec)

Charsetは複数のCollationをもつため、utf8mb4だけでも75個のCollationがあります。utf8mb4のデフォルトのCollationはutf8mb4_0900_ai_ciです。データベースにCollationを設定する場合は下記のように、COLLATEのあとにつなげます。

mysql> CREATE DATABASE charset_db2 COLLATE utf8mb4_0900_ai_ci;
Query OK, 1 row affected (0.00 sec)

utf8mb4_0900_ai_ciはどんな意味があるかは_で要素が区切られているので、推測できます。utf8mb4_0900_ai_ciは、utf8mb4Unicodeのバージョンが9.0.0で、アクセントの違いを区別しないaiで大文字小文字を区別しないciということになります。

要素 内容
Charset Charsetの名前
言語 ja(日本) / zh(中国語) / ru(ロシア)など
ai / as アクセントの違いを区別しないai / アクセントの違いを区別するas
ci / cs 大文字小文字を区別しないci / 大文字小文字を区別するcs
ks ひらがなとカタカナを区別する

例えば、utf8mb4_0900_ai_ciはアクセントや大文字小文字を区別しないので、AÃは区別されないし、有名だが「はは」「ばば」「ぱぱ」は区別しない。「ぱぁでんねん」と「ぱあでんねん」も同じ扱いとなる。

mysql> SET NAMES utf8mb4 COLLATE utf8mb4_0900_ai_ci;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT "はは" = "ばば";
+---------------------+
| "はは" = "ばば"     |
+---------------------+
|                   1 |
+---------------------+
1 row in set (0.00 sec)

utf8mb4_0900_as_ciは、アクセントの違いは区別するので、「はは」「ばば」「ぱぱ」は区別される。

mysql> SET NAMES utf8mb4 COLLATE utf8mb4_0900_as_ci;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT "はは" = "ばば";
+---------------------+
| "はは" = "ばば"     |
+---------------------+
|                   0 |
+---------------------+
1 row in set (0.01 sec)

utf8mb4_0900_as_csは、アクセント、大文字小文字、全角半角、平仮名カタカナも区別されるので、「ぱぁでんねん」と「ぱあでんねん」も区別される。

mysql> SET NAMES utf8mb4 COLLATE utf8mb4_0900_as_ci;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT "ぱぁでんねん" = "ぱあでんねん";
+---------------------------------------------+
| "ぱぁでんねん" = "ぱあでんねん"             |
+---------------------------------------------+
|                                           1 |
+---------------------------------------------+
1 row in set (0.00 sec)

mysql> SET NAMES utf8mb4 COLLATE utf8mb4_0900_as_cs;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT "ぱぁでんねん" = "ぱあでんねん";
+---------------------------------------------+
| "ぱぁでんねん" = "ぱあでんねん"             |
+---------------------------------------------+
|                                           0 |
+---------------------------------------------+
1 row in set (0.00 sec)

utf8mb4_binUnicodeの規則に従わず、すべての文字が区別される。

mysql> SET NAMES utf8mb4 COLLATE utf8mb4_bin;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT "ぱぁでんねん" = "ぱあでんねん";
+---------------------------------------------+
| "ぱぁでんねん" = "ぱあでんねん"             |
+---------------------------------------------+
|                                           0 |
+---------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT "はは" = "ばぱ";
+---------------------+
| "はは" = "ばぱ"     |
+---------------------+
|                   0 |
+---------------------+
1 row in set (0.00 sec)