Menulis hasil pilih ke file csv

37

Kita perlu menulis hasil kueri SELECT ke file csv. Bagaimana itu bisa dilakukan dengan menggunakan T-SQL di SQL Server 2008 r2? Saya tahu itu bisa dilakukan di SSIS, tetapi untuk beberapa alasan, kami tidak memiliki opsi ini.

Saya mencoba menggunakan proc yang disarankan dalam artikel di bawah ini, tetapi ketika saya menjalankan proc, SQL mengeluh bahwa tidak dapat menjalankan sys.sp_OACreate dan sys.sp_OADestroy yang dipanggil dalam proc ini.

Apakah Anda tahu cara mengaktifkan komponen ini atau mengetahui cara lain yang lebih baik untuk menulis ke file menggunakan T-SQL?

Terima kasih sebelumnya.

Langit
sumber

Jawaban:

52

Gunakan utilitas BCP

bcp "SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable" queryout "D:\MyTable.csv" -c -t , -S SERVERNAME -T

The -cArgumen menspesifikasikan c keluaran haracter, sebagai lawan ke format biner asli SQL; ini default untuk nilai-nilai yang dipisahkan tab, tetapi -t ,mengubah t erminator bidang menjadi koma. -Tmenentukan otentikasi Windows (" t rusted connection"), jika tidak gunakan -U MyUserName -P MyPassword.

Ini tidak mengekspor tajuk kolom secara default. Anda perlu menggunakan UNION ALL untuk tajuk

ATAU

Gunakan SQLCMD

SQLCMD -S SERVERNAME -E -Q "SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable"
-s "," -o "D:\MyData.csv" 

ATAU

Gunakan Powershell

Berikut ini tautan ke sebuah artikel . Jika Anda akhirnya menggunakan ini, Anda mungkin ingin menambahkan -notypesetelahnya Export-Csv $extractFileuntuk menyingkirkan kolom yang tidak perlu pada file output.

RK Kuppala
sumber
4
+1 Untuk utilitas BCP - sangat mudah digunakan, ini adalah alat tercepat yang pernah saya gunakan untuk informasi ekspor / impor dan ada banyak opsi. Saya akan menyarankan Anda untuk menambahkan "> FileName.log" di akhir pernyataan - ini akan membuat file log.
Gotqn
24

Menambahkan ke jawaban sebelumnya, yang membantu Anda mengotomatiskan tindakan, jika Anda hanya membutuhkannya dari waktu ke waktu Anda dapat melakukannya di Management Studio, cukup klik kanan pada header - Simpan hasil sebagai -> pilih file .csv .

Atau jika Anda ingin melakukan itu untuk setiap pernyataan pilih yang Anda jalankan, Anda bisa mengubah arah output dari hasil ke file. Gunakan Alat -> Opsi -> Hasil Kueri - Hasil ke file .

Cara lain, yang dapat diotomatisasi dengan mudah, dan memanfaatkan SSIS, adalah dengan menggunakan fitur Ekspor Data Management Studio. Klik kanan pada database -> Tugas -> Ekspor data. Ada penyihir dengan banyak opsi di sana. Anda harus memilih sumber basis data, tujuan dan opsi lainnya. Untuk tujuan, pastikan itu "Flat file", telusuri dan pilih tipe .csv, pilih format apa pun yang Anda butuhkan dan pada akhirnya Anda akan mendapatkan paket SSIS yang dapat disimpan secara lokal dan diulang sesuai kebutuhan.

Marian
sumber
10

Gunakan T-SQL

INSERT INTO OPENROWSET('Microsoft.ACE.OLEDB.12.0','Text;Database=D:\;HDR=YES;FMT=Delimited','SELECT * FROM [FileName.csv]')
SELECT Field1, Field2, Field3 FROM DatabaseName

Tapi, ada beberapa peringatan:

  1. Anda harus memiliki penyedia Microsoft.ACE.OLEDB.12.0 tersedia. Penyedia Jet 4.0 akan bekerja juga, tapi ini kuno, jadi saya menggunakan yang ini sebagai gantinya.
  2. File .CSV harus sudah ada. Jika Anda menggunakan tajuk (HDR = YA), pastikan baris pertama file .CSV adalah daftar semua bidang yang dibatasi.
Slogmeister Luar Biasa
sumber
1
Jawaban terbaik sejauh ini!
ajeh
1
pekerjaan hebat termasuk peringatan
JJS
5

Teknologi rendah, tapi ...

select
   col1 + ','
+  cast(col2 as varchar(10)) + ','
+  col3
from mytable;
Alain
sumber
MySQL memperlakukan col1 + ',' + cast(col2 as varchar(10)) + ',' + col3sebagai nama kolom, dan mencetak NULL di semua tempat.
Nikhil Wagh
4

Sepertinya Anda sudah memiliki solusi yang dapat diterima, tetapi jika Anda memiliki pengaturan db mail, Anda berpotensi melakukan sesuatu seperti ini:

EXEC msdb.dbo.sp_send_dbmail
    @recipients='[email protected]',
    @subject='CSV Extract', 
    @body='See attachment',
    @query ='SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable',
    @attach_query_result_as_file = 1,
    @query_attachment_filename = 'CSV_Extract.txt',
    @query_result_separator = ',',
    @query_result_header = 1

Jika Anda tetap mengirim email ke suatu tempat, mungkin ada beberapa langkah yang bisa Anda lakukan.

Shane Estelle
sumber
Apa yang saya cari, pujian untuk Anda!
Mashchax
Meskipun Anda perlu menambahkan parameter @profile_name jika Anda tidak memiliki profil pribadi default untuk pengguna Anda atau profil publik untuk database.
Mashchax
1

Ini dapat dengan mudah dilakukan dalam proses 3 langkah:

  1. Tulis kueri Anda sebagai SELECT INTOkueri. Ini pada dasarnya akan mengekspor hasil permintaan Anda ke dalam tabel.

    Select
      Field1
     ,Field2
     ,Field3
    INTO dbo.LogTableName         --Table where the query Results get logged into.
    From Table

    Catatan, tabel ini tidak dapat ada saat kueri berjalan, karena jenis kueri ini ingin membuat tabel sebagai bagian dari eksekusi.

  2. Kemudian gunakan SSIS untuk mengekspor hasil dari tabel itu ke .csv. Panduan Ekspor SSIS memungkinkan Anda memilih pembatas, dll. Ini sangat berguna untuk menggunakan | pembatas dalam kasus di mana set hasil berisi koma.

    Klik kanan DB Name > Tasks > Export Data

  3. Setelah Ekspor selesai, jalankan DROP TABLEperintah untuk membersihkan tabel log Anda.

    Drop Table dbo.LogTableName
Don Moehling
sumber
3
Hai, Don. Saya menambahkan beberapa format ke jawaban Anda. Anda dapat mengklik 'edit' di kiri bawah untuk melihat apa yang berubah dan klik bit "diedit" xx menit "untuk melihat riwayat lengkap jika Anda ingin memutar kembali. Walaupun bisa diterapkan, jawaban Anda tidak menambahkan terlalu banyak apa yang sudah ditulis dan tidak mungkin menarik banyak perhatian
Michael Green
0

Saya menggunakan MS Access DoCMD untuk mengekspor CSV dari SQL Server. Itu dapat melakukannya dengan satu perintah. Database akses hanya digunakan untuk mengaktifkan perintah akses. Berkinerja baik, dan sebagai manfaat tambahan (tidak yakin mengapa) itu membuat skema.ini untuk tabel yang diekspor.

Adam

CMD="SELECT * INTO [Text;HDR=Yes;DATABASE=C:\].[Results.txt]  
FROM [ODBC;DSN=SQL2017;Description=SQL2017;UID=.;Trusted_Connection=Yes;APP=Microsoft Office 2013;WSID=LAPTOP-XYZ;DATABASE=TempDB_DataDump_1].Results "

 Set appAccess = CreateObject("Access.Application") 
                appAccess.OpenCurrentDatabase "anyAccessdatabase.mdb" 
                   ' appAccess.DoCmd.SetWarnings 0
                    appAccess.DoCmd.runsql "CMD"
Adam
sumber
-1

Prosedur ini akan menghasilkan file CSV dengan output dari kueri yang Anda berikan sebagai parameter. Parameter ke-2 adalah nama file CSV Anda, pastikan Anda memberikan nama file dengan jalur yang dapat ditulis.

Berikut ini skrip untuk membuat prosedur:

CREATE procedure [dbo].[usp_create_csv_file_from_query]
    @sql Nvarchar(MAX),
    @csvfile Nvarchar(200)
    as
    BEGIN
        if IsNull(@sql,'') = '' or IsNull(@csvfile,'') = ''
        begin
            RAISERROR ('Invalid SQL/CsvFile values passed!; Aborting...', 0, 1) WITH NOWAIT
            return
        end
        DROP TABLE if exists global_temp_CSVtable;
        declare 
            @columnList varchar(4000), 
            @columnList1 varchar(4000),
            @sqlcmd varchar(4000),
            @dos_cmd nvarchar(4000)

        set @sqlcmd = replace(@sql, 'from', 'into global_temp_CSVtable from')
        EXECUTE (@sqlcmd); 

        declare @cols table (i int identity, colname varchar(100))
        insert into @cols
        select column_name
        from information_schema.COLUMNS
        where TABLE_NAME = 'global_temp_CSVtable'

        declare @i int, @maxi int
        select @i = 1, @maxi = MAX(i) from @cols

        while(@i <= @maxi)
        begin
            select @sql = 'alter table global_temp_CSVtable alter column [' + colname + '] VARCHAR(max) NULL'
            from @cols
            where i = @i
            exec sp_executesql @sql
            select @i = @i + 1
        end

        SELECT 
             @columnList = COALESCE(@columnList + ''', ''', '') + column_name 
            ,@columnList1 = COALESCE(@columnList1 + ', ', '') + column_name
        from information_schema.columns
        where table_name =  'global_temp_CSVtable'
        ORDER BY ORDINAL_POSITION;

        SELECT @columnList = '''' + @columnList + '''';

        SELECT @dos_cmd='BCP "SELECT ' + @columnList + 
                        ' UNION ALL ' +
                        'SELECT * from ' + db_name() + '..global_temp_CSVtable" ' + 
                        'QUERYOUT ' + @csvfile + 
                        ' -c -t, -T'
        exec master.dbo.xp_cmdshell @dos_cmd, No_output 
        DROP TABLE if exists global_temp_CSVtable;
    end
Sharief Pareed
sumber
2
hanya kode jawaban yang dianggap tidak dapat diterima di sini - dapatkah Anda menambahkan komentar tentang jawaban Anda dan mengapa itu berhasil? (komentar kode mungkin akan membantu di sini juga)
George.Palacios
Ya, dan bisakah Anda juga menambahkan contoh bagaimana Anda berhasil menggunakannya?
Marcello Miorelli