SELECT INTO OUTFILE kullanırken başlıklar dahil edilsin mi?


117

MySQL kullanılırken başlıkları bir şekilde dahil etmek mümkün müdür INTO OUTFILE?

Yanıtlar:


166

Bu başlıkları kendiniz kodlamanız gerekir. Gibi bir şey:

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT ColName1, ColName2, ColName3
    FROM YourTable
    INTO OUTFILE '/path/outfile'

14
Bir varsa Ama işe yaramaz ORDER BYiçinde SELECTmaddesi. Başlık satırı, sıraya bağlı olarak oluşturulan dosyanın herhangi bir yerinde olabilir.
Bobin

ORDER BY kullanma hakkında fikirler için aşağıdaki birkaç yanıta ve ayrıca tüm ColName1, ColName2, vb. Hızlı bir şekilde tüm ColName1, ColName2, vb. Elde etmenin bir yolu için Matt'in yanıtına bakın.
Andrew T

1
Bu cevap doğru görünüyor, cehennem onu ​​dev sunucumda neredeyse körü körüne kullandım ... Sütun başlıkları olmadan 240 milyon satırı boşaltmak yaklaşık 50 saniye sürer. Bu UNION ALL ile sunucu, her şeyi atmadan önce geçici bir tablo yapmaya çalışırken büyük sıkıntılara giriyor, şimdi 10 dakikadan fazla oldu ve hala geçici tablonun diske yazılmasını bekliyor! Bunun farkında olun! Dosyayı başka bir programlama diliyle açmak anlamına gelse bile, sütun adlarını kesinlikle başka bir şekilde eklemeyi tercih edersiniz.
Salketer

Bu, yalnızca YourTable'ın tüm sütunları bir karakter veri türü ise işe yarıyor gibi görünür, bu da mantıklıdır. Aksi takdirde, yardımcı olmayan bir hata alırsınız: "Kullanılan SELECT deyimlerinin farklı sayıda sütunu var".
TheBamf

1
Bu, başka bir DBMS'ye geçmeyi düşünmemin nedenlerinden biri.
e18r

85

Joe Steanelli tarafından sağlanan çözüm işe yarıyor, ancak düzinelerce veya yüzlerce sütun söz konusu olduğunda bir sütun listesi yapmak sakıncalıdır. İşte tablo sütun listesini almak için nasıl my_table içinde my_schema .

-- override GROUP_CONCAT limit of 1024 characters to avoid a truncated result
set session group_concat_max_len = 1000000;

select GROUP_CONCAT(CONCAT("'",COLUMN_NAME,"'"))
from INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'my_table'
AND TABLE_SCHEMA = 'my_schema'
order BY ORDINAL_POSITION

Artık elde edilen satırı Joe'nun yönteminde ilk ifade olarak kopyalayıp yapıştırabilirsiniz.


2
Bu, tek bir alanda birleştirilmiş tüm sütunları döndürür. Bunu birden çok alan döndüren başka bir select ifadesiyle birleştiremiyorum. Bu, çıktı dosyamın başlığı olarak kopyalayıp yapıştırabileceğim bir satır almak için gerçekten kullanışlıdır.
tmoore82

1
Buradaki fikir, elde edilen tek alanı kopyalayıp, Joe'nun yöntemini (kabul edilen cevap) kullanırken sütun1, sütun2, vb. Gibi manuel olarak yazmak yerine UNION ifadenize yapıştırmaktır, böylece sütunların listesini daha hızlı elde edebilirsiniz!
Andrew T

Tüm tablo / alan şemamı dışa aktarmak istiyordum. Kabul edilen cevapla birleştirilen bu cevap hile yaptı!
Rémi Breton

@Chris bunu ORDER BY ORDINAL_POSITIONhalleder
matt

1
SİPARİŞ BY ordinal_position olarak GROUP_CONCAT () çağrısının parçası olmalıdırGROUP_CONCAT(CONCAT('"',COLUMN_NAME,'"') order BY ORDINAL_POSITION)
Apuleius

15

ORDER BY ile karmaşık seçim için aşağıdakileri kullanıyorum:

SELECT * FROM (
    SELECT 'Column name #1', 'Column name #2', 'Column name ##'
    UNION ALL
    (
        // complex SELECT statement with WHERE, ORDER BY, GROUP BY etc.
    )
) resulting_set
INTO OUTFILE '/path/to/file';

Bu çözüm, ikinci (karmaşık) sorguyu sipariş ederken işe yarar; Bu şekilde yapmazsanız, ilk sütunu da sıralayacaksınız ki bu da istenmeyen bir durumdur. Güzel öneri @evilguc!
Aaron

Benimle çalışmadı,
UNION'u

6

Lucek'in cevabı ile hazırlanmış ifadeyi kullanabilir ve CSV'de sütun adı ile dinamik olarak tablo dışa aktarabilirsiniz:

--If your table has too many columns
SET GLOBAL group_concat_max_len = 100000000;
--Prepared statement
SET @SQL = ( select CONCAT('SELECT * INTO OUTFILE \'YOUR_PATH\' FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\' ESCAPED BY \'\' LINES TERMINATED BY \'\\n\' FROM (SELECT ', GROUP_CONCAT(CONCAT("'",COLUMN_NAME,"'")),' UNION select * from YOUR_TABLE) as tmp') from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'YOUR_TABLE' AND TABLE_SCHEMA = 'YOUR_SCHEMA' order BY ORDINAL_POSITION );
--Execute it
PREPARE stmt FROM @SQL;
EXECUTE stmt;

Teşekkür ederim lucek.


6

Bu, sıralı sütunlara ve / veya bir limite sahip olmanızı sağlayacaktır.

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT * from (SELECT ColName1, ColName2, ColName3
    FROM YourTable order by ColName1 limit 3) a
    INTO OUTFILE '/path/outfile';

1
Bu sorgu düzeninin MariaDB 10.1'de benim için de çalıştığını not edin; bu ileti dizisinde önerilen diğer düzenler bunu yapmadı.
ProgrammerDan

Başlığı bir nedenden ötürü alt tarafa atıyor, ancak bir elektronik tablo uygulamasında bunu en üste çıkarmak için gayet iyi çalışıyor, garip ama alkışlıyor
Dmitri DB

Ben de mariaDB kullanıyorum. Yalnızca 100 olası satışın çıkarılmasıyla bu, kabul edilen yanıtı çalıştırmaktan 14 saniyeden daha hızlıydı. Kabul edilen ilk geçiş: Query OK, 100 rows affected (14.72 sec) Sizinki ile ikinci geçişQuery OK, 101 rows affected (0.00 sec)
Casper Wilkes

6

İlk olarak sütun adlarıyla sorgu çıktısı almak için (sınır 1) (sabit kod yok, Birleştirmelerle ilgili sorun yok, Sıralama ölçütü, özel sütun adları, vb.) Ve ikincisi kendisini sorgulamak ve dosyaları tek bir CSV'de birleştirmek için basitçe 2 sorgu yapıyorum. dosya:

CSVHEAD=`/usr/bin/mysql $CONNECTION_STRING -e "$QUERY limit 1;"|head -n1|xargs|sed -e "s/ /'\;'/g"`
echo "\'$CSVHEAD\'" > $TMP/head.txt
/usr/bin/mysql $CONNECTION_STRING -e "$QUERY into outfile '${TMP}/data.txt' fields terminated by ';' optionally enclosed by '\"' escaped by '' lines terminated by '\r\n';"
cat $TMP/head.txt $TMP/data.txt > $TMP/data.csv

5

NodeJS'de büyük tablolarda mysql sorgusunu çalıştırırken benzer bir sorunla karşılaştım. CSV dosyama başlık eklemek için izlediğim yaklaşım aşağıdaki gibidir

  1. Başlıklar olmadan dosya hazırlamak için OUTFILE sorgusunu kullanın

        SELECT * INTO OUTFILE [FILE_NAME] FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED 
        BY '\"' LINES TERMINATED BY '\n' FROM [TABLE_NAME]
  2. 1. noktada kullanılan tablo için sütun başlıklarını getir

        select GROUP_CONCAT(CONCAT(\"\",COLUMN_NAME,\"\")) as col_names from 
        INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = [TABLE_NAME] AND TABLE_SCHEMA 
        = [DATABASE_NAME] ORDER BY ORDINAL_POSITION
  3. Başa eklenen dosya npm paketini kullanarak 1. adımda oluşturulan dosyaya sütun başlıklarını ekleyin

Her adımın yürütülmesi NodeJS'deki vaatler kullanılarak kontrol edildi.


3

Python veya R'ye aşina iseniz ve tablonuz belleğe sığabiliyorsa, bu alternatif bir hiledir.

SQL tablosunu Python veya R'ye içe aktarın ve oradan bir CSV olarak dışa aktarın; sütun adlarının yanı sıra verileri de alırsınız.

R kullanarak bunu nasıl yapıyorum, RMySQL kitaplığını gerektirir:

db <- dbConnect(MySQL(), user='user', password='password', dbname='myschema', host='localhost')

query <- dbSendQuery(db, "select * from mytable")
dataset <- fetch(query, n=-1)

write.csv(dataset, 'mytable_backup.csv')

Bu biraz hile ama sütun sayım yukarıdaki concat yöntemini kullanmak için çok uzun olduğunda bunun hızlı bir geçici çözüm olduğunu buldum. Not: R, CSV'nin başlangıcına bir 'satır.adları' sütunu ekleyecektir, bu nedenle tabloyu yeniden oluşturmak için CSV'ye güvenmeniz gerekiyorsa, bunu kaldırmak isteyeceksiniz.


2

Dolayısıyla, içindeki tüm sütunlar my_tablebir karakter veri türündeyse, başlığın otomatik olarak tek bir 'basit' SQL sorgusuna eklenmesini sağlamak için en iyi yanıtları (Joe, matt ve evilguc tarafından) birleştirebiliriz, örn.

select * from (
  (select column_name
    from information_schema.columns
    where table_name = 'my_table'
    and table_schema = 'my_schema'
    order by ordinal_position)
  union all
  (select *  // potentially complex SELECT statement with WHERE, ORDER BY, GROUP BY etc.
  from my_table)) as tbl
into outfile '/path/outfile'
fields terminated by ',' optionally enclosed by '"' escaped by '\\'
lines terminated by '\n';

Son birkaç satırın csv çıktısını oluşturduğu yer.

my_tableÇok büyükse bunun yavaş olabileceğini unutmayın .


"Kullanılan SELECT deyimlerinde farklı sayıda sütun var" hatası var. Efendim
Bowei Liu

1

Bir UNION kullanırsanız işe yarayacağını düşünüyorum:

select 'header 1', 'header 2', ...
union
select col1, col2, ... from ...

Başlıkları doğrudan INTO OUTFILE sözdizimi ile belirtmenin bir yolunu bilmiyorum.


1
UNION ALL daha güvenli ve daha hızlı olacaktır.
toxalot

1

Aslında bir ORDER BY ile bile çalışmasını sağlayabilirsiniz.

İfadeye göre sırayla biraz hileye ihtiyaç var - bir case deyimi kullanıyoruz ve başlık değerini listede ilk sırada sıralanması garanti edilen başka bir değerle değiştiriyoruz (açıkçası bu, alan türüne ve ASC'yi mi yoksa ASC'yi mi sıraladığınıza bağlıdır. DESC)

Ad (varchar), is_active (bool), date_something_happens (tarih) olmak üzere üç alanınız olduğunu ve ikinci ikisini azalan düzende sıralamak istediğinizi varsayalım:

select 
        'name'
      , 'is_active' as is_active
      , date_something_happens as 'date_something_happens'

 union all

 select name, is_active, date_something_happens

 from
    my_table

 order by
     (case is_active when 'is_active' then 0 else is_active end) desc
   , (case date when 'date' then '9999-12-30' else date end) desc

1

"Üstbilgileri dahil et" işlevi henüz yerleşik görünmediğinden ve buradaki çoğu "çözümün" sütun adlarını manuel olarak yazması gerektiğinden ve / veya birleşimleri hesaba katmadığından, şunu tavsiye ederim sorunun üstesinden gelmek .

  • Şimdiye kadar bulduğum en iyi alternatif, iyi bir araç kullanmaktır ( HeidiSQL kullanıyorum ).
    İsteğinizi koyun, ızgarayı seçin, sadece sağ tıklayın ve bir dosyaya aktarın. Temiz bir ihracat için gerekli tüm seçeneklere sahiptir ve çoğu ihtiyacı karşılamalıdır.

  • Aynı fikirde, user3037511'in yaklaşımı gayet iyi çalışıyor ve kolayca otomatikleştirilebilir . Başlıklarınızı almak için
    isteğinizi bir komut satırı ile başlatın . Verileri bir DIŞ DOSYA SEÇİMİ ile alabilirsiniz ... veya sorgunuzu sınırsız çalıştırarak, sizin seçiminize göre.

    Bir dosyaya çıktı yeniden yönlendirmesinin hem Linux hem de Windows'ta bir cazibe gibi çalıştığını unutmayın.


Bu , zamanın% 80'inde INFILE'DEN SEÇ veya OUTFILE SEÇ'i kullanmak istediğimde başka bir şey kullandığımı vurgulamak istememe neden oluyor. , bazı sınırlamalar nedeniyle neden oluyor (burada, 'başlık seçeneklerinin' olmaması bir AWS-RDS, eksik haklar vb.)

Dolayısıyla, ben tam olarak op en cevap vermiyorum sorusuna ... ama bu onun yanıtı vermeleri ihtiyaçlar :)
EDIT: ve aslında onun soruya cevap vermek: hayır
2017-09-07 itibarıyla, sadece başlıklarını içeremez eğer SELECT INTO OUTFILE komutu ile devam edin
: |


1

Benim veritabanı tablo adı bir örnek sensörü ile colums (id, zaman, ünite)

select ('id') as id, ('time') as time, ('unit') as unit
UNION ALL
SELECT * INTO OUTFILE 'C:/Users/User/Downloads/data.csv'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM sensor

0

Kodumu PHP'de yazıyordum ve concat ve union işlevlerini kullanırken biraz sorun yaşadım ve ayrıca SQL değişkenlerini kullanmadım, herhangi bir şekilde çalışmasını sağladım, işte kodum:

//first I connected to the information_scheme DB

$headercon=mysqli_connect("localhost", "USERNAME", "PASSWORD", "information_schema");

//took the healders out in a string (I could not get the concat function to work, so I wrote a loop for it)

    $headers = '';
    $sql = "SELECT column_name AS columns FROM `COLUMNS` WHERE table_schema = 'YOUR_DB_NAME' AND table_name = 'YOUR_TABLE_NAME'";
    $result = $headercon->query($sql);
    while($row = $result->fetch_row())
    {
        $headers = $headers . "'" . $row[0] . "', ";
    }
$headers = substr("$headers", 0, -2);

// connect to the DB of interest

$con=mysqli_connect("localhost", "USERNAME", "PASSWORD", "YOUR_DB_NAME");

// export the results to csv
$sql4 = "SELECT $headers UNION SELECT * FROM YOUR_TABLE_NAME WHERE ... INTO OUTFILE '/output.csv' FIELDS TERMINATED BY ','";
$result4 = $con->query($sql4);

0

Başlık başlıklarını sütun adlarından dinamik olarak almanın bir yolu.

/* Change table_name and database_name */
SET @table_name = 'table_name';
SET @table_schema = 'database_name';
SET @default_group_concat_max_len = (SELECT @@group_concat_max_len);

/* Sets Group Concat Max Limit larger for tables with a lot of columns */
SET SESSION group_concat_max_len = 1000000;

SET @col_names = (
  SELECT GROUP_CONCAT(QUOTE(`column_name`)) AS columns
  FROM information_schema.columns
  WHERE table_schema = @table_schema
  AND table_name = @table_name);

SET @cols = CONCAT('(SELECT ', @col_names, ')');

SET @query = CONCAT('(SELECT * FROM ', @table_schema, '.', @table_name,
  ' INTO OUTFILE \'/tmp/your_csv_file.csv\'
  FIELDS ENCLOSED BY \'\\\'\' TERMINATED BY \'\t\' ESCAPED BY \'\'
  LINES TERMINATED BY \'\n\')');

/* Concatenates column names to query */
SET @sql = CONCAT(@cols, ' UNION ALL ', @query);

/* Resets Group Contact Max Limit back to original value */
SET SESSION group_concat_max_len = @default_group_concat_max_len;

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

1
Oldukça bir çözüm söylemeliyim. Benim amaçlarım için benimsedi. Teşekkürler!
Denis Kulagin

0

Sangam Belose tarafından sağlanan cevaba eklemek istiyorum. İşte kodu:

select ('id') as id, ('time') as time, ('unit') as unit
UNION ALL
SELECT * INTO OUTFILE 'C:/Users/User/Downloads/data.csv'
  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
  FROM sensor

Ancak, "secure_file_priv"değişkenler dahilinde ayarlamadıysanız , çalışmayabilir. Bunun için, bu değişkende ayarlanan klasörü şu şekilde kontrol edin:

SHOW VARIABLES LIKE "secure_file_priv"

Çıktı şöyle görünmelidir:

mysql> show variables like "%secure_file_priv%";
+------------------+------------------------------------------------+
| Variable_name    | Value                                          |
+------------------+------------------------------------------------+
| secure_file_priv | C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\ |
+------------------+------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

Bu değişkeni değiştirebilir veya sorguyu, dosyayı gösterilen varsayılan yola çıkacak şekilde değiştirebilirsiniz.


0

MySQL tek başına bunu basitçe yapmak için yeterli değildir. Aşağıda, CSV'ye sütun ve veri çıkışı sağlayacak bir PHP betiği bulunmaktadır.

Veritabanı adınızı ve tablolarınızı üst tarafa yakın bir yere girin.

<?php

set_time_limit( 24192000 );
ini_set( 'memory_limit', '-1' );
setlocale( LC_CTYPE, 'en_US.UTF-8' );
mb_regex_encoding( 'UTF-8' );

$dbn = 'DB_NAME';
$tbls = array(
'TABLE1',
'TABLE2',
'TABLE3'
);

$db = new PDO( 'mysql:host=localhost;dbname=' . $dbn . ';charset=UTF8', 'root', 'pass' );

foreach( $tbls as $tbl )
{
    echo $tbl . "\n";
    $path = '/var/lib/mysql/' . $tbl . '.csv';

    $colStr = '';
    $cols = $db->query( 'SELECT COLUMN_NAME AS `column` FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = "' . $tbl . '" AND TABLE_SCHEMA = "' . $dbn . '"' )->fetchAll( PDO::FETCH_COLUMN );
    foreach( $cols as $col )
    {
        if( $colStr ) $colStr .= ', ';
        $colStr .= '"' . $col . '"';
    }

    $db->query(
    'SELECT *
    FROM
    (
        SELECT ' . $colStr . '
        UNION ALL
        SELECT * FROM ' . $tbl . '
    ) AS sub
    INTO OUTFILE "' . $path . '"
    FIELDS TERMINATED BY ","
    ENCLOSED BY "\""
    LINES TERMINATED BY "\n"'
    );

    exec( 'gzip ' . $path );

    print_r( $db->errorInfo() );
}

?>

Bunun çıktı almak istediğiniz dizin olması için ihtiyacınız olacak. MySQL'in dizine yazma yeteneğine sahip olması gerekir.

$path = '/var/lib/mysql/' . $tbl . '.csv';

Sorgudaki CSV dışa aktarma seçeneklerini düzenleyebilirsiniz:

INTO OUTFILE "' . $path . '"
FIELDS TERMINATED BY ","
ENCLOSED BY "\""
LINES TERMINATED BY "\n"'

Sonunda CSV GZip'e bir exec çağrısı var.


-1
'SütunAdı1', 'SütunAdı2', 'SütunAdı3'ü SEÇİN
BİRLİĞİ TÜMÜ
SütunAdı1, SütunAdı2, SütunAdı3'ü SEÇİN
    YourTable'DAN
    OUTFILE 'c: \\ datasheet.csv' TARAFINDAN SONLANDIRILAN ALANLAR ',' İSTEĞE BAĞLI OLARAK KAPSAYAN '"' '\ n' TARAFINDAN SONLANDIRILAN HATLAR 
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.