2011/05/21

phpMyAdminのCSVエクスポートが変な件

これはだいぶ前からおかしかったという認識なんだけど、最新版の3.4でも相変わらずだったのでついカッとなってこのエントリを書いている。



知らない人はこんな記事読まないと思うけど念のため。

phpMyAdmin

「phpMyAdmin」とはMySQLのテーブル定義やデータを参照・操作するためのPHPで書かれたWEBアプリである。
歴史は長く、LAMP環境で使えるため非常にメジャーでユーザーも多い。
MySQLとの接続の拡張モジュールは「mysql」もしくは「mysqli」から選べるが、「PDO」は使えない。
なにせPHP4で書かれているので。

CSV

「CSV」とは「Comma-Separated Values」の略であり日本語訳すると「カンマ(,)で区切られた値群」といったところか。
そして今回のエントリで大事なのが「CSV」の仕様である。
詳細はWikipediaでも見ていただければいいんだけど、今回大事なのは以下の3点。
  1. フィールドはカンマ「,」(U+002C) で区切られる。
  2. フィールドがカンマ、ダブルクォート、改行を含む場合は、かならずダブルクォート「"」で囲む。
  3. フィールドに含まれるダブルクォートは2つ並べて「""」エスケープする。
これがRFC4180の規格なのだ。


CSVエクスポートなんて

そもそもほんとは使いたくない。
でも複数のレコードをまとめて編集したい場合があって、社内の人間が全員SQLのUPDATE文を正確に書ければいいんだけどウチはSIerではなくただのOA機器の販社なのでそうは行かない。
そんな場合はやはりエクセルで編集するのが早い。
よって、わざわざCSVで吐き出し、テキストエディタで文字コードをSJISに変換してEXCELで編集後またUTF-8に戻してインポートするという手順を踏んでもらっている。
実際ExcelでCSVを開く際、上記のRFC4180の規格に沿っていればあとは「文字コードがSJIS」なら正常に操作できる。

phpMyAdminのCSVエクスポート

さてphpMyAdminの機能でCSVエクスポートをしようと思ったときにまず迷うのが、複数あるCSVの種類だ。
まず選ばされるのが以下の2つ。
1.CSV
2.MS Excel 用の CSV

・・・・二つ目のはなんだ。なにが違うんだ。さっそく不安だぞ。


「CSV」エクスポートの挙動

エクスポートする際の区切り文字、囲み文字、エスケープ文字が自分で入力できる。
ここでひとつおかしな点は、デフォルトのエスケープ記号が「\」。

・・・チガウダロ。

まぁここの値は入力で変更できるし、もっと言えば標準の設定ファイル(config.inc.php)で変更できるのでまだいい。
問題はこの先にある。

「何言ってるんだエスケープは「"」だろ?」ってことで「"」を指定してエクスポートを実行すると、
エクスポートされたファイルで「""」(2つ)になるべきところがなぜか「""""」(4つ)になっているのだ。
サービス精神が旺盛なのか「さらに倍」。余計なお世話である。

ということで、ひとつめのCSVは使えない。
ちなみに多分この挙動は前のバージョン(phpMyAdmin3.3以前)から引き継いでいる。

「MS Excel 用の CSV」エクスポートの挙動

選択できるオプションは以下の通り。


今度は自分で記号を入力したりは出来なくなっている。
そこで我々は「ExcelでCSVで保存したときと同じ書式」になるに違いないと推測する。
で、よくわからないのが「Excelのエディション」だ。
ExcelのバージョンによってCSVが変わるのか?意味不明だ。

Mac好きに言わせれば、「2008年にMacintoshなんて製品はない」んだけど、それは置いといてひとつずつ試してみる。
ひとつめ「Windows」。エクスポートしたら区切り文字が「;」で終了。
ふたつめ「Excel2003 / Macintosh」。やっぱり区切り文字が「;」で終了。
みっつめ「Excel2008 / Macintosh」。区切り文字が初めて「,」に進展!
さらに囲み文字も「"」で、エスケープも「"」。
ここまで来てやっとまともな結果が得られた。
まぁ改行文字が「CRLF」ではなくて「LF」なので完璧とは言えないんだけど、問題としては軽度なのでスルーできる。
Windowsで使うのに「(今はなき)Macintosh」を選択しなければならないという不条理を我慢できるならこれを使うべきだろう。

PHPであることの利点

phpMyAdminはソースがPHPであり、ファイルを覗けばここら辺の原因はわかるし、
直接編集してしまえば理想の形にしあげることはできる。
具体的には以下のファイルの記述されているのでPHPが読めるならソースを見てもらえばわかると思う。
/phpMyAdmin/libraries/export/csv.php
(「MS Excel 用の CSV」もこのファイルを使っている。 )

だが、リビジョンアップの多いアプリでのソースの書き換えはあまり得策とはいえない。
そしてphpMyAdminはリビジョンアップが少ない製品ではない。未だに。


結論

phpMyAdminにおいてRFC4180の仕様に従ってCSVエクスポートをしたいなら、以下3つから選択する。
  1. 上記ファイルのソースを書き換える。
  2. 「MS Excel 用の CSV」-「Excel2008 / Macintosh」でエクスポートする。
  3. バグ報告をして改修を待つ。もしくは自ら開発に参画する。

まぁそもそも実際CSVの規格なんて製品ごとに違ってるのは理解してるつもり。
でもCSVでエクスポートする場合は少なくともMySQL以外で触るために出すんだから、
そこは標準規格にあわせるべきなんじゃないのか。で、標準規格っていったらRFC4180しかないんだし。


蛇足 - その1

MySQLのファイル書き出し(SELECT ~ INTO OUTFILE ~)でエクスポートした場合、
指定しない限りカラムの区切りはタブ記号になり、タブ記号をエスケープするのは「\」である。
これはもともと「CSVエクスポート」とは名乗っていないので別にかまわない。

蛇足 - その2

「CSV」が「Character-Separated Values」だと開きなおるなら、区切りが「;」なのはしょうがない。


検証環境

  • Windows Server 2003 / Windows 7
  • MySQL 5.1 / 5.5
  • Apache 2.2
  • PHP 5.2
  • phpMyAdmin 3.4.0 / 3.4.1
  • IE6 / Chrome11

2 件のコメント:

  1. はじめまして。
    完全な素人ですが、少しづつ貴方のサイトで勉強させて頂いています。
    エクセルで作成したデータをCSVに変換してphpMyAdminにインポートする事は出来たのですが、
    再度エクセルで作成したデータを編集したものをインポートするとエラーが出てしまいます。
    上書きでインポートする事は不可能なのでしょうか?
    身近に質問できる方がいなくて.....
    申し訳ありませんが、ご教示頂けると幸いです

    返信削除
    返信
    1. こんにちは。
      色々な原因が想像できますが、コメント頂いた内容だけでは特定できないゆえ、表示されるエラーメッセージを教えていただけますか?

      削除