132

使用 MySQL 时是否可以以某种方式包含标头INTO OUTFILE

4

21 回答 21

182

您必须自己对这些标头进行硬编码。就像是:

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT ColName1, ColName2, ColName3
    FROM YourTable
    INTO OUTFILE '/path/outfile'
于 2011-05-09T20:05:44.157 回答
90

Joe Steanelli 提供的解决方案是可行的,但是当涉及数十或数百个列时,列出列是不方便的。这是在my_schema中获取表my_table的列列表的方法。

-- override GROUP_CONCAT limit of 1024 characters to avoid a truncated result
set session group_concat_max_len = 1000000;

select GROUP_CONCAT(CONCAT("'",COLUMN_NAME,"'"))
from INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'my_table'
AND TABLE_SCHEMA = 'my_schema'
order BY ORDINAL_POSITION

现在您可以将结果行复制并粘贴为 Joe 方法中的第一条语句。

于 2012-11-28T11:13:08.790 回答
16

对于使用 ORDER BY 的复杂选择,我使用以下命令:

SELECT * FROM (
    SELECT 'Column name #1', 'Column name #2', 'Column name ##'
    UNION ALL
    (
        // complex SELECT statement with WHERE, ORDER BY, GROUP BY etc.
    )
) resulting_set
INTO OUTFILE '/path/to/file';
于 2014-08-08T14:25:13.253 回答
11

这将使您拥有有序的列和/或限制

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT * from (SELECT ColName1, ColName2, ColName3
    FROM YourTable order by ColName1 limit 3) a
    INTO OUTFILE '/path/outfile';
于 2016-09-01T17:58:43.253 回答
8

您可以将准备好的语句与 lucek 的答案一起使用,并使用 CSV 中的列名动态导出表:

--If your table has too many columns
SET GLOBAL group_concat_max_len = 100000000;
--Prepared statement
SET @SQL = ( select CONCAT('SELECT * INTO OUTFILE \'YOUR_PATH\' FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\' ESCAPED BY \'\' LINES TERMINATED BY \'\\n\' FROM (SELECT ', GROUP_CONCAT(CONCAT("'",COLUMN_NAME,"'")),' UNION select * from YOUR_TABLE) as tmp') from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'YOUR_TABLE' AND TABLE_SCHEMA = 'YOUR_SCHEMA' order BY ORDINAL_POSITION );
--Execute it
PREPARE stmt FROM @SQL;
EXECUTE stmt;

谢谢卢克。

于 2013-10-03T10:03:06.157 回答
7

我只需进行 2 个查询,首先获取带有列名的查询输出(限制 1)(无硬编码,连接没有问题,排序方式,自定义列名等),其次进行查询本身,并将文件组合成一个 CSV文件:

CSVHEAD=`/usr/bin/mysql $CONNECTION_STRING -e "$QUERY limit 1;"|head -n1|xargs|sed -e "s/ /'\;'/g"`
echo "\'$CSVHEAD\'" > $TMP/head.txt
/usr/bin/mysql $CONNECTION_STRING -e "$QUERY into outfile '${TMP}/data.txt' fields terminated by ';' optionally enclosed by '\"' escaped by '' lines terminated by '\r\n';"
cat $TMP/head.txt $TMP/data.txt > $TMP/data.csv
于 2017-03-23T12:07:39.697 回答
5

在 NodeJS 中对大表执行 mysql 查询时,我遇到了类似的问题。我在我的 CSV 文件中包含标题的方法如下

  1. 使用 OUTFILE 查询准备没有标题的文件

        SELECT * INTO OUTFILE [FILE_NAME] FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED 
        BY '\"' LINES TERMINATED BY '\n' FROM [TABLE_NAME]
    
  2. 获取第 1 点中使用的表的列标题

        select GROUP_CONCAT(CONCAT(\"\",COLUMN_NAME,\"\")) as col_names from 
        INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = [TABLE_NAME] AND TABLE_SCHEMA 
        = [DATABASE_NAME] ORDER BY ORDINAL_POSITION
    
  3. 使用prepend-file npm 包将列标题附加到在步骤 1 中创建的文件

使用 NodeJS 中的 Promise 控制每个步骤的执行。

于 2018-09-04T06:51:45.057 回答
3

如果您熟悉 Python 或 R,这是另一种作弊方法,并且您的表可以放入内存。

将 SQL 表导入 Python 或 R,然后从那里导出为 CSV,您将获得列名和数据。

这是我使用 R 的方法,需要 RMySQL 库:

db <- dbConnect(MySQL(), user='user', password='password', dbname='myschema', host='localhost')

query <- dbSendQuery(db, "select * from mytable")
dataset <- fetch(query, n=-1)

write.csv(dataset, 'mytable_backup.csv')

这有点作弊,但是当我的列数太长而无法使用上面的 concat 方法时,我发现这是一个快速的解决方法。注意:R 将在 CSV 的开头添加一个“row.names”列,因此如果您确实需要依赖 CSV 来重新创建表,则需要删除它。

于 2015-07-25T11:51:25.280 回答
2

我认为如果您使用 UNION 它将起作用:

select 'header 1', 'header 2', ...
union
select col1, col2, ... from ...

我不知道直接使用 INTO OUTFILE 语法指定标头的方法。

于 2011-05-09T20:07:13.330 回答
2

因此,如果其中的所有列my_table都是字符数据类型,我们可以将最佳答案(由 Joe、matt 和 evilguc)组合在一起,以在一个“简单”SQL 查询中自动添加标题,例如

select * from (
  (select column_name
    from information_schema.columns
    where table_name = 'my_table'
    and table_schema = 'my_schema'
    order by ordinal_position)
  union all
  (select *  // potentially complex SELECT statement with WHERE, ORDER BY, GROUP BY etc.
  from my_table)) as tbl
into outfile '/path/outfile'
fields terminated by ',' optionally enclosed by '"' escaped by '\\'
lines terminated by '\n';

最后几行输出csv。

请注意,如果my_table非常大,这可能会很慢。

于 2016-07-08T10:58:06.697 回答
2

由于“包含标题”功能似乎还没有内置,并且这里的大多数“解决方案”需要手动输入列名,和/或甚至不考虑连接,我建议解决问题

  • 到目前为止,我发现的最好的选择是使用一个不错的工具(我使用HeidiSQL)。
    提出您的要求,选择网格,只需右键单击并导出到文件。它为干净的导出提供了所有必要的选项,应该可以满足大多数需求。

  • 同样的想法,user3037511 的方法运行良好,并且可以轻松实现自动化
    只需使用一些命令行启动您的请求即可获取您的标头。您可以使用 SELECT INTO OUTFILE... 或通过无限制地运行查询来获取数据,您可以选择。

    请注意,输出重定向到文件在 Linux 和 Windows 上都非常有用。


这让我想强调80% 的时间,当我想使用 SELECT FROM INFILE 或 SELECT INTO OUTFILE 时,由于某些限制,我最终使用了其他东西(这里,没有“标题选项”,在AWS-RDS、缺失的权限等。)

因此,我不完全回答操作员的问题......但它应该回答他的需求:)
编辑:并实际回答他的问题:
截至 2017 年 9 月 7 日,如果你不能包含标题坚持使用 SELECT INTO OUTFILE 命令
:|

于 2017-09-07T09:58:40.023 回答
1

实际上,即使使用 ORDER BY,您也可以使其工作。

只需要在 order by 语句中使用一些技巧 - 我们使用 case 语句并将标题值替换为保证在列表中首先排序的其他值(显然这取决于字段的类型以及您是在排序 ASC 还是DESC)

假设您有三个字段,name (varchar)、is_active (bool)、date_something_happens (date),并且您想对后两个降序排序:

select 
        'name'
      , 'is_active' as is_active
      , date_something_happens as 'date_something_happens'

 union all

 select name, is_active, date_something_happens

 from
    my_table

 order by
     (case is_active when 'is_active' then 0 else is_active end) desc
   , (case date when 'date' then '9999-12-30' else date end) desc
于 2014-07-30T14:52:23.080 回答
1

我的数据库表名传感器中的一个示例,带有列(id、时间、单位)

select ('id') as id, ('time') as time, ('unit') as unit
UNION ALL
SELECT * INTO OUTFILE 'C:/Users/User/Downloads/data.csv'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM sensor
于 2018-09-05T06:21:47.803 回答
1

最简单的方法是自己对列进行硬编码以更好地控制输出文件:

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT ColName1, ColName2, ColName3
    FROM YourTable
    INTO OUTFILE '/path/outfile'
于 2021-01-01T10:12:20.550 回答
1

如果您使用的是 MySQL Workbench:

  1. 从 SCHEMAS 选项卡中选择所有列 -> 右键单击​​ -> 复制到剪贴板 -> 名称

  2. 将其粘贴到任何文本编辑器中,然后将“`”替换为“'”

  3. 将其复制回来并在您的 UNION 查询中使用它(如接受的答案中所述):

    SELECT [Paste your text here]
    UNION ALL
    SELECT *
    FROM table_name
    INTO OUTFILE 'file_path'
    
于 2021-08-27T23:39:38.170 回答
0

这是一种从列名动态获取标题标题的方法。

/* Change table_name and database_name */
SET @table_name = 'table_name';
SET @table_schema = 'database_name';
SET @default_group_concat_max_len = (SELECT @@group_concat_max_len);

/* Sets Group Concat Max Limit larger for tables with a lot of columns */
SET SESSION group_concat_max_len = 1000000;

SET @col_names = (
  SELECT GROUP_CONCAT(QUOTE(`column_name`)) AS columns
  FROM information_schema.columns
  WHERE table_schema = @table_schema
  AND table_name = @table_name);

SET @cols = CONCAT('(SELECT ', @col_names, ')');

SET @query = CONCAT('(SELECT * FROM ', @table_schema, '.', @table_name,
  ' INTO OUTFILE \'/tmp/your_csv_file.csv\'
  FIELDS ENCLOSED BY \'\\\'\' TERMINATED BY \'\t\' ESCAPED BY \'\'
  LINES TERMINATED BY \'\n\')');

/* Concatenates column names to query */
SET @sql = CONCAT(@cols, ' UNION ALL ', @query);

/* Resets Group Contact Max Limit back to original value */
SET SESSION group_concat_max_len = @default_group_concat_max_len;

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
于 2015-11-02T20:28:10.157 回答
0

我正在用 PHP 编写代码,但在使用 concat 和 union 函数时遇到了一些麻烦,而且也没有使用 SQL 变量,无论如何我让它工作,这是我的代码:

//first I connected to the information_scheme DB

$headercon=mysqli_connect("localhost", "USERNAME", "PASSWORD", "information_schema");

//took the healders out in a string (I could not get the concat function to work, so I wrote a loop for it)

    $headers = '';
    $sql = "SELECT column_name AS columns FROM `COLUMNS` WHERE table_schema = 'YOUR_DB_NAME' AND table_name = 'YOUR_TABLE_NAME'";
    $result = $headercon->query($sql);
    while($row = $result->fetch_row())
    {
        $headers = $headers . "'" . $row[0] . "', ";
    }
$headers = substr("$headers", 0, -2);

// connect to the DB of interest

$con=mysqli_connect("localhost", "USERNAME", "PASSWORD", "YOUR_DB_NAME");

// export the results to csv
$sql4 = "SELECT $headers UNION SELECT * FROM YOUR_TABLE_NAME WHERE ... INTO OUTFILE '/output.csv' FIELDS TERMINATED BY ','";
$result4 = $con->query($sql4);
于 2015-12-12T11:53:53.030 回答
0

我想补充 Sangam Belose 提供的答案。这是他的代码:

select ('id') as id, ('time') as time, ('unit') as unit
UNION ALL
SELECT * INTO OUTFILE 'C:/Users/User/Downloads/data.csv'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM sensor

但是,如果你没有设置你"secure_file_priv"的变量,它可能不起作用。为此,请通过以下方式检查在该变量上设置的文件夹:

SHOW VARIABLES LIKE "secure_file_priv"

输出应如下所示:

mysql> show variables like "%secure_file_priv%";
+------------------+------------------------------------------------+
| Variable_name    | Value                                          |
+------------------+------------------------------------------------+
| secure_file_priv | C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\ |
+------------------+------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

您可以更改此变量或更改查询以将文件输出到默认路径显示。

于 2018-11-16T08:54:34.670 回答
0

仅 MySQL 不足以简单地做到这一点。下面是将列和数据输出到 CSV 的 PHP 脚本。

在顶部附近输入您的数据库名称和表格。

<?php

set_time_limit( 24192000 );
ini_set( 'memory_limit', '-1' );
setlocale( LC_CTYPE, 'en_US.UTF-8' );
mb_regex_encoding( 'UTF-8' );

$dbn = 'DB_NAME';
$tbls = array(
'TABLE1',
'TABLE2',
'TABLE3'
);

$db = new PDO( 'mysql:host=localhost;dbname=' . $dbn . ';charset=UTF8', 'root', 'pass' );

foreach( $tbls as $tbl )
{
    echo $tbl . "\n";
    $path = '/var/lib/mysql/' . $tbl . '.csv';

    $colStr = '';
    $cols = $db->query( 'SELECT COLUMN_NAME AS `column` FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = "' . $tbl . '" AND TABLE_SCHEMA = "' . $dbn . '"' )->fetchAll( PDO::FETCH_COLUMN );
    foreach( $cols as $col )
    {
        if( $colStr ) $colStr .= ', ';
        $colStr .= '"' . $col . '"';
    }

    $db->query(
    'SELECT *
    FROM
    (
        SELECT ' . $colStr . '
        UNION ALL
        SELECT * FROM ' . $tbl . '
    ) AS sub
    INTO OUTFILE "' . $path . '"
    FIELDS TERMINATED BY ","
    ENCLOSED BY "\""
    LINES TERMINATED BY "\n"'
    );

    exec( 'gzip ' . $path );

    print_r( $db->errorInfo() );
}

?>

您需要将其作为要输出到的目录。MySQL 需要具有写入目录的能力。

$path = '/var/lib/mysql/' . $tbl . '.csv';

您可以在查询中编辑 CSV 导出选项:

INTO OUTFILE "' . $path . '"
FIELDS TERMINATED BY ","
ENCLOSED BY "\""
LINES TERMINATED BY "\n"'

最后有一个对 GZip CSV 的 exec 调用。

于 2019-07-21T12:57:22.060 回答
0

我对这些都没有运气,所以在找到解决方案后,我想将其添加到之前的答案中。Python==3.8.6 MySQL==8.0.19

(请原谅我缺少 SO 格式化 foo。请有人清理。)

注意几件事:

首先,返回列名的查询不能容忍标点符号。在 'schema_name' 和 'table_name' 周围使用 ` 反引号或省略 ' 引号将引发“未知列”错误。

WHERE TABLE_SCHEMA = 'schema' AND TABLE_NAME = 'table'

其次,列标题名称作为单实体元组返回,所有列名称连接在一个带引号的字符串中。转换为引用列表很容易,但并不直观(至少对我而言)。

headers_list = headers_result[0].split(",")

第三,游标必须被缓冲,否则“懒惰”的东西不会在你需要时获取你的结果。对于非常大的表,内存可能是个问题。也许分块可以解决这个问题。

cur = db.cursor(buffered=True)

最后,所有类型的 UNION 尝试都对我产生了错误。通过将整个混乱压缩到一个字典列表中,使用 csv.DictWriter 写入 csv 变得微不足道。

headers_sql = """   
SELECT 
GROUP_CONCAT(CONCAT(COLUMN_NAME) ORDER BY ORDINAL_POSITION)   
FROM INFORMATION_SCHEMA.COLUMNS   
WHERE TABLE_SCHEMA = 'schema' AND TABLE_NAME = 'table';   
"""" 

cur = db.cursor(buffered=True) 
cur.execute(header_sql) 
headers_result = cur.fetchone() 
headers_list = headers_result[0].split(",")

rows_sql = """   SELECT * FROM schema.table;   """" 

data = cur.execute(rows_sql) 
data_rows = cur.fetchall() 
data_as_list_of_dicts = [dict(zip(headers_list, row)) for row in data_rows]

with open(csv_destination_file, 'w', encoding='utf-8') as destination_file_opened: 
    dict_writer = csv.DictWriter(destination_file_opened, fieldnames=headers_list) 
    dict_writer.writeheader()   for dict in dict_list:
        dict_writer.writerow(dict)
于 2020-11-02T00:42:45.520 回答
-1
选择“ColName1”、“ColName2”、“ColName3”
联合所有
选择 ColName1、ColName2、ColName3
    从你的桌子
    INTO OUTFILE 'c:\\datasheet.csv' 由 ',' 终止的字段可选地由 '"' 包围 由 '\n' 终止的行
于 2014-12-09T15:33:24.283 回答