環境-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進数で抜き出す(どこかに出力させる)ことができればもう少しわかりそうなのですが。