Sqlcmd, .sql betiği başarısız olduğunda 0 dışında bir ERRORLEVEL döndürmesini nasıl sağlayabilirim?


38

Bir toplu iş dosyasından sqlcmd kullanıyorum ve yedeklemede bir şeyler ters gittiğinde nasıl 0'dan farklı bir ERRORLEVEL döndüreceğini merak ediyorum.


Toplu iş dosyalarından daha güçlü (özellikle hata işleme sırasında) bir şey kullanmayı düşündünüz mü?
Aaron Bertrand

Powershell gibi mi demek istiyorsun? Kullandığımız ürün için firmanın önerdiği yöntemi kullanmaya başladık. Sorun, önerilen yöntemin bir veritabanını yedeklediğinizi varsayar; ama bu engelin üstesinden geldim. Yani yedekleme işe yaramazsa, sadece bir hata kodu atmasını sağlamanın yolu yok mu?
leeand00

3
Ne olursa olsun, şu anki işimde, yüzlerce sunucudaki binlerce veritabanını yedeklemek için Ola Hallengren'in saklı yedeklemeli prosedürlerini (bazı kurum içi sarıcılarla birlikte saklı yordamları kullanarak) kullanıyoruz ve onlarla ilgili herhangi bir sorun yaşamadık.
James L,

Yanıtlar:


53

-B seçeneğini sqlcmd olarak kullanmalısınız.

-b Sqlcmd'nin çıkıp bir hata oluştuğunda DOS ERRORLEVEL değeri döndürdüğünü belirtir. DOS ERRORLEVEL değişkenine döndürülen değer, SQL Server hata iletisi 10'dan büyük bir önem düzeyine sahip olduğunda 1'dir; Aksi takdirde döndürülen değer 0 olur.

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


9

MSDN SQLCMD Utility sayfasından: http://msdn.microsoft.com/en-us/library/ms162773.aspx

RAISERROR bir sqlcmd betiğinde kullanılırsa ve 127 durumu yükseltilirse, sqlcmd çıkıp mesaj kimliğini tekrar istemciye iade edecektir. Örneğin:

RAISERROR (50001, 10, 127)

Böylece BACKUP DATABASE...komutu bir TRY...CATCHbloğa sarabilir ve sqlcmddaha sonra toplu iş dosyasına geri dönecek olan uygun hata mesajını yükseltebilirsiniz .

Örneğin, aşağıdaki errorleveltest.sqldosyayı göz önünde bulundurun :

: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

Ve aşağıdaki .bat dosyası: (ilk satır okunabilirlik için sarılmış, ancak tek bir satırda olması gerekiyor.)

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

Bu benim cmd.exe isteminden aşağıdakileri döndürür:

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

Gördüğünüz gibi, 0 normal dönüş değeri yerine ERRORLEVEL 1 döndürülür. ERRORLEVEL 'in gerçek hata numarasını yansıtmasını sağlayamıyorum, bu durumda 50002; belki kodumda bir sorun var ya da belki çevremle ilgili bir sorun var.


1
RAISERROR'un ilk parametresi olarak sayısal bir değer sağlarsanız, bunun SADECE işe yaradığını buldum. örneğin: Bu sonuçların, bir% errorlevel% = 1: RAISERROR (50002, 10.127) Ancak bu döner% errorlevel% = 0: RAISERROR (10,127 'myErrMsg.')

5
Son paragrafa ilişkin FYI: ERRORLEVELSQL Server'dan bildirilen Hata Numarası ile aynı değerde olması beklenmemelidir. ErrorNumber, neden (yani SQL Server) sonlandırıldığını gösteren bir SQL Server'a özgü değerdir. Öte yandan, ERRORLEVELneden (yani SQLCMD) sonlandırıldığını belirten SQLCMD'ye özgü bir değerdir.
Solomon Rutzky
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.