Обработка ошибок с помощью пакетного файла и Sqlcmd

У меня есть пакетный файл, который запускает несколько запросов SELECT с использованием sqlcmd, помещает результаты в текстовые файлы и загружает эти файлы на FTP-сервер. Что все работает так, как должно, а именно так, как мне нравится, что нужно работать.

Мне было интересно, что я буду делать в случае ошибки. Скажем, кто-то меняет структуру данных базы данных, на которую я нажимаю, и не уведомляет меня. Если бы я запустил инструкцию SELECT sqlcmd и опустил результат в текстовый файл, я бы просто получил текстовый файл с ошибкой, который затем перешел бы прямо на FTP, как будто ничего не случилось. (Я протестировал это.)

Я хотел бы иметь возможность проверять ошибки, возникающие из sqlcmd - тайм-ауты, плохие учетные данные, неверный запрос и т.д., я просто не уверен, как это делается или что такое "лучшая практика". Я всегда мог попробовать обходить выходной текстовый файл и искать ошибки, которые, как мне кажется, могут произойти, но это проблематично по ряду причин.

У кого-нибудь есть опыт с этим, что они хотели бы поделиться?

Ответ 1

Вы можете проверить errorlevel, возвращенный с SQLCMD, чтобы узнать, не сработало ли оно.

    sqlcmd -b <yourscript>
    IF ERRORLEVEL 1 goto err_handler
    goto done
    :err_handler
    REM handle the error here

    :done 
    REM script completion code here

Ответ 2

Возможно, я начну с размещения возвращаемых значений в вашем SQL, например:

DECLARE @IsBored bit = 1

... do work ...

SELECT 0 -- Success!

Вы можете сделать это немного дальше и использовать блоки TRY/CATCH для ловушки ошибок и возврата кода ошибки. С помощью SQLCMD вы можете использовать код возврата из вашего SQL в качестве кода выхода приложения, например:

sqlcmd -b -S ServerName -E -d DbName -q "EXIT(EXEC dbo.YourProc)" 
       -o "C:\Logs\output.log" -u

Если вы управляете своими вызовами SQLCMD с помощью чего-то вроде планировщика, вы можете принять меры на основе кодов возврата из SQLCMD. Поскольку вы просто используете пакетные файлы, я думаю, вы можете сделать что-то вроде этого:

@ECHO OFF
sqlcmd -b -S ServerName -E -d DbName -q "EXIT(EXEC dbo.YourProc)" 
       -o "C:\Logs\output.log" -u
IF %ERRORLEVEL% NEQ 0 ECHO "Error"

Удачи!

Ответ 3

for %%G in (*.sql) do (sqlcmd /S %sqlhost% /d %sqldbname% -E -b -i "%%G" >> output.txt if ERRORLEVEL 1 exit)

Выше код будет проходить через все *.sql в папке. Если ошибка встречается в любом из script, ошибка будет регистрироваться в файле output.txt и немедленно остановит пакетный процесс.

Ответ 4

Я построил minilanguage в python, чтобы решить подобную проблему. Используя библиотеку подпроцессов, вы можете запустить свой код через sqlcmd, затем получить вывод и любые коды ошибок. Разбирайте результат перед тем, как поместить его в свой текстовый файл, и при необходимости перейдите в состояние исправления ошибок. Эти состояния могут изменять код или параметры и повторять отправку через sqlcmd. Если все остальное не удается, напишите человеку.

Конечно, поскольку я использовал такой питон, я вообще не интересовался sqlcmd и просто использовал библиотеки python odbc для прямого подключения к базе данных. Я мог бы отменить мои транзакции, если у меня был катастрофический сбой, запустить его в интерактивном режиме или с помощью командного файла и т.д. И т.д.

Это куча работы. Для более упрощенной проверки ошибок просто добавьте фильтр в ваш конвейер, скажем, grep или awk. Или сверните свой собственный с помощью flex.