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


1182

有没有一种简单的方法可以从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

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


1
您可以REPLACE()在查询中使用引号转义。
dsm

看看我在[这个计算器]答案[1] [1]:stackoverflow.com/questions/12242772/...
biniam


2
对此问题的公认答案可能是最好的方法:stackoverflow.com/questions/3760631/mysql-delimiter-question
SamuelÅslund16年

我在MariaDB错误跟踪器(jira.mariadb.org/browse/MDEV-12879)上写了一个功能请求,您可以对此投票。
杰瑞德·贝克

Answers:


1761

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进程的用户必须具有写入所选目录的权限,否则该命令将失败。

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


16
@Tomas如果您有权访问远程文件系统和MySQL,则必须能够在某个地方写。尝试使用/home/yourusername/file.csv代替/ tmp-如果失败,并且结果集不是那么大,则可以从SSH客户端复制输出并粘贴到本地计算机。
Michael Butler 2012年

63
该问题指定了MySQL,而不是“符合标准”。
Paul Tomblin

35
如何也包括标题?
Bogdan Gusiev 2013年

66
@BogdanGusiev,您可以通过在真实查询之前添加“ SELECT'order_id','product_name','qty'UNION”来包含标头。首先选择查询返回标头,第二次查询返回真实数据;UNION将其结合在一起。
petrkotek

19
@迈克尔·巴特勒:嗯,不,实际上。如果您使用的是Amazon RDS,Heroku或任何其他托管解决方案,则不可能只写到其他人的服务器。
肯·金德

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

用制表符分隔。像这样通过管道传输以获取真实的CSV(感谢@therefromhere):

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

5
不仅如此,而且它还允许从远程数据库主机创建内容,这与写入本地文件系统不同。
tmarthal 2011年

31
它是制表符分隔的,而不是逗号分隔的。
Flimm

13
@Flimm,假设您没有在字段中嵌入逗号/制表符,则可以通过将结果传递到以下位置来进行转换:| sed 's/\t/,/g'
John Carter

111
sed的“修复”不补偿任何选定数据中可能出现的逗号,并且会相应地倾斜输出的列
Joey T

14
消极有效..它可能为你工作,但现在它很可能咬你将来当你的数据包括标签或逗号等。
约翰·亨特

203

mysql --batch,-B

使用tab作为列分隔符打印结果,每一行都换行。使用该选项,mysql不使用历史文件。批处理模式导致以非表格格式输出格式并转义特殊字符。可以通过使用原始模式来禁用转义。请参阅--raw选项的说明。

这将为您提供一个制表符分隔的文件。由于逗号(或包含逗号的字符串)不会被转义,因此将分隔符更改为逗号并非易事。


12
这是一种首选的解决方案:1)制表符分隔值列表在UNIX中很常见2)大多数导入系统(包括Excel,OpenOffice Spreadsheets等)都原生支持TSV导入。3)无需对文本字段的引号字符进行转义4 )使命令行输出变得轻而易举
Joey T

5
这是最好的解决方案,因为与第一个不同,不需要像RDS这样的服务器具有权限
Muayyad Alsadi

8
一个巧妙的技巧:如果将制表符分隔的文件另存为.xls而不是.csv,它将在excel中打开,而无需进行“文本到数据”转换,也没有任何区域设置问题。
serbaut

3
@Joey T-您仍然需要转义制表符和回车符。同样,如果字段的内容看起来像是带引号或转义的字段,则导入的内容可能看起来不像原始内容。
mc0e

2
您会遇到NULL问题..它们将以字符串null出现。.–
Jonathan

141

这是一种相当粗糙的方法。在某个地方找到它,不能功劳

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

效果很好。尽管正则表达式再次证明只写。


正则表达式说明:

  • s ///表示将第一个//之间的内容替换为第二个//之间的内容
  • 最后的“ 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

3
-e标志正是我要的!谢谢!
加拉夫·古普塔

1
这个正则表达式非常简单。就像本页上的许多其他答案一样,它只是清除的输出mysql -B。如果您将正则表达式分成几行放在单独的语句中,那么对理解正则表达式的人来说,这将非常简单。

7
乍一看,这看起来很糟。制表符和回车内容将被错误处理。“ s /'/ \'/;” 根本不执行任何操作,因为shell命令中的双引号占用了反斜杠。反斜杠丢失的许多其他类似错误。在db字段中不处理反斜杠。
mc0e

1
看来此命令在Linux上运行良好,但在Mac上却不行
Hemerson Varela 2014年

6
如果您的文本字段包含制表符,反斜杠",",和许多其他内容,则此操作将中断。正则表达式不是解决此问题的方法
aidan 2014年

93

仅限于Unix / Cygwin,将其通过'tr'传递:

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

注意:这既不处理嵌入式逗号,也不处理嵌入式制表符。


53

这节省了我几次。快速且有效!

--batch 使用tab作为列分隔符打印结果,每一行都换行。

--raw 禁用字符转义(\ n,\ t,\ 0和\)

例:

mysql -udemo_user -p -h127.0.0.1 --port=3306 \
   --default-character-set=utf8mb4 --database=demo_database \
   --batch --raw < /tmp/demo_sql_query.sql > /tmp/demo_csv_export.tsv

为了完整起见,您可以转换为csv(但请注意,因为制表符可能位于字段值内-例如文本字段)

tr '\t' ',' < file.tsv > file.csv


4
除非我缺少任何内容,否则会创建一个TSV文件,而不是CSV文件...
PressingOnAlways

@PressingOnAlways是。MySQL doc引用:“使用制表符作为列分隔符打印结果,每一行都换行。” 但是使用任何定界符解析都不应该成为问题。我用它为我的客户制作excel文件。
hrvoj3e

39

Paul Tomblin提供的OUTFILE解决方案导致将文件写入MySQL服务器本身,因此,只有在您具有FILE访问权,登录访问权或其他从该框中检索文件的方式时,此方法才有效。

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


36

MySQL Workbench可以将记录集导出为CSV,并且似乎可以很好地处理字段中的逗号。CSV在OpenOffice中可以正常打开。


2
感谢百万大卫。在花了3个小时使换行符正确输出数据中的HTML内容之后,我使用了MySQL Workbench,并在2分钟内准备好了CSV文件。
mr-euro

我刚刚发现它也可以另存为XML,这很棒。我希望通过使用XSLT将XML转换为适合导入到目标应用程序的CSV文件,从一个应用程序迁移到另一个应用程序。
大卫·奥利弗

mysql workbench是导入导出功能的最佳选择。
cijagani 2015年

1
我刚刚使用mysql工作台成功导出了超过一百万行,因此大文件似乎不是问题。您只需确保在运行查询之前删除选择限制,并且还可能需要在my.ini文件中增加以下值:max_allowed_pa​​cket = 500M,net_read_timeout = 600,net_write_timeout = 600
Vincent,

3
当您以CSV格式导出数据时,MySQL工作台会出现一个令人尴尬的内存泄漏,如果您有大数据集(如多1或200万行),则12 GB RAM(在我的linux计算机上测试过)不足,并且除非清除内存,否则不会清除内存杀死或阻止它。对于大数据集,这不是解决方案。
Ostico

33

怎么样:

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

2
我真的很喜欢这一个。它更干净,我喜欢使用awk。但是,我可能会这样做: mysql -uUser -pPassword your_database < my_requests.sql | awk 'BEGIN{OFS="=";} {print $1,$2}' > out.csv
乔什(Josh)2012年

7
对于带空格的字段值,此操作将失败。
Barun Sharma 2015年

29

迄今为止,这里的所有解决方案,除了MySQL工作台之外,对于mysql db中至少某些可能的内容都是不正确的,并且很可能是不安全的(即安全性问题)。

MYSQL Workbench(和类似的PHPMyAdmin)提供了一种形式正确的解决方案,但旨在将输出下载到用户的位置。它们对于诸如自动数据导出之类的功能不是那么有用。

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

我曾考虑为此编写一个脚本,但是一想到要使用的脚本,就想到以同一个名称搜索预先存在的作品。虽然我还没有彻底解决它,但是https://github.com/robmiller/mysql2csv上的解决方案看起来很有希望。根据您的应用程序,用于指定SQL命令的yaml方法可能会或可能不会吸引人。我也不为比我的Ubuntu 12.04笔记本电脑或Debian Squeeze服务器标配的最新版本的ruby感到高兴。是的,我知道我可以使用RVM,但是我不想为了一个简单的目的而维护它。

希望有人会指出一个合适的工具,该工具已经过测试。否则,当我找到或编写一个时,可能会更新它。


1
没错,对于表中的复杂字符串,您必须使用一些不错的库,而不仅仅是bash。我认为nodejs对于这种动作有更好的解决方案。像这个例子
yeya 16'-

1
嗨,好的答案,我将添加一个指向在stackoverflow.com/a/35123787/1504300下面提出的python解决方案的链接,该方法运行良好且非常简单。我曾尝试编辑您的信息,但编辑被拒绝了
真的很好,2017年

26

此页面上的许多答案都很薄弱,因为它们无法处理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输入格式的特殊情况。

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


8
一个更可靠的解决方案是使用Python实际连接到数据库,然后您应该有一个更轻松的时间来处理大型数据集(分块结果,流式传输等)所需的工作。
Josh Rumbut '02

@JoshRumbut,真的晚了,但我做了stackoverflow.com/a/41840534/2958070以配合您的评论


17
  1. 逻辑:

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

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


1
很好,因为这是正确的,不需要任何其他调整。
安德鲁·舒尔曼

13

此答案使用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
# /programming/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='\n')
    csv_writer.writerows(results)

已经提供了使用python的答案。stackoverflow.com/a/35123787/5470883
亚历山大·巴尔塔萨

4
@AlexanderBaltasar,对,它看起来很有用,但是它没有使用Python代码与数据库进行交互。请参阅有关该问题的评论。

11

这很简单,它可以在不需要批处理模式或输出文件的情况下运行:

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, ...)

而已!


1
请注意,NULL值将被跳过concat_ws(),从而导致列不匹配。为避免这种情况,只需使用一个空字符串代替:(IFNULL(field, '')或您用来表示的其他任何字符NULL
Marco Roy

10

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

然后,您的硬盘上就会有一个始终为CSV格式的文件,您可以直接对其进行复制而不进行处理。


1
在文件大小/写入/读取/等等方面有什么限制?
扎克·史密斯

8

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

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    

4
转换为CSV:mysql -B -D mydatabase -e 'select * from mytable' | sed -e 's/\t/,/g'
DSimon 2015年

7
使用sed -e 's/\t/,/g',如果你确信你的数据不包含任何逗号或制表符是唯一安全的。
瓦特2015年

7

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

?>

1
美观,干净且可以快速运行-如果您可以在该环境中运行PHP,这是一个很好的解决方案!
约翰·菲亚拉

7

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

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


5

这是我的工作:

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方面做得很好。


这很棒。稍微改善可能是引用除数字以外的所有内容perl -F"\t" -lane 'print join ",", map {s/"/""/g; /^\d+(?:\.\d+)?$/ ? $_ : qq("$_")} @F '-您不会引用1.2.3
-artfulrobot

5

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

tee foobar.txt
SELECT foo FROM bar;

您可以使用禁用它notee

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


如果使用.csv扩展名而不是.txt,是否有任何格式问题需要注意?
datalifenyc

@myidealab格式问题是由逗号等引起的。CSV是纯文本格式,因此仅换出扩展名就没有格式问题。
jkmartindale

3

使用Tim张贴的解决方案,我创建了这个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

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


3

如果在服务器上设置了PHP,则可以使用mysql2csv导出(实际上有效的)CSV文件用于任意mysql查询。在MySQL上查看我的答案-SELECT * INTO OUTFILE LOCAL?以获得更多上下文/信息。

我试图从中维护选项名称,mysql因此提供--file--query选项应该足够了:

./mysql2csv --file="/tmp/result.csv" --query='SELECT 1 as foo, 2 as bar;' --user="username" --password="password"

mysql2csv通过“安装”

wget https://gist.githubusercontent.com/paslandau/37bf787eab1b84fc7ae679d1823cf401/raw/29a48bb0a43f6750858e1ddec054d3552f3cbc45/mysql2csv -O mysql2csv -q && (sha256sum mysql2csv | cmp <(echo "b109535b29733bd596ecc8608e008732e617e97906f119c66dd7cf6ab2865a65  mysql2csv") || (echo "ERROR comparing hash, Found:" ;sha256sum mysql2csv) ) && chmod +x mysql2csv

(下载要点的内容,检查校验和并使其可执行)。


3

对我有用的是:

SELECT *
FROM students
WHERE foo = 'bar'
LIMIT 0,1200000
INTO OUTFILE './students-1200000.csv'
FIELDS TERMINATED BY ',' ESCAPED BY '"'
ENCLOSED BY '"'
LINES TERMINATED BY '\r\n';

该线程上的所有解决方案均不适用于我的特殊情况,其中一列中包含漂亮的json数据,这些数据会在我的csv输出中弄乱。对于那些有类似问题的用户,请尝试使用\ r \ n终止的行。

对于那些尝试使用Microsoft Excel打开csv的人来说,另一个问题是,请记住,单个单元格可以容纳32,767个字符的限制,超过此限制它就会溢出到下面的行。要确定列中的哪些记录有问题,请使用下面的查询。然后,您可以截断这些记录或根据需要进行处理。

SELECT id,name,CHAR_LENGTH(json_student_description) AS 'character length'
FROM students
WHERE CHAR_LENGTH(json_student_description)>32767;

2

如果您遇到的错误,secure-file-priv则还要在将目标文件位置C:\ProgramData\MySQL\MySQL Server 8.0\Uploads移到内之后,然后在查询后-

SELECT * FROM attendance INTO OUTFILE 'C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\FileName.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n';

不起作用,您只需\将查询的(反斜线)更改为/(正斜线)

那行得通!

例:

选择*从出席者入场文件'C:/ ProgramData / MySQL / MySQL Server 8.0 / Uploads / FileName.csv'字段以','封闭''

每次运行成功查询时,每次都会生成新的csv文件!酷吧?


1

https://stackoverflow.com/a/5395421/2841607启发,用于对CSV转储进行简单查询的微型bash脚本。

#!/bin/bash

# $1 = query to execute
# $2 = outfile
# $3 = mysql database name
# $4 = mysql username

if [ -z "$1" ]; then
    echo "Query not given"
    exit 1
fi

if [ -z "$2" ]; then
    echo "Outfile not given"
    exit 1
fi

MYSQL_DB=""
MYSQL_USER="root"

if [ ! -z "$3" ]; then
    MYSQL_DB=$3
fi

if [ ! -z "$4" ]; then
    MYSQL_USER=$4
fi

if [ -z "$MYSQL_DB" ]; then
    echo "Database name not given"
    exit 1
fi

if [ -z "$MYSQL_USER" ]; then
    echo "Database user not given"
    exit 1
fi

mysql -u $MYSQL_USER -p -D $MYSQL_DB -B -s -e "$1" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" > $2
echo "Written to $2"

1

以下bash脚本适用于我。也可以选择获取所请求表的架构。

#!/bin/bash
#
# export mysql data to CSV
#/programming/356578/how-to-output-mysql-query-results-in-csv-format
#

#ansi colors
#http://www.csc.uvic.ca/~sae/seng265/fall04/tips/s265s047-tips/bash-using-colors.html
blue='\033[0;34m'
red='\033[0;31m'
green='\033[0;32m' # '\e[1;32m' is too bright for white bg.
endColor='\033[0m'

#
# a colored message 
#   params:
#     1: l_color - the color of the message
#     2: l_msg - the message to display
#
color_msg() {
  local l_color="$1"
  local l_msg="$2"
  echo -e "${l_color}$l_msg${endColor}"
}


#
# error
#
# show the given error message on stderr and exit
#
#   params:
#     1: l_msg - the error message to display
#
error() {
  local l_msg="$1"
  # use ansi red for error
  color_msg $red "Error:" 1>&2
  color_msg $red "\t$l_msg" 1>&2
  usage
}

#
# display usage 
#
usage() {
  echo "usage: $0 [-h|--help]" 1>&2
  echo "               -o  | --output      csvdirectory"    1>&2
  echo "               -d  | --database    database"   1>&2
  echo "               -t  | --tables      tables"     1>&2
  echo "               -p  | --password    password"   1>&2
  echo "               -u  | --user        user"       1>&2
  echo "               -hs | --host        host"       1>&2
  echo "               -gs | --get-schema"             1>&2
  echo "" 1>&2
  echo "     output: output csv directory to export mysql data into" 1>&2
  echo "" 1>&2
  echo "         user: mysql user" 1>&2
  echo "     password: mysql password" 1>&2
  echo "" 1>&2
  echo "     database: target database" 1>&2
  echo "       tables: tables to export" 1>&2
  echo "         host: host of target database" 1>&2
  echo "" 1>&2
  echo "  -h|--help: show help" 1>&2
  exit 1
}

#
# show help 
#
help() {
  echo "$0 Help" 1>&2
  echo "===========" 1>&2
  echo "$0 exports a csv file from a mysql database optionally limiting to a list of tables" 1>&2
  echo "   example: $0 --database=cms --user=scott --password=tiger  --tables=person --output person.csv" 1>&2
  echo "" 1>&2
  usage
}

domysql() {
  mysql --host $host -u$user --password=$password $database
}

getcolumns() {
  local l_table="$1"
  echo "describe $l_table" | domysql | cut -f1 | grep -v "Field" | grep -v "Warning" | paste -sd "," - 2>/dev/null
}

host="localhost"
mysqlfiles="/var/lib/mysql-files/"

# parse command line options
while true; do
  #echo "option $1"
  case "$1" in
    # options without arguments
    -h|--help) usage;;
    -d|--database)     database="$2" ; shift ;;
    -t|--tables)       tables="$2" ; shift ;;
    -o|--output)       csvoutput="$2" ; shift ;;
    -u|--user)         user="$2" ; shift ;;
    -hs|--host)        host="$2" ; shift ;;
    -p|--password)     password="$2" ; shift ;;
    -gs|--get-schema)  option="getschema";; 
    (--) shift; break;;
    (-*) echo "$0: error - unrecognized option $1" 1>&2; usage;;
    (*) break;;
  esac
  shift
done

# checks
if [ "$csvoutput" == "" ]
then
  error "ouput csv directory not set"
fi
if [ "$database" == "" ]
then
  error "mysql database not set"
fi
if [ "$user" == "" ]
then
  error "mysql user not set"
fi
if [ "$password" == "" ]
then
  error "mysql password not set"
fi

color_msg $blue "exporting tables of database $database"
if [ "$tables" = "" ]
then
tables=$(echo "show tables" | domysql)
fi

case $option in
  getschema) 
   rm $csvoutput$database.schema
   for table in $tables
   do
     color_msg $blue "getting schema for $table"
     echo -n "$table:" >> $csvoutput$database.schema
     getcolumns $table >> $csvoutput$database.schema
   done  
   ;;
  *)
for table in $tables
do
  color_msg $blue "exporting table $table"
  cols=$(grep "$table:" $csvoutput$database.schema | cut -f2 -d:)
  if [  "$cols" = "" ]
  then
    cols=$(getcolumns $table)
  fi
  ssh $host rm $mysqlfiles/$table.csv
cat <<EOF | mysql --host $host -u$user --password=$password $database 
SELECT $cols FROM $table INTO OUTFILE '$mysqlfiles$table.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n';
EOF
  scp $host:$mysqlfiles/$table.csv $csvoutput$table.csv.raw
  (echo "$cols"; cat $csvoutput$table.csv.raw) > $csvoutput$table.csv
  rm $csvoutput$table.csv.raw
done
  ;;
esac

1

我遇到了同样的问题,保罗的答案不是一个选择,因为它是RDS。用逗号替换选项卡不起作用,因为数据中嵌入了逗号和选项卡。我发现mycli是mysql-client的一种替代替代品,支持带有--csv标志的开箱即用的csv输出

mycli db_name --csv -e "select * from flowers" > flowers.csv

1

如果在尝试导出文件时遇到此错误

错误1290(HY000):MySQL服务器正在使用--secure-file-priv选项运行,因此它无法执行此语句

您将无法解决此错误。您可以通过简单地运行此python脚本来做一件事

import mysql.connector
import csv

con = mysql.connector.connect(
    host="localhost",
    user="root",
    passwd="Your Password"
)

cur = con.cursor()

cur.execute("USE DbName")
cur.execute("""
select col1,col2 from table
where <cond>
""")

with open('Filename.csv',mode='w') as data:
    fieldnames=["Field1","Field2"]
    writer=csv.DictWriter(data,fieldnames=fieldnames)
    writer.writeheader()
    for i in cur:
        writer.writerow({'Field1':i[0],'Field2':i[1]})

欢迎使用Stack Overflow!这不能回答问题。请查看stackoverflow.com/help/how-to-answer
stephenwade

0

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

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

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

我包括该--php-ini开关,因为您可能需要使用自己的PHP配置来启用MySQL扩展。在PHP 5.3.0+上,默认情况下启用该扩展,因此不再需要使用配置来启用它。

然后,您可以像任何普通的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和text字段,它没有问题。那些字段被正确引用,并且其中的那些换行符将由CSV阅读器解释为文本的一部分,而不是记录分隔符。事后用sed很难纠正。


1
这不是不必要的复杂,但这是唯一可能朝着正确方向发展的解决方案-尽管还有更多工作要做。CSV比它最初出现时要复杂得多,您犯了许多错误。例如原件中的反斜杠。最好使用已经解决了所有写入CSV问题的库。
mc0e 2013年

@ mc0e通常,您将引号加倍或将其转义。我决定将报价加倍,因此不需要转义字符。不同的软件对CSV详细信息有不同的想法。例如,MySQL中的LOAD DATA实际上将\视为转义字符,而Open Office Calc则不这样。当我写下答案时,我正在将数据导出到电子表格中。
user7610 2015年

1
我的代码处理了一天导出我的数据集所需的一切;)您的答案也是朝着正确方向迈出的一步,但正如那里的第一条评论所述,它应该:1)以如下方式直接从脚本连接到sql数据库以及2)使用适当的csv库。
user7610
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.