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
aus xp_cmdshell
.
Wenn Sie einfach die tatsächlichen Fehler erfassen möchten, die von ausgelöst werden BCP
, ist dies sehr einfach, da der ERRORLEVEL
Wert als INT
von der xp_cmdshell
gespeicherten Prozedur zurückgegeben wird:
DECLARE @ErrorLevel INT;
EXEC @ErrorLevel = xp_cmdshell
N'BCP "SELECT * FROM sys.objects where 1= " queryout C:\temp\BCPtest.txt -T -w ';
SELECT @ErrorLevel;
Kehrt zurück:
1
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:
DECLARE @ErrorLevel INT;
EXEC @ErrorLevel = xp_cmdshell
N'BCP "SELECT * FROM sys.objects where 1= 0 " queryout C:\temp\BCPtest.txt -T -w && (FORFILES /P C:\TEMP\ /M BCPtest.txt /C "CMD /C IF @fsize LSS 3 DEL C:\TEMP\BCPtest.txt" & IF NOT EXIST C:\temp\BCPtest.txt EXIT -3)';
SELECT @ErrorLevel;
Kehrt zurück:
-3
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:
&& (
FORFILES /P C:\TEMP\
/M BCPtest.txt
/C "CMD /C IF @fsize LSS 3 DEL C:\TEMP\BCPtest.txt"
& IF NOT EXIST C:\temp\BCPtest.txt EXIT -3
)
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 darin BCP
, den ERRORLEVEL
Wert festlegen zu können, wenn ein Fehler auftritt. die Befehle auf der rechten Seite werden nur benötigt , wenn BCP
sie nicht in einen Fehler läuft noch zurück 0 Zeilen.
(
Die Klammern gruppieren die darin enthaltenen Befehle. Dadurch können wir die Befehle FORFILES
und IF
nur ausführen, wenn BCP
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 dem find
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 anfangen CMD /C
. Der IF
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 (dh LSS 3
), wird die Datei einfach gelöscht. Bei meinen Tests stellte ich fest, dass die Verwendung von entweder -c
oder nichts mit BCP
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 werden FORFILES
, 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 wurde xp_cmdshell
) beendet, während der ERRORLEVEL
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 muss EXIT
nur explizit verwendet werden, wenn Sie festlegen möchten ERRORLEVEL
(ähnlich wie entweder keine Angabe RETURN
am Ende einer gespeicherten Prozedur oder Angabe, um einen Nichtwert zurückzugeben 0
).