如何以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 '\n'; 

使用这个命令列名不会被导出。

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

如果您想从远程服务器(特别是托pipe或虚拟化机器,如Heroku或Amazon RDS)将输出写入本地计算机,则此解决scheme不适用。

 $ mysql your_database --password=foo < my_requests.sql > out.csv 

这是选项卡分隔。 像这样pipe得到一个真正的CSV(谢谢@从这里):

 ... .sql | sed 's/\t/,/g' > out.csv 

mysql –batch,-B

使用选项卡作为列分隔符打印结果,每行放在一个新行中。 使用这个选项,mysql不会使用历史文件。 批处理模式导致非表格输出格式和转义特殊字符。 通过使用原始模式可能会禁用转义。 请参阅–raw选项的说明。

这会给你一个选项卡分隔的文件。 由于逗号(或包含逗号的string)不会被转义,因此将分隔符更改为逗号并不简单。

这是一个相当粗糙的做法。 find它的地方,不能拿任何信用

mysql --user=wibble --password wobble -B -e "select * from vehicle_categories;" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" > vehicle_categories.csv

工作得很好。 再一次,虽然正则expression式certificate只写。


正则expression式

  • / / / /意味着取代之间的第一/ /之间的第二个/ /
  • 最后的“g”是一个修饰符,意思是“所有实例,而不仅仅是第一个”
  • ^(在这种情况下)意味着行的开始
  • $(在这种情况下)意味着行尾

所以,把它们放在一起:

 s/'/\'/ replace ' with \' s/\t/\",\"/g replace all \t (tab) with "," s/^/\"/ at the beginning of the line place a " s/$/\"/ at the end of the line place a " s/\n//g replace all \n (newline) with nothing 

只有Unix / Cygwin ,通过'tr'pipe道:

 mysql <database> -e "<query here>" | tr '\t' ',' > data.csv 

注意:这不处理embedded的逗号,也不embedded标签。

由Paul Tomblin给出的OUTFILE解决scheme导致文件被写入到MySQL服务器本身,所以只有当你有FILE访问权时 ,以及login访问或其他方式从该文件夹中检索文件,才能工作。

如果您没有这样的访问权限,并且制表符分隔的输出是CSV的合理替代(例如,如果您的最终目标是导入Excel),那么Serbaut的解决scheme(使用mysql --batch和可选的--raw )是要走的路。

怎么样:

 mysql your_database -p < my_requests.sql | awk '{print $1","$2}' > out.csv 

MySQL Workbench可以将logging集导出到CSV,并且它似乎很好地处理字段中的逗号。 CSV在OpenOffice中打开罚款。

到目前为止,除了Mysql工作台之外,所有这些解决scheme都是不正确的,而且很可能对于至less一些可能的内容在MySQL数据库中是不安全的(即安全问题)。

Mysql Workbench(以及类似的PHPMyAdmin)提供了一个正式的正确的解决scheme,但是被devise用于将输出下载到用户的位置。 它们对于自动化数据导出等function并不是那么有用。

mysql -B -e 'SELECT ...'的输出中不可能生成可靠正确的csv,因为它不能编码字段中的回车和空格。 mysql的'-s'标志做反斜杠转义,并可能导致正确的解决scheme。 然而,使用脚本语言(一个体面的内部数据结构,而不是bash),以及编码问题已被仔细研究的库更安全。

我曾想过为此编写一个脚本,但是一想到我所说的内容,就想到用同样的名字search已经存在的工作。 虽然我没有彻底的了解它,但是https://github.com/robmiller/mysql2csv的解决scheme看起来很有希望。; 根据您的应用程序,yaml方法来指定SQL命令可能会或可能不吸引。 我也不会对最近版本的ruby的要求比我的Ubuntu 12.04笔记本电脑或Debian Squeeze服务器的标准要求。 是的,我知道我可以使用RVM,但是我不想为了这么简单的目的而保留这个。

希望有人会指出一个合适的工具,这是有点testing。 否则,我可能会更新,当我find或写一个。

这节省了我几次。 快速,它的作品!

– 批量

– 生的

例:

 sudo mysql -udemo_user -p -h127.0.0.1 --port=3306 \ --default-character-set=utf8 --database=demo_database \ --batch --raw < /var/demo_sql_query.sql > /var/demo_csv_export.csv 

从你的命令行,你可以这样做:

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

积分:将 Amazon RDS中的表导出为csv文件

  1. 逻辑:

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

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

这很简单,它可以在任何情况下工作,而不需要批处理模式或输出文件:

 select concat_ws(',', concat('"', replace(field1, '"', '""'), '"'), concat('"', replace(field2, '"', '""'), '"'), concat('"', replace(field3, '"', '""'), '"')) from your_table where etc; 

说明:

  1. 在每个字段中用“”replace“>”replace(field1,''',''''')
  2. 在引号中围绕每个结果 – > concat(''',result1,''')
  3. 在每个引用结果之间放置一个逗号 – > concat_ws(',',quoted1,quoted2,…)

而已!

本页面上的许多答案都很薄弱,因为它们不处理CSV格式中可能出现的一般情况。 例如embedded字段中的逗号和引号以及最终总是出现的其他条件。 我们需要一个适用于所有有效的CSVinput数据的通用解决scheme。

Python中有一个简单而强大的解决scheme:

 #!/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 ,把它放在你的path上,给它执行权限,然后使用它列出这个:

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

Python CSV处理函数覆盖了CSVinput格式的边angular情况。

这可以通过stream式处理来改善以处理非常大的文件。

或者对上面的答案,你可以有一个使用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 

这就是我所做的:

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

perl脚本(从其他地方狙击)可以很好地将制表符分隔字段转换为CSV。

基于用户7610,这是做到这一点的最好方法。 用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); ?> 

使用Tim发布的解决scheme,我创build了这个bash脚本来促进这个过程(请求root密码,但是您可以轻松修改脚本来请求其他用户):

 #!/bin/bash if [ "$1" == "" ];then echo "Usage: $0 DATABASE TABLE [MYSQL EXTRA COMMANDS]" exit fi DBNAME=$1 TABLE=$2 FNAME=$1.$2.csv MCOMM=$3 echo "MySQL password:" stty -echo read PASS stty echo mysql -uroot -p$PASS $MCOMM $DBNAME -B -e "SELECT * FROM $TABLE;" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" > $FNAME 

它将创build一个名为: database.table.csv的文件

不完全是CSV格式,但是可以使用来自MySQL 客户端的 tee命令将输出保存到本地文件中:

 tee foobar.txt SELECT foo FROM bar; 

您可以使用notee禁用它。

SELECT … INTO OUTFILE …; 是它需要权限才能在服务器上写入文件。

这个答案使用Python和一个stream行的第三方库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 isn't much better, but this is an example # http://stackoverflow.com/questions/12461484/is-it-secure-to-store-passwords-as-environment-variables-rather-than-as-plain-t 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='\n') csv_writer.writerows(results) 
 Try this code: SELECT 'Column1', 'Column2', 'Column3', 'Column4', 'Column5' UNION ALL SELECT column1, column2, column3 , column4, column5 FROM demo INTO OUTFILE '/tmp/demo.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n'; for more: http://dev.mysql.com/doc/refman/5.1/en/select-into.html 

如果您正在使用的计算机上安装了PHP,则可以编写一个PHP脚本来执行此操作。 它要求PHP安装已经安装了MySQL扩展。

您可以从命令行调用PHP解释器,如下所示:

 php --php-ini path/to/php.ini your-script.php 

我包括--php-ini开关,因为您可能需要使用您自己的PHPconfiguration来启用MySQL扩展。 在PHP 5.3.0以上,该扩展默认是启用的,所以不再需要使用configuration来启用它。

然后你可以像任何普通的PHP脚本一样编写你的导出脚本:

 <?php #mysql_connect("localhost", "username", "password") or die(mysql_error()); mysql_select_db("mydb") or die(mysql_error()); $result = mysql_query("SELECT * FROM table_with_the_data p WHERE p.type = $typeiwant"); $result || die(mysql_error()); while($row = mysql_fetch_row($result)) { $comma = false; foreach ($row as $item) { # Make it comma separated if ($comma) { echo ','; } else { $comma = true; } # Quote the quotes $quoted = str_replace("\"", "\"\"", $item); # Quote the string echo "\"$quoted\""; } echo "\n"; } ?> 

这种方法的优点是,它没有与varchar和文本字段,有文字包含换行符的问题。 这些字段被正确引用,并且这些字段中的换行符将被CSV阅读器解释为文本的一部分,而不是logging分隔符。 这是事后很难用sed左右来纠正的。