如何以CSV格式输出MySQL查询结果?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何以CSV格式输出MySQL查询结果?相关的知识,希望对你有一定的参考价值。

有没有一种简单的方法可以从Linux命令行运行mysql查询并以CSV 格式输出结果?

这就是我现在正在做的事情:

mysql -u uid -ppwd -D dbname << EOQ | sed -e 's/        /,/g' | tee list.csv
select id, concat(""",name,""") as name
from students
EOQ

当有很多列需​​要用引号括起来,或者结果中有引号需要转义时,它会变得混乱。

答案

来自http://www.tech-recipes.com/rx/1475/save-mysql-query-results-into-a-text-or-csv-file/

SELECT order_id,product_name,qty
FROM orders
WHERE foo = 'bar'
INTO OUTFILE '/var/lib/mysql-files/orders.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '
';

使用此命令将不会导出列名称。

另请注意,/var/lib/mysql-files/orders.csv将位于运行MySQL的服务器上。运行MySQL进程的用户必须具有写入所选目录的权限,否则命令将失败。

如果要从远程服务器(尤其是托管或虚拟机,如Heroku或Amazon RDS)将输出写入本地计算机,则此解决方案不适用。

另一答案

迄今为止,除MySQL工作台之外的所有解决方案都是不正确的,并且对于mysql数据库中的至少一些可能内容而言可能是不安全的(即安全问题)。

MYSQL Workbench(以及类似的phpMyAdmin)提供了一个正式正确的解决方案,但设计用于将输出下载到用户的位置。它们对于自动化数据导出等问题并不那么有用。

无法从mysql -B -e 'SELECT ...'的输出生成可靠正确的csv,因为它无法对字段中的回车符和空格进行编码。 mysql的'-s'标志确实执行反斜杠转义,并可能导致正确的解决方案。但是,使用脚本语言(具有良好的内部数据结构,而不是bash),以及已经仔细制定编码问题的库会更安全。

我想为此写一个脚本,但是当我想到我称之为什么时,我就想到了用同一个名字搜索已有的作品。虽然我没有彻底解决它,但https://github.com/robmiller/mysql2csv的解决方案看起来很有希望。根据您的应用程序,指定SQL命令的yaml方法可能会或可能不会吸引人。我对于更新版本的ruby的要求并不像我的Ubuntu 12.04笔记本电脑或Debian Squeeze服务器那样标准。是的我知道我可以使用RVM,但我不想为了这么简单的目的而维护它。

希望有人会指出一个合适的工具,这需要进行一些测试。否则,当我找到或写一个时,我可能会更新它。

另一答案

从命令行,您可以执行以下操作:

mysql -h *hostname* -P *port number* --database=*database_name* -u *username* -p -e *your SQL query* | sed 's/	/","/g;s/^/"/;s/$/"/;s/
//g' > *output_file_name.csv*

致谢:Exporting table from Amazon RDS into a csv file

另一答案

此页面上的许多答案都很薄弱,因为它们无法处理CSV格式的一般情况。例如字段中嵌入的逗号和引号以及最终总会出现的其他条件。我们需要一个适用于所有有效CSV输入数据的通用解决方案。

这是Python中一个简单而强大的解决方案:

#!/usr/bin/env python

import csv
import sys

tab_in = csv.reader(sys.stdin, dialect=csv.excel_tab)
comma_out = csv.writer(sys.stdout, dialect=csv.excel)

for row in tab_in:
    comma_out.writerow(row)

将文件命名为tab2csv,将其放在路径上,赋予它执行权限,然后像这样使用它:

mysql OTHER_OPTIONS --batch --execute='select * from whatever;' | tab2csv > outfile.csv

Python CSV处理功能涵盖了CSV输入格式的极端情况。

这可以通过流方法来改进以处理非常大的文件。

另一答案
  1. 逻辑:

CREATE TABLE () (SELECT data FROM other_table ) ENGINE=CSV ;

创建CSV表时,服务器会在数据库目录中创建表格式文件。该文件以表名开头,扩展名为.frm。存储引擎还会创建一个数据文件。它的名称以表名开头,并具有.CSV扩展名。数据文件是纯文本文件。将数据存储到表中时,存储引擎会以逗号分隔值格式将其保存到数据文件中。

另一答案

这很简单,它适用于任何不需要批处理模式或输出文件的东西:

select concat_ws(',',
    concat('"', replace(field1, '"', '""'), '"'),
    concat('"', replace(field2, '"', '""'), '"'),
    concat('"', replace(field3, '"', '""'), '"'))

from your_table where etc;

说明:

  1. 在每个字段中用"替换"" - > replace(field1, '"', '""')
  2. 用引号括起每个结果 - > concat('"', result1, '"')
  3. 在每个引用的结果 - > concat_ws(',', quoted1, quoted2, ...)之间放置一个逗号

而已!

另一答案

这个答案使用Python和流行的第三方库PyMySQL。我正在添加它,因为Python的csv库足够强大,可以正确处理.csv的许多不同风格,没有其他答案使用Python代码与数据库交互。

import contextlib
import csv
import datetime
import os

# https://github.com/PyMySQL/PyMySQL
import pymysql

SQL_QUERY = """
SELECT * FROM my_table WHERE my_attribute = 'my_attribute';
"""

# embedding passwords in code gets nasty when you use version control
# the environment is not much better, but this is an example
# https://stackoverflow.com/questions/12461484
SQL_USER = os.environ['SQL_USER']
SQL_PASS = os.environ['SQL_PASS']

connection = pymysql.connect(host='localhost',
                             user=SQL_USER,
                             password=SQL_PASS,
                             db='dbname')

with contextlib.closing(connection):
    with connection.cursor() as cursor:
        cursor.execute(SQL_QUERY)
        # Hope you have enough memory :)
        results = cursor.fetchall()

output_file = 'my_query-{}.csv'.format(datetime.datetime.today().strftime('%Y-%m-%d'))
with open(output_file, 'w', newline='') as csvfile:
    # http://stackoverflow.com/a/17725590/2958070 about lineterminator
    csv_writer = csv.writer(csvfile, lineterminator='
')
    csv_writer.writerows(results)
另一答案

除上述答案外,您还可以拥有一个使用CSV引擎的MySQL表。

然后,您的硬盘上将有一个文件,该文件将始终采用CSV格式,您可以在不进行处理的情况下进行复制。

另一答案

要扩展以前的答案,以下单行将单个表导出为制表符分隔文件。它适用于自动化,每天导出数据库。

mysql -B -D mydatabase -e 'select * from mytable'

方便的是,我们可以使用相同的技术列出MySQL的表,并描述单个表上的字段:

mysql -B -D mydatabase -e 'show tables'

mysql -B -D mydatabase -e 'desc users'

Field   Type    Null    Key Default Extra
id  int(11) NO  PRI NULL    auto_increment
email   varchar(128)    NO  UNI NULL    
lastName    varchar(100)    YES     NULL    
title   varchar(128)    YES UNI NULL    
userName    varchar(128)    YES UNI NULL    
firstName   varchar(100)    YES     NULL    
另一答案

此外,如果您在Bash命令行上执行查询,我相信tr命令可用于将默认选项卡替换为任意分隔符。

$ echo "SELECT * FROM Table123" | mysql Database456 | tr " " ,

另一答案

在user7610的基础上,这是最好的方法。使用mysql outfile,有60分钟的文件所有权和覆盖问题。

它并不酷,但它可以在5分钟内完成。

php csvdump.php localhost root password database tablename > whatever-you-like.csv

<?php

$server = $argv[1];
$user = $argv[2];
$password = $argv[3];
$db = $argv[4];
$table = $argv[5];

mysql_connect($server, $user, $password) or die(mysql_error());
mysql_select_db($db) or die(mysql_error());

// fetch the data
$rows = mysql_query('SELECT * FROM ' . $table);
$rows || die(mysql_error());


// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');

// output the column headings

$fields = [];
for($i = 0; $i < mysql_num_fields($rows); $i++) {
    $field_info = mysql_fetch_field($rows, $i);
    $fields[] = $field_info->name;
}
fputcsv($output, $fields);

// loop over the rows, outputting them
while ($row = mysql_fetch_assoc($rows)) fputcsv($output, $row);

?>
另一答案
$ mysql your_database --password=foo < my_requests.sql > out.csv

哪个是制表符分隔。像这样管道以获得真正的CSV(感谢@therefromhere):

... .sql | sed 's/	/,/g' > out.csv
另一答案

这是我做的:

echo $QUERY | 
  mysql -B  $MYSQL_OPTS | 
  perl -F"	" -lane 'print join ",", map {s/"/""/g; /^[d.]+$/ ? $_ : qq("$_")} @F ' | 
  mail -s 'report' person@address

perl脚本(从其他地方狙击)在将制表符间隔字段转换为CSV方面做得很好。

另一答案

不完全是CSV格式,但MySQL客户端的tee command可用于将输出保存到本地文件中:

tee foobar.txt
SELECT foo FROM bar;

你可以使用notee禁用它。

SELECT … INTO OUTFILE …;的问题是它需要在服务器上写文件的权限。