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

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


当前回答

本页上的许多答案都很薄弱,因为它们没有处理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输入格式的大小写。

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

其他回答

从Save 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或Amazon RDS)向本地机器写入输出,则此解决方案不适合。

微小的Bash脚本,用于对CSV转储进行简单查询,灵感来自Tim Harding的回答。

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

Use:

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

另外,如果在Bash命令行上执行查询,我认为可以使用tr命令将默认选项卡替换为任意分隔符。

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

如果您正在使用的机器上安装了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和文本字段没有任何问题。这些字段被正确地引用,其中的换行符将被CSV阅读器解释为文本的一部分,而不是记录分隔符。这在sed之后是很难纠正的。