Як змусити sqlcmd повернути ERRORLEVEL, відмінний від 0, коли сценарій .sql не працює?


38

Я запускаю sqlcmd з пакетного файлу, і мені було цікаво, як змусити його повернути ERRORLEVEL, відмінний від 0, коли з резервною копією щось піде не так.


Чи думали ви використовувати щось більш надійне (особливо при роботі з помилками), ніж пакетні файли?
Аарон Бертран

О, ти маєш на увазі, як Пауершелл? Ми просто збиралися з рекомендованим компанією методом для продукту, який ми використовуємо. Проблема - це метод рекомендування, який передбачає, що ви створюєте резервну копію однієї бази даних; але я подолав цю перешкоду. Тож немає способу змусити його просто закинути код помилки, якщо резервна копія не працює?
leeand00

3
Для того, що варто, на моїй теперішній роботі ми використовуємо резервні збережені резервні процедури Ola Hallengren (з деякими внутрішніми обгортками, які зберігаються навколо них) для резервного копіювання тисяч баз даних на сотнях серверів, і ми з ними не мали жодних проблем.
Джеймс Л

Відповіді:


54

Вам слід скористатися опцією -b в sqlcmd.

-b Вказує, що sqlcmd виходить і повертає значення DOS ERRORLEVEL, коли виникає помилка. Значення, яке повертається до змінної DOS ERRORLEVEL, дорівнює 1, коли повідомлення про помилку SQL Server має рівень вираженості більше 10; в іншому випадку повернене значення дорівнює 0

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


10

На сторінці утиліти MSDN SQLCMD за адресою: http://msdn.microsoft.com/en-us/library/ms162773.aspx

Якщо RAISERROR використовується в скрипті sqlcmd і стан 127 піднято, sqlcmd вийде і поверне ідентифікатор повідомлення назад клієнту. Наприклад:

РАЙЗЕР (50001, 10, 127)

Таким чином, ви можете загорнути BACKUP DATABASE...команду в TRY...CATCHблок і підняти відповідне повідомлення про помилку, яке sqlcmdпотім повернеться до вашого пакетного файлу.

Наприклад, врахуйте такий errorleveltest.sqlфайл:

: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

І наступний .bat файл: (перший рядок обгортається для читабельності, але він повинен бути в одному рядку.)

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

Це повертає моє запит 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

Як ви бачите, ERRORLEVEL 1 повертається замість нормального значення повернення 0. Я не можу заставити ERRORLEVEL відображати фактичне число помилки, у цьому випадку 50002; можливо, в моєму коді є проблема, або, можливо, є проблема з моїм оточенням.


1
Я виявив, що це ТІЛЬКИ працює, якщо ви вводите числове значення як перший параметр RAISERROR. наприклад: Це повертає% errorlevel% = 1: RAISERROR (50002, 10,127), але це повертає% errorlevel% = 0: RAISERROR ('myErrMsg.', 10,127)

5
FYI щодо останнього абзацу: ERRORLEVELне слід очікувати, що воно буде таким самим значенням, як номер помилки, повідомлений на SQL Server. ErrorNumber - це специфічне для SQL Server значення, яке вказує, чому воно (тобто SQL Server) припиняється. З іншого боку, ERRORLEVELє специфічним для SQLCMD значення, яке вказує, чому воно (тобто SQLCMD) припиняється.
Соломон Руцький
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.