使用SELECT INTO OUTFILE时是否包含标题?


Answers:


166

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

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT ColName1, ColName2, ColName3
    FROM YourTable
    INTO OUTFILE '/path/outfile'

14
但是,如果ORDER BYSELECT子句中有in ,它将无法正常工作。标题行可以在生成文件中的任意位置,具体取决于顺序。
线圈2014年

请参阅下面的一些答案,以获取有关使用ORDER BY的想法以及matt的答案,以快速获取所有ColName1,ColName2等的方法。这个很好的答案非常有用!
Andrew T

1
这个答案似乎是正确的,该死,我什至在我的开发服务器上几乎盲目地使用了它……没有列标题,转储2.4亿行大约需要50秒。有了这个UNION ALL,服务器在尝试转储所有内容之前尝试创建临时表时遇到了大麻烦,现在已经超过10分钟了,仍然在等待将临时表写入磁盘!注意这一点!您当然希望以另一种方式添加列名,即使这意味着使用另一种编程语言来打开文件。
Salketer '16

仅当YourTable的所有列都是字符数据类型时,这才起作用。否则,您将得到无用的错误:“使用的SELECT语句具有不同的列数”。
TheBamf '16

1
这就是我考虑切换到另一个DBMS的原因之一。
e18r

85

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的方法中的第一条语句。


2
这将返回在单个字段中串联在一起的所有列。我无法与另一个返回多个字段的select语句合并。不过,这对于获得可以复制并粘贴为外文件头的行非常有用。
tmoore82 2014年

1
这个想法是复制结果单个字段并将其粘贴到您的UNION语句中,而不是在使用Joe的方法(可接受的答案)时手动键入column1,column2等,这样您可以更快地获得列列表!
Andrew T

我想导出所有表/字段架构。这个答案与被接受的答案相辅相成!
雷米·布列塔尼

@Chris ORDER BY ORDINAL_POSITION处理了这个问题
马特

1
ORDER BY ORDINAL_POSITION应该是GROUP_CONCAT()调用的一部分,例如GROUP_CONCAT(CONCAT('"',COLUMN_NAME,'"') order BY ORDINAL_POSITION)
Apuleius,

15

对于使用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';

订购第二个(复杂)查询时,此解决方案效果很好。如果您不这样做,那么最终也将订购第一列,这是不可取的。不错的建议@evilguc!
亚伦

不能与我一起工作,在执行UNION ALL后,id列的顺序被弄乱了
Mohanad Kaleia,

6

您可以将准备好的语句与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;

谢谢lucek。


6

这将使您能够订购列和/或限制

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT * from (SELECT ColName1, ColName2, ColName3
    FROM YourTable order by ColName1 limit 3) a
    INTO OUTFILE '/path/outfile';

1
请注意,此查询布局在MariaDB 10.1中也适用于我;该线程建议的其他布局则没有。
ProgrammerDan

出于某种原因,将标题弹出到底部,但可以正常工作以将其重新弹出到电子表格应用程序的顶部,这很奇怪但很高兴
Dmitri DB

我也坚持使用mariaDB。仅提取100个线索,这比运行接受的答案快了14秒。首次通过并被接受:Query OK, 100 rows affected (14.72 sec) 与您的第二次通过Query OK, 101 rows affected (0.00 sec)
卡斯珀·威尔克斯

6

我只简单地进行2个查询,首先获取具有列名的查询输出(限制1)(无硬编码,Join,Order by,自定义列名等无问题),其次生成查询本身,然后将文件合并为一个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

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中的promises进行控制。


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来重新创建表,则需要删除该列。


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太大,这可能会很慢。


它具有“使用的SELECT语句具有不同的列数”错误。爵士
刘博伟

1

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

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

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


1
UNION ALL将更安全,更快。
toxalot 2013年

1

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

只是需要一些按顺序排序的技巧-我们使用case语句并将标头值替换为可以保证在列表中排在第一位的其他值(显然,这取决于字段的类型以及是否要对ASC或DESC)

假设您有三个字段,名称(varchar),is_active(布尔),date_something_happens(日期),并且要对后两个降序进行排序:

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

1

由于“ include-headers”功能似乎尚未内置,并且此处的大多数“解决方案”都需要手动输入列名称,并且/或者甚至不考虑联接,因​​此我建议解决问题

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

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

    请注意,在Linux和Windows上,将输出重定向到文件的操作都像一个超级按钮。


这使我想强调一下,在80%的时间里,当我想使用SELECT FROM INFILE或SELECT INTO OUTFILE时,我最终都会使用其他东西由于某些限制(在此情况下,由于缺少“标题选项”, AWS-RDS,缺少的权利,等等。)

因此,我无法完全回答操作者的问题 ...但是它应该满足他的需求 :)
编辑:并实际回答他的问题:
截至2017-09-07,如果您不能包含标题,坚持使用SELECT INTO OUTFILE命令
:|


1

来自数据库表名称传感器的一个带有列(id,time,unit)的示例

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

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);

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;

1
我应该说一个很好的解决方案。为我的目的采用了它。谢谢!
丹尼斯·库拉金

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)

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


0

仅MySQL并不能简单地做到这一点。下面是一个PHP脚本,它将列和数据输出到CSV。

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

<?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"'

最后,有一个exec调用来对CSV进行GZip。


-1
选择'ColName1','ColName2','ColName3'
全联盟
SELECT ColName1,ColName2,ColName3
    从YourTable
    进入输出'c:\\ datasheet.csv'字段以','结尾,可选地以'“'结尾,以'\ n'结尾 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.