如何以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文件
- 逻辑:
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;
说明:
- 在每个字段中用“”replace“>”replace(field1,''',''''')
- 在引号中围绕每个结果 – > concat(''',result1,''')
- 在每个引用结果之间放置一个逗号 – > 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左右来纠正的。