MySQL экспорт в выходной файл: CSV экранирование символов - PullRequest
42 голосов
/ 13 июля 2009

У меня есть таблица расписаний с некоторыми общими полями.

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 ....

Но ...

Когда я пытаюсь посмотреть на источник выходного файла, в нем все еще существуют новые строки, поэтому импорт CSV для Excel разбивает все модные макросы и сводные таблицы, созданные мастером Excel.

Есть мысли о том, как лучше поступить?

Ответы [ 5 ]

71 голосов
/ 29 июля 2009

Я думаю, что ваше заявление должно выглядеть так:

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)

Дайте нам знать, как вы поживаете.

15 голосов
/ 18 мая 2010

Вот что сработало здесь: Имитирует 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 будет считать начало следующей строки.
2 голосов
/ 15 июля 2009

На самом деле, не видя ваш выходной файл для подтверждения, я предполагаю, что вам нужно избавиться от значения FIELDS ESCAPED BY.

MySQL FIELDS ESCAPED BY, вероятно, ведет себя двумя способами, на которые вы не рассчитывали: (1) это только один символ, поэтому в вашем случае он, вероятно, равен только одной кавычке; (2) он используется перед каждым символом, который, по мнению MySQL, требует экранирования, включая значения FIELDS TERMINATED BY и LINES TERMINATED BY. Это имеет смысл для большей части компьютерного мира, но это не тот способ, которым Excel удается избежать.

Я думаю, что ваш двойной REPLACE работает, и вы успешно заменяете буквальные символы новой строки пробелами (два пробела в случае символов новой строки в стиле Windows). Но если у вас есть какие-либо запятые в ваших данных (литералы, а не разделители полей), им предшествуют кавычки, которые Excel обрабатывает по-разному, чем MySQL. Если это так, то ошибочные символы новой строки, запускающие Excel, на самом деле являются символами новой строки, которые MySQL намеревался использовать в качестве ограничителей строки.

2 голосов
/ 14 июля 2009

Что произойдет, если вы попробуете следующее?

Вместо вашего двойного REPLACE выражения, попробуйте:

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

Кроме того, я думаю, что это должно быть LINES TERMINATED BY '\r\n' вместо '\n'

0 голосов
/ 29 июля 2009

Возможно, это не поможет, но вы можете попробовать создать таблицу 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 ....
...