วิธีทำให้ sqlcmd ส่งคืน ERRORLEVEL นอกเหนือจาก 0 เมื่อสคริปต์. sql ล้มเหลว


38

ฉันกำลังเรียกใช้ sqlcmd จากแบตช์ไฟล์และฉันสงสัยว่าจะทำให้ ERRORLEVEL คืนเป็นค่าอื่นนอกเหนือจาก 0 ได้อย่างไรเมื่อมีบางอย่างผิดพลาดในการสำรองข้อมูล


คุณได้พิจารณาการใช้สิ่งที่มีประสิทธิภาพมากขึ้น (โดยเฉพาะอย่างยิ่งในการจัดการข้อผิดพลาด) กว่าไฟล์แบตช์หรือไม่?
Aaron Bertrand

โอ้คุณหมายถึงเช่น Powershell? เราเพิ่งจะไปกับวิธีการที่ บริษัท แนะนำสำหรับผลิตภัณฑ์ที่เราใช้ ปัญหาคือวิธีการแนะนำสมมติว่าคุณกำลังสำรองฐานข้อมูลเดียว แต่ฉันได้เอาชนะสิ่งกีดขวางนั้นแล้ว ดังนั้นจึงไม่มีวิธีที่จะทำให้มันเป็นเพียงแค่โยนรหัสข้อผิดพลาดหากการสำรองข้อมูลไม่ทำงาน?
leeand00

3
สำหรับสิ่งที่คุ้มค่าสำหรับงานปัจจุบันของเราเราใช้โพรซีเดอร์ที่จัดเก็บสำรองของ Ola Hallengren (พร้อมขั้นตอนการเก็บข้อมูลที่ห่อหุ้มอยู่ภายใน) เพื่อสำรองฐานข้อมูลนับพันในเซิร์ฟเวอร์นับร้อยและเราไม่มีปัญหากับพวกเขา
James L

คำตอบ:


53

คุณควรใช้ตัวเลือก -b ใน sqlcmd

-b ระบุว่า sqlcmd ออกจากและส่งคืนค่า DOS ERRORLEVEL เมื่อเกิดข้อผิดพลาด ค่าที่ส่งคืนไปยังตัวแปร DOS ERRORLEVEL คือ 1 เมื่อข้อความแสดงข้อผิดพลาด SQL Server มีระดับความรุนแรงมากกว่า 10 มิฉะนั้นค่าที่ส่งคืนคือ 0

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


9

จากหน้ายูทิลิตี้ MSDN SQLCMD ที่: http://msdn.microsoft.com/en-us/library/ms162773.aspx

หากใช้ RAISERROR ภายในสคริปต์ sqlcmd และสถานะของ 127 ถูกยกขึ้น sqlcmd จะปิดและส่งกลับรหัสข้อความกลับไปยังลูกค้า ตัวอย่างเช่น:

RAISERROR (5,0001, 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 (5,0002, 10,127) แต่สิ่งนี้จะส่งกลับ% errorlevel%% 0 0: RAISERROR ('myErrMsg.', 10,127)

5
FYI เกี่ยวกับย่อหน้าสุดท้าย: ERRORLEVELไม่ควรคาดว่าจะเป็นค่าเดียวกันกับหมายเลขข้อผิดพลาดที่รายงานจาก SQL Server ErrorNumber เป็นค่าเฉพาะของเซิร์ฟเวอร์ SQL เพื่อระบุสาเหตุที่ถูกยกเลิก (เช่น SQL Server) ในทางกลับกันERRORLEVELเป็นค่าเฉพาะ SQLCMD เพื่อระบุว่าทำไมมัน (เช่น SQLCMD) ถูกยกเลิก
โซโลมอน Rutzky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.