49

我有一个包含一些常见字段的时间表数据库表。

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

还有更多,但这就是它的要点。

我有一夜之间在该表上运行导出到 CSV 文件,以便为用户提供其数据的备份。它还用作带有一些自定义报告的宏 Excel 文件的数据导入。

这一切都适用于我使用 php 循环浏览时间表并将这些行打印到文件中。

问题在于大型数据库可能需要数小时才能运行,这是不可接受的。所以我用 MySQLINTO 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 向导创建的所有花哨的宏和数据透视表。

关于最佳行动方案的任何想法?

4

6 回答 6

82

我认为您的陈述应如下所示:

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)

让我们知道您的身体情况如何。

于 2009-07-28T22:06:40.013 回答
18

这是这里的工作:模拟 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 会认为它是下一行的开始。
于 2010-05-18T16:12:50.067 回答
2

如果您尝试以下操作会发生什么?

而不是你的双重REPLACE声明,尝试:

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

另外,我认为它应该LINES TERMINATED BY '\r\n'不仅仅是'\n'

于 2009-07-14T06:22:59.053 回答
2

在没有实际看到您的输出文件进行确认的情况下,我的猜测是您必须摆脱该FIELDS ESCAPED BY值。

MySQL 的FIELDS ESCAPED BY行为可能有两种你不指望的方式:(1)它只是一个字符,所以在你的情况下它可能只等于一个引号;(2) 它用于在MySQL 认为需要转义的每个FIELDS TERMINATED BY字符之前,包括andLINES TERMINATED BY值。这对大多数计算世界来说都是有意义的,但这不是 Excel 转义的方式。

我认为您的替身REPLACE正在工作,并且您成功地用空格替换了文字换行符(在 Windows 样式换行符的情况下为两个空格)。但是,如果您的数据中有任何逗号(文字,而不是字段分隔符),则这些逗号前面都带有引号,Excel 对它的处理与 MySQL 大不相同。如果是这种情况,那么导致 Excel 出错的错误换行符实际上是 MySQL 打算作为行终止符的换行符。

于 2009-07-15T03:25:27.410 回答
0

可能无济于事,但您可以尝试使用该内容创建一个 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 ....
于 2009-07-29T14:45:47.080 回答
0

下面的过程为我解决了所有转义问题,并使该过程更具通用性。

CREATE PROCEDURE `export_table`(
IN tab_name varchar(50), 
IN select_columns varchar(1000),
IN filename varchar(100),
IN where_clause varchar(1000),
IN header_row varchar(2000))

BEGIN
INSERT INTO impl_log_activities(TABLE_NAME, LOG_MESSAGE,CREATED_TS) values(tab_name, where_clause,sysdate());
COMMIT;
SELECT CONCAT( "SELECT ", header_row,
    " UNION ALL ",
    "SELECT ", select_columns, 
    " INTO OUTFILE ", "'",filename,"'"
    " FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY '""' ",
    " LINES TERMINATED BY '\n'"
    " FROM ", tab_name, " ",
    (case when where_clause is null then "" else where_clause end)
) INTO @SQL_QUERY;

INSERT INTO impl_log_activities(TABLE_NAME, LOG_MESSAGE,CREATED_TS) values(tab_name, @SQL_QUERY, sysdate());
COMMIT;

PREPARE stmt FROM @SQL_QUERY;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

结尾

于 2020-07-02T11:06:19.207 回答