Экспорт MySQL в outfile: CSV экранирующие символы

у меня есть таблица базы данных расписаний с некоторыми общими feilds.

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

есть еще, но в этом суть.

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

все это работает со мной, циклически просматривая расписания с помощью php и печатая строки в файл.

проблема с большая база данных может занять несколько часов, что неприемлемо. Поэтому я переписал его с MySQL INTO OUTFILE команда, и она уменьшила ее до нескольких секунд, чтобы запустить, что было здорово.

проблема в том, что я не могу избежать всех новых символов строки и т. д. в поле Описание. Действительно, пользователь может ввести потенциально любую комбинацию символов здесь, включая возврат каретки / новые строки.

Это фрагмент кода MySQL I есть:

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 ответов


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

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

в основном без , OPTIONALLY ENCLOSED BY '"' будет делать трюк для полей описания и т. д., И ваши номера будут рассматриваться как числа в Excel (а не строки, состоящие из цифр)

также попробуйте позвонить:

SET NAMES utf8;

перед выбором outfile это может помочь получить встроенные кодировки символов (все UTF8)

дайте нам знать, как вы получите на.


вот что получилось : Имитирует 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 подумает, что это начало следующей строки.

фактически не видя ваш выходной файл для подтверждения, я предполагаю, что вы должны избавиться от полей, экранированных по значению.

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

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


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

вместо вашего double REPLACE заявление, попробуйте:

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

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


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