【SQLiteからMySQLへの移行3】 MySQL側での文字化けの解消

前回「【SQLiteからMySQLへの移行2】 SQLiteダンプしたSQLのMySQLでの実行」では、SQLiteでダンプしたデータをMySQLへ投入したが、文字化けしたところまで確認して終わった。

今回はこの原因を突き止めて、解決方法を探る。

1.文字コードの確認
そういえば、character_set_databaseをsjisに変更していたのを忘れていたw。
SQLiteはutfがデフォルトでsjisを許容していないので、文字化けの原因は恐らくこれだろう。

mysql> show variables like 'char%';
+--------------------------+--------------------------------+
| Variable_name            | Value                          |
+--------------------------+--------------------------------+
| character_set_client     | utf8                           |
| character_set_connection | utf8                           |
| character_set_database   | sjis                           |
| character_set_filesystem | binary                         |
| character_set_results    | utf8                           |
| character_set_server     | utf8                           |
| character_set_system     | utf8                           |
| character_sets_dir       | C:\dev\mysql55\share\charsets\ |
+--------------------------+--------------------------------+
8 rows in set (0.00 sec)


ここを参考にすると、次のようにある。

色々な値が表示されますが、特に関係があるのは次の値です。

character_set_client utf8 クライアントが送信する文字コード
character_set_connection utf8 文字コード情報が無い文字列の文字コード
character_set_results utf8 クライアントへ送信する文字コード
character_set_server utf8 サーバのデフォルト文字コード

2.文字コードを変更する

mysql> alter database test character set utf8;
Query OK, 1 row affected (0.07 sec)

mysql> show variables like 'char%';
+--------------------------+--------------------------------+
| Variable_name            | Value                          |
+--------------------------+--------------------------------+
| character_set_client     | utf8                           |
| character_set_connection | utf8                           |
| character_set_database   | utf8                           |
| character_set_filesystem | binary                         |
| character_set_results    | utf8                           |
| character_set_server     | utf8                           |
| character_set_system     | utf8                           |
| character_sets_dir       | C:\dev\mysql55\share\charsets\ |
+--------------------------+--------------------------------+
8 rows in set (0.00 sec)

3.データを再投入してみる
あれれ、文字化けが直らない・・・。

mysql> delete from historicaldate;
Query OK, 1 row affected (0.05 sec)

mysql> source C:\dev\SQLite\EventDateDump.sql
ERROR 1050 (42S01): Table 'historicaldate' already exists
Query OK, 1 row affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> select * from historicaldate \G;
*************************** 1. row ***************************
   id: 1
  nen: 2007
 tuki: 9
 niti: 17
   zi: -1
  fun: 0
 kuni: JP
event: 莨大エ・域噴閠√・譌・・
 lank: 0
  mae: NULL
 yoso: NULL
 keka: NULL
1 row in set (0.00 sec)

4.データベースのcharset以外に、テーブルのcharsetも変更する
そういえば、テーブルのcharsetも変更したのだったw・・・。
まずは、テーブルのcharsetの確認。

mysql> show create table Historicaldate \G;
*************************** 1. row ***************************
       Table: Historicaldate
Create Table: CREATE TABLE `historicaldate` (
  `id` int(11) NOT NULL,
  `nen` int(11) DEFAULT NULL,
  `tuki` int(11) DEFAULT NULL,
  `niti` int(11) DEFAULT NULL,
  `zi` int(11) DEFAULT NULL,
  `fun` int(11) DEFAULT NULL,
  `kuni` text,
  `event` text,
  `lank` int(11) DEFAULT NULL,
  `mae` text,
  `yoso` text,
  `keka` text,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=sjis
1 row in set (0.00 sec)

DEFAULT CHARSET=sjisとあるので、utf8に戻す。

mysql> alter table Historicaldate character set utf8;
Query OK, 1 row affected (0.37 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> show create table Historicaldate \G;
*************************** 1. row ***************************
       Table: Historicaldate
Create Table: CREATE TABLE `historicaldate` (
  `id` int(11) NOT NULL,
  `nen` int(11) DEFAULT NULL,
  `tuki` int(11) DEFAULT NULL,
  `niti` int(11) DEFAULT NULL,
  `zi` int(11) DEFAULT NULL,
  `fun` int(11) DEFAULT NULL,
  `kuni` text CHARACTER SET sjis,
  `event` text CHARACTER SET sjis,
  `lank` int(11) DEFAULT NULL,
  `mae` text CHARACTER SET sjis,
  `yoso` text CHARACTER SET sjis,
  `keka` text CHARACTER SET sjis,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

5.それでも文字化けが直らない
おかしい。。。SJISで開かれている。。。なんでだろう。

mysql> select * from historicaldate \G;
*************************** 1. row ***************************
   id: 1
  nen: 2007
 tuki: 9
 niti: 17
   zi: -1
  fun: 0
 kuni: JP
event: 莨大エ・域噴閠√・譌・・
 lank: 0
  mae: NULL
 yoso: NULL
 keka: NULL
1 row in set (0.00 sec)

コマンドラインに直接貼り付けて実行してみた。

mysql> INSERT INTO HistoricalDate VALUES(1,2007,9,17,-1,0,"JP","休場(敬老の日)
",0,NULL,NULL,NULL);
ERROR 1366 (HY000): Incorrect string value: '\x8Bx\x8F\xEA\x81i...' for column '
event' at row 1

これはクライアントの文字コードがutf8に設定されているのに対して、入力文字がshift-jisだからか、返却結果をutf8で解釈しているからだろう。

-- クライアントの文字コードをshift-jisに変更
mysql> set character_set_client=sjis;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO HistoricalDate VALUES(1,2007,9,17,-1,0,"JP","休場(敬老の日)
",0,NULL,NULL,NULL);
Query OK, 1 row affected (0.00 sec)

mysql> select * from historicaldate \G;
*************************** 1. row ***************************
   id: 1
  nen: 2007
 tuki: 9
 niti: 17
   zi: -1
  fun: 0
 kuni: JP
event: 莨大エ・域噴閠√・譌・・
 lank: 0
  mae: NULL
 yoso: NULL
 keka: NULL
1 row in set (0.00 sec)

クライアント側の文字コードをshift-jisに変更するだけでは文字化け。
そのため、出力結果表示時の文字コードもshift-jisに変更する。

mysql> set character_set_results=sjis;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from historicaldate \G;
*************************** 1. row ***************************
   id: 1
  nen: 2007
 tuki: 9
 niti: 17
   zi: -1
  fun: 0
 kuni: JP
event: 休場(敬老の日)
 lank: 0
  mae: NULL
 yoso: NULL
 keka: NULL
1 row in set (0.00 sec)

コマンドラインに直接SQLを打ち込んだ場合の文字化けはこれで解消。
これでも、ファイルからSQLを実行した場合は、文字化けが解消しない。
ファイルの文字コードをshift-jisにしたり、utf8にしたりと試したのだが上手くいかない。何でだろう。

mysql> source C:\dev\SQLite\EventDateDump.sql
ERROR 1050 (42S01): Table 'historicaldate' already exists
Query OK, 1 row affected (0.04 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> select * from historicaldate \G;
*************************** 1. row ***************************
   id: 1
  nen: 2007
 tuki: 9
 niti: 17
   zi: -1
  fun: 0
 kuni: JP
event: 莨大?エ?域噴閠√?譌・?
 lank: 0
  mae: NULL
 yoso: NULL
 keka: NULL
1 row in set (0.00 sec)

原因分からずで、いったん入力となるSQLSJISで作成して保存して実行した。
DB側の文字コードも全てSJISで実行・・・。

mysql> select * from historicaldate where id between 1 and 10 \G;
*************************** 1. row ***************************
   id: 1
  nen: 2007
 tuki: 9
 niti: 17
   zi: -1
  fun: 0
 kuni: JP
event: 休場(敬老の日)
 lank: 0
  mae: NULL
 yoso: NULL
 keka: NULL
*************************** 2. row ***************************
   id: 2
  nen: 2007
 tuki: 9
 niti: 17
   zi: 10
  fun: 0
 kuni: EU
event: 7月貿易収支<季調前>
 lank: 1
  mae: +76億ユーロ
 yoso: +70億ユーロ
 keka: +46億ユーロ