4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

chcp 65001 すると MySQLが日本語を受け付けてくれない

Last updated at Posted at 2021-01-22

環境-1つめ:10.1.32-MariaDB , XAMPP v3.2.2 , Windows10 Enterprise
環境-2つめ:10.4.17-MariaDB , XAMPP v3.2.4 , Windows10 PRO

結論から書くと私の場合は chcp 65001 を使ってWindowsコマンドプロンプト上から utf-8 の入力をするのは避けたほうがいい気がする。となりました。

##起こったこと

  • Windowsコマンドプロンプトから MySQL を操作する時、chcp 65001 でコマンドプロンプトの文字コードを utf-8 にすると MySQL が日本語(3バイトuft-8)を受け付けてくれない
  • 読み出し時の文字化けはない。
  • また chcp 932 のまま、MySQL内で set names cp932 をすればなにも問題は起きない。
  • ふたつの環境で再現する。
# chcp 65001
///// ウィンドウが変わる
Active code page: 65001

# mysql -u root -p

MariaDB [(none)]> USE db1
Database changed

///// insert を試みる
MariaDB [db1]> INSERT INTO tb10(num,name) VALUES(1,'佐藤');
    '>
    '>
    '>     ///// ← 処理が完了していない
    '> ;    ///// ← セミコロン入れても完了しない
    '>
    '> '    ///// ← よく見るとシングルクオーテーション抜けだと言われてるので入力する
    ->
    -> ;    ///// ← セミコロンを入れて完了しエラー文が出る
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1

この挙動は insert だけではなく as句 による名付けや、他の構文内で日本語を使った場合でもほぼ変わらない。
(as句だとシングルクオーテーションのありなしで少し変わる)

MariaDB [db1]> SELECT name AS '名前' FROM tb10;
    '> '
    -> ;
ERROR 1054 (42S22): Unknown column 'name' in 'field list'

MariaDB [db1]> SELECT name AS 名前 FROM tb10;
    -> ;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1

MariaDB [db1]> SELECT ROD('あ');
    '> '
    -> ;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1

#####直接文字コードを書くことによる insert はできる
utf-8 を CHAR()関数によって変換することはできる。
また直接文字コードを書くことによる insert もできる。

MariaDB [db1]> SELECT CHAR(0xe38182 using utf8);
+---------------------------+
| CHAR(0xe38182 using utf8) |
+---------------------------+
| あ                        |
+---------------------------+
1 row in set (0.000 sec)

MariaDB [db1]> INSERT INTO tb10(num,name) VALUES(1,0xe38182e38184);
Query OK, 1 row affected (0.00 sec)

MariaDB [db1]> SELECT * FROM tb10;
+------+--------+
| num  | name   |
+------+--------+
|    1 | あい   |
+------+--------+
1 row in set (0.000 sec)

#####接続が utf8 でカラムが utf8 のとき、4bit文字が現れるとそこで文字が切れる現象を思い出す
参考:https://tmtms.hatenablog.com/entry/2016/09/06/mysql-utf8

日本語の後ろが読まれてないのでは? というわけで日本語の末尾から行を分けてinsertしてみる。

MariaDB [db1]> insert into tb10(num,name) values(3,'佐藤
    '> ');                 ///// 『 '); 』を改行してから入力する
Query OK, 1 row affected (0.011 sec)

MariaDB [db1]> select * from tb10;
+------+--------+
| num  | name   |
+------+--------+
|    1 | あい   |
|    2 | 鈴木   |
|    3 |
      |
+------+--------+
3 rows in set (0.000 sec)

受け付けてくれた。
……なんかおかしいけど。
ただinsertできたらこっちのもので出力させます。

MariaDB [db1]> SELECT * FROM tb10 INTO OUTFILE 'a.dmp';
Query OK, 3 rows affected, 1 warning (0.001 sec)

これをテキストと16進数とでそれぞれ見て……

>type a.dmp
1       あい
2       鈴木
3       \


>certutil -f -encodehex a.dmp a_16.txt 4    ///// 16進数への変換
Input Length = 12
Output Length = 38
CertUtil: -encodehex command completed successfully.

>type a_16.txt
31 09 e3 81 82 e3 81 84  0a 32 09 e9 88 b4 e6 9c
a8 0a 33 09 5c 0a 0a

うん…………?

ちょっとわかりにくいので、新しく tb11 を作り2回insertします。

MariaDB [db1]> CREATE TABLE tb11(text VARCHAR(100));   ///// テーブルの作成から
Query OK, 0 rows affected (0.007 sec)

MariaDB [db1]> INSERT INTO tb11(text) VALUES('あい
    '> ');
Query OK, 1 row affected (0.003 sec)

MariaDB [db1]> INSERT INTO tb11(text) VALUES('高橋
    '> ');
Query OK, 1 row affected (0.001 sec)

MariaDB [db1]> SELECT * FROM tb11;
+------+
| text |
+------+
|
    |
|
    |
+------+
2 rows in set (0.000 sec)

MariaDB [db1]> SELECT * FROM tb11 INTO OUTFILE 'b.dmp';   ///// 出力する
Query OK, 2 rows affected, 1 warning (0.002 sec)

それをまたテキストファイルと16進数とで見て

>type b.dmp
\

\


>type b_16.txt
5c 0a 0a 5c 0a 0a

うん…………。
0a=<LF> の改行がひとつ多く入ってるのはシングルクォーテーションの間で一度改行してるのを正しく反映していると言えます。
その前、どんな文字を入れても 5c になってるのは、ちょっとわからない。
(BOM も疑ったけどBOMは EF BB BF だからいまいちそれと確信持てない……)

と、ここでお手上げになりました。

##以下はMySQLの設定の確認
MySQL側の文字コードは utf-8 で統一されている(はず)

#####character_set の確認

MariaDB [(none)]> show global variables like 'char%';
+--------------------------+----------------------------------------------------------------+
| Variable_name            | Value                                                          |
+--------------------------+----------------------------------------------------------------+
| character_set_client     | utf8mb4                                                        |
| character_set_connection | utf8mb4                                                        |
| character_set_database   | utf8mb4                                                        |
| character_set_filesystem | binary                                                         |
| character_set_results    | utf8mb4                                                        |
| character_set_server     | utf8mb4                                                        |
| character_set_system     | utf8                                                           |
| character_sets_dir       | C:\ <--中略--> mysql\share\charsets\ |
+--------------------------+----------------------------------------------------------------+
8 rows in set (0.001 sec)

MariaDB [(none)]> show session variables like 'char%';
+--------------------------+----------------------------------------------------------------+
| Variable_name            | Value                                                          |
+--------------------------+----------------------------------------------------------------+
| character_set_client     | utf8mb4                                                        |
| character_set_connection | utf8mb4                                                        |
| character_set_database   | utf8mb4                                                        |
| character_set_filesystem | binary                                                         |
| character_set_results    | utf8mb4                                                        |
| character_set_server     | utf8mb4                                                        |
| character_set_system     | utf8                                                           |
| character_sets_dir       | C:\ <--中略--> mysql\share\charsets\ |
+--------------------------+----------------------------------------------------------------+
8 rows in set (0.000 sec)

#####その上で作られた db1

MariaDB [(none)]> select * from INFORMATION_SCHEMA.SCHEMATA where SCHEMA_NAME='db1';
+--------------+-------------+----------------------------+------------------------+----------+
| CATALOG_NAME | SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME | SQL_PATH |
+--------------+-------------+----------------------------+------------------------+----------+
| def          | db1         | utf8mb4                    | utf8mb4_unicode_ci     | NULL     |
+--------------+-------------+----------------------------+------------------------+----------+
1 row in set (0.002 sec)

#####その上で作られた tb10

MariaDB [db1]> show create table tb10;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                         |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tb10  | CREATE TABLE `tb10` (
  `num` int(11) DEFAULT NULL,
  `name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.000 sec)

#####一応 my.ini の記述も置いておきます

[mysqld]
## UTF 8 Settings
init-connect='SET NAMES utf8mb4'
collation_server=utf8mb4_unicode_ci
character_set_server=utf8mb4
skip-character-set-client-handshake
character_sets-dir="C:/ <--中略--> mysql/share/charsets"
sql_mode=NO_ZERO_IN_DATE,NO_ZERO_DATE,NO_ENGINE_SUBSTITUTION
log_bin_trust_function_creators = 1

[mysqldump]
default-character-set	= utf8mb4

[mysql]
default-character-set	= utf8mb4

##Shift_JIS のまま set names すれば問題は起きない

# chcp
現在のコード ページ: 932

# mysql -u root -p

MariaDB [(none)]> SET NAMES cp932;
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> USE db1
Database changed

MariaDB [db1]> INSERT INTO tb10(num,name) VALUES(2,'鈴木');
Query OK, 1 row affected (0.003 sec)

MariaDB [db1]> SELECT * from tb10;
+------+------+
| num  | name |
+------+------+
|    1 | あい     |
|    2 | 鈴木     |
+------+------+
2 rows in set (0.003 sec)

怪しいのは chcp 65001 かな…………

コマンドラインから MySQL に渡している文字列を16進数で抜き出す(どこかに出力させる)ことができればもう少しわかりそうなのですが。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?