Schreiben eines Auswahlergebnisses in eine CSV-Datei

37

Wir müssen die SELECT-Abfrageergebnisse in eine CSV-Datei schreiben. Wie geht das mit T-SQL in SQL Server 2008 r2? Ich weiß, dass dies in SSIS möglich ist, aber aus bestimmten Gründen haben wir diese Option nicht.

Ich habe versucht, das im folgenden Artikel vorgeschlagene Verfahren zu verwenden, aber wenn ich das Verfahren ausführe, beklagt sich SQL, dass sys.sp_OACreate und sys.sp_OADestroy, die in diesem Verfahren aufgerufen werden, nicht ausgeführt werden können.

Wissen Sie, wie wir diese Komponenten einschalten können oder wie Sie mit T-SQL besser in eine Datei schreiben können?

Danke im Voraus.

Himmel
quelle

Antworten:

52

Verwenden Sie das Dienstprogramm BCP

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

Das -cArgument gibt c HARACTER Ausgang, wie zum SQL nativen Binärformat entgegengesetzt; Voreingestellt ist Tabulatorzeichen getrennte Werte, aber -t ,ändert das Feld t erminator zu Kommas. -TGibt die Windows-Authentifizierung an (" Keine verrostete Verbindung"), andernfalls verwenden -U MyUserName -P MyPassword.

Standardmäßig werden dabei keine Spaltenüberschriften exportiert. Sie müssen UNION ALL für Header verwenden

ODER

Verwenden Sie SQLCMD

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

ODER

Verwenden Sie PowerShell

Hier ist ein Link zu einem Artikel . Wenn Sie sich mit diesem beenden, sollten Sie anhängen -notypenach Export-Csv $extractFileder unnötigen Spalte auf der Ausgabedatei , um loszuwerden.

RK Kuppala
quelle
4
+1 Für das BCP-Dienstprogramm - es ist sehr einfach zu bedienen, es ist das schnellste Tool, das ich je für den Export / Import von Informationen verwendet habe, und es gibt viele Optionen. Ich werde Ihnen raten, am Ende der Anweisung "> FileName.log" hinzuzufügen. Dadurch wird eine Protokolldatei erstellt.
Gotqn
24

Zur vorherigen Antwort hinzufügen, die Ihnen hilft, die Aktion zu automatisieren. Wenn Sie sie nur von Zeit zu Zeit in Management Studio benötigen, klicken Sie einfach mit der rechten Maustaste auf die Überschrift - Ergebnisse speichern unter -> wählen Sie eine CSV-Datei .

Wenn Sie dies für jede ausgewählte Anweisung tun möchten, die Sie ausführen, können Sie die Ausgaberichtung der Ergebnisse in eine Datei ändern. Verwenden Sie Extras -> Optionen -> Abfrageergebnisse - Ergebnisse in Datei .

Eine andere Möglichkeit, die einfach automatisiert werden kann und SSIS nutzt, ist die Verwendung der Exportdaten-Funktion von Management Studio. Klicken Sie mit der rechten Maustaste auf die Datenbank -> Aufgaben -> Daten exportieren. Es gibt dort einen Assistenten mit vielen Optionen. Sie sollten die Quelldatenbank, das Ziel und andere Optionen auswählen. Stellen Sie als Ziel sicher, dass es sich um eine "Flat-Datei" handelt, suchen Sie nach dem CSV-Typ und wählen Sie die gewünschte Formatierung aus. Am Ende erhalten Sie ein SSIS-Paket, das lokal gespeichert und bei Bedarf wiederholt werden kann.

Marian
quelle
10

Verwenden Sie 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

Aber es gibt ein paar Einschränkungen:

  1. Sie benötigen den Microsoft.ACE.OLEDB.12.0-Anbieter. Der Jet 4.0-Anbieter wird auch funktionieren, aber er ist uralt, also habe ich stattdessen diesen verwendet.
  2. Die CSV-Datei muss bereits vorhanden sein. Wenn Sie Header verwenden (HDR = YES), stellen Sie sicher, dass die erste Zeile der CSV-Datei eine durch Trennzeichen getrennte Liste aller Felder ist.
Slogmeister Extraordinaire
quelle
1
Beste Antwort bisher!
6.
1
gute Arbeit, einschließlich Vorbehalte
JJS
5

Low Tech, aber ...

select
   col1 + ','
+  cast(col2 as varchar(10)) + ','
+  col3
from mytable;
Alain
quelle
MySQL wird col1 + ',' + cast(col2 as varchar(10)) + ',' + col3als Spaltenname behandelt und überall mit NULL ausgegeben.
Nikhil Wagh
4

Es sieht so aus, als hätten Sie bereits eine akzeptable Lösung, aber wenn Sie DB-Mail eingerichtet haben, könnten Sie möglicherweise Folgendes tun:

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

Wenn Sie die Datei trotzdem per E-Mail versenden, können Sie einige Schritte sparen.

Shane Estelle
quelle
Genau das, wonach ich gesucht habe, ein dickes Lob an Sie!
Mashchax
Sie müssen jedoch den Parameter @profile_name hinzufügen, wenn Sie für Ihren Benutzer kein privates Standardprofil und für die Datenbank kein öffentliches Profil haben.
Mashchax
1

Dies kann leicht in einem dreistufigen Prozess durchgeführt werden:

  1. Schreiben Sie Ihre Anfrage als SELECT INTOAnfrage. Dadurch werden Ihre Abfrageergebnisse im Wesentlichen in eine Tabelle exportiert.

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

    Beachten Sie, dass diese Tabelle nicht vorhanden sein kann , wenn die Abfrage ausgeführt wird, da dieser Abfragetyp die Tabelle als Teil der Ausführung erstellen möchte.

  2. Verwenden Sie dann SSIS, um die Ergebnisse dieser Tabelle nach zu exportieren .csv. Mit dem SSIS-Export-Assistenten können Sie Ihr Trennzeichen usw. auswählen. Dies ist sehr praktisch, wenn Sie ein | verwenden Trennzeichen in Fällen, in denen die Ergebnismenge Kommas enthält.

    Rechtsklick auf DB Name > Tasks > Export Data

  3. Führen Sie nach Abschluss des Exports den DROP TABLEBefehl aus, um Ihre Protokolltabelle zu bereinigen.

    Drop Table dbo.LogTableName
Don Moehling
quelle
3
Hi Don. Ich habe Ihrer Antwort einige Formatierungen hinzugefügt. Sie können unten links auf "Bearbeiten" klicken, um zu sehen, was sich geändert hat, und auf das Bit "Bearbeitet" xx Minuten klicken, um einen vollständigen Verlauf anzuzeigen, wenn Sie einen Rollback durchführen möchten Was bereits geschrieben wurde und kaum Aufmerksamkeit erregen wird
Michael Green
0

Ich verwende MS Access DoCMD, um CSVs von SQL Server zu exportieren. Es ist in der Lage, dies mit einem einzigen Befehl zu tun. Die Zugriffsdatenbank wird nur zum Aktivieren des Zugriffsbefehls verwendet. Die Leistung ist gut und als zusätzlicher Vorteil (nicht sicher, warum) wird eine schema.ini für die exportierte Tabelle erstellt.

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
quelle
-1

Diese Prozedur generiert eine CSV-Datei mit der Ausgabe der Abfrage, die Sie als Parameter übergeben. Der zweite Parameter ist Ihr CSV-Dateiname. Stellen Sie sicher, dass Sie den Dateinamen mit einem gültigen schreibbaren Pfad übergeben.

Hier ist das Skript, um die Prozedur zu erstellen:

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
Scharfsinn
quelle
2
Antworten nur mit Code werden hier nicht als akzeptabel angesehen. Können Sie einen Kommentar zu Ihrer Antwort hinzufügen und erklären, warum dies funktioniert? (Code Kommentare würden wahrscheinlich auch hier helfen)
George.Palacios
Ja, und können Sie auch ein Beispiel hinzufügen, wie Sie es erfolgreich einsetzen?
Marcello Miorelli