web-dev-qa-db-ja.com

MySQLをoutfileにエクスポート:CSVエスケープ文字

いくつかの一般的なフィールドを持つタイムシートのデータベーステーブルがあります。

id, client_id, project_id, task_id, description, time, date 

もっとありますが、それはその要点です。

そのテーブルでCSVファイルへのエクスポートを一晩実行して、ユーザーにデータのバックアップを提供しています。また、いくつかのカスタムレポートを含むマクロExcelファイルのデータインポートとしても使用されます。

これはすべて、phpを使用してタイムシートをループ処理し、行をファイルに出力することで機能します。

問題は大きなデータベースであり、実行に数時間かかる可能性があり、これは受け入れられません。そこで、MySQL INTO OUTFILEコマンドを実行すると、実行時間が数秒に短縮されました。

ここでの問題は、説明フィールドですべての改行文字などをエスケープできないように見えることです。実際、ユーザーは、ここに改行や改行を含む文字の任意の組み合わせを入力できます。

これは、私が持っているMySQLコードのスニペットです。

SELECT id, 
       client,
       project,
       task,
       REPLACE(REPLACE(ifnull(ts.description,''),'\n',' '),'\r',' ') AS description, 
       time,
       date  
      INTO OUTFILE '/path/to/file.csv'
      FIELDS ESCAPED BY '""'
      TERMINATED BY ',' ENCLOSED BY '"'
      LINES TERMINATED BY '\n'
      FROM ....

しかし...

出力ファイルのソースを見ると、ファイル内に改行が残っているため、ExcelのCSVインポートにより、Excelウィザードが作成したすべての派手なマクロとピボットテーブルが破損します。

最善の行動方針についての考えはありますか?

43
Derek Organ

あなたの声明は次のようになるはずだと思います

SELECT id, 
   client,
   project,
   task,
   description, 
   time,
   date  
  INTO OUTFILE '/path/to/file.csv'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM ts

主にFIELDS ESCAPED BY '""'オプションなしで、OPTIONALLY ENCLOSED BY '"'は説明フィールドなどのトリックを行い、数値はExcelで数値として扱われます(数値で構成される文字列ではありません)

また、呼び出してみてください:

SET NAMES utf8;

出力ファイルを選択する前に、文字エンコーディングをインラインにするのに役立つ場合があります(すべてUTF8)

乗車方法をお知らせください。

76
Question Mark

ここで働いたものは次のとおりです。Excel 2003をシミュレートします(CSV形式で保存)

SELECT 
REPLACE( IFNULL(notes, ''), '\r\n' , '\n' )   AS notes
FROM sometables
INTO OUTFILE '/tmp/test.csv' 
FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '"'
LINES TERMINATED BY '\r\n';
  1. Excelでは、行区切り記号として\ r\nが保存されます。
  2. Excelは、列データ内の改行文字に対して\ nを保存します
  3. 最初にデータ内の\ r\nを置換する必要があります。そうしないと、Excelは次の行の始まりと見なします。
15
Felix Z

確認のために出力ファイルを実際に見ることなく、私の推測では、FIELDS ESCAPED BY値を削除する必要があります。

MySQLのFIELDS ESCAPED BYはおそらく、期待していない2つの方法で動作しています。(1)それは1文字のみであるため、おそらく1つの引用符に等しいでしょう。 (2)FIELDS TERMINATED BYおよびLINES TERMINATED BYの値を含む、MySQLがエスケープする必要があると考えるeach文字の前に使用されます。これはほとんどのコンピューティングの世界にとって理にかなっていますが、Excelが逃げる方法ではありません。

ダブルREPLACEは機能しており、リテラルの改行をスペース(Windowsスタイルの改行の場合は2つのスペース)に正常に置き換えていると思います。ただし、データにコンマ(フィールドセパレーターではなくリテラル)がある場合、これらの前に引用符が付けられます。Excelでは、MySQLとはかなり異なる方法で処理されます。その場合、Excelをトリップしている誤った改行は、実際にはMySQLが行末記号として意図した改行です。

2
John Y

以下を試したらどうなりますか?

ダブルREPLACEステートメントの代わりに、次を試してください。

REPLACE(IFNULL(ts.description, ''),'\r\n', '\n')

また、LINES TERMINATED BY '\r\n'だけでなく'\n'であるべきだと思います

2
devuxer

おそらく助けにはなりませんが、そのコンテンツでCSVテーブルを作成してみてください:

DROP TABLE IF EXISTS foo_export;
CREATE TABLE foo_export LIKE foo;
ALTER TABLE foo_export ENGINE=CSV;
INSERT INTO foo_export SELECT id, 
   client,
   project,
   task,
   REPLACE(REPLACE(ifnull(ts.description,''),'\n',' '),'\r',' ') AS description, 
   time,
   date
  FROM ....
0
Jorge Bernal