Bagaimana cara menampilkan hasil permintaan MySQL dalam format CSV?

1183

Apakah ada cara mudah untuk menjalankan kueri MySQL dari baris perintah Linux dan menampilkan hasilnya dalam format CSV ?

Inilah yang saya lakukan sekarang:

mysql -u uid -ppwd -D dbname << EOQ | sed -e 's/        /,/g' | tee list.csv
select id, concat("\"",name,"\"") as name
from students
EOQ

Itu menjadi berantakan ketika ada banyak kolom yang perlu dikelilingi oleh tanda kutip, atau jika ada tanda kutip dalam hasil yang perlu diloloskan.

MCS
sumber
1
Anda dapat menggunakan REPLACE()dalam kueri Anda untuk mendapatkan penawaran.
dsm
Lihatlah jawaban saya di [stackoverflow ini] [1] [1]: stackoverflow.com/questions/12242772/…
biniam
Anda bisa memformat data tabel sebagai tabel teks .
Somnath Muluk
2
Jawaban yang diterima untuk pertanyaan stackoverflow ini mungkin adalah cara terbaik: stackoverflow.com/questions/3760631/mysql-delimiter-question
Samuel Åslund
Saya menulis permintaan fitur pada pelacak bug MariaDB ( jira.mariadb.org/browse/MDEV-12879 ) Anda dapat memberikan suaranya.
Jared Beck

Jawaban:

1760

Dari http://www.tech-recipes.com/rx/1475/save-mysql-query-result-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';

Menggunakan perintah ini kolom nama tidak akan diekspor.

Perhatikan juga bahwa /var/lib/mysql-files/orders.csvakan berada di server yang menjalankan MySQL. Pengguna yang menjalankan proses MySQL harus memiliki izin untuk menulis ke direktori yang dipilih, atau perintah akan gagal.

Jika Anda ingin menulis keluaran ke mesin lokal Anda dari server jauh (terutama mesin yang dihosting atau divirtualkan seperti Heroku atau Amazon RDS), solusi ini tidak cocok.

Paul Tomblin
sumber
16
@ Thomas jika Anda memiliki akses ke sistem file jarak jauh dan MySQL, Anda harus dapat menulis di suatu tempat. alih-alih / tmp, coba /home/yourusername/file.csv - jika itu gagal, dan set hasilnya tidak terlalu besar, Anda bisa menyalin output dari klien SSH Anda dan menempelkannya ke mesin lokal Anda.
Michael Butler
63
Pertanyaannya ditentukan MySQL, bukan "standar sesuai".
Paul Tomblin
35
Bagaimana cara memasukkan tajuk juga?
Bogdan Gusiev
66
@BogdanGusiev, Anda dapat memasukkan tajuk dengan menambahkan "SELECT 'order_id', 'product_name', 'qty' UNION" sebelum permintaan yang sebenarnya. Pertama pilih header pengembalian permintaan, permintaan kedua mengembalikan data nyata; UNION bergabung bersama.
petrkotek
19
@ Michael Butler: Ya, tidak, sebenarnya. Jika Anda menggunakan Amazon RDS, Heroku, atau solusi yang di-host lainnya, Anda tidak mungkin hanya dapat menulis ke server orang lain.
Ken Kinder
459
$ mysql your_database --password=foo < my_requests.sql > out.csv

Yang dipisahkan tab. Pipa seperti itu untuk mendapatkan CSV yang benar (terima kasih @therefromhere):

... .sql | sed 's/\t/,/g' > out.csv
Stan
sumber
5
tidak hanya itu, tetapi memungkinkan konten untuk dibuat dari host basis data jauh, tidak seperti yang lain menulis ke sistem file lokal.
tmarthal
31
Ini dipisahkan tab, tidak dipisahkan koma.
Flimm
13
@ Flimm, dengan asumsi Anda tidak memiliki koma / tab yang tertanam di bidang Anda dapat mengonversinya dengan memipipkan hasilnya ke| sed 's/\t/,/g'
John Carter
111
perbaikan 'sed' tidak mengompensasi koma yang mungkin muncul di salah satu data yang dipilih dan akan condong kolom Anda dihasilkan sesuai
Joey T
14
Negativitas itu valid .. ini mungkin bekerja untuk Anda sekarang tetapi itu bisa menggigit Anda di masa depan ketika data Anda menyertakan tab atau koma dll.
John Hunt
204

mysql --batch, -B

Cetak hasil menggunakan tab sebagai pemisah kolom, dengan setiap baris pada baris baru. Dengan opsi ini, mysql tidak menggunakan file riwayat. Mode batch menghasilkan format output non-tabular dan keluar dari karakter khusus. Lolos dapat dinonaktifkan dengan menggunakan mode mentah; lihat deskripsi untuk opsi --raw.

Ini akan memberi Anda file yang dipisahkan tab. Karena koma (atau string yang mengandung koma) tidak lolos, tidak mudah untuk mengubah pembatas menjadi koma.

serbaut
sumber
12
ini adalah solusi yang lebih disukai: 1) daftar nilai yang dipisahkan-tab adalah umum di UNIX 2) Impor TSV didukung secara asli oleh sebagian besar sistem impor, termasuk Excel, OpenOffice Spreadsheets, dll. 3) tidak perlu melarikan diri karakter kutipan untuk bidang teks 4 ) membuat ekspor baris perintah menjadi mudah
Joey T
5
ini adalah solusi terbaik karena tidak seperti yang pertama tidak perlu memiliki izin pada server seperti RDS
Muayyad Alsadi
8
Trik yang rapi: jika Anda menyimpan file yang dipisahkan tab sebagai .xls alih-alih .csv, itu akan terbuka di excel tanpa perlu konversi "teks ke data" dan tanpa masalah pengaturan regional.
serbaut
3
@ Joey T - Anda masih perlu menghindari tab dan carriage return. Juga jika konten bidang tampak seperti bidang yang dikutip atau lolos, konten yang diimpor mungkin tidak terlihat seperti aslinya.
mc0e
2
Anda akan memiliki masalah dengan NULLs .. mereka akan keluar sebagai string nulls ..
Jonathan
141

Inilah cara yang cukup sulit untuk melakukannya. Ditemukan di suatu tempat, tidak dapat mengambil kredit

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

Bekerja dengan cukup baik. Sekali lagi meskipun regex hanya membuktikan menulis.


Penjelasan Regex:

  • s /// berarti mengganti apa antara yang pertama // dengan apa yang ada di antara yang kedua //
  • "g" pada akhirnya adalah pengubah yang berarti "semua contoh, bukan hanya yang pertama"
  • ^ (dalam konteks ini) berarti awal baris
  • $ (dalam konteks ini) berarti ujung baris

Jadi, kumpulkan semuanya:

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
Tim Harding
sumber
3
Bendera -e persis seperti yang saya cari! Terima kasih!
Gaurav Gupta
1
Regex ini sebenarnya cukup sederhana; seperti banyak jawaban lain di halaman ini, itu hanya membersihkan keluaran dari mysql -B. Jika Anda memisahkan regex menjadi pernyataan individual pada baris terpisah, itu akan cukup sederhana (untuk seseorang yang tahu regex) untuk memahaminya.
Mei
7
Sekilas, ini terlihat sangat rusak. Tab dan carriage return dalam konten akan salah penanganan. "s / '/ \' /;" tidak melakukan apa-apa, karena tanda kutip ganda dalam perintah shell mengkonsumsi backslash. Banyak bug serupa lainnya dengan backslash hilang. Tidak ada penanganan untuk backslash di bidang db.
mc0e
1
Sepertinya perintah ini bekerja dengan baik di Linux tetapi tidak di Mac
Hemerson Varela
6
Ini akan pecah jika Anda memiliki bidang teks yang berisi tab, garis miring terbalik ",",, dan sejumlah hal lainnya. Regex bukanlah cara untuk menyelesaikan masalah ini
aidan
93

Hanya Unix / Cygwin , pipa melalui 'tr':

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

NB: Ini tidak menangani koma yang disematkan, atau tab yang disematkan.

strickli
sumber
53

Ini menyelamatkan saya beberapa kali. Cepat dan berhasil!

--batch Mencetak hasil menggunakan tab sebagai pemisah kolom, dengan setiap baris pada baris baru.

--raw menonaktifkan menonaktifkan karakter (\ n, \ t, \ 0, dan \)

Contoh:

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

Untuk kelengkapan, Anda dapat mengonversi ke csv (tapi hati-hati karena tab bisa berada di dalam nilai bidang - misalnya bidang teks)

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

hrvoj3e
sumber
4
Kecuali saya kehilangan sesuatu, ini membuat file TSV, bukan file CSV ...
PressingOnAlways
@TekanOnAlways Ya. Kutipan dokumen MySQL: "Cetak hasil menggunakan tab sebagai pemisah kolom, dengan setiap baris pada baris baru." Tapi parsing seharusnya tidak menjadi masalah dengan pembatas apa pun. Saya menggunakannya untuk membuat file excel untuk klien saya.
hrvoj3e
39

Solusi OUTFILE yang diberikan oleh Paul Tomblin menyebabkan file ditulis di server MySQL itu sendiri, jadi ini hanya akan berfungsi jika Anda memiliki FILE akses , serta akses masuk atau cara lain untuk mengambil file dari kotak itu.

Jika Anda tidak memiliki akses seperti itu, dan keluaran yang dibatasi-tab adalah pengganti yang wajar untuk CSV (mis., Jika tujuan akhir Anda adalah mengimpor ke Excel), maka solusi Serbaut (menggunakan mysql --batchdan opsional --raw) adalah cara yang harus dilakukan.

Leland Woodbury
sumber
36

MySQL Workbench dapat mengekspor set rekaman ke CSV, dan tampaknya menangani koma di bidang dengan sangat baik. CSV terbuka di OpenOffice fine.

David Oliver
sumber
2
Terima kasih sejuta David. Setelah menghabiskan 3 jam mendapatkan baris baru untuk menampilkan dengan benar untuk konten HTML dalam data, saya menggunakan MySQL Workbench dan dalam 2 menit saya sudah menyiapkan file CSV saya.
mr-euro
Saya baru saja menemukan itu dapat menyimpan sebagai XML, yang bagus. Saya berharap untuk bermigrasi dari satu aplikasi ke aplikasi lain dengan menggunakan XSLT untuk mengubah XML ini menjadi file CSV yang cocok untuk diimpor ke aplikasi target.
David Oliver
meja kerja mysql adalah opsi terbaik untuk fitur ekspor impor.
cijagani
1
Saya baru saja berhasil mengekspor lebih dari setengah juta baris menggunakan meja kerja mysql sehingga file-file besar tampaknya tidak menjadi masalah. Anda hanya perlu memastikan bahwa Anda menghapus batas pilih sebelum menjalankan kueri Anda dan Anda mungkin juga harus meningkatkan nilai berikut dalam file my.ini Anda: max_allowed_packet = 500M, net_read_timeout = 600, net_write_timeout = 600
Vincent
3
MySQL workbench memiliki kebocoran memori yang memalukan ketika mengekspor data dalam CSV, jika Anda memiliki kumpulan data besar seperti 1 atau 2 juta baris lebih, RAM 12 GB (diuji pada mesin linux saya) tidak cukup dan memori tidak dihapus kecuali Anda bunuh atau hentikan. Untuk kumpulan data besar ini bukan solusi.
Ostico
33

Bagaimana tentang:

mysql your_database -p < my_requests.sql | awk '{print $1","$2}' > out.csv
Steve
sumber
2
Saya sangat suka yang ini. Jauh lebih bersih, dan saya suka menggunakan awk. Namun, saya mungkin akan pergi dengan ini: mysql -uUser -pPassword your_database < my_requests.sql | awk 'BEGIN{OFS="=";} {print $1,$2}' > out.csv
Josh
7
Ini gagal untuk nilai bidang dengan spasi.
Barun Sharma
29

Semua solusi di sini sampai saat ini, kecuali satu workbench MySQL, salah dan sangat mungkin tidak aman (yaitu masalah keamanan) untuk setidaknya beberapa konten yang mungkin di mysql db.

MYSQL Workbench (dan juga PHPMyAdmin) memberikan solusi yang benar secara formal, tetapi dirancang untuk mengunduh output ke lokasi pengguna. Mereka tidak begitu berguna untuk hal-hal seperti mengotomatisasi ekspor data.

Tidak mungkin untuk menghasilkan csv yang benar andal dari output mysql -B -e 'SELECT ...' karena tidak dapat menyandikan carriage return dan ruang putih di bidang. Bendera '-s' ke mysql tidak menghilangkan backslash, dan mungkin mengarah ke solusi yang benar. Namun, menggunakan bahasa scripting (yang dengan struktur data internal yang layak, bukan bash), dan perpustakaan di mana masalah pengkodean telah dipecahkan dengan hati-hati jauh lebih aman.

Saya berpikir untuk menulis skrip untuk ini, tetapi segera setelah saya memikirkan apa yang saya sebut, terpikir oleh saya untuk mencari karya yang sudah ada sebelumnya dengan nama yang sama. Meskipun saya belum membahasnya secara menyeluruh, solusi di https://github.com/robmiller/mysql2csv terlihat menjanjikan. Tergantung pada aplikasi Anda, pendekatan yaml untuk menentukan perintah SQL mungkin atau mungkin tidak menarik. Saya juga tidak senang dengan persyaratan untuk versi ruby ​​yang lebih baru daripada datang sebagai standar dengan laptop Ubuntu 12,04 saya atau server Debian Squeeze. Ya saya tahu saya bisa menggunakan RVM, tapi saya lebih suka tidak mempertahankannya untuk tujuan yang sederhana.

Semoga seseorang akan menunjukkan alat yang cocok, yang telah sedikit diuji. Kalau tidak, saya mungkin akan memperbarui ini ketika saya menemukan atau menulis satu.

mc0e
sumber
1
Anda benar, untuk string kompleks dalam tabel Anda harus menggunakan beberapa perpustakaan yang layak, bukan hanya bash. Saya pikir nodejs memiliki solusi yang lebih baik untuk tindakan semacam ini. seperti contoh
yeya
1
Hai, jawaban yang bagus, saya akan menambahkan tautan ke solusi python yang diusulkan di bawah ini stackoverflow.com/a/35123787/1504300 , yang berfungsi dengan baik dan sangat sederhana. Saya mencoba mengedit posting Anda tetapi hasil editnya ditolak
reallynice
26

Banyak jawaban di halaman ini lemah karena mereka tidak menangani kasus umum tentang apa yang dapat terjadi dalam format CSV. mis. koma dan kutipan tertanam di bidang dan kondisi lain yang selalu muncul akhirnya. Kami membutuhkan solusi umum yang berfungsi untuk semua data input CSV yang valid.

Berikut adalah solusi sederhana dan kuat dalam 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)

Beri nama file itu tab2csv, letakkan di jalur Anda, berikan izin eksekusi, lalu gunakan seperti ini:

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

Fungsi penanganan CSV Python mencakup kasus sudut untuk format input CSV.

Ini dapat ditingkatkan untuk menangani file yang sangat besar melalui pendekatan streaming.

Chris Johnson
sumber
8
Solusi yang bahkan lebih dapat diandalkan adalah dengan benar-benar terhubung ke database dengan Python, maka Anda harus memiliki waktu yang lebih mudah melakukan apa yang perlu Anda lakukan untuk menangani dataset yang lebih besar (hasil chunking, streaming, dll).
Josh Rumbut
@JoshRumbut, benar-benar terlambat, tapi saya membuat stackoverflow.com/a/41840534/2958070 untuk melengkapi komentar Anda
Ben
24

Dari baris perintah Anda, Anda dapat melakukan ini:

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*

Kredit: Mengekspor tabel dari Amazon RDS ke file csv

Sri Murthy Upadhyayula
sumber
itu salah satu oneliner gila. hatsoff
Elias Escalante
17
  1. logika:

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

Saat Anda membuat tabel CSV, server membuat file format tabel di direktori database. File dimulai dengan nama tabel dan memiliki ekstensi .frm. Mesin penyimpanan juga membuat file data. Namanya dimulai dengan nama tabel dan memiliki ekstensi .CSV. File data adalah file teks biasa. Saat Anda menyimpan data ke dalam tabel, mesin penyimpanan menyimpannya ke file data dalam format nilai yang dipisahkan koma.

zloctb
sumber
1
Bagus karena ini benar tanpa penyesuaian lain yang diperlukan.
Andrew Schulman
13

Jawaban ini menggunakan Python dan perpustakaan pihak ketiga yang populer, PyMySQL . Saya menambahkan karena Python csv perpustakaan cukup kuat untuk benar menangani banyak rasa yang berbeda dari .csvdan tidak ada jawaban lainnya menggunakan kode Python untuk berinteraksi dengan 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
# /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)
Ben
sumber
Jawaban menggunakan python sudah disediakan. stackoverflow.com/a/35123787/5470883
Alexander Baltasar
4
@AlexanderBaltasar, benar, dan ini terlihat bermanfaat, tetapi tidak menggunakan kode Python untuk berinteraksi dengan database. Lihat komentar tentang itu pada pertanyaan itu.
Ben
11

Ini sederhana, dan berfungsi pada apa pun tanpa perlu mode batch atau file output:

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

from your_table where etc;

Penjelasan:

  1. Ganti "dengan ""di setiap bidang ->replace(field1, '"', '""')
  2. Kelilingi setiap hasil dalam tanda kutip -> concat('"', result1, '"')
  3. Tempatkan koma di antara setiap hasil yang dikutip -> concat_ws(',', quoted1, quoted2, ...)

Itu dia!

Marty Hirsch
sumber
1
Perhatikan bahwa NULLnilai akan dilewati oleh concat_ws(), menghasilkan ketidakcocokan kolom. Untuk menghindari ini, cukup gunakan string kosong sebagai gantinya: IFNULL(field, '')(atau apa pun yang Anda gunakan untuk mewakili NULL)
Marco Roy
10

Atau dengan jawaban di atas, Anda dapat memiliki tabel MySQL yang menggunakan mesin CSV.

Kemudian Anda akan memiliki file di hard disk Anda yang akan selalu dalam format CSV yang bisa Anda salin tanpa memprosesnya.

Jonathan
sumber
1
Apa batasan ini dalam hal ukuran file / wrote / baca / etc?
Zach Smith
8

Untuk memperluas jawaban sebelumnya, satu-baris berikut ini mengekspor satu tabel sebagai file yang dipisahkan dengan tab. Ini cocok untuk otomatisasi, mengekspor database setiap hari atau lebih.

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

Dengan mudah, kita dapat menggunakan teknik yang sama untuk membuat daftar tabel MySQL, dan untuk menggambarkan bidang pada satu tabel:

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    
johntellsallall
sumber
4
Untuk mengkonversi ke CSV:mysql -B -D mydatabase -e 'select * from mytable' | sed -e 's/\t/,/g'
DSimon
7
Penggunaan sed -e 's/\t/,/g'hanya aman jika Anda yakin bahwa data Anda tidak mengandung koma atau tab.
awatts
7

Membangun di user7610, di sini adalah cara terbaik untuk melakukannya. Dengan mysql outfileada 60 menit kepemilikan file dan masalah menimpa.

Itu tidak keren, tetapi bekerja dalam 5 menit.

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

?>
Michael Cole
sumber
1
Bagus, bersih, dan bekerja dengan cepat - ini adalah solusi hebat jika Anda dapat menjalankan PHP di lingkungan itu!
John Fiala
7

Juga, jika Anda melakukan kueri pada baris perintah Bash, saya yakin trperintah itu dapat digunakan untuk mengganti tab default menjadi pembatas yang berubah-ubah.

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

Brian
sumber
5

Inilah yang saya lakukan:

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

Script perl (diambil dari tempat lain) melakukan pekerjaan yang bagus untuk mengonversi tab spasi bidang ke CSV.

pesawat luar angkasa
sumber
Ini bagus. Peningkatan sedikit mungkin mengutip semuanya kecuali angka perl -F"\t" -lane 'print join ",", map {s/"/""/g; /^\d+(?:\.\d+)?$/ ? $_ : qq("$_")} @F '- milik Anda tidak akan mengutip1.2.3
artfulrobot
5

Tidak persis seperti format CSV, tetapi teeperintah dari klien MySQL dapat digunakan untuk menyimpan output ke file lokal :

tee foobar.txt
SELECT foo FROM bar;

Anda dapat menonaktifkannya menggunakan notee .

Masalahnya SELECT … INTO OUTFILE …;adalah bahwa itu memerlukan izin untuk menulis file di server.

Denilson Sa Maia
sumber
Jika ekstensi .csv digunakan sebagai ganti .txt, apakah ada masalah pemformatan yang harus diperhatikan?
datalifenyc
@myidealab Masalah pemformatan muncul dari koma dll. tidak keluar. CSV adalah format teks biasa sehingga tidak ada masalah pemformatan hanya dari menukar ekstensi.
jkmartindale
3

Menggunakan solusi yang diposting oleh Tim, saya membuat skrip bash ini untuk memudahkan proses (root password diminta, tetapi Anda dapat memodifikasi skrip dengan mudah untuk meminta pengguna lain):

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

Ini akan membuat file bernama: database.table.csv

lepe
sumber
3

Jika Anda memiliki PHP yang disiapkan di server, Anda dapat menggunakan mysql2csv untuk mengekspor file CSV (benar-benar valid) untuk permintaan mysql yang sangat besar. Lihat jawaban saya di MySQL - SELECT * INTO OUTFILE LOCAL? untuk lebih banyak konteks / info.

Saya mencoba mempertahankan nama opsi dari mysqlsehingga cukup untuk menyediakan --filedan --queryopsi:

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

"Instal" mysql2csvmelalui

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

(unduh konten intinya, periksa checksum dan buat itu dapat dieksekusi).

Hirnhamster
sumber
3

Apa yang berhasil untuk saya:

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

Tidak ada solusi di utas ini bekerja untuk kasus khusus saya, saya punya data json cantik di salah satu kolom, yang akan kacau dalam output csv saya. Bagi mereka yang memiliki masalah serupa, coba baris yang diakhiri oleh \ r \ n sebagai gantinya.

Juga masalah lain bagi mereka yang mencoba untuk membuka csv dengan Microsoft Excel, perlu diingat ada batas 32.767 karakter yang dapat dimiliki oleh satu sel, di atas itu melimpah ke baris di bawah ini. Untuk mengidentifikasi catatan mana dalam kolom yang memiliki masalah, gunakan kueri di bawah ini. Anda kemudian dapat memotong catatan itu atau menanganinya seperti yang Anda inginkan.

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

Jika Anda mendapatkan kesalahan secure-file-privsaat itu, juga setelah menggeser lokasi file tujuan Anda di dalam C:\ProgramData\MySQL\MySQL Server 8.0\Uploadsdan juga setelah itu 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';

tidak berfungsi, Anda hanya perlu mengubah \(backsplash) dari kueri menjadi/ (forwardsplash)

Dan itu berhasil !!

Contoh:

PILIH * DARI KEBERADAAN KEPENTINGAN 'C: / ProgramData / MySQL / MySQL Server 8.0 / Uploads / FileName.csv' BIDANG-BIDANG YANG DITENTUKAN OLEH ',' DITUTUP OLEH '"' JALUR DITENTUKAN OLEH '\ n';

Setiap kali ketika Anda menjalankan kueri yang berhasil, itu akan menghasilkan file csv baru setiap kali! Keren kan?

AAYUSH SHAH
sumber
1

Skrip bash kecil untuk melakukan kueri sederhana ke CSV dumps, terinspirasi oleh https://stackoverflow.com/a/5395421/2841607 .

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

Skrip bash berikut berfungsi untuk saya. Secara opsional juga mendapat skema untuk tabel yang diminta.

#!/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
Wolfgang Fahl
sumber
1

Saya mengalami masalah yang sama dan Jawaban Paulus bukan pilihan karena itu RDS. Mengganti tab dengan koma tidak berfungsi karena data telah menyematkan koma & tab. Saya menemukan bahwa mycli yang merupakan alternatif drop-in untuk klien mysql mendukung output csv dari kotak dengan --csvflag

mycli db_name --csv -e "select * from flowers" > flowers.csv
Shenal Silva
sumber
1

Jika Anda mendapatkan kesalahan ini saat Anda mencoba untuk mengekspor file Anda

GALAT 1290 (HY000): Server MySQL berjalan dengan opsi --secure-file-priv sehingga tidak dapat menjalankan pernyataan ini

dan Anda tidak dapat menyelesaikan kesalahan ini. Anda dapat melakukan satu hal hanya dengan menjalankan skrip python ini

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]})
Pranav
sumber
Selamat Datang di Stack Overflow! Ini tidak menjawab pertanyaan. Harap tinjau stackoverflow.com/help/how-to-answer .
stephenwade
0

Jika ada PHP yang diinstal pada mesin yang Anda gunakan, Anda dapat menulis skrip PHP untuk melakukannya. Diperlukan instalasi PHP agar ekstensi MySQL diinstal.

Anda dapat memanggil juru bahasa PHP dari baris perintah seperti:

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

Saya termasuk --php-inisaklar, karena Anda mungkin perlu menggunakan konfigurasi PHP Anda sendiri yang memungkinkan ekstensi MySQL. Pada PHP 5.3.0+ ekstensi itu diaktifkan secara default, sehingga tidak perlu lagi menggunakan konfigurasi untuk mengaktifkannya.

Kemudian Anda dapat menulis skrip ekspor seperti skrip PHP biasa:

<?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";
    }
?>

Keuntungan dari metode ini adalah, bahwa ia tidak memiliki masalah dengan bidang varchar dan teks, yang memiliki teks yang mengandung baris baru. Bidang-bidang tersebut dikutip dengan benar dan baris-baris baru di dalamnya akan ditafsirkan oleh pembaca CSV sebagai bagian dari teks, bukan catatan pemisah. Itu adalah sesuatu yang sulit untuk diperbaiki setelahnya dengan sed atau lebih.

user7610
sumber
1
Jauh dari rumit yang tidak perlu, ini adalah satu-satunya solusi di sini yang mengarah ke arah yang mungkin benar - meskipun dengan sedikit pekerjaan. CSV lebih kompleks daripada yang pertama kali muncul, dan Anda telah melakukan berbagai kesalahan. misalnya backslash dalam aslinya. Lebih baik menggunakan perpustakaan yang telah menyelesaikan semua masalah untuk menulis ke CSV.
mc0e
@ mc0e Biasanya Anda menggandakan penawaran atau melarikan diri dari penawaran. Saya memutuskan untuk menggandakan kutipan, oleh karena itu saya tidak perlu karakter melarikan diri. Perangkat lunak yang berbeda memiliki ide yang berbeda tentang detail CSV. Misalnya, LOAD DATA di MySQL memang memperlakukan \ sebagai karakter pelarian, sedangkan Open Office Calc tidak. Ketika saya menulis jawabannya, saya mengekspor data ke dalam spreadsheet.
user7610
1
Kode saya menangani semua yang diperlukan untuk mengekspor dataset saya kembali pada hari itu;) Jawaban Anda juga merupakan langkah ke arah yang benar, tetapi seperti komentar pertama di sana, itu harus 1) terhubung ke database sql dari skrip langsung sebagai dan juga 2) menggunakan perpustakaan csv yang tepat.
user7610