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

Posted

技术标签:

【中文标题】如何以 CSV 格式输出 MySQL 查询结果?【英文标题】:How can I output MySQL query results in CSV format? 【发布时间】:2010-09-26 06:35:56 【问题描述】:

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

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

【问题讨论】:

您可以在查询中使用REPLACE() 来转义引号。 看看我在 [this ***][1] [1] 中的回答:***.com/questions/12242772/… 你可以Format Table Data as Text table。 这个***问题的公认答案可能是最好的方法:***.com/questions/3760631/mysql-delimiter-question 我在 MariaDB 错误跟踪器 (jira.mariadb.org/browse/MDEV-12879) 上写了一个功能请求,您可以投票。 【参考方案1】:

来自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';

注意:该语法可能需要重新排序为

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

在最新版本的 MySQL 中。

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

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

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

【讨论】:

您可能需要成为 root。 “该文件是在服务器主机上创建的,因此您必须具有 FILE 权限才能使用此语法。” - dev.mysql.com/doc/refman/8.0/en/select-into.html 是的,它依赖于 MySQL 权限和本地文件系统某处的写入权限。 LINES TERMINATED BY '\n' 不是必需的,它是默认值。通常,如果您省略所有其他参数,您将获得一个以制表符分隔的文件,其中不包含字段。【参考方案2】:
mysql your_database --password=foo < my_requests.sql > out.csv

这是制表符分隔的。像这样通过管道获取真正的 CSV(感谢 to user John Carter):

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

【讨论】:

它是制表符分隔的,不是逗号分隔的。 @Flimm,假设您没有在字段中嵌入逗号/制表符,您可以通过将结果管道转换为 | sed 's/\t/,/g' sed 'fix' 不会补偿可能出现在任何选定数据中的逗号,并且会相应地倾斜您输出的列【参考方案3】:

mysql --batch, -B

使用制表符作为列分隔符打印结果,每一行在一个 新队。使用此选项,mysql 不使用历史文件。 批处理模式导致非表格输出格式和转义 特殊字符。使用原始模式可以禁用转义;看 --raw 选项的描述。

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

【讨论】:

【参考方案4】:

这是一种相当粗糙的方法[1]

mysql --user=wibble --password wobble -B -e "select * from vehicle_categories;" | sed "s/'/'/;s/\t/","/g;s/^/"/;s/$/"/;s/\n//g" &gt; 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

[1] 我在某个地方找到了它,无法获得任何功劳。

【讨论】:

【参考方案5】:

通过 'tr' 管道(仅限 Unix/Cygwin):

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

注意:这既不处理嵌入的逗号,也不处理嵌入的标签。

【讨论】:

我很惊讶这个解决方案的投票率如此之低。目前,***解决方案需要许多 db 用户没有的特权(并且有充分的理由;管理员将其提供给它是一种安全风险。)您的解决方案在这里没有任何特殊特权,也可以改进以解决逗号或制表符的缺点,可能在查询本身中进行了替换。 这是一个绝妙的解决方案,效果很好。【参考方案6】:

这救了我几次。它速度快而且效果好!

--batch 使用制表符作为列分隔符打印结果,每一行在一个 换行。

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

为了完整起见,您可以convert to CSV(但要小心,因为选项卡可能位于字段值内 - 例如,文本字段)

tr '\t' ',' &lt; file.tsv &gt; file.csv

【讨论】:

【参考方案7】:

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

如果您没有此类访问权限,并且制表符分隔的输出是 CSV 的合理替代品(例如,如果您的最终目标是导入 Excel),那么 serbaut's solution(使用 mysql --batch 和可选的 @987654325 @) 是要走的路。

【讨论】:

【参考方案8】:

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

【讨论】:

感谢一百万大卫。在花了 3 个小时让换行符正确输出数据中的 HTML 内容后,我使用了 MySQL Workbench,并在 2 分钟内准备好了我的 CSV 文件。 我刚刚发现它也可以保存为 XML,这很棒。我希望通过使用 XSLT 将此 XML 转换为适合导入目标应用程序的 CSV 文件来从一个应用程序迁移到另一个应用程序。 mysql 工作台是导入导出功能的最佳选择。 好吧,但是每次工作台将选择记录限制为 1000 条,当涉及到更多记录时,它就不能很好地工作,如果我尝试导入相同的条件,它通常会被阻止通过workbench将一个比较大的csv文件导入mysql数据库。 我刚刚使用 mysql 工作台成功导出了超过一百万行,所以大文件似乎不是问题。您只需要确保在运行查询之前删除选择限制,并且您可能还必须增加 my.ini 文件中的以下值:max_allowed_pa​​cket = 500M, net_read_timeout = 600, net_write_timeout = 600【参考方案9】:

用途:

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

【讨论】:

我真的很喜欢这个。它更干净,我喜欢使用 awk。但是,我可能会选择这个:mysql -uUser -pPassword your_database &lt; my_requests.sql | awk 'BEGINOFS="="; print $1,$2' &gt; out.csv 这对于带有空格的字段值失败。【参考方案10】:

到目前为止,除the MySQL Workbench one 之外的所有解决方案对于 MySQL 数据库中的至少一些可能的内容都是不正确的并且很可能不安全(即安全问题)。

MySQL Workbench(以及类似的phpMyAdmin)提供了形式上正确的解决方案,但它们旨在将输出下载到用户的位置。它们对于自动数据导出之类的事情不是那么有用。

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

我曾想过为此编写一个脚本,但当我想到我会如何称呼它时,我突然想到要搜索已有的同名作​​品。虽然我还没有彻底了解它,但mysql2csv 看起来很有希望。根据您的应用程序,指定 SQL 命令的 YAML 方法可能会或可能不会吸引人。对于我的Ubuntu 12.04(Precise Pangolin)笔记本电脑或Debian 6.0(Squeeze)服务器标配的更新版本的Ruby,我也不满意。是的,我知道我可以使用 RVM,但我不想为了这么简单的目的而维护它。

【讨论】:

你是对的,对于表中的复杂字符串,你必须使用一些像样的库,而不仅仅是 bash。我认为 nodejs 对这种行为有更好的解决方案。像这样example 嗨,好答案,我会在***.com/a/35123787/1504300下面添加一个python解决方案的链接,效果很好,也很简单。我试图编辑你的帖子,但编辑被拒绝了 Rob Miller 的 mysql2csv 脚本坚持通过网络或套接字连接到数据库本身,并且不能用作 unix 样式的管道。也许这是必需的,但它确实限制了使用。 @chrisinmtown 你想输入什么? myslqldump 的输出可能吗?正如我所指出的,mysql -B 的输出无法修复。 @mc0e 我想通过管道 in 输出 mysqldump 的输出,将其读取为 stdin。【参考方案11】:

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

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

【讨论】:

更可靠的解决方案是使用 Python 实际连接到数据库,然后您应该可以更轻松地执行处理更大数据集所需的操作(分块结果、流式传输等) . @JoshRumbut,真的来晚了,但我发了***.com/a/41840534/2958070 来补充您的评论 请参阅***.com/questions/356578/… 了解此脚本的扩展版本,其输入方言可处理嵌入的逗号和双引号字符! 它的要点是什么?使用图书馆?内置库?可以link to documentation等吗? (但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。)。 流媒体方法需要什么?你能在你的答案中详细说明一下吗? (但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。)【参考方案12】:

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

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*

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

【讨论】:

那是一个疯狂的 oneliner 。帽子【参考方案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
# https://***.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://***.com/a/17725590/2958070 about lineterminator
    csv_writer = csv.writer(csvfile, lineterminator='\n')
    csv_writer.writerows(results)

【讨论】:

已经提供了使用 python 的答案。 ***.com/a/35123787/5470883 @AlexanderBaltasar,对,它看起来很有用,但它没有使用 Python 代码与数据库交互。请参阅关于该问题的评论。 Re“没有其他答案是使用 Python 代码与数据库进行交互。”:没有,但 Chris Johnson's answer 也使用 'csv' 库。 @PeterMortensen,那个答案的 cmets 促使我写这个答案:)【参考方案14】:

这很简单,无需批处理模式或输出文件即可处理任何事情:

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

from your_table where etc;

解释:

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

就是这样!

【讨论】:

请注意NULL 的值将被concat_ws() 跳过,从而导致列不匹配。为避免这种情况,只需使用空字符串:IFNULL(field, '')(或您用来表示 NULL 的任何其他内容)【参考方案15】:

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

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

【讨论】:

如果您在文件权限方面遇到问题,这是一个不错的方法,但它不会引用您的字段,因此如果您的数据包含逗号或引号,其他工具可能会误解 CSV。 需要 -s(静默)选项来生成选项卡式输出【参考方案16】:

我遇到了同样的问题,Paul's Answer 不是一个选项,因为它是Amazon RDS。用逗号替换制表符不起作用,因为数据已嵌入逗号和制表符。我发现mycli 是 mysql-client 的替代品,它支持带有 --csv 标志的开箱即用的 CSV 输出:

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

【讨论】:

就像一个魅力,你可以通过:brew update &amp;&amp; brew install mycli 在 macOS 中安装 mycli。我再也不会使用股票 mysql 客户端了,mycli 是如此合法! Mycli 和它的表弟 pgcli 都很棒。我来这里是为了添加这个技巧 mysql,因为我没有得到任何其他解决方案。使用 mysql 干净地输出到本地 .csv 非常困难。 太棒了,很遗憾这个答案很少得到“喜欢”。这是唯一符合我需求的解决方案。除了这个,所有其他的对我来说都不是完美的。我在列中有换行符 - 打开文件时导致 Excel 程序中出现新行。 如果您在使用 1.8.1 版本时遇到问题(可能是因为您使用的是仍然有 Python 2.x 的旧操作系统),则此答案将不起作用,因为“--csv”是'在该版本中不可用。【参考方案17】:

您可以拥有一个使用 CSV 引擎的 MySQL 表。

然后,您的硬盘上就会有一个文件,该文件将始终采用 CSV 格式,您可以直接复制而无需处理它。

【讨论】:

这在文件大小/写入/读取/等方面有什么限制?【参考方案18】:

为了扩展先前的答案,以下单行将单个表导出为制表符分隔的文件。适合自动化,每天左右导出数据库。

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    

【讨论】:

转换为 CSV:mysql -B -D mydatabase -e 'select * from mytable' | sed -e 's/\t/,/g' 只有在您确定您的数据不包含任何逗号或制表符的情况下,使用 sed -e 's/\t/,/g' 才是安全的。【参考方案19】:

这是我的工作:

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 的改进。【参考方案20】:

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

这不是很酷,但它在 5 分钟内起作用。

php csvdump.php localhost root password database tablename &gt; 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);

?>

【讨论】:

不错,干净,运行迅速 - 如果您可以在该环境中运行 PHP,这是一个很好的解决方案!【参考方案21】:

不完全是 CSV 格式,但来自 MySQL clienttee command 可用于将输出保存到 local 文件中:

tee foobar.txt
SELECT foo FROM bar;

您可以使用notee 禁用它。

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

【讨论】:

如果使用 .csv 扩展名而不是 .txt,是否有任何格式问题需要注意? @myidealab 格式问题源于逗号等未转义。 CSV 是纯文本格式,因此只需更换扩展名就不会出现格式问题。【参考方案22】:

什么对我有用:

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;

【讨论】:

Re "...漂亮的 JSON 数据...":漂亮在什么方面?【参考方案23】:

在我的情况下,from table_name ..... INTO OUTFILE ..... 之前给出一个错误:

子句的意外排序。 (靠近位置 10 的“FROM”)

什么对我有用:

SELECT *
INTO OUTFILE '/Volumes/Development/sql/sql/enabled_contacts.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM table_name
WHERE column_name = 'value'

【讨论】:

【参考方案24】:

使用the solution posted by Tim Harding,我创建了这个 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

的文件

【讨论】:

嵌入的双引号字符呢?他们也需要被转义,但我在 sed 咒语中看不到他们的模式。【参考方案25】:

如果您在服务器上设置了 PHP,则可以使用 mysql2csv 导出(实际有效的)CSV 文件以进行任意 MySQL 查询。有关更多上下文/信息,请参阅my answer at 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

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

【讨论】:

【参考方案26】:

以下生成制表符分隔且有效的 CSV 输出。与大多数其他答案不同,此技术可以正确处理制表符、逗号、引号和新行的转义,而无需任何流过滤器,例如 sed、AWK 或 tr。

该示例展示了如何使用流将远程 MySQL 表直接通过管道传输到本地 SQLite 数据库。这无需 FILE 权限或 SELECT INTO OUTFILE 权限即可工作。为了便于阅读,我添加了新行。

mysql -B -C --raw -u 'username' --password='password' --host='hostname' 'databasename'
-e 'SELECT
    CONCAT('\''"'\'',REPLACE(`id`,'\''"'\'', '\''""'\''),'\''"'\'') AS '\''id'\'',
    CONCAT('\''"'\'',REPLACE(`value`,'\''"'\'', '\''""'\''),'\''"'\'') AS '\''value'\''
    FROM sampledata'
2>/dev/null | sqlite3 -csv -separator $'\t' mydb.db '.import /dev/stdin mycsvtable'

需要2&gt;/dev/null 来抑制命令行上有关密码的警告。

如果您的数据有 NULL,您可以在查询中使用 IFNULL() 函数。

【讨论】:

【参考方案27】:

如果您收到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';

不起作用,您只需将查询中的 \(backsplash) 更改为 / (forwardsplash)

这行得通!

例子:

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

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

【讨论】:

在 Windows 上,大概?它测试了什么,包括。版本(Windows、MySQL 等)?【参考方案28】:

用 Python 编写一个带有标头的标准格式 CSV 文件并将数据作为流写入的简单解决方案(低内存使用):

import csv

def export_table(connection, table_name, output_filename):
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM " + table_name)

    # thanks to https://gist.github.com/madan712/f27ac3b703a541abbcd63871a4a56636 for this hint
    header = [descriptor[0] for descriptor in cursor.description]

    with open(output_filename, 'w') as csvfile:
        csv_writer = csv.writer(csvfile, dialect='excel')
        csv_writer.writerow(header)
        for row in cursor:
            csv_writer.writerow(row)

你可以像这样使用它:

import mysql.connector as mysql
# (or https://github.com/PyMySQL/PyMySQL should work but I haven't tested it)

db = mysql.connect(
    host="localhost",
    user="USERNAME",
    db="DATABASE_NAME",
    port=9999)

for table_name in ['table1', 'table2']:
    export_table(db, table_name, table_name + '.csv')

db.close()

为简单起见,这故意不包括来自another answer 的一些更高级的东西,例如使用环境变量作为凭据,contextlib 等。那里提到了我尚未评估的行尾的微妙之处。

【讨论】:

【参考方案29】:

Tim Harding's answer 启发的用于对 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"

【讨论】:

这使用忽略嵌入双引号字符的 sed 咒语。建议改用 perl 解决方案。【参考方案30】:

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

#!/bin/bash
#
# Export MySQL data to CSV
#https://***.com/questions/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 standard error and exit
#
#   Parameters:
#     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 "output CSV directory is not set"
fi
if [ "$database" == "" ]
then
  error "MySQL database is not set"
fi
if [ "$user" == "" ]
then
  error "MySQL user is not set"
fi
if [ "$password" == "" ]
then
  error "MySQL password is 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

【讨论】:

以上是关于如何以 CSV 格式输出 MySQL 查询结果?的主要内容,如果未能解决你的问题,请参考以下文章

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

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

如何以 csv 格式输出 MySQL 查询结果(到屏幕,而不是文件)?

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

如何设定PLSQL DEVELOPER导出的CSV文件中单元格格式为文本?

将 MySQL 命令行结果的输出格式更改为 CSV