如何以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
当有很多列需要用引号引起来时,或者结果中存在需要转义的引号时,它会变得混乱。
Is there an easy way to run a MySQL query from the Linux command line and output the results in CSV format?
Here's what I'm doing now:
mysql -u uid -ppwd -D dbname << EOQ | sed -e 's/ /,/g' | tee list.csv
select id, concat("\"",name,"\"") as name
from students
EOQ
It gets messy when there are a lot of columns that need to be surrounded by quotes, or if there are quotes in the results that need to be escaped.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
来自 将 MySQL 查询结果保存到文本或 CSV 文件中:
该语法可能需要重新排序
注意:在更新版本的 MySQL 中,
。 使用此命令,不会导出列名称。
另请注意,
/var/lib/mysql-files/orders.csv
将位于运行 MySQL 的服务器上。 运行 MySQL 进程的用户必须具有写入所选目录的权限,否则命令将失败。如果您想从远程服务器(尤其是托管或虚拟机,例如 Heroku< /a> 或 Amazon RDS),此解决方案不合适。
From Save MySQL query results into a text or CSV file:
Note: That syntax may need to be reordered to
in more recent versions of MySQL.
Using this command, columns names will not be exported.
Also note that
/var/lib/mysql-files/orders.csv
will be on the server that is running MySQL. The user that the MySQL process is running under must have permissions to write to the directory chosen, or the command will fail.If you want to write output to your local machine from a remote server (especially a hosted or virtualize machine such as Heroku or Amazon RDS), this solution is not suitable.
这会产生制表符分隔的格式。 如果您确定逗号不会出现在任何列数据中(制表符也不会出现),您可以使用此管道命令来获取真正的 CSV(感谢 致用户John Carter):
This produces a tab-separated format. If you are certain that commas do not appear in any of the column data (and neither do tabs), you can use this pipe command to get a true CSV (thanks to user John Carter):
这将为您提供一个制表符分隔的文件。 由于逗号(或包含逗号的字符串)不会被转义,因此将分隔符更改为逗号并不简单。
This will give you a tab-separated file. Since commas (or strings containing comma) are not escaped, it is not straightforward to change the delimiter to comma.
这是一种相当粗糙的方法[1]:
效果很好。 不过,正则表达式再次被证明是只写的。
正则表达式解释:
所以,把它们放在一起:
[1] 我在某个地方找到了它,不能接受任何功劳。
Here's a fairly gnarly way of doing it[1]:
It works pretty well. Once again, though, a regular expression proves write-only.
Regex Explanation:
So, putting it all together:
[1] I found it somewhere and can't take any credit.
通过 'tr' 进行管道传输(仅限 Unix/Cygwin):
注意:这不会处理嵌入的逗号,也没有嵌入的选项卡。
Pipe it through 'tr' (Unix/Cygwin only):
N.B.: This handles neither embedded commas, nor embedded tabs.
这救了我几次。 它速度快而且有效!
示例:
为了完整起见,您可以 转换为 CSV(但是要小心,因为选项卡可能位于字段值内 - 例如文本字段)
This saved me a couple of times. It is fast and it works!
Example:
For completeness you could convert to CSV (but be careful because tabs could be inside field values - e.g., text fields)
OUTFILE 解决方案 Paul Tomblin 给出< /a> 会导致在 MySQL 服务器本身上写入一个文件,因此仅当您具有 FILE 访问,以及登录访问或从该框中检索文件的其他方式。
如果您没有此类访问权限,并且制表符分隔的输出是 CSV 的合理替代品(例如,如果您的最终目标是导入到 Excel),则 serbaut 的解决方案(使用
mysql --batch
和可选的--raw
) 是正确的选择。The OUTFILE solution given by Paul Tomblin causes a file to be written on the MySQL server itself, so this will work only if you have FILE access, as well as login access or other means for retrieving the file from that box.
If you don't have such access, and tab-delimited output is a reasonable substitute for CSV (e.g., if your end goal is to import to Excel), then serbaut's solution (using
mysql --batch
and optionally--raw
) is the way to go.MySQL Workbench 可以将记录集导出为 CSV,而且它似乎可以很好地处理字段中的逗号出色地。 CSV 在 OpenOffice Calc 很好。
MySQL Workbench can export recordsets to CSV, and it seems to handle commas in fields very well. The CSV opens up in OpenOffice Calc fine.
迄今为止的所有解决方案,除了 MySQL Workbench 一个是不正确的,并且对于 MySQL 数据库中的至少某些可能的内容来说很可能是不安全的(即安全问题)。
MySQL Workbench(以及类似的 phpMyAdmin)提供了形式上正确的解决方案,但它们是为下载输出而设计的到用户的位置。 它们对于自动化数据导出之类的事情不太有用。
无法从 mysql -B -e 'SELECT ...' 的输出生成可靠、正确的 CSV 内容,因为它无法对字段中的回车符和空格进行编码。
mysql
的“-s”标志确实会进行反斜杠转义,并且可能会导致正确的解决方案。 然而,使用脚本语言(一种具有良好内部数据结构的语言,而不是 Bash)以及已经仔细解决了编码问题的库要安全得多。我想过为此编写一个脚本,但当我想到我要给它起什么名字时,我就想到要搜索现有的同名作品。 虽然我还没有彻底了解它,但 mysql2csv 看起来很有希望。 根据您的应用程序,指定 SQL 命令的 YAML 方法可能会也可能不会有吸引力。 我对比我的 Ubuntu 12.04 (Precise Pangolin) 笔记本电脑或 Debian 6.0 (Squeeze) 服务器。 是的,我知道我可以使用 RVM,但我不想为了如此简单的目的而维护它。
All of the solutions here to date, except the MySQL Workbench one, are incorrect and quite possibly unsafe (i.e., security issues) for at least some possible content in the MySQL database.
MySQL Workbench (and similarly phpMyAdmin) provide a formally correct solution, but they are designed for downloading the output to a user's location. They're not so useful for things like automating data export.
It is not possible to generate reliably correct CSV content from the output of
mysql -B -e 'SELECT ...'
because that cannot encode carriage returns and white space in fields. The '-s' flag tomysql
does do backslash escaping, and might lead to a correct solution. However, using a scripting language (one with decent internal data structures that is, not Bash), and libraries where the encoding issues have already been carefully worked out is far safer.I thought about writing a script for this, but as soon as I thought about what I'd call it, it occurred to me to search for preexisting work by the same name. While I haven't gone over it thoroughly, mysql2csv looks promising. Depending on your application, the YAML approach to specifying the SQL commands might or might not appeal though. I'm also not thrilled with the requirement for a more recent version of Ruby than comes as standard with my Ubuntu 12.04 (Precise Pangolin) laptop or Debian 6.0 (Squeeze) servers. Yes, I know I could use RVM, but I'd rather not maintain that for such a simple purpose.
此页面上的许多答案都很薄弱,因为它们不处理 CSV 格式中可能发生的一般情况。 例如,字段中嵌入的逗号和引号以及最终总会出现的其他条件。 我们需要一个适用于所有有效 CSV 输入数据的通用解决方案。
这是一个简单而强大的 Python 解决方案:
将该文件命名为
tab2csv
,将其放在您的路径中,授予其执行权限,然后像这样使用它:Python CSV 处理函数涵盖了 CSV 输入的极端情况格式。
这可以改进以通过流方法处理非常大的文件。
Many of the answers on this page are weak, because they don't handle the general case of what can occur in CSV format. E.g., commas and quotes embedded in fields and other conditions that always come up eventually. We need a general solution that works for all valid CSV input data.
Here's a simple and strong solution in Python:
Name that file
tab2csv
, put it on your path, give it execute permissions, then use it like this:The Python CSV-handling functions cover corner cases for CSV input format(s).
This could be improved to handle very large files via a streaming approach.
使用:
Use:
从命令行,您可以执行以下操作:
鸣谢: 将表从 Amazon RDS 导出到 CSV 文件
From your command line, you can do this:
Credits: Exporting table from Amazon RDS into a CSV file
我遇到了同样的问题,并且 Paul's Answer 不是一个选项,因为它是 Amazon RDS。 用逗号替换制表符不起作用,因为数据嵌入了逗号和制表符。 我发现 mycli 是 mysql 客户端的替代方案,支持 CSV 输出带有
--csv
标志的框:I encountered the same problem and Paul's Answer wasn't an option since it was Amazon RDS. Replacing the tab with the commas did not work as the data had embedded commas and tabs. I found that mycli, which is a drop-in alternative for the mysql-client, supports CSV output out of the box with the
--csv
flag:此答案使用 Python 和流行的第三方库 PyMySQL。 我添加它是因为 Python 的 csv 库功能强大,足以正确地 处理许多不同风格的
.csv
并且没有其他答案使用 Python 代码与数据库交互。This answer uses Python and a popular third party library, PyMySQL. I'm adding it because Python's csv library is powerful enough to correctly handle many different flavors of
.csv
and no other answers are using Python code to interact with the database.另外,如果您在 Bash 命令行上执行查询,我相信 tr 命令可用于将默认制表符替换为任意分隔符。
Also, if you're performing the query on the Bash command line, I believe the
tr
command can be used to substitute the default tabs to arbitrary delimiters.这很简单,它可以在任何情况下工作,不需要批处理模式或输出文件:
说明:
"
替换为""
-->replace( field1, '"', '""')
concat('"', result1, '"')
concat_ws(',',quoted1,quoted2,...)
就是这样!
This is simple, and it works on anything without needing batch mode or output files:
Explanation:
"
with""
in each field -->replace(field1, '"', '""')
concat('"', result1, '"')
concat_ws(',', quoted1, quoted2, ...)
That's it!
您可以拥有一个使用 CSV 引擎的 MySQL 表。
然后,您的硬盘上将有一个始终为 CSV 格式的文件,您只需复制该文件即可,无需对其进行处理。
You can have a MySQL table that uses the CSV engine.
Then you will have a file on your hard disk that will always be in a CSV format which you could just copy without processing it.
为了扩展之前的答案,以下一行将单个表导出为制表符分隔的文件。 它适合自动化,每天左右导出数据库。
方便地,我们可以使用相同的技术列出 MySQL 的表,并描述单个表上的字段:
To expand on previous answers, the following one-liner exports a single table as a tab-separated file. It's suitable for automation, exporting the database every day or so.
Conveniently, we can use the same technique to list out MySQL's tables, and to describe the fields on a single table:
建立在 user7610 的基础上,这是最好的方法。 使用
mysql outfile
时,存在 60 分钟的文件所有权和覆盖问题。虽然不太酷,但 5 分钟内就成功了。
php csvdump.php localhost root 密码数据库表名> 无论你喜欢什么.csv
Building on user7610, here is the best way to do it. With
mysql outfile
there were 60 mins of file ownership and overwriting problems.It's not cool, but it worked in 5 mins.
php csvdump.php localhost root password database tablename > whatever-you-like.csv
这就是我所做的:
Perl 脚本(从其他地方截取)很好地将制表符间隔字段转换为 CSV。
Here's what I do:
The Perl script (snipped from elsewhere) does a nice job of converting the tab spaced fields to CSV.
不完全是 CSV 格式,而是
MySQL 客户端中的 tee
命令可用于将输出保存到本地文件中:您可以使用
notee< 禁用它/代码>。
SELECT … INTO OUTFILE …;
的问题是它需要在服务器上写入文件的权限。Not exactly as a CSV format, but the
tee
command from the MySQL client can be used to save the output into a local file:You can disable it using
notee
.The problem with
SELECT … INTO OUTFILE …;
is that it requires permission to write files at the server.就我而言,
INTO OUTFILE .....
之前的from table_name .....
给出错误:什么对我有用:
In my case
from table_name .....
beforeINTO OUTFILE .....
gives an error:What works for me:
对我有用的:
该线程上的解决方案都不适合我的特定情况。 我的其中一列中有相当多的 JSON 数据,这些数据在我的 CSV 输出中会变得混乱。 对于那些有类似问题的人,请尝试以 \r\n 结尾的行。
对于那些尝试使用 Microsoft Excel 打开 CSV 的人来说,还有另一个问题,请记住,单个单元格可以容纳的字符数最多为 32,767 个字符,超过此限制,它会溢出到下面的行。 要确定列中的哪些记录存在问题,请使用以下查询。 然后,您可以截断这些记录或根据需要处理它们。
What worked for me:
None of the solutions on this thread worked for my particular case. I had pretty JSON data inside one of the columns, which would get messed up in my CSV output. For those with a similar problem, try lines terminated by \r\n instead.
Also another problem for those trying to open the CSV with Microsoft Excel, keep in mind there is a limit of 32,767 characters that a single cell can hold, above that it overflows to the rows below. To identify which records in a column have the issue, use the query below. You can then truncate those records or handle them as you'd like.
使用蒂姆·哈丁发布的解决方案< /a>,我创建了这个 Bash 脚本来简化该过程(需要 root 密码,但您可以轻松修改脚本以询问任何其他用户):
它将创建一个名为:database.table.csv< /强>
Using the solution posted by Tim Harding, I created this Bash script to facilitate the process (root password is requested, but you can modify the script easily to ask for any other user):
It will create a file named: database.table.csv
如果您在服务器上设置了 PHP,则可以使用 mysql2csv 导出一个(实际上有效的) 用于任意 MySQL 查询的 CSV 文件。 请参阅我在 MySQL - SELECT * INTO OUTFILE LOCAL 上的回答? 了解更多上下文/信息。
我尝试维护
mysql
中的选项名称,因此提供--file
和--query
选项就足够了:通过“安装”
mysql2csv
(下载要点内容,检查校验和并使其可执行。)
If you have PHP set up on the server, you can use mysql2csv to export an (actually valid) CSV file for an arbitrary MySQL query. See my answer at MySQL - SELECT * INTO OUTFILE LOCAL ? for a little more context/info.
I tried to maintain the option names from
mysql
so it should be sufficient to provide the--file
and--query
options:"Install"
mysql2csv
via(Download content of the gist, check checksum and make it executable.)
以下生成制表符分隔且有效的 CSV 输出。 与大多数其他答案不同,此技术可以正确处理制表符、逗号、引号和换行符的转义,而无需任何流过滤器,例如 sed、AWK 或 tr。
该示例展示了如何使用流将远程 MySQL 表直接通过管道传输到本地 SQLite 数据库。 这无需 FILE 权限或 SELECT INTO OUTFILE 权限即可工作。 为了便于阅读,我添加了新行。
需要
2>/dev/null
来抑制命令行上有关密码的警告。如果您的数据包含 NULL,您可以在查询中使用 IFNULL() 函数。
The following produces tab-delimited and valid CSV output. Unlike most of the other answers, this technique correctly handles escaping of tabs, commas, quotes, and new lines without any stream filter like sed, AWK, or tr.
The example shows how to pipe a remote MySQL table directly into a local SQLite database using streams. This works without FILE permission or SELECT INTO OUTFILE permission. I have added new lines for readability.
The
2>/dev/null
is needed to suppress the warning about the password on the command line.If your data has NULLs, you can use the IFNULL() function in the query.
Python 中的一个简单解决方案,可编写带有标头的标准格式 CSV 文件并将数据作为流写入(内存使用量低):
您可以像这样使用它:
为简单起见,这故意不包含 另一个答案,例如使用环境变量作为凭据、
contextlib
等。那里提到了关于行结尾的微妙之处我还没有评价过。A simple solution in Python that writes a standard-format CSV file with headers and writes data as a stream (low memory use):
You could use it like:
For simplicity, this intentionally doesn't include some fancier stuff from another answer like using an environment variable for credentials,
contextlib
, etc. There is a subtlety mentioned there about line endings that I haven't evaluated.用于对 CSV 转储进行简单查询的小型 Bash 脚本,灵感来自 蒂姆·哈丁的回答。
Tiny Bash script for doing simple query to CSV dumps, inspired by Tim Harding's answer.
如果您收到
secure-file-priv
错误,那么在将目标文件位置移动到C:\ProgramData\MySQL\MySQL Server 8.0\Uploads
后,然后查询 -SELECT * FROM attend INTO OUTFILE 'C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\FileName.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n ';
不起作用,您只需将查询中的
\
(backsplash) 更改为/
(forwardsplash)即可,
示例:
每次运行成功时查询,每次都会生成新的CSV文件!
很酷,对吧?
If you are getting an error of
secure-file-priv
then, also after shifting your destination file location inside theC:\ProgramData\MySQL\MySQL Server 8.0\Uploads
and also after then the query -SELECT * FROM attendance INTO OUTFILE 'C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\FileName.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n';
is not working, you have to just change
\
(backsplash) from the query to/
(forwardsplash)And that works!!
Example:
Each time when you run the successful query, it will generate the new CSV file each time!
Cool, right?
这又脏又丑。 它仅适用于您拥有的只是 PHP-*-admin 并且服务器使用
--secure-file-priv
选项运行的特定情况,因此您不能使用INTO OUTFILE '/path/to/export.csv'
查询中的子句。您可以做的是使用...等待它!,
CONCAT
解析 CSV 行,然后复制结果并将其粘贴到文件中。这是一个示例,我需要 SQL 格式(将其调整为 CSV 很简单):
这提供了很好的、准备好导入的输出,类似于:
This is dirty and ugly. It is only suitable for the particular situation where all you have is a PHP-*-admin and the server is running with the
--secure-file-priv
option, so then you cannot use theINTO OUTFILE '/path/to/export.csv'
clause in your query.What you can do is parse lines of CSV with ... wait for it!,
CONCAT
, then copy the results and paste them into a file.Here's an example, where I needed SQL format (it'd be trivial to adapt it for CSV):
That gives nice, ready for import output similar to this: