Scrittura del risultato selezionato in un file CSV


37

Dobbiamo scrivere i risultati della query SELECT in un file CSV. Come si può fare usando T-SQL in SQL Server 2008 r2? So che può essere fatto in SSIS, ma per alcuni motivi non abbiamo questa opzione.

Ho provato a utilizzare il proc suggerito nell'articolo seguente, ma quando eseguo il proc, SQL si lamenta che non è possibile eseguire sys.sp_OACreate e sys.sp_OADestroy che vengono chiamati in questo proc.

Sai come possiamo accendere questi componenti o conoscere un modo migliore per scrivere su un file usando T-SQL?

Grazie in anticipo.

Risposte:


52

Usa l' utilità BCP

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

L' -cargomento specifica l' output di c haracter, al contrario del formato binario nativo di SQL; questo valore predefinito valori separati da tabulazione, ma -t ,cambia il campo t erminator in virgole. -Tspecifica l'autenticazione di Windows (" t rusted connection"), altrimenti usa -U MyUserName -P MyPassword.

Questo non esporta le intestazioni di colonna per impostazione predefinita. È necessario utilizzare UNION ALL per le intestazioni

O

Usa SQLCMD

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

O

Usa Powershell

Ecco un link ad un articolo . Se finisci per usarlo, potresti voler aggiungere -notypedopo Export-Csv $extractFileper sbarazzarti della colonna non necessaria sul file di output.


4
+1 Per l'utilità BCP: è molto facile da usare, è lo strumento più veloce che io abbia mai usato per le informazioni di esportazione / importazione e ci sono molte opzioni. Ti consiglierò di aggiungere "> FileName.log" alla fine dell'istruzione - questo creerà un file di registro.
gotqn,

24

Aggiungendo alla risposta precedente, che ti aiuta ad automatizzare l'azione, se ne hai bisogno solo di tanto in tanto puoi farlo in Management Studio, fai semplicemente clic con il pulsante destro del mouse sull'intestazione - Salva risultati come -> scegli un file .csv .

Oppure, se si desidera farlo per ogni istruzione select eseguita, è possibile modificare la direzione di output dei risultati in un file. Usa Strumenti -> Opzioni -> Risultati query - Risultati su file .

Un altro modo, che può essere automatizzato facilmente e utilizza SSIS, è utilizzando la funzione Esporta dati di Management Studio. Fare clic con il tasto destro sul database -> Attività -> Esporta dati. C'è un mago con molte opzioni lì. È necessario scegliere il database di origine, la destinazione e altre opzioni. Per la destinazione assicurati che sia "File flat", sfoglia e scegli il tipo .csv, scegli la formattazione di cui hai bisogno e alla fine otterrai un pacchetto SSIS che può essere salvato localmente e ripetuto in caso di necessità.


10

Usa 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

Ma ci sono un paio di avvertenze:

  1. È necessario disporre del provider Microsoft.ACE.OLEDB.12.0 disponibile. Anche il provider Jet 4.0 funzionerà, ma è antico, quindi ho usato questo.
  2. Il file .CSV dovrà esistere già. Se stai usando le intestazioni (HDR = YES), assicurati che la prima riga del file .CSV sia un elenco delimitato di tutti i campi.

1
La migliore risposta finora!
ajeh,

1
ottimo lavoro compresi avvertimenti
JJS

5

Bassa tecnologia, ma ...

select
   col1 + ','
+  cast(col2 as varchar(10)) + ','
+  col3
from mytable;

MySQL considera il col1 + ',' + cast(col2 as varchar(10)) + ',' + col3nome di una colonna e stampa NULL ovunque.
Nikhil Wagh,

4

Sembra che tu abbia già una soluzione accettabile, ma se hai impostato db mail potresti potenzialmente fare qualcosa del genere:

EXEC msdb.dbo.sp_send_dbmail
    @recipients='your.email@domain.com',
    @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

Se stai inviando il file via e-mail da qualche parte, potrebbe salvarti alcuni passaggi.


Proprio quello che stavo cercando, complimenti a te!
Mashchax

Sebbene sia necessario aggiungere il parametro @profile_name se non si dispone di un profilo privato predefinito per l'utente o di un profilo pubblico per il database.
Mashchax

1

Questo può essere fatto facilmente in un processo in 3 fasi:

  1. Scrivi la tua query come una SELECT INTOquery. Ciò essenzialmente esporterà i risultati della query in una tabella.

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

    Nota, questa tabella non può esistere quando viene eseguita la query, poiché questo tipo di query vuole creare la tabella come parte dell'esecuzione.

  2. Quindi utilizzare SSIS per esportare i risultati di quella tabella .csv . La procedura guidata di esportazione SSIS ti consente di scegliere il delimitatore, ecc. Questo è molto utile per usare un | delimitatore nei casi in cui il set di risultati contiene virgole.

    Fare clic destro su DB Name > Tasks > Export Data

  3. Al termine dell'esportazione, eseguire il DROP TABLEcomando per pulire la tabella di registro.

    Drop Table dbo.LogTableName

3
Ciao don Ho aggiunto un po 'di formattazione alla tua risposta. Puoi fare clic su "modifica" in basso a sinistra per vedere cosa è cambiato e fare clic sul bit "modificato" xx minuti "per visualizzare una cronologia completa se desideri eseguire il rollback. Sebbene fattibile, la tua risposta non aggiunge molto ciò che è già stato scritto ed è improbabile che attiri molta attenzione.
Michael Green,

0

Uso MS Access DoCMD per esportare CSV da SQL Server. È in grado di farlo con un solo comando. Il database di accesso viene utilizzato solo per abilitare il comando di accesso. Funziona bene e come ulteriore vantaggio (non so perché) crea uno schema.ini per la tabella esportata.

Adamo

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"

-1

Questa procedura genererà un file CSV con l'output della query che passi come parametro. Il secondo parametro è il nome del tuo file CSV, assicurati di passare il nome del file con un percorso scrivibile valido.

Ecco lo script per creare la procedura:

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

2
qui solo le risposte al codice non sono accettabili: potresti aggiungere qualche commento alla tua risposta e perché funziona? (probabilmente anche i commenti in codice potrebbero aiutare qui)
George.Palacios

Sì, e potresti anche aggiungere un esempio come utilizzarlo con successo?
Marcello Miorelli,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.