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.