Freitag, 26. März 2021

SQL-Abfrage direkt in Datei ausgeben

Problem: Ich möchte eine Abfrage direkt in eine Datei ausgeben. 

Nutzer von MySQL oder MariaDB werden müde lächeln - da gibt es entsprechende Befehle, die das tun. Im MSSQL habe ich keine gefunden. Es gibt aber Lösungen:

Lösung 1: Im SSMS selbst

Im SSMS kann ich das einstellen: Unter Extras, Optionen, Abfrageergebnisse kann ich einstellen, dass direkt in eine Datei ausgegeben wird:


Das ist OK, hat aber zwei Nachteile: 

  1. Die Einstellung gilt nun für alle Abfragen im SSMS
  2. Es wird "nur" eine .RPT - Datei erstellt

Ich würde aber gern nur diese eine Abfrage als Datei ausgeben...


Lösung 2: SQLCMD

Der Befehl SQLSCMD in eine Batch eingebunden könnte in etwa so aussehen:

SQLCMD -S "SERVER\INSTANZ" -U BENUTZER -P PASSWORT -d DATENBANK -i "C:\PFAD\ZUR\ABFRAGE\ABFRAGESKRIPT.sql" -o "C:\PFAD\ZUM\ERGEBNIS\ERGEBNIS.csv" -W -w 1024 -s";"

Die Schalter -S -U -P und -d sind klar.

-i zeigt auf die Abfrage, und -o auf Ausgabe.
-W entfernt Leerzeichen in Spalten
-w verlängert die Ausgabe pro Zeile (die sonst nach 80 Zeichen endet) hier auf 1024 Zeichen.
-s definiert den Seperator zwischen den Spalten

Denkbar ist noch -u, um den Zeichensatz der Ausgabe zu beeinflussen.

Das funktioniert gut. Allerdings wurden bei mir Ergebnisse aus Feldern mit dem Typ MONEY seltsamerweise mit sinnfreien Nullen aufgefüllt, was das Ergebnis unbrauchbar gemacht hat. Ich habe auch nichts gefunden, das erklärt, warum das so ist. Seltsam, seltsam...

Es muss also eine andere Lösung her.

Lösung 3: PowerShell

Das Pendant zu SQLCMD im PowerShell ist Invoke-Sqlcmd. Der Code der .PS1-Datei sieht dann folgendermaßen aus:

#Mandant_Anpassung
$SQLdb = "DATENBANK"
$ExpFile = "C:\PFAD\ZUR\AUSGABE\Export.csv"


#Kunden_Anpassung
$SQLServer = "SERVER\INSTANZ"  
$uid ="BENUTZER"
$pwd = "PASSWORT"
$ImpFile = "C:\PFAD\ZUR\ABFRAGE\ABFRAGE.sql"


#Befehl
Invoke-Sqlcmd -ServerInstance $SQLServer -Database $SQLdb -UserName $uid -Password $pwd -Inputfile $ImpFile | Export-Csv $ExpFile -Delimiter ";" -NoTypeInformation -Encoding UTF8

Seltsamerweise ist die Standard-Ausgabe von Invoke-Sqlcmd zwar "hübsch", aber nicht weiterverarbeitbar, weil nicht im Tabellenformat. Dementsprechend sind vor allem folgende Schalter unablässig:

-Delimiter ";"  - definiert den Seperator
-NoTypeInformation - lässt sinnfreie Informationen der Ausgabe weg.
-Encoding UTF8 - sorgt dafür, dass der richtige Zeichensatz verwendet wird.

Nun erfolgt die Ausgabe mit korrekten und nicht nachformatierten Werten.

Farbe ist das neue Schwarz

Das gute alte Batch - sie funktioniert und tut, aber leider ist sie so schwarz und unschön. Dabei gibt es von (nahezu) Anfang an die Möglich...