MySQL には CSV 出力する機能が備わっていることに、初めて気がつきました。
喜び勇んで試してみたものの、Excel ではどうにもうまく読み込めません。特に、セル内で改行があると、次の行という扱いになってしまうのですよね。。。
そこで、何とかしてみたメモを残しておきます。
ポイント
- 今時なので MySQL は UTF-8 です。Excel で読むために Shift-JIS に変更する必要があります。
- セル内での改行は LF、行末の改行は CRLF にする必要があります。
- セルを「”」で囲む場合があるため、「”」をエスケープする必要があります。
やってみた
まずは CSV 出力する MySQL です。2種類の方法がありますが、今回は SELECT を使う方法です。
mysql> SELECT * FROM wp_posts INTO OUTFILE "/tmp/wp_posts.csv" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY "\r\n"; Query OK, 784 rows affected (0.06 sec)
続いて、上のポイントを解決していきます。
# \\ → \ sed -i -e 's|\\\\|\\|g' /tmp/wp_posts.csv # \" → "" sed -i -e 's|\\"|""|g' /tmp/wp_posts.csv # \CRLF → LF ^Mはこのままコピペしても意味ないです。「^M」は「Ctrl」+「V」→「Ctrl」+「M」と続けて入力します。 sed -i -e 's|\\^M||g' /tmp/wp_posts.csv # Shift-JIS に変換 nkf -s --overwrite /tmp/wp_posts.csv
実は回りくどいことをしています。が、最重要ポイントを書きます。
SELECT のときに指定しなかった、「ESCAPED BY」というオプションが鍵です。
このオプションで、エスケープ文字を指定できるのですが、ポイントに書いた「”」をわざと指定せず、デフォルトの「\」としました。
エスケープ文字として「”」を指定しなかった理由はセル内の改行を発見するためです。
「”」のままだと、セル内改行時は「”CRLF」、行末時は「”CRLF」と同じとなってしまうため見分けがつかないのです。そこで、あえて「\」を指定することでセル内改行時と行末時の見分けをつけています。
ただ、完全ではありません。行末が「\CRLF」となる可能性もありますよね。この場合、、、どうしたらよいでしょうか?わかりません。
テーブルに入るデータの最後のカラムが最終更新日時で NOT NULL だから行末が「\CRLF」となることはありえない、などのテーブルでしたら気にしなくてもよいのですけれども。
sed コマンドの解説です。
エスケープ文字を「\」としましたのでデータ中の \ は \\ に、” は \” にエスケープされています。これを、\\ は \ に、\” は “” に変換しているのが1つ目と2つ目の sed コマンドです。
sed を用いたファイル内の置換で、わたくしが調べながら躓いたのが次の3点です。
- たとえば ‘s|\\\\|\\|g’ の「g」をつけないと各行で最初に一致した箇所しか置換されません。つまり、最初の「\\」しか変換されません。
- 「\」はエスケープする必要があります。「\\」とします。
- 改行文字の CR は「^M」と表現されますが、指定するには「^」と「M」を打ち込んではだめです。「^M」はキーボードの「Ctrl」+「V」→「Ctrl」+「M」と続けて入力します。
あと、最後の sed コマンドを少しだけ補足しておくと、「\CRLF」→「LF」は引き算です。「\CR」をを抜けば、改行文字の残った部分「LF」がUnix の改行として働いてくれます。
課題
わたくしの今回の方法ですと、わかっているだけで2点問題があります。
- 行末が「\CRLF」となった場合、次の行が行末のセルの続きとみなされてしまう。
- MySQL でNULL のデータが \N と表現されてしまう。
2点目は、「ESCAPED BY」オプションを何も指定しないようにすれば回避できますが、エスケープができなくなる問題が発生します。
うーん、わかりません。
おわりに
参考にさせていただいたページです。大変ありがとうございます♪
- MySQL mysqldump+αでExcelで読めるCSV出力 – 130単位
今回の投稿の骨子を支えてくださったページです。ありがとうございます。 - MySQL :: MySQL 5.1 リファレンスマニュアル :: 12.2.5 LOAD DATA INFILE 構文
長くて全部読みたくないのですけれども、本家ドキュメントならではの安心感。おろそかにはできません。。。 - 改行コードの変換方法: 仕事を早く片付けて遊ぶための技術メモ
「^M」について実践的に書いてあり、参考になりました。ありがうございます。 - メモ 【Linux】改行コードの変換
sed コマンドの中で「^M」を使う実例が載っており、参考&勇気付けられました。ありがとうございます。