Sertakan tajuk saat menggunakan SELECT INTO OUTFILE?

117

Apakah mungkin untuk menyertakan header saat menggunakan MySQL INTO OUTFILE?

Brett
sumber

Jawaban:

166

Anda harus membuat kode keras untuk header itu sendiri. Sesuatu seperti:

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT ColName1, ColName2, ColName3
    FROM YourTable
    INTO OUTFILE '/path/outfile'
Joe Stefanelli
sumber
14
Tapi itu tidak akan berhasil jika ada ORDER BYdi SELECTklausa. Baris tajuk bisa berada di mana saja dalam file yang dibuat tergantung pada urutannya.
COil
Lihat beberapa jawaban di bawah ini untuk ide-ide tentang penggunaan ORDER BY dan juga jawaban matt untuk cara cepat mendapatkan semua ColName1, ColName2, dll. Pengaya yang sangat berguna untuk jawaban hebat ini!
Andrew T
1
Jawaban ini sepertinya benar, saya bahkan menggunakannya hampir secara membabi buta di server dev saya ... Tanpa header kolom, dibutuhkan sekitar 50 detik untuk membuang 240 juta baris. Dengan UNION ALL ini, server mengalami masalah besar saat mencoba melakukan tabel sementara sebelum membuang semuanya, sudah lebih dari 10 menit sekarang dan masih menunggu tabel sementara untuk ditulis di disk! Sadarilah itu! Anda pasti lebih suka menambahkan nama kolom dengan cara lain, meskipun itu berarti membuka file setelahnya dengan bahasa pemrograman lain.
Salketer
Ini hanya tampak berfungsi jika semua kolom TabelAnda adalah tipe data karakter, yang memang masuk akal. Jika tidak, Anda mendapatkan error yang tidak membantu: "Pernyataan SELECT yang digunakan memiliki jumlah kolom yang berbeda".
TheBamf
1
Ini adalah salah satu alasan mengapa saya mempertimbangkan untuk beralih ke DBMS lain.
e18r
85

Solusi yang disediakan oleh Joe Steanelli berfungsi, tetapi membuat daftar kolom tidak nyaman ketika lusinan atau ratusan kolom terlibat. Berikut cara mendapatkan daftar kolom tabel my_table di 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

Sekarang Anda dapat menyalin & menempel baris yang dihasilkan sebagai pernyataan pertama dalam metode Joe.

Matt
sumber
2
Ini mengembalikan semua kolom yang digabungkan menjadi satu bidang. Saya tidak dapat menggabungkannya dengan pernyataan pilih lain yang mengembalikan beberapa bidang. Ini sangat berguna untuk mendapatkan baris yang bisa saya salin dan tempel sebagai header outfile saya.
tmoore82
1
Idenya adalah untuk menyalin kolom tunggal yang dihasilkan dan menempelkannya ke pernyataan UNION Anda daripada mengetik secara manual di kolom1, kolom2, dll saat menggunakan metode Joe (jawaban yang diterima) sehingga Anda bisa mendapatkan daftar kolom lebih cepat!
Andrew T
Saya ingin mengekspor semua skema tabel / bidang saya. Jawaban ini dikombinasikan dengan jawaban yang diterima berhasil!
Rémi Breton
@ Chris ORDER BY ORDINAL_POSITIONmengatasinya
matt
1
ORDER BY ORDINAL_POSITION harus menjadi bagian dari panggilan GROUP_CONCAT (), seperti dalamGROUP_CONCAT(CONCAT('"',COLUMN_NAME,'"') order BY ORDINAL_POSITION)
Apuleius
15

Untuk pemilihan kompleks dengan ORDER BY saya menggunakan yang berikut ini:

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';
evilguc
sumber
Solusi ini bekerja dengan baik saat memesan kueri kedua (kompleks); jika Anda tidak melakukannya dengan cara ini Anda akan berakhir dengan memesan kolom pertama juga yang tidak diinginkan. Saran bagus @evilguc!
Aaron
Tidak bekerja dengan saya, setelah melakukan UNION SEMUA urutan kolom id kacau
Mohanad Kaleia
6

Anda dapat menggunakan pernyataan yang sudah disiapkan dengan jawaban lucek dan mengekspor tabel secara dinamis dengan nama kolom di CSV:

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

Terima kasih lucek.

Vrag
sumber
6

Ini akan memungkinkan Anda untuk memiliki kolom terurut dan / atau batas

SELECT 'ColName1', 'ColName2', 'ColName3'
UNION ALL
SELECT * from (SELECT ColName1, ColName2, ColName3
    FROM YourTable order by ColName1 limit 3) a
    INTO OUTFILE '/path/outfile';
Donald Wagner
sumber
1
Perlu diketahui bahwa tata letak kueri ini juga berfungsi untuk saya di MariaDB 10.1; tata letak lain yang disarankan di utas ini tidak.
ProgrammerDan
Munculkan tajuk di bagian bawah untuk beberapa alasan, tetapi berfungsi dengan baik untuk memunculkan kembali di atas dalam aplikasi spreadsheet, aneh tetapi bersorak
Dmitri DB
Saya juga terjebak menggunakan mariaDB. dengan ekstraksi hanya 100 prospek, ini lebih cepat 14 detik daripada menjalankan jawaban yang diterima. Pass pertama dengan diterima: Query OK, 100 rows affected (14.72 sec) Pass kedua dengan milik AndaQuery OK, 101 rows affected (0.00 sec)
Casper Wilkes
6

Saya cukup membuat 2 query, pertama untuk mendapatkan query output (limit 1) dengan nama kolom (tanpa hardcode, tidak ada masalah dengan Join, Order by, custom column names, dll), dan kedua membuat query itu sendiri, dan menggabungkan file menjadi satu CSV mengajukan:

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
pengguna3037511
sumber
5

Saya menghadapi masalah serupa saat menjalankan kueri mysql pada tabel besar di NodeJS. Pendekatan yang saya ikuti untuk memasukkan header dalam file CSV saya adalah sebagai berikut

  1. Gunakan query OUTFILE untuk mempersiapkan file tanpa header

        SELECT * INTO OUTFILE [FILE_NAME] FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED 
        BY '\"' LINES TERMINATED BY '\n' FROM [TABLE_NAME]
  2. Ambil tajuk kolom untuk tabel yang digunakan di poin 1

        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. Tambahkan tajuk kolom ke file yang dibuat pada langkah 1 menggunakan paket npm file prepend

Eksekusi setiap langkah dikontrol menggunakan promise di NodeJS.

rahul shukla
sumber
3

Ini adalah cheat alternatif jika Anda terbiasa dengan Python atau R, dan tabel Anda dapat masuk ke dalam memori.

Impor tabel SQL ke Python atau R dan kemudian ekspor dari sana sebagai CSV dan Anda akan mendapatkan nama kolom serta datanya.

Inilah cara saya melakukannya menggunakan R, membutuhkan pustaka RMySQL:

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

Ini sedikit curang tetapi saya menemukan ini adalah solusi cepat ketika jumlah kolom saya terlalu panjang untuk menggunakan metode concat di atas. Catatan: R akan menambahkan kolom 'row.names' di awal CSV sehingga Anda ingin menghapusnya jika memang perlu mengandalkan CSV untuk membuat ulang tabel.

Bergabung dengan Dots
sumber
2

Jadi, jika semua kolom di my_tableadalah tipe data karakter , kita dapat menggabungkan jawaban teratas (oleh Joe, matt dan evilguc) bersama-sama, untuk menambahkan tajuk secara otomatis dalam satu kueri SQL 'sederhana', misalnya

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

dimana beberapa baris terakhir membuat output csv.

Perhatikan bahwa ini mungkin lambat jika my_tablesangat besar.

TheBamf
sumber
itu memiliki kesalahan "Pernyataan SELECT yang digunakan memiliki jumlah kolom yang berbeda". Sir
Bowei Liu
1

Saya pikir jika Anda menggunakan UNION, itu akan berhasil:

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

Saya tidak tahu cara menentukan header dengan sintaks INTO OUTFILE secara langsung.

Paul W.
sumber
1
UNION ALL akan lebih aman dan lebih cepat.
Toxalot
1

Sebenarnya Anda dapat membuatnya berfungsi bahkan dengan ORDER BY.

Hanya perlu beberapa tipu daya dalam urutan berdasarkan pernyataan - kami menggunakan pernyataan kasus dan mengganti nilai header dengan beberapa nilai lain yang dijamin untuk mengurutkan terlebih dahulu dalam daftar (jelas ini tergantung pada jenis bidang dan apakah Anda mengurutkan ASC atau DESC)

Misalkan Anda memiliki tiga bidang, nama (varchar), is_active (bool), date_something_happens (tanggal), dan Anda ingin mengurutkan dua menurun:

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
Simon Woolf
sumber
1

Karena fungsi 'include-headers' tampaknya belum terpasang, dan sebagian besar "solusi" di sini perlu mengetik nama kolom secara manual, dan / atau bahkan tidak memperhitungkan gabungan, saya akan merekomendasikan untuk mengatasi masalah .

  • Alternatif terbaik yang saya temukan sejauh ini adalah menggunakan alat yang layak (saya menggunakan HeidiSQL ).
    Masukkan permintaan Anda, pilih kisi, cukup klik kanan dan ekspor ke file. Itu mendapat semua opsi yang diperlukan untuk ekspor bersih, dan harus menangani sebagian besar kebutuhan.

  • Dalam ide yang sama, pendekatan user3037511 berfungsi dengan baik, dan dapat diotomatiskan dengan mudah .
    Cukup luncurkan permintaan Anda dengan beberapa baris perintah untuk mendapatkan header Anda. Anda mungkin mendapatkan data dengan SELECT INTO OUTFILE ... atau dengan menjalankan kueri Anda tanpa batas, milik Anda untuk dipilih.

    Perhatikan bahwa pengalihan keluaran ke file berfungsi seperti pesona di Linux DAN Windows.


Ini membuat saya ingin menyoroti bahwa 80% dari waktu, ketika saya ingin menggunakan SELECT FROM INFILE atau SELECT INTO OUTFILE, saya akhirnya menggunakan sesuatu yang lain karena beberapa batasan (di sini, tidak adanya 'opsi tajuk', di AWS-RDS, hak yang hilang, dan sebagainya.)

Oleh karena itu, saya tidak benar-benar menjawab pertanyaan op ... tetapi itu harus menjawab kebutuhannya :)
EDIT: dan untuk benar-benar menjawab pertanyaannya: tidak
Pada 2017-09-07, Anda tidak dapat menyertakan header jika Anda tetap dengan perintah SELECT INTO OUTFILE
: |

Balmipour
sumber
1

contoh dari sensor nama tabel database saya dengan kolom (id, waktu, unit)

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
Dayanand SK
sumber
0

Saya sedang menulis kode saya dalam PHP, dan saya mengalami sedikit masalah dalam menggunakan fungsi concat dan union, dan juga tidak menggunakan variabel SQL, cara apa pun yang saya gunakan untuk berfungsi, berikut adalah kode saya:

//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);
pengguna5671922
sumber
0

Berikut ini cara untuk mendapatkan judul header dari nama kolom secara dinamis.

/* 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;
RNickMcCandless
sumber
1
Solusi yang cukup harus saya katakan. Mengadopsi untuk tujuan saya. Terima kasih!
Denis Kulagin
0

Saya ingin menambahkan jawaban yang diberikan oleh Sangam Belose. Ini kodenya:

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

Namun, jika Anda belum menyiapkan "secure_file_priv"variabel Anda, itu mungkin tidak berfungsi. Untuk itu, periksa folder yang disetel pada variabel itu dengan:

SHOW VARIABLES LIKE "secure_file_priv"

Outputnya akan terlihat seperti ini:

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)

Anda dapat mengubah variabel ini atau mengubah kueri untuk mengeluarkan file ke jalur default yang ditampilkan.

RGregg
sumber
0

MySQL saja tidak cukup untuk melakukan ini dengan mudah. Di bawah ini adalah skrip PHP yang akan menampilkan kolom dan data ke CSV.

Masukkan nama database dan tabel Anda di dekat bagian atas.

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

?>

Anda memerlukan ini untuk menjadi direktori yang Anda inginkan untuk menghasilkan keluaran. MySQL harus memiliki kemampuan untuk menulis ke direktori.

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

Anda dapat mengedit opsi ekspor CSV dalam kueri:

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

Di bagian akhir, ada panggilan eksekutif ke GZip CSV.

Kohjah Breese
sumber
-1
PILIH 'ColName1', 'ColName2', 'ColName3'
UNI SEMUA
PILIH ColName1, ColName2, ColName3
    FROM YourTable
    INTO OUTFILE 'c: \\ datasheet.csv' FIELDS DIHENTIKAN OLEH ',' OPSI TERMASUK OLEH '"' LINES DIHENTIKAN OLEH '\ n' 
manoj singh
sumber