ITエンジニアのブログ

IT企業でエンジニアやってる人間の日常について

PHPとMySQLの文字列設定について

自然言語処理のために文字列のアノテーションを行うためのブラウザインターフェースを、 PHP, MySQL, JavaScript で作っていたのですが、コーパス文字コードが統一されていなくて、それを UTF-8 に変換して使うために苦戦したので記しておきます。
PHP の文字列関数で文字コードを考慮する場合は、通常の文字列関数 substr, strlen などに接頭辞 mb_ を付与したものになります。すると文字コードを指定すると良く、

<?php echo strlen("あいうえお"); ?>
<?php echo mb_strlen("あいうえお", "UTF-8"); ?>

UTF-8 の端末の環境では、前者は 15, 後者は 5 になります。
読み込み用のファイルも UTF-8 にすれば問題なさそうですが、ファイル内容を MySQL に保管したものを取り出していて、そこで齟齬が起きていました。
MySQL において table を作成するとき、文字コードを指定できます。例えばある名前と、アノテーション対象となる文字列の開始位置、そして備考を保存するテーブルを作成します。(文字コードの管理がしっかりできていないと、このインデックスがずれてしまって困るのです。)

mysql> create table annotations (name varchar(64), index int, memo text) default character set utf8;

create table をする際に文字コードを設定しますが、それだけでは正常に動作しない場合があり、 MySQL文字コードの設定次第では、一例として次のようになっている場合があります。

mysql> show create table annotations;
| Table | Create Table |
| annotations | CREATE TABLE `annotations`(
`name` varchar(64) CHARSET SET latin1 DEFAULT NULL,
`index` int(11) DEFAULT NULL,
`memo` text CHARSET SET latin1 DEFAULT NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8

中味の varchar や text が latin1 になっているのです。 MySQL のデフォルト文字コードの設定は、

mysql> status
Server characterset:    utf8
Db     characterset:    latin1
Client characterset:    utf8
Conn.  characterset:    utf8

となっており、 Db characterset が latin1 になっているからかもしれません。
そもそも status で表示されるこれらの文字コードを修正すれば解決するかもしれませんが、なぜか Db characterset だけは変更する方法が分かりませんでした。ですが、テーブルを作るときにテーブル内部のそれぞれの項目に対して文字コードを設定することができます。

mysql> create table annotations (name varchar(64) charset set utf8, index int, memo text charset set utf8) default character set utf8;

インターフェースはこれで正常動作しました。