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

发布于 2024-07-10 19:46:40 字数 428 浏览 7 评论 0原文

有没有一种简单的方法可以从 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

标点 2024-07-17 19:46:40

来自 将 MySQL 查询结果保存到文本或 CSV 文件中

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< /a> 或 Amazon RDS),此解决方案不合适。

From 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';

Note: That syntax may need to be reordered to

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

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.

岁月打碎记忆 2024-07-17 19:46:40
mysql your_database --password=foo < my_requests.sql > out.tsv

这会产生制表符分隔的格式。 如果您确定逗号不会出现在任何列数据中(制表符也不会出现),您可以使用此管道命令来获取真正的 CSV(感谢 致用户John Carter):

... .sql | sed 's/\t/,/g' > out.csv
mysql your_database --password=foo < my_requests.sql > out.tsv

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

... .sql | sed 's/\t/,/g' > out.csv
黎夕旧梦 2024-07-17 19:46:40

mysql --batch,-B

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

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

mysql --batch, -B

Print results using tab as the column separator, with each row on a
new line. With this option, mysql does not use the history file.
Batch mode results in non-tabular output format and escaping of
special characters. Escaping may be disabled by using raw mode; see
the description for the --raw option.

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.

陌伤浅笑 2024-07-17 19:46:40

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

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

效果很好。 不过,正则表达式再次被证明是只写的。


正则表达式解释:

  • s/// 表示将第一个 // 之间的内容替换为第二个 // 之间的内容 //
  • 末尾的“g”是修饰符,表示“所有实例,而不仅仅是第一个”
  • ^(在此上下文中)表示开始of line
  • $ (在这种情况下)意味着行尾

所以,把它们放在一起:

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] 我在某个地方找到了它,不能接受任何功劳。

Here's a fairly gnarly way of doing it[1]:

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

It works pretty well. Once again, though, a regular expression proves write-only.


Regex Explanation:

  • s/// means substitute what's between the first // with what's between the second //
  • the "g" at the end is a modifier that means "all instance, not just first"
  • ^ (in this context) means beginning of line
  • $ (in this context) means end of line

So, putting it all together:

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] I found it somewhere and can't take any credit.

陪我终i 2024-07-17 19:46:40

通过 'tr' 进行管道传输(仅限 Unix/Cygwin):

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

注意:这不会处理嵌入的逗号,也没有嵌入的选项卡。

Pipe it through 'tr' (Unix/Cygwin only):

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

N.B.: This handles neither embedded commas, nor embedded tabs.

一袭水袖舞倾城 2024-07-17 19:46:40

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

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

--raw < em>禁用字符转义(\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' ',' < 文件.tsv > 文件.csv

This saved me a couple of times. It is fast and it works!

--batch
Print results using tab as the column separator, with each row on a
new line.

--raw disables character escaping (\n, \t, \0, and \)

Example:

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

For completeness you could convert to CSV (but be careful because tabs could be inside field values - e.g., text fields)

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

紫南 2024-07-17 19:46:40

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.

無心 2024-07-17 19:46:40

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.

掌心的温暖 2024-07-17 19:46:40

迄今为止的所有解决方案,除了 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 to mysql 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.

溺ぐ爱和你が 2024-07-17 19:46:40

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

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

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:

#!/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)

Name that file tab2csv, put it on your path, give it execute permissions, then use it like this:

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

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.

静若繁花 2024-07-17 19:46:40

使用:

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

Use:

mysql your_database -p < my_requests.sql | awk '{print $1","$2}' > out.csv
梅倚清风 2024-07-17 19:46:40

从命令行,您可以执行以下操作:

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

From your command line, you can do this:

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*

Credits: Exporting table from Amazon RDS into a CSV file

若沐 2024-07-17 19:46:40

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

mycli db_name --csv -e "select * from flowers" > flowers.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:

mycli db_name --csv -e "select * from flowers" > flowers.csv
甚是思念 2024-07-17 19:46:40

此答案使用 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://stackoverflow.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://stackoverflow.com/a/17725590/2958070 about lineterminator
    csv_writer = csv.writer(csvfile, lineterminator='\n')
    csv_writer.writerows(results)

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.

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://stackoverflow.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://stackoverflow.com/a/17725590/2958070 about lineterminator
    csv_writer = csv.writer(csvfile, lineterminator='\n')
    csv_writer.writerows(results)
难理解 2024-07-17 19:46:40

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

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

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.

$ echo "SELECT * FROM Table123" | mysql Database456 | tr "\t" ,
⒈起吃苦の倖褔 2024-07-17 19:46:40

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

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

就是这样!

This is simple, and it works on anything without needing batch mode or output files:

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

from your_table where etc;

Explanation:

  1. Replace " with "" in each field --> replace(field1, '"', '""')
  2. Surround each result in quotation marks --> concat('"', result1, '"')
  3. Place a comma between each quoted result --> concat_ws(',', quoted1, quoted2, ...)

That's it!

箜明 2024-07-17 19:46:40

您可以拥有一个使用 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.

幸福丶如此 2024-07-17 19:46:40

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

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    

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.

mysql -B -D mydatabase -e 'select * from mytable'

Conveniently, we can use the same technique to list out MySQL's tables, and to describe the fields on a single table:

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    
却一份温柔 2024-07-17 19:46:40

建立在 user7610 的基础上,这是最好的方法。 使用 mysql outfile 时,存在 60 分钟的文件所有权和覆盖问题。

虽然不太酷,但 5 分钟内就成功了。

php csvdump.php localhost root 密码数据库表名> 无论你喜欢什么.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);

?>

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

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

?>
旧瑾黎汐 2024-07-17 19:46:40

这就是我所做的:

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。

Here's what I do:

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

The Perl script (snipped from elsewhere) does a nice job of converting the tab spaced fields to CSV.

疧_╮線 2024-07-17 19:46:40

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

tee foobar.txt
SELECT foo FROM bar;

您可以使用 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:

tee foobar.txt
SELECT foo FROM bar;

You can disable it using notee.

The problem with SELECT … INTO OUTFILE …; is that it requires permission to write files at the server.

鸠魁 2024-07-17 19:46:40

就我而言, INTO OUTFILE ..... 之前的 from table_name ..... 给出错误:

子句的顺序意外。 (位置 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'

In my case from table_name ..... before INTO OUTFILE ..... gives an error:

Unexpected ordering of clauses. (near "FROM" at position 10)

What works for me:

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'
望笑 2024-07-17 19:46:40

对我有用的:

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;

What worked for me:

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

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.

SELECT id,name,CHAR_LENGTH(json_student_description) AS 'character length'
FROM students
WHERE CHAR_LENGTH(json_student_description)>32767;
无需解释 2024-07-17 19:46:40

使用蒂姆·哈丁发布的解决方案< /a>,我创建了这个 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< /强>

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

#!/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

It will create a file named: database.table.csv

忆梦 2024-07-17 19:46:40

如果您在服务器上设置了 PHP,则可以使用 mysql2csv 导出一个(实际上有效的) 用于任意 MySQL 查询的 CSV 文件。 请参阅我在 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

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

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:

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

"Install" mysql2csv via

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

(Download content of the gist, check checksum and make it executable.)

梦与时光遇 2024-07-17 19:46:40

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

该示例展示了如何使用流将远程 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 

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

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

\t' mydb.db '.import /dev/stdin mycsvtable'

需要 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.

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 

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.

\t' mydb.db '.import /dev/stdin mycsvtable'

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.

恬淡成诗 2024-07-17 19:46:40

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

为简单起见,这故意不包含 另一个答案,例如使用环境变量作为凭据、contextlib等。那里提到了关于行结尾的微妙之处我还没有评价过。

A simple solution in Python that writes a standard-format CSV file with headers and writes data as a stream (low memory use):

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)

You could use it like:

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

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.

赠我空喜 2024-07-17 19:46:40

用于对 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"

Tiny Bash script for doing simple query to CSV dumps, inspired by Tim Harding's answer.

#!/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"
幸福丶如此 2024-07-17 19:46:40

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

即可,

示例:

从出勤中选择 * INTO OUTFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/FileName.csv' 字段以 ',' 结尾,由 '"' 结尾,行以 '\n' 结尾;

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

If you are getting an error of secure-file-priv then, also after shifting your destination file location inside the C:\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:

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

Each time when you run the successful query, it will generate the new CSV file each time!
Cool, right?

痴者 2024-07-17 19:46:40

这又脏又丑。 它仅适用于您拥有的只是 PHP-*-admin 并且服务器使用 --secure-file-priv 选项运行的特定情况,因此您不能使用 INTO OUTFILE '/path/to/export.csv' 查询中的子句。

您可以做的是使用...等待它!,CONCAT 解析 CSV 行,然后复制结果并将其粘贴到文件中。

这是一个示例,我需要 SQL 格式(将其调整为 CSV 很简单):

SELECT CONCAT(
"('",
`username`, "', '",
`password`, "', '",
`first_name`, "', '",
`last_name`, "', '",
`gender`, "'),"
) AS `row` 
FROM `users`
WHERE `role` != 'Not set'
AND `user_status` = 'Active'
ORDER BY `role`, `gender`, `user_id`
LIMIT 200

这提供了很好的、准备好导入的输出,类似于:

('jane', '3d7ff...', 'Jane', 'Doe', 'Female'),  
('john', 'd2a33...', 'John', 'Doe', 'Male'),
...

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 the INTO 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):

SELECT CONCAT(
"('",
`username`, "', '",
`password`, "', '",
`first_name`, "', '",
`last_name`, "', '",
`gender`, "'),"
) AS `row` 
FROM `users`
WHERE `role` != 'Not set'
AND `user_status` = 'Active'
ORDER BY `role`, `gender`, `user_id`
LIMIT 200

That gives nice, ready for import output similar to this:

('jane', '3d7ff...', 'Jane', 'Doe', 'Female'),  
('john', 'd2a33...', 'John', 'Doe', 'Male'),
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文