Mit dem BCP-Befehl generiere ich Dateien von SQL Server DB-Tabellen. Der BCP-Befehl erstellt eine leere Datei für jede Tabelle, wenn keine Daten in die Dateien ausgegeben werden können. Dies kann durch einen Fehler in der geschriebenen Abfrage verursacht werden oder eine leere Variable wird an den BCP-Befehl übergeben.
Gibt es eine Möglichkeit, diese Ereignisse als Fehler zu erfassen und einen Fehlercode zurückzugeben?
Ich führe dies von einer gespeicherten Prozedur aus. Gibt es eine Möglichkeit, wie ich in SP damit umgehen kann?
sql-server
stored-procedures
error-handling
bcp
MySQL DBA
quelle
quelle
Antworten:
Powershell ist dein Freund hier. Wenn Sie mit cmd-Befehlen in Powershell arbeiten, können Sie die
$LASTEXITCODE
Variable verwenden, um das Ergebnis des von Ihnen ausgeführten Befehls zu lesen.Der folgende Code übergibt einen
BCP
Befehl an das Cmdlet Invoke-Expression und erfasst dessen Ausgabe.Ich bin mir nicht sicher, wie Sie mit dem Fehler umgehen möchten, daher habe ich
Write-Host
den Fehler nur für dieses Beispiel angezeigt. Sie können den Fehler im Ereignisprotokoll, in einer Datei, einer Tabelle in SQL usw. protokollieren.quelle
Die Frage ist etwas vage in Bezug darauf, wie BCP ausgeführt wird, außer dass es innerhalb einer gespeicherten Prozedur durchgeführt wird. Da aber , dass alles , was wir wirklich im Moment wissen, werde ich davon ausgehen , dass Sie anrufen
BCP.EXE
ausxp_cmdshell
.Wenn Sie einfach die tatsächlichen Fehler erfassen möchten, die von ausgelöst werden
BCP
, ist dies sehr einfach, da derERRORLEVEL
Wert alsINT
von derxp_cmdshell
gespeicherten Prozedur zurückgegeben wird:Kehrt zurück:
Wenn Sie jedoch Abfragen behandeln möchten, die erfolgreich abgeschlossen wurden und dennoch 0 Zeilen als "Fehler" -Zustand zurückgeben, ist dies ebenfalls möglich. Dies erfordert nur etwas mehr Aufwand:
Kehrt zurück:
Bitte beachten Sie, dass die lange Befehlszeile entweder als einzelne Zeile beibehalten oder in ein
.CMD
Skript eingefügt werden muss, damit sie ordnungsgemäß funktioniert.Die zusätzliche Logik in einem besser lesbaren Format lautet:
Erläuterung:
&&
Dieser Operator führt den Befehl auf der rechten Seite nur aus, wenn der Befehl auf der linken Seite erfolgreich ausgeführt wurde. Der Grund für die Verwendung dieses Operators besteht darinBCP
, denERRORLEVEL
Wert festlegen zu können, wenn ein Fehler auftritt. die Befehle auf der rechten Seite werden nur benötigt , wennBCP
sie nicht in einen Fehler läuft noch zurück 0 Zeilen.(
Die Klammern gruppieren die darin enthaltenen Befehle. Dadurch können wir die BefehleFORFILES
undIF
nur ausführen, wennBCP
sie erfolgreich abgeschlossen wurden. Andernfalls wird keiner der Befehle innerhalb von(
und)
ausgeführt.FORFILES
Durchläuft eine Liste von Dateien, die von bestimmten Schaltern angegeben werden, und führt für jede Datei einen Befehl aus, der den Kriterien entspricht (ähnlich demfind
Befehl in Unix)./P
ist der Startpfad. Es muss ein Pfad sein und darf den Dateinamen nicht enthalten./M
ist der Dateinamenfilter oder "Maske"./C
ist der Befehl, der für jede Datei ausgeführt werden soll. Es muss so ziemlich anfangenCMD /C
. DerIF
Befehl testet die Größe der Datei, die über die@fsize
Variable gefunden wird, die durch ersetzt wird.FORFILES
Wenn sie kleiner als 3 ist (dhLSS 3
), wird die Datei einfach gelöscht. Bei meinen Tests stellte ich fest, dass die Verwendung von entweder-c
oder nichts mitBCP
zur Angabe der ASCII / VARCHAR-Ausgabe zu einer leeren Datei mit 0 Byte führen würde. Die Verwendung der-w
Unicode / NVARCAR-Ausgabe führt jedoch zu leeren Dateien mit 2 Bytes (dies sollte das Byte Order Mark sein). Daher deckt das Testen auf "Größe <3" beide Szenarien ab.Der Grund für das Löschen der Datei ist, dass sie im übergeordneten Prozess getestet werden kann. Da
CMD /C
der Befehl zum Ausführen des Befehls für Dateien verwendet wird, die von gefunden werdenFORFILES
, handelt es sich um einen Unterprozess, und Umgebungsvariablen bleiben nicht bestehen (ähnlich wie beim Erstellen einer lokalen temporären Tabelle in Dynamic SQL), und das Beenden mit einem Fehlercode wird einfach an das übergeordnete Element zurückgegeben Prozess wie es schon gehen würde. Das Erstellen einer leeren Datei als Indikator ist eine Option, muss dann aber entweder bereinigt werden oder ist unübersichtlich. Und wenn der Prozess als Fehler angesehen wird, weil keine Zeilen zurückgegeben werden, möchten wir die Datei sowieso nicht.&
Dieser Operator führt den Befehl auf der rechten Seite aus, unabhängig vom Erfolgs- oder Fehlerstatus des Befehls auf der linken Seite.IF
Dies führt einen einfachen Test auf das Vorhandensein der angegebenen Datei durch. Wenn diese Datei nicht vorhanden ist, wird der angegebene Befehl ausgeführt.EXIT -3
Dadurch wird der aktuelle Prozess (der Betriebssystemprozess der obersten Ebene, von dem gestartet wurdexp_cmdshell
) beendet, während derERRORLEVEL
Wert auf gesetzt wird-3
. Sie können den-3
Wert in einen beliebigen Wert ändern. Achten Sie jedoch darauf, keine Werte zu verwenden, die bereits von verwendet werden,BCP
damit Sie zwischen diesen unterscheiden können. Das mussEXIT
nur explizit verwendet werden, wenn Sie festlegen möchtenERRORLEVEL
(ähnlich wie entweder keine AngabeRETURN
am Ende einer gespeicherten Prozedur oder Angabe, um einen Nichtwert zurückzugeben0
).quelle