Làm cách nào để sqlcmd trả về ERRORLEVEL khác 0 khi tập lệnh .sql không thành công?


38

Tôi đang chạy sqlcmd từ một tệp bó và tôi đã tự hỏi làm thế nào để làm cho nó trả về một LRI khác 0 khi có sự cố với bản sao lưu.


Bạn đã cân nhắc sử dụng một cái gì đó mạnh mẽ hơn (đặc biệt là xử lý lỗi) so với các tệp bó?
Aaron Bertrand

Oh bạn có nghĩa là như Powershell? Chúng tôi chỉ đi với phương pháp được đề xuất của công ty cho sản phẩm chúng tôi đang sử dụng. Rắc rối là phương pháp đề xuất giả định rằng bạn đang sao lưu một cơ sở dữ liệu; Nhưng tôi đã vượt qua rào cản đó. Vì vậy, không có cách nào để khiến nó chỉ ném mã lỗi nếu bản sao lưu không hoạt động?
leeand00

3
Đối với những gì đáng giá, trong công việc hiện tại của tôi, chúng tôi sử dụng các thủ tục được lưu trữ dự phòng của Ola Hallengren (với một số thủ tục được lưu trữ trong nhà xung quanh chúng) để sao lưu hàng ngàn cơ sở dữ liệu trên hàng trăm máy chủ và chúng tôi không gặp vấn đề gì với chúng.
James L

Câu trả lời:


54

Bạn nên sử dụng tùy chọn -b trong sqlcmd.

-b Chỉ định rằng sqlcmd thoát và trả về giá trị DOS ERRORLEVEL khi xảy ra lỗi. Giá trị được trả về biến DOS ERRORLEVEL là 1 khi thông báo lỗi Máy chủ SQL có mức độ nghiêm trọng lớn hơn 10; mặt khác, giá trị trả về là 0

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


10

Từ trang Tiện ích SQLCMD của MSDN tại: http://msdn.microsoft.com/en-us/l Library / ms162773.aspx

Nếu RAISERROR được sử dụng trong tập lệnh sqlcmd và trạng thái 127 được nâng lên, sqlcmd sẽ thoát và trả lại ID tin nhắn cho khách hàng. Ví dụ:

RAISERROR (50001, 10, 127)

Vì vậy, bạn có thể gói BACKUP DATABASE...lệnh trong một TRY...CATCHkhối và đưa ra thông báo lỗi thích hợp, sqlcmdsau đó sẽ trở lại tệp bó của bạn.

Ví dụ, xem xét các errorleveltest.sqltập tin sau :

: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

Và tệp .bat sau: (dòng đầu tiên được gói để dễ đọc, nhưng cần phải nằm trên một dòng.)

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

Điều này trả về như sau từ dấu nhắc cmd.exe của tôi:

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

Như bạn có thể thấy, ERRORLEVEL 1 được trả về thay vì giá trị trả về thông thường là 0. Tôi không thể lấy ERRORLEVEL để phản ánh số lỗi thực tế, trong trường hợp này là 50002; có lẽ có một vấn đề trong mã của tôi, hoặc có lẽ có một số vấn đề với môi trường của tôi.


1
Tôi đã thấy rằng CHỈ này hoạt động nếu bạn cung cấp một giá trị số làm tham số đầu tiên của RAISERROR. ví dụ: Điều này trả về% errorlevel% = 1: RAISERROR (50002, 10.127) Nhưng điều này trả về% errorlevel% = 0: RAISERROR ('myErrMsg.', 10.127)

5
FYI liên quan đến đoạn cuối: ERRORLEVELkhông nên có cùng giá trị với Số lỗi được báo cáo từ SQL Server. ErrorNumber là một giá trị dành riêng cho SQL Server để cho biết lý do tại sao nó (tức là SQL Server) bị chấm dứt. Mặt khác, ERRORLEVELlà một giá trị dành riêng cho SQLCMD để cho biết lý do tại sao nó (tức là SQLCMD) bị chấm dứt.
Solomon Rutzky 4/12/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.