Come fare in modo che sqlcmd restituisca un ERRORLEVEL diverso da 0 quando lo script .sql fallisce?


38

Sto eseguendo sqlcmd da un file batch e mi chiedevo come farlo restituire un ERRORLEVEL diverso da 0 quando qualcosa non va nel backup.


Hai preso in considerazione l'utilizzo di qualcosa di più robusto (in particolare nella gestione degli errori) rispetto ai file batch?
Aaron Bertrand

Oh vuoi dire come Powershell? Stavamo seguendo il metodo raccomandato dalla società per il prodotto che stiamo utilizzando. Il problema è che il metodo consigliato presuppone che si stia eseguendo il backup di un database; ma ho superato questo ostacolo. Quindi non c'è modo di farlo lanciare un codice di errore se il backup non funziona?
leeand00,

3
Per quello che vale, nel mio attuale lavoro, utilizziamo le procedure memorizzate di backup di Ola Hallengren (con alcune procedure memorizzate dal wrapper interno attorno a esse) per eseguire il backup di migliaia di database su centinaia di server e non abbiamo avuto problemi con essi.
James L

Risposte:


54

Dovresti usare l'opzione -b in sqlcmd.

-b Specifica che sqlcmd esce e restituisce un valore DOS ERRORLEVEL quando si verifica un errore. Il valore restituito alla variabile DOS ERRORLEVEL è 1 quando il messaggio di errore di SQL Server ha un livello di gravità maggiore di 10; in caso contrario, il valore restituito è 0

http://msdn.microsoft.com/en-us/library/ms162773.aspx


10

Dalla pagina Utilità MSQ SQLCMD all'indirizzo: http://msdn.microsoft.com/en-us/library/ms162773.aspx

Se RAISERROR viene utilizzato all'interno di uno script sqlcmd e viene generato uno stato di 127, sqlcmd verrà chiuso e restituirà l'ID del messaggio al client. Per esempio:

RAISERROR (50001, 10, 127)

Quindi potresti avvolgere il BACKUP DATABASE...comando in un TRY...CATCHblocco e sollevare il messaggio di errore appropriato, che sqlcmdtornerebbe al tuo file batch.

Ad esempio, considerare il seguente errorleveltest.sqlfile:

:ON ERROR EXIT
BEGIN TRY
    /* creates error 3147 Backup and restore operations 
            are not allowed on database tempdb */
    BACKUP DATABASE tempdb; 
END TRY
BEGIN CATCH
    DECLARE @msg NVARCHAR(255);
    SET @msg = 'An error occurred: ' + ERROR_MESSAGE();
    RAISERROR (50002, 10, 127);
END CATCH

E il seguente file .bat: (la prima riga è racchiusa per leggibilità, ma deve essere su una sola riga.)

@echo off
"C:\Program Files\Microsoft SQL Server\110\Tools\Binn\sqlcmd" -S "someinstance" -E 
    -i .\errorleveltest.sql
ECHO Errorlevel: %ERRORLEVEL%

Ciò restituisce quanto segue dal mio prompt di cmd.exe:

Msg 18054, Level 16, State 1, Server CP708-D377\MV, Line 9
Error 50002, severity 10, state 127 was raised, but no message with that error number 
was found in sys.messages. If error is larger than 50000, make sure the user-defined 
message is added using sp_addmessage.
Errorlevel: 1

Come puoi vedere, viene restituito ERRORLEVEL 1 invece del normale valore di ritorno di 0. Non riesco a far sì che ERRORLEVEL rifletta il numero di errore effettivo, in questo caso 50002; forse c'è un problema nel mio codice o forse c'è qualche problema con il mio ambiente.


1
Ho scoperto che funziona SOLO se fornisci un valore numerico come primo parametro di RAISERROR. ad esempio: questo restituisce un% errorlevel% = 1: RAISERROR (50002, 10.127) Ma questo restituisce% errorlevel% = 0: RAISERROR ('myErrMsg.', 10.127)

5
Cordiali saluti per quanto riguarda l'ultimo paragrafo: ERRORLEVELnon dovrebbe essere previsto lo stesso valore del numero di errore riportato da SQL Server. ErrorNumber è un valore specifico di SQL Server per indicare il motivo per cui (ovvero SQL Server) è stato terminato. D'altra parte, ERRORLEVELè un valore specifico di SQLCMD per indicare il motivo per cui (ovvero SQLCMD) è terminato.
Solomon Rutzky il
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.