MySQL sorgu sonuçlarını CSV formatında nasıl çıktılarım?


1183

Linux komut satırından bir MySQL sorgusu çalıştırmanın ve sonuçları CSV formatında çıkarmanın kolay bir yolu var mı ?

İşte şimdi ne yapıyorum:

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

Tırnaklarla çevrelenmesi gereken çok sayıda sütun olduğunda veya sonuçlarda kaçması gereken tırnaklar varsa dağınık hale gelir.


1
REPLACE()Tırnak işaretleri kaçmak için sorgunuzda kullanabilirsiniz .
dsm

Cevabımı [bu stackoverflow] [1] [1] 'e bak: stackoverflow.com/questions/12242772/…
biniam



MariaDB hata izleyicisine bir özellik isteği yazdım ( jira.mariadb.org/browse/MDEV-12879 ) Buna oy verebilirsiniz.
Jared Beck

Yanıtlar:


1760

Gönderen http://www.tech-recipes.com/rx/1475/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';

Bu komut kullanıldığında sütun adları dışa aktarılmaz.

Ayrıca MySQL çalıştıran sunucuda/var/lib/mysql-files/orders.csv olacağını unutmayın . MySQL işleminin altında çalıştığı kullanıcının seçilen dizine yazma iznine sahip olması gerekir, aksi takdirde komut başarısız olur.

Yerel makinenize uzak bir sunucudan (özellikle Heroku veya Amazon RDS gibi barındırılan veya sanallaştırılan bir makine) çıktı yazmak istiyorsanız, bu çözüm uygun değildir.


16
@Tomas, uzak bir dosya sistemine ve MySQL'e erişiminiz varsa, bir yere yazabilmeniz gerekir. / tmp yerine /home/yourusername/file.csv dosyasını deneyin - bu başarısız olursa ve sonuç kümesi o kadar büyük değilse, çıktıyı SSH istemcinizden kopyalayıp yerel makinenize yapıştırabilirsiniz.
Michael Butler

63
Soru, MySQL'i belirledi, "standartlara uygun" değil.
Paul Tomblin

35
Üstbilgi de nasıl dahil edilir?
Bogdan Gusiev

66
@BogdanGusiev, gerçek sorgudan önce "SELECT 'order_id', 'product_name', 'qty' UNION" başlığını ekleyerek üstbilgi ekleyebilirsiniz. İlk seçme sorgusu üstbilgiyi, ikinci sorgu gerçek verileri döndürür; BİRLİK buna katılır.
petrkotek

19
@Michael Butler: Aslında hayır. Amazon RDS, Heroku veya başka bir barındırılan çözüm kullanıyorsanız, başka birinin sunucusuna yazmanız mümkün değildir.
Ken Kinder

459
$ mysql your_database --password=foo < my_requests.sql > out.csv

Hangi sekme ayrılmış. Gerçek bir CSV elde etmek için bu şekilde bağlayın (teşekkürler @therefromhere):

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

5
sadece bu değil, aynı zamanda yerel dosya sistemine yazmanın aksine, uzak bir veritabanı ana bilgisayarından içeriğin oluşturulmasına izin verir.
tmarthal

31
Sekmeyle ayrılmış, virgülle ayrılmış değil.
Flimm

13
@Flimm, sonuçlara boru ekleyerek alanlara virgül / sekme eklemediğinizi varsayarsak| sed 's/\t/,/g'
John Carter

111
sed 'fix' seçilen verilerin herhangi birinde görünebilecek virgülleri telafi etmez ve sütunlarınızı buna göre çıktılandıracaktır
Joey T

14
Olumsuzluk geçerlidir .. şimdi sizin için işe yarayabilir, ancak verileriniz bir sekme veya virgül vb.
John Hunt

204

mysql - toplu iş, -B

Her satır yeni bir satırda olacak şekilde sütun ayırıcı olarak sekmeyi kullanarak sonuçları yazdırın. Bu seçenekle, mysql geçmiş dosyasını kullanmaz. Toplu iş modu tablo dışı çıktı biçimine ve özel karakterlerden kaçmaya neden olur. Çıkış, ham mod kullanılarak devre dışı bırakılabilir; --raw seçeneğinin açıklamasına bakın.

Bu size sekmeyle ayrılmış bir dosya verecektir. Virgüllerden (veya virgül içeren dizelerden) kaçılmadığından, sınırlayıcıyı virgülle değiştirmek kolay değildir.


12
bu tercih edilen bir çözümdür: 1) sekmeyle ayrılmış değer listeleri UNIX 2'de yaygındır) TSV içe aktarma, Excel, OpenOffice E-Tablolar vb. dahil olmak üzere çoğu içe aktarma sistemi tarafından yerel olarak desteklenir. 3) metin alanları için tırnak karakterlerinden kaçmaya gerek yoktur 4 ) komut satırı ihracatını bir esinti yapar
Joey T

5
bu en iyi çözümdür çünkü
ilkinden farklı olarak

8
Düzgün bir hile: sekmeyle ayrılmış dosyayı .csv yerine .xls olarak kaydederseniz, "metin-veri" dönüştürmesine gerek kalmadan ve herhangi bir bölgesel ayar sorunu olmadan excel'de açılır.
serbaut

3
@Joey T - hala sekmelerden ve satır başlarından kaçmanız gerekiyor. Ayrıca bir alanın içeriği tırnak içine alınmış veya kaçan bir alana benziyorsa, içe aktarılan içerik orijinal gibi görünmeyebilir.
mc0e

2
NULLs ile ilgili bir sorun olacak .. onlar dize nulls olarak çıkacak ..
Jonathan

141

İşte bunu yapmanın oldukça çirkin bir yolu. Bir yerde buldum, kredi alamıyorum

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

Oldukça iyi çalışıyor. Bir kez daha bir normal ifade sadece yazmayı kanıtlıyor.


Normal İfade Açıklaması:

  • s ///, ilk // ile ikincisini ikincisi ile ikame etmek anlamına gelir //
  • sonunda "g", "sadece ilk değil tüm örnek" anlamına gelen bir değiştiricidir
  • ^ (bu bağlamda) satır başı anlamına gelir
  • $ (bu bağlamda) satır sonu anlamına gelir

Yani, hepsini bir araya getirmek:

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

3
-E bayrağı tam olarak aradığım şeydi! Teşekkürler!
Gaurav Gupta

1
Bu normal ifade gerçekten oldukça basit; Bu sayfadaki diğer birçok cevap gibi, sadece çıktıyı temizliyor mysql -B. Normal ifadeyi ayrı satırlardaki ayrı ifadelere ayırırsanız, (normal ifadeyi bilen biri için) anlaşılması oldukça basit olacaktır.
Mei

7
İlk bakışta, bu oldukça kırık görünüyor. İçerikteki sekmeler ve satır başları yanlış kullanılır. "s / '/ \' /;" hiçbir şey yapmaz, çünkü kabuk komutundaki çift tırnaklar ters eğik çizgiyi kullanır. Ters eğik çizginin kaybolmasıyla benzer birçok hata. Db alanında ters eğik çizgi kullanılmaz.
mc0e

1
Bu komut Linux'ta iyi çalışıyor gibi görünüyor ama Mac'te değil
Hemerson Varela

6
Sekmeler, ters eğik çizgiler ","ve bir dizi başka şey içeren bir metin alanınız varsa, bu durum bozulur . Bir normal ifade bu sorunu çözmenin yolu değil
aidan

93

Yalnızca Unix / Cygwin , bunu 'tr' yoluyla yapın:

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

Not: Bu, ne gömülü virgülleri ne de gömülü sekmeleri işler.


53

Bu beni birkaç kez kurtardı. Hızlı ve işe yarıyor!

--batch Her satırı yeni bir satırda olacak şekilde sütun ayırıcı olarak sekmeyi kullanarak sonuçları yazdırın .

--raw karakter çıkışını devre dışı bırakır (\ n, \ t, \ 0 ve \)

Misal:

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

Bütünlüğü için size olabilir csv dönüştürmek (ama dikkatli olun sekmeler iç alan değerleri olabilir çünkü - örneğin metin alanları)

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


4
Ben bir şey eksik sürece, bu bir CSV dosyası değil bir TSV dosyası oluşturur ...
PressingOnAlways

@ PressingOnAlways Evet. MySQL doc quote: "Her satır yeni bir satırda olacak şekilde sütun ayırıcı olarak sekmeyi kullanarak sonuçları yazdırın." Ancak ayrıştırma herhangi bir sınırlayıcı ile ilgili bir sorun olmamalıdır. Müşterim için excel dosyaları yapmak için kullandım.
hrvoj3e

39

Paul Tomblin tarafından verilen OUTFILE çözümü, bir dosyanın MySQL sunucusunun kendisine yazılmasına neden olur, bu nedenle bu yalnızca FILE'niz varsa çalışır erişiminiz ve bu kutudan dosyayı almak için oturum açma erişimi veya diğer araçlarla çalışır.

Böyle bir erişiminiz yoksa ve sekmeyle ayrılmış çıktı CSV için makul bir alternatifse (örneğin, nihai hedefiniz Excel'e aktarmaksa), o zaman Serbaut'un çözümü ( mysql --batchve isteğe bağlı olarak --raw) kullanmanın yoludur.


36

MySQL Workbench , kayıt kümelerini CSV'ye aktarabilir ve alanlardaki virgüllerle çok iyi başa çıktığı görülmektedir. CSV, OpenOffice para cezasıyla açılır.


2
Bir milyon David teşekkürler. Yeni satırların verilerdeki HTML içeriği için düzgün çıktı almasını sağladıktan sonra MySQL Workbench'i kullandım ve 2 dakika içinde CSV dosyamı hazırladım.
mr-euro

Ben de XML olarak kaydedebilirsiniz buldum, bu harika. Hedef uygulama içine almak için uygun bir CSV dosyasına bu XML dönüştürmek için XSLT kullanarak bir uygulamadan diğerine taşımak umuyoruz.
David Oliver

mysql tezgah ithalat ihracat özelliği için en iyi seçenektir.
cijagani

1
Ben sadece büyük dosyaları bir sorun gibi görünmüyor mysql tezgah kullanarak yarım milyondan fazla satır başarıyla ihraç. Sorgunuzu çalıştırmadan önce seçme sınırını kaldırdığınızdan emin olmanız gerekir ve ayrıca my.ini dosyanızda şu değerleri artırmanız gerekebilir: max_allowed_packet = 500M, net_read_timeout = 600, net_write_timeout = 600
Vincent

3
MySQL çalışma tezgahı, CSV'de veri dışa aktarırken utanç verici bir bellek sızıntısına sahiptir, 1 veya 2 milyon daha fazla satır gibi büyük bir veri kümeniz varsa, 12 GB RAM (linux makinemde test edilmiştir) yeterli değildir ve siz öldür ya da durdur. Büyük veri seti için bu bir çözüm değildir.
Ostico

33

Nasıl olur:

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

2
Bunu gerçekten beğendim. Çok daha temiz ve awk kullanımını seviyorum. Ancak, muhtemelen bu ile giderdi: mysql -uUser -pPassword your_database < my_requests.sql | awk 'BEGIN{OFS="=";} {print $1,$2}' > out.csv
Josh

7
Bu, boşluklu alan değerleri için başarısız olur.
Barun Sharma

29

MySQL çalışma tezgahı dışında bugüne kadarki tüm çözümler mysql db'deki en azından bazı olası içerikler için yanlış ve büyük olasılıkla güvensizdir (yani güvenlik sorunları).

MYSQL Workbench (ve benzer şekilde PHPMyAdmin) resmi olarak doğru bir çözüm sunar, ancak çıktıyı kullanıcının konumuna indirmek için tasarlanmıştır. Veri dışa aktarmayı otomatikleştirmek gibi şeyler için çok kullanışlı değiller.

Çıktısından güvenilir bir şekilde doğru csv üretmek mümkün değildir mysql -B -e 'SELECT ...' çünkü bu alanlardaki satır başlarını ve boşlukları kodlayamaz. Mysql '-s' bayrağı kaçış ters eğik çizgi yapar ve doğru bir çözüm yol açabilir. Bununla birlikte, bir komut dosyası dili (bash değil, iyi iç veri yapılarına sahip bir dil) ve kodlama sorunlarının daha önce dikkatle çalıştığı kütüphanelerin kullanılması çok daha güvenlidir.

Bunun için bir senaryo yazmayı düşündüm, ama ne dediğimi düşündüğüm anda, aynı isimle önceden var olan işleri aramak bana geldi. Ben iyice geçemesem de, https://github.com/robmiller/mysql2csv adresindeki çözüm umut verici görünüyor. Uygulamanıza bağlı olarak, SQL komutlarını belirtmeye yönelik yaml yaklaşımı yine de cazip gelebilir. Ayrıca Ubuntu 12.04 dizüstü bilgisayarım veya Debian Squeeze sunucularım ile standart olarak sunulan ruby'nin daha yeni bir sürümüne olan gereksinimden de memnun değilim. Evet RVM kullanabileceğimi biliyorum, ama bunu böyle basit bir amaç için sürdürmemeyi tercih ederim.

Umarım birisi uygun bir araç işaret edecektir, bu biraz test edildi. Aksi takdirde, bir tane bulduğumda veya yazdığımda bunu muhtemelen güncelleyeceğim.


1
Haklısın, tablodaki karmaşık dizeler için sadece bash değil, iyi bir kütüphane kullanmalısın. Bence nodejs bu tür eylemler için daha iyi çözümlere sahip. bu örnek
yeya

1
Merhaba, iyi cevap, aşağıda önerilen python çözümüne bir bağlantı eklerdim stackoverflow.com/a/35123787/1504300 iyi çalışan ve çok basit , . Yayınınızı düzenlemeye çalıştım ancak düzenleme reddedildi
reallynice

26

Bu sayfadaki cevapların çoğu zayıftır çünkü CSV biçiminde neler olabileceğinin genel durumunu ele almazlar. örneğin, alanlara gömülü virgüller ve tırnak işaretleri ve eninde sonunda ortaya çıkan diğer koşullar. Tüm geçerli CSV giriş verileri için çalışan genel bir çözüme ihtiyacımız var.

İşte Python'da basit ve güçlü bir çözüm:

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

Bu dosyayı adlandırın tab2csv, yolunuza koyun, yürütme izinleri verin, ardından şu şekilde kullanın:

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

Python CSV işleme işlevleri, CSV giriş biçimleri için köşe durumlarını kapsar.

Bu, akış yaklaşımı yoluyla çok büyük dosyaları işlemek için geliştirilebilir.


8
Daha da güvenilir bir çözüm, aslında veritabanına Python ile bağlanmak olacaktır, o zaman daha büyük veri kümeleriyle (parçalama sonuçları, akış vb.)
Josh Rumbut

@JoshRumbut, gerçekten geç, ama yorumunuzu tamamlamak için stackoverflow.com/a/41840534/2958070 yaptım
Ben


17
  1. mantık:

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

Bir CSV tablosu oluşturduğunuzda, sunucu veritabanı dizininde bir tablo biçimi dosyası oluşturur. Dosya tablo adıyla başlar ve bir .frm uzantısına sahiptir. Depolama motoru da bir veri dosyası oluşturur. Adı tablo adıyla başlar ve bir .CSV uzantısına sahiptir. Veri dosyası düz bir metin dosyasıdır. Verileri tabloya kaydettiğinizde, depolama motoru verileri veri dosyasına virgülle ayrılmış değerler biçiminde kaydeder.


1
Güzel, çünkü bu herhangi bir ayarlama gerektirmeden doğru.
Andrew Schulman

13

Bu cevap Python ve popüler bir üçüncü taraf kütüphanesi PyMySQL kullanıyor . Bunu ekliyorum çünkü Python'un csv kütüphanesi, birçok farklı lezzeti doğru şekilde işleyebilecek kadar güçlü .csvve başka hiçbir cevap veritabanıyla etkileşim kurmak için Python kodunu kullanıyor.

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)

Python kullanarak bir cevap zaten sağlandı. stackoverflow.com/a/35123787/5470883
Alexander Baltasar

4
@AlexanderBaltasar, doğru ve kullanışlı görünüyor, ancak veritabanıyla etkileşim kurmak için Python kodu kullanmıyor. Bu soru hakkındaki açıklamaya bakınız.
Ben

11

Bu basittir ve toplu iş moduna veya çıktı dosyalarına ihtiyaç duymadan herhangi bir şey üzerinde çalışır:

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

from your_table where etc;

Açıklama:

  1. Değiştir "ile ""her alanda ->replace(field1, '"', '""')
  2. Her sonucu tırnak içine alın -> concat('"', result1, '"')
  3. Alıntılanan her sonuç arasına virgül koyun -> concat_ws(',', quoted1, quoted2, ...)

Bu kadar!


1
Bu Not NULLdeğerleri atlanır concat_ws()bir sütun uyumsuzluğu ile sonuçlanır. Bundan kaçınmak için bunun yerine boş bir dize kullanın: IFNULL(field, '')(veya temsil etmek için kullandığınız her şeyi kullanın NULL)
Marco Roy

10

Yukarıdaki cevaba alternatif olarak, CSV motorunu kullanan bir MySQL tablonuz olabilir.

Ardından sabit diskinizde her zaman CSV biçiminde olacak ve dosyayı işlemeden kopyalayabileceğiniz bir dosya olacaktır.


1
Bunun dosya boyutu / yazma / okuma / vb. Açısından sınırları nelerdir?
Zach Smith

8

Önceki yanıtları genişletmek için, aşağıdaki tek satır tek bir tabloyu sekmeyle ayrılmış dosya olarak dışa aktarır. Otomasyon için uygundur, her gün veritabanını dışa aktarır.

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

Uygun bir şekilde, MySQL'in tablolarını listelemek ve alanları tek bir tablodaki tanımlamak için aynı tekniği kullanabiliriz:

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    

4
CSV'ye dönüştürmek için:mysql -B -D mydatabase -e 'select * from mytable' | sed -e 's/\t/,/g'
DSimon

7
Kullanımı sed -e 's/\t/,/g'yalnızca verilerinizde virgül veya sekme bulunmadığından eminseniz güvenlidir.
awatts

7

User7610 üzerine inşa etmek, bunu yapmanın en iyi yolu. İle mysql outfiledosya mülkiyet ve üzerine yazma problemlerinin 60 dakika vardı.

Serin değil, ama 5 dakika içinde çalıştı.

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

?>

1
Güzel, temiz ve hızlı çalışır - PHP'yi bu ortamda çalıştırabiliyorsanız bu harika bir çözümdür!
John Fiala

7

Ayrıca, Bash komut satırında sorguyu gerçekleştiriyorsanız, komutun trvarsayılan sekmeleri rasgele sınırlayıcılarla değiştirmek için kullanılabileceğine inanıyorum .

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


5

İşte yaptığım şey:

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

Perl betiği (başka bir yerden kesilmiş) sekme aralıklı alanları CSV'ye dönüştürmek için iyi bir iş çıkarır.


Bu harika. Sayılar hariç her şeyi alıntılamak biraz iyileşme olabilir perl -F"\t" -lane 'print join ",", map {s/"/""/g; /^\d+(?:\.\d+)?$/ ? $_ : qq("$_")} @F '- seninki alıntı 1.2.3
yapmaz

5

Tam olarak bir CSV biçimi olarak değil, ancak MySQL istemcisinin teekomutu çıktıyı yerel bir dosyaya kaydetmek için kullanılabilir :

tee foobar.txt
SELECT foo FROM bar;

Düğmesini kullanarak devre dışı bırakabilirsiniz notee.

Sorun SELECT … INTO OUTFILE …;, sunucuya dosya yazma izni gerektirmesidir.


.Txt yerine .csv uzantısı kullanılıyorsa, bilinmesi gereken biçimlendirme sorunları var mı?
datalifenyc

@ myidealab Biçimlendirme sorunları, virgüllerden vb. kaçılmamasından kaynaklanır. CSV düz bir metin biçimidir, bu nedenle yalnızca uzantıyı değiştirmekten biçimlendirme sorunu yoktur.
jkmartindale

3

Tim tarafından yayınlanan çözümü kullanarak, işlemi kolaylaştırmak için bu bash betiğini oluşturdum (kök parola istenir, ancak komut dosyasını başka bir kullanıcı istemek için kolayca değiştirebilirsiniz):

#!/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 adlı bir dosya oluşturur.


3

Sunucuda PHP ayarladıysanız, abysrary bir mysql sorgusu için (gerçekten geçerli) bir CSV dosyasını dışa aktarmak için mysql2csv'yi kullanabilirsiniz . Bkz SEÇ * INTO ÇIKDOSYA LOCAL - MySQL de cevabım?biraz daha bağlam / bilgi için.

Seçenek adlarını korumaya çalıştım, mysqlbu yüzden --fileve --queryseçeneklerini sağlamak için yeterli olmalı :

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

mysql2csvÜzerinden "yükle"

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

(özün içeriğini indirin, sağlama toplamını kontrol edin ve yürütülebilir yapın).


3

Benim için ne işe yaradı:

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

Bu konudaki çözümlerin hiçbiri benim özel durumum için işe yaramadı, csv çıktımda bozulacak sütunlardan birinin içinde oldukça json verileri vardı. Benzer sorunu olanlar için, \ r \ n ile sonlandırılmış satırları deneyin.

Ayrıca csv'yi Microsoft Excel ile açmaya çalışanlar için başka bir sorun, tek bir hücrenin tutabileceği 32.767 karakterlik bir sınır olduğunu unutmayın, bunun üstünde aşağıdaki satırlara taşar. Bir sütundaki hangi kayıtların sorun olduğunu belirlemek için aşağıdaki sorguyu kullanın. Daha sonra bu kayıtları kısaltabilir veya istediğiniz gibi işleyebilirsiniz.

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

2

O zaman bir hata secure-file-privalıyorsanız, hedef dosya konumunuzu içinde C:\ProgramData\MySQL\MySQL Server 8.0\Uploadsve sonra da değiştirdikten sonra

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

çalışmıyorsa, yalnızca \sorgudan /(ileriye doğru) (forsplash) değerini değiştirmeniz gerekir.

Ve bu işe yarıyor !!

Misal:

SEÇİMDEN DAHA FAZLA SEÇİME 'C: / ProgramData / MySQL / MySQL Server 8.0 / Yüklemeler / DosyaAdı.csv' TARAFINDAN SONLANDIRILAN ALANLAR ',' '' 'TERMİNE EDİLEN ALANLAR' \ n ';

Başarılı sorguyu her çalıştırdığınızda, her seferinde yeni csv dosyası oluşturur! Havalı değil mi?


1

Https://stackoverflow.com/a/5395421/2841607 esinlenerek CSV dökümlerine basit sorgulama yapmak için küçük bash betiği .

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

1

Aşağıdaki bash betiği benim için çalışıyor. İsteğe bağlı olarak istenen tabloların şemasını da alır.

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

1

Aynı sorunla karşılaştım ve RDS olduğundan Paul'un Cevabı bir seçenek değildi. Verileri virgül ve sekmeler katıştırdığı için sekmeyi virgülle değiştirmek işe yaramadı. MySQL istemcisi için bir drop-in alternatif olan mycli--csv bayrağı ile kutu csv çıkışını desteklediğini buldum

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

1

Dosyanızı dışa aktarmaya çalışırken bu hatayı alıyorsanız

HATA 1290 (HY000): MySQL sunucusu --secure-file-priv seçeneğiyle çalışıyor, bu nedenle bu ifadeyi yürütemiyor

ve bu hatayı çözemezsiniz. Bu python betiğini çalıştırarak bir şey yapabilirsiniz

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]})

Stack Overflow'a hoş geldiniz! Bu soruya cevap vermiyor. Lütfen stackoverflow.com/help/how-to-answer adresini inceleyin .
stephenwade

0

Kullandığınız makinede yüklü PHP varsa, bunu yapmak için bir PHP betiği yazabilirsiniz. PHP kurulumunun MySQL uzantısının kurulu olmasını gerektirir.

PHP yorumlayıcısını komut satırından şöyle çağırabilirsiniz:

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

--php-iniAnahtarı dahil ediyorum , çünkü MySQL uzantısını etkinleştiren kendi PHP yapılandırmanızı kullanmanız gerekebilir. PHP 5.3.0+ sürümünde bu uzantı varsayılan olarak etkindir, bu nedenle yapılandırmayı etkinleştirmek için artık gerekli değildir.

Daha sonra dışa aktarma komut dosyanızı herhangi bir normal PHP komut dosyası gibi yazabilirsiniz:

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

Bu yöntemin avantajı, yeni satırlar içeren metin içeren varchar ve metin alanlarıyla ilgili herhangi bir sorunu olmamasıdır. Bu alanlar doğru şekilde alıntılanır ve içindeki yeni satırlar, CSV okuyucu tarafından ayırıcıları değil metnin bir parçası olarak yorumlanır. Bu daha sonra sed ya da benzeri ile düzeltilmesi zor bir şeydir .


1
Gereksiz derecede karmaşık olmaktan çok, burada biraz daha fazla iş olsa da, doğru olması muhtemel bir yönde giden tek çözüm budur. CSV, ilk göründüğünden daha karmaşık ve çeşitli hatalar yaptınız. örneğin orijinaldeki ters eğik çizgiler. CSV'ye yazmak için tüm konuları çalıştıran bir kütüphane kullanmak daha iyidir.
mc0e

@ mc0e Genellikle teklifi ikiye katlarsınız veya tekliften kaçarsınız. Alıntıyı ikiye katlamaya karar verdim, bu yüzden kaçış karakterine ihtiyacım yok. Farklı yazılımların CSV ayrıntıları hakkında farklı fikirleri vardır. Örneğin, MySQL'deki LOAD DATA gerçekten \ kaçış karakteri olarak davranırken, Open Office Calc bunu yapmaz. Cevabı yazdığımda bir elektronik tabloya veri aktarıyordum.
user7610

1
İhracat ihtiyaç vardı Kodum kolları her şey benim günde veri kümesi geri;) Cevabınız da doğru yönde atılmış bir adım olduğunu, ancak orada diyor ilk yorum olarak, yalnızca 1) doğrudan komut dosyasından sql veritabanına bağlanmak gerekir 2) uygun bir csv kütüphanesi kullanın.
user7610
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.