SQL Server - หยุดหรือหยุดการทำงานของสคริปต์ SQL


325

มีวิธีหยุดการทำงานของสคริปต์ SQL ใน SQL server ทันทีเช่นคำสั่ง "break" หรือ "exit" หรือไม่?

ฉันมีสคริปต์ที่ทำการตรวจสอบความถูกต้องและการค้นหาก่อนที่จะเริ่มการแทรกและฉันต้องการให้สคริปต์หยุดหากการตรวจสอบความถูกต้องหรือการค้นหาล้มเหลว

คำตอบ:


371

RAISERRORวิธี

raiserror('Oh no a fatal error', 20, -1) with log

การดำเนินการนี้จะยุติการเชื่อมต่อดังนั้นจึงหยุดการทำงานของสคริปต์ที่เหลือ

โปรดทราบว่าทั้งความรุนแรงระดับ 20 หรือสูงกว่าและWITH LOGตัวเลือกที่จำเป็นสำหรับการทำงานด้วยวิธีนี้

สิ่งนี้สามารถใช้งานได้กับคำสั่ง GO เช่น

print 'hi'
go
raiserror('Oh no a fatal error', 20, -1) with log
go
print 'ho'

จะให้ผลลัพธ์:

hi
Msg 2745, Level 16, State 2, Line 1
Process ID 51 has raised user error 50000, severity 20. SQL Server is terminating this process.
Msg 50000, Level 20, State 1, Line 1
Oh no a fatal error
Msg 0, Level 20, State 0, Line 0
A severe error occurred on the current command.  The results, if any, should be discarded.

โปรดสังเกตว่า 'ho' ไม่ได้ถูกพิมพ์ออกมา

คำเตือน:

  • ใช้งานได้เฉพาะเมื่อคุณเข้าสู่ระบบในฐานะผู้ดูแลระบบ (บทบาท 'sysadmin') และทำให้คุณไม่มีการเชื่อมต่อฐานข้อมูล
  • หากคุณยังไม่ได้เข้าเป็นผู้ดูแลระบบ, RAISEERROR () ที่เรียกตัวเองจะล้มเหลวและสคริปต์ที่จะยังคงดำเนินการ
  • เมื่อเรียกใช้ด้วย sqlcmd.exe รหัสการออก 2745 จะถูกรายงาน

การอ้างอิง: http://www.mydatabasesupport.com/forums/ms-sqlserver/174037-sql-server-2000-abort-whole-script.html#post761334

วิธี noexec

วิธีการที่จะทำงานร่วมกับงบ GO set noexec onอีกประการหนึ่งคือ สิ่งนี้ทำให้สคริปต์ที่เหลือถูกข้ามไป มันไม่ได้ยุติการเชื่อมต่อ แต่คุณต้องnoexecปิดอีกครั้งก่อนที่คำสั่งใด ๆ จะทำงาน

ตัวอย่าง:

print 'hi'
go

print 'Fatal error, script will not continue!'
set noexec on

print 'ho'
go

-- last line of the script
set noexec off -- Turn execution back on; only needed in SSMS, so as to be able 
               -- to run this script again in the same session.

14
ที่น่ากลัว! มันเป็นวิธีการ "บิ๊กสติ๊ก" แต่มีบางครั้งที่คุณต้องการมันจริงๆ โปรดทราบว่ามันต้องการทั้งความรุนแรง 20 (หรือสูงกว่า) และ "With LOG"
Rob Garrison

5
โปรดทราบว่าด้วยวิธี noexec สคริปต์ที่เหลือยังคงถูกตีความดังนั้นคุณจะยังคงได้รับข้อผิดพลาดในการคอมไพล์เช่นคอลัมน์ไม่มีอยู่ หากคุณต้องการจัดการกับการเปลี่ยนแปลงสคีมาอย่างเป็นเงื่อนไขที่เกี่ยวข้องกับคอลัมน์ที่ขาดหายไปโดยการข้ามโค้ดบางอย่างวิธีเดียวที่ฉันรู้ว่าต้องใช้คือ: r ในโหมด sqlcommand เพื่ออ้างอิงไฟล์ภายนอก
David Eison

20
สิ่งที่ยอดเยี่ยมคือ noexec ขอบคุณมาก!
Gaspa79

2
"สิ่งนี้จะยุติการเชื่อมต่อ" - ดูเหมือนว่าอย่างน้อยก็เป็นสิ่งที่ฉันเห็น
jcollum

6
ฉันกำลังลองวิธีนี้และไม่ได้ผลลัพธ์ที่ถูกต้องเมื่อฉันรู้ว่า ... มีเพียงคนเดียวเท่านั้นที่อยู่ในสายฝน ...
bobkingof12vs

187

เพียงใช้ RETURN (มันจะทำงานทั้งในและนอกกระบวนการที่เก็บไว้)


2
ด้วยเหตุผลบางอย่างฉันคิดว่าการกลับมาไม่ได้ทำงานในสคริปต์ แต่ฉันแค่ลองแล้วก็ทำได้! ขอบคุณ
Andy White

4
ในสคริปต์คุณไม่สามารถทำ RETURN ด้วยค่าอย่างที่คุณสามารถทำได้ในกระบวนงานที่เก็บไว้ แต่คุณสามารถทำ RETURN ได้
Rob Garrison

53
ไม่สิ้นสุดเท่านั้นจนกว่าจะถึง GOถัดไปชุดถัดไป (หลังจาก GO) จะทำงานตามปกติ
mortb

2
อันตรายที่จะสันนิษฐานว่ามันจะดำเนินต่อไปหลังจากนั้น GO ถัดไป
Justin

1
GO เป็นตัวยุติสคริปต์หรือตัวคั่น ไม่ใช่รหัส SQL GO เป็นเพียงคำแนะนำสำหรับลูกค้าที่คุณใช้เพื่อส่งคำสั่งไปยังเอ็นจิ้นฐานข้อมูลที่สคริปต์ใหม่เริ่มต้นหลังจากตัวคั่น GO
วิศวกรที่กลับรายการ

50

หากคุณสามารถใช้โหมด SQLCMD ก็จะใช้คาถา

:on error exit

(รวมถึงโคลอน) จะทำให้ RAISERROR หยุดสคริปต์จริง เช่น,

:on error exit

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SOMETABLE]') AND type in (N'U')) 
    RaisError ('This is not a Valid Instance Database', 15, 10)
GO

print 'Keep Working'

จะส่งออก:

Msg 50000, Level 15, State 10, Line 3
This is not a Valid Instance Database
** An error was encountered during execution of batch. Exiting.

และชุดจะหยุด หากโหมด SQLCMD ไม่ได้เปิดคุณจะได้รับข้อผิดพลาดในการแยกวิเคราะห์เกี่ยวกับลำไส้ใหญ่ โชคร้ายที่มันไม่ได้เป็นกระสุนอย่างสมบูรณ์ราวกับว่าสคริปต์ทำงานโดยไม่ต้องอยู่ในโหมด SQLCMD, SQL Managment Studio มีลมพัดผ่านแม้แต่ตอนที่แยกวิเคราะห์ข้อผิดพลาด! อย่างไรก็ตามหากคุณเรียกใช้จากบรรทัดคำสั่งนี่ก็ใช้ได้


4
ความคิดเห็นที่ดีขอบคุณ ฉันจะเพิ่มที่ในโหมด SSMS SQLCmd เป็นสลับภายใต้เมนูแบบสอบถาม
David Peters

สิ่งนี้มีประโยชน์ - หมายความว่าคุณไม่จำเป็นต้องใช้ตัวเลือก -b เมื่อใช้งาน
JonnyRaa

2
จากนั้นคาถา ... แต่ฉันจะส่ง Magic Missle ได้อย่างไร!
JJS

1
สมบูรณ์ ไม่ต้องการสิทธิ์ผู้ใช้พิเศษ sysadmin
Pac0

21

ฉันจะไม่ใช้ RAISERROR- SQL มีคำสั่ง IF ที่สามารถใช้เพื่อวัตถุประสงค์นี้ ทำการตรวจสอบความถูกต้องและการค้นหาของคุณและตั้งค่าตัวแปรโลคัลจากนั้นใช้ค่าของตัวแปรในคำสั่ง IF เพื่อทำให้ส่วนแทรกมีเงื่อนไข

คุณไม่จำเป็นต้องตรวจสอบผลลัพธ์ที่เปลี่ยนแปลงได้ของการทดสอบการตรวจสอบความถูกต้องทุกครั้ง โดยปกติคุณสามารถทำสิ่งนี้ได้ด้วยตัวแปรแฟลกเดียวเพื่อยืนยันว่าทุกเงื่อนไขผ่านไปแล้ว:

declare @valid bit

set @valid = 1

if -- Condition(s)
begin
  print 'Condition(s) failed.'
  set @valid = 0
end

-- Additional validation with similar structure

-- Final check that validation passed
if @valid = 1
begin
  print 'Validation succeeded.'

  -- Do work
end

แม้ว่าการตรวจสอบของคุณจะมีความซับซ้อนมากขึ้นคุณควรต้องการตัวแปรการตั้งค่าสถานะเพียงเล็กน้อยเพื่อรวมไว้ในการตรวจสอบขั้นสุดท้ายของคุณ


ใช่ฉันใช้ IFs ในส่วนอื่น ๆ ของสคริปต์ แต่ฉันไม่ต้องการตรวจสอบตัวแปรท้องถิ่นทุกตัวก่อนที่ฉันจะลองแทรก ฉันต้องการหยุดสคริปต์ทั้งหมดและบังคับให้ผู้ใช้ตรวจสอบอินพุต (นี่เป็นเพียงสคริปต์รวดเร็วและสกปรก)
แอนดี้สีขาว

4
ฉันไม่แน่ใจว่าทำไมคำตอบนี้ถูกทำเครื่องหมายเพราะมันถูกต้องทางเทคนิคไม่ใช่สิ่งที่โปสเตอร์ "ต้องการ" ที่จะทำ
John Sansom

เป็นไปได้หรือไม่ที่จะมีหลายช่วงตึกในช่วงเริ่มต้น .. หรือไม่? งบความหมาย; ไป; คำให้การ; ไป; ฯลฯ ฯลฯ ฉันได้รับข้อผิดพลาดและฉันคิดว่านั่นอาจเป็นเหตุผล
Nenotlep

3
สิ่งนี้มีความน่าเชื่อถือมากกว่าRAISERRORโดยเฉพาะอย่างยิ่งถ้าคุณไม่รู้ว่าใครกำลังจะเรียกใช้สคริปต์และมีสิทธิ์ใดบ้าง
Cypher

@John Sansom: ปัญหาเดียวที่ฉันเห็นที่นี่คือว่าคำสั่ง IF ไม่ทำงานหากคุณพยายามที่จะแตกสาขาผ่านคำสั่ง GO นี่เป็นปัญหาใหญ่หากสคริปต์ของคุณใช้คำสั่ง GO (เช่นคำสั่ง DDL) นี่คือตัวอย่างที่ใช้งานได้โดยไม่มีคำสั่ง go แรก:declare @i int = 0; if @i=0 begin select '1st stmt in IF block' go end else begin select 'ELSE here' end go
James Jensen

16

ใน SQL 2012+ คุณสามารถใช้โยน

THROW 51000, 'Stopping execution because validation failed.', 0;
PRINT 'Still Executing'; -- This doesn't execute with THROW

จาก MSDN:

เพิ่มข้อยกเว้นและถ่ายโอนการดำเนินการไปยังบล็อก CATCH ของ TRY … CATCH สร้าง ... หากโครงสร้าง TRY … CATCH ไม่พร้อมใช้งานเซสชันจะสิ้นสุดลง หมายเลขบรรทัดและโพรซีเดอร์ที่ยกข้อยกเว้นขึ้นมา ความรุนแรงตั้งไว้ที่ 16


1
THROW นั้นหมายถึงการแทนที่ RAISERROR แต่คุณไม่สามารถป้องกันแบทช์ที่ตามมาในไฟล์สคริปต์เดียวกันได้
NReilingh

ถูกต้อง @NReilingh นั่นคือสิ่งที่คำตอบของ Blorgbeard เป็นทางออกเดียวเท่านั้น มันต้องดูแลระบบแม้ว่า (ระดับความรุนแรง 20) และมันค่อนข้างหนักถ้าไม่มีสคริปต์หลายชุด
Jordan Parker

2
ตั้งค่า xact abort on หากคุณต้องการยกเลิกการแปลงปัจจุบันเช่นกัน
นูเรttin

13

ฉันขยายโซลูชันเปิด / ปิด noexec สำเร็จด้วยธุรกรรมเพื่อเรียกใช้สคริปต์ในลักษณะทั้งหมดหรือไม่ก็เลย

set noexec off

begin transaction
go

<First batch, do something here>
go
if @@error != 0 set noexec on;

<Second batch, do something here>
go
if @@error != 0 set noexec on;

<... etc>

declare @finished bit;
set @finished = 1;

SET noexec off;

IF @finished = 1
BEGIN
    PRINT 'Committing changes'
    COMMIT TRANSACTION
END
ELSE
BEGIN
    PRINT 'Errors occured. Rolling back changes'
    ROLLBACK TRANSACTION
END

เห็นได้ชัดว่าคอมไพเลอร์ "เข้าใจ" ตัวแปร @finished ใน IF แม้ว่าจะมีข้อผิดพลาดและการดำเนินการถูกปิดใช้งาน อย่างไรก็ตามค่าจะถูกตั้งค่าเป็น 1 เฉพาะในกรณีที่การดำเนินการไม่ได้ถูกปิดใช้งาน ดังนั้นฉันสามารถกระทำหรือย้อนกลับธุรกรรมตาม


ฉันไม่เข้าใจ. ฉันทำตามคำแนะนำ ฉันป้อน SQL ต่อไปนี้หลังจากแต่ละ GO IF (XACT_STATE()) <> 1 BEGIN Set NOCOUNT OFF ;THROW 525600, 'Rolling back transaction.', 1 ROLLBACK TRANSACTION; set noexec on END; แต่การดำเนินการไม่เคยหยุดและฉันสิ้นสุดด้วยข้อผิดพลาด "ย้อนกลับธุรกรรม" สามข้อ ความคิดใด ๆ
user1161391

12

คุณสามารถตัดคำสั่ง SQL ของคุณในขณะที่วนซ้ำและใช้ BREAK หากจำเป็น

WHILE 1 = 1
BEGIN
   -- Do work here
   -- If you need to stop execution then use a BREAK


    BREAK; --Make sure to have this break at the end to prevent infinite loop
END

5
ฉันชอบลักษณะของสิ่งนี้ดูเหมือนว่าจะดีกว่าข้อผิดพลาดเล็กน้อย แน่นอนว่าไม่ต้องการที่จะลืมจุดจบในตอนท้าย!
Andy White

1
คุณสามารถใช้ตัวแปรและตั้งค่าไว้ที่ด้านบนของลูปได้ทันทีเพื่อหลีกเลี่ยงการ "แยก" DECLARE @ST INT; SET @ST = 1; WHILE @ST = 1; BEGIN; SET @ST = 0; ...; ENDverbose เพิ่มเติม แต่ heck มันเป็น TSQL อยู่แล้ว ;-)

นี่คือวิธีที่บางคนเล่นข้ามไป แต่มันก็สับสนมากกว่าที่จะตามไป
นูเรttin

วิธีการนี้ป้องกันจาก GO ที่ไม่คาดคิดเป็นครั้งคราว เห็นคุณค่า
it3xl

10

คุณสามารถเปลี่ยนลำดับการดำเนินการโดยใช้คำสั่งGOTO :

IF @ValidationResult = 0
BEGIN
    PRINT 'Validation fault.'
    GOTO EndScript
END

/* our code */

EndScript:

2
ใช้ goto เป็นวิธีที่ยอมรับได้ในการจัดการข้อยกเว้น ลดจำนวนของตัวแปรและการซ้อนและไม่ทำให้เกิดการเชื่อมต่อ มันอาจจะดีกว่าข้อยกเว้นโบราณที่จัดการสคริปต์ SQL Server อนุญาต
Antonio Drusin

เช่นเดียวกับข้อเสนอแนะอื่น ๆ ทั้งหมดที่นี่วิธีนี้ใช้ไม่ได้หาก "รหัสของเรา" มีคำสั่ง "GO"
Mike Gledhill

9

เพิ่มเติมวิธี Sglasses refinig เส้นข้างต้นบังคับใช้โหมด SQLCMD และทั้ง scirpt ทมิฬถ้าไม่ใช้โหมด SQLCMD หรือใช้:on error exitเพื่อออกจากข้อผิดพลาดใด ๆ
CONTEXT_INFOจะใช้ในการติดตามสถานะ

SET CONTEXT_INFO  0x1 --Just to make sure everything's ok
GO 
--treminate the script on any error. (Requires SQLCMD mode)
:on error exit 
--If not in SQLCMD mode the above line will generate an error, so the next line won't hit
SET CONTEXT_INFO 0x2
GO
--make sure to use SQLCMD mode ( :on error needs that)
IF CONTEXT_INFO()<>0x2 
BEGIN
    SELECT CONTEXT_INFO()
    SELECT 'This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!'
    RAISERROR('This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!',16,1) WITH NOWAIT 
    WAITFOR DELAY '02:00'; --wait for the user to read the message, and terminate the script manually
END
GO

----------------------------------------------------------------------------------
----THE ACTUAL SCRIPT BEGINS HERE-------------

2
นี่เป็นวิธีเดียวที่ฉันพบว่าจะหลีกเลี่ยงความบ้าคลั่งของ SSMS ที่ไม่สามารถยกเลิกสคริปต์ได้ แต่ฉันเพิ่ม 'SET NOEXEC OFF' ที่จุดเริ่มต้นและ 'SET NOEXEC ON' หากไม่ได้อยู่ในโหมด SQLCMD มิฉะนั้นสคริปต์จริงจะยังคงทำงานต่อไปจนกว่าคุณจะเพิ่มข้อผิดพลาดที่ระดับ 20 พร้อมกับบันทึก
Mark Sowul

8

นี่เป็นขั้นตอนการจัดเก็บหรือไม่ ถ้าเป็นเช่นนั้นฉันคิดว่าคุณสามารถทำ Return ได้เช่น "Return NULL";


ขอบคุณสำหรับคำตอบที่ดีที่จะรู้ แต่ในกรณีนี้มันไม่ได้เป็น proc เก็บไว้เพียงไฟล์สคริปต์
แอนดี้สีขาว

1
@Gordon ไม่เสมอ (ที่นี่ฉันค้นหา) ดูคำตอบอื่น ๆ (ไปเพิ่มเพื่อสิ่งหนึ่ง)
Mark Sowul

6

ฉันขอแนะนำให้คุณใส่บล็อคโค้ดที่เหมาะสมในบล็อก catch ลอง จากนั้นคุณสามารถใช้เหตุการณ์ Raiserror ด้วยระดับความรุนแรง 11 เพื่อทำลายบล็อก catch ถ้าคุณต้องการ หากคุณเพียงแค่ต้องการผู้ก่อ แต่ดำเนินการต่อในการลองบล็อกแล้วใช้ความรุนแรงที่ต่ำกว่า

ทำให้รู้สึก?

ไชโยจอห์น

[แก้ไขเพื่อรวมการอ้างอิง BOL]

http://msdn.microsoft.com/en-us/library/ms175976(SQL.90).aspx


ฉันไม่เคยเห็นลองใช้ SQL มาก่อน - คุณจะโพสต์ตัวอย่างรวดเร็วของสิ่งที่คุณหมายถึงหรือไม่
Andy White

2
มันใหม่สำหรับปี 2005 BEGIN ลองใช้ {sql_statement | Statement_block} END TRY BEGIN CATCH {sql_statement | statement_block} END CATCH [; ]
Sam

@Andy: เพิ่มการอ้างอิงแล้วตัวอย่างรวมอยู่ด้วย
John Sansom

2
บล็อค TRY-CATCH ไม่อนุญาตให้เข้าไปในตัวมัน
AntonK

4

คุณสามารถใช้RAISERROR


3
สิ่งนี้ไม่สมเหตุสมผลสำหรับฉัน - ทำให้เกิดข้อผิดพลาดที่หลีกเลี่ยงได้ (สมมติว่าเรากำลังพูดถึงการตรวจสอบความถูกต้องของการอ้างอิงที่นี่) เป็นวิธีที่น่ากลัวในการทำเช่นนี้หากการตรวจสอบความถูกต้องเป็นไปได้
Dave Swersky

2
ผู้ใช้ raiserr สามารถใช้เป็นข้อความที่ให้ข้อมูลพร้อมการตั้งค่าความรุนแรงต่ำ
Mladen Prajdic

2
สคริปต์จะดำเนินการต่อไปเว้นแต่จะมีเงื่อนไขตามที่ระบุไว้ในคำตอบที่ยอมรับแล้ว
Eric J.

4

ไม่สามารถใช้งานได้กับคำสั่ง 'GO' ในรหัสนี้ไม่ว่าความรุนแรงจะเป็น 10 หรือ 11 คุณจะได้รับคำสั่ง PRINT สุดท้าย

สคริปต์ทดสอบ:

-- =================================
PRINT 'Start Test 1 - RAISERROR'

IF 1 = 1 BEGIN
    RAISERROR('Error 1, level 11', 11, 1)
    RETURN
END

IF 1 = 1 BEGIN
    RAISERROR('Error 2, level 11', 11, 1)
    RETURN
END
GO

PRINT 'Test 1 - After GO'
GO

-- =================================
PRINT 'Start Test 2 - Try/Catch'

BEGIN TRY
    SELECT (1 / 0) AS CauseError
END TRY
BEGIN CATCH
    SELECT ERROR_MESSAGE() AS ErrorMessage
    RAISERROR('Error in TRY, level 11', 11, 1)
    RETURN
END CATCH
GO

PRINT 'Test 2 - After GO'
GO

ผล:

Start Test 1 - RAISERROR
Msg 50000, Level 11, State 1, Line 5
Error 1, level 11
Test 1 - After GO
Start Test 2 - Try/Catch
 CauseError
-----------

ErrorMessage
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Divide by zero error encountered.

Msg 50000, Level 11, State 1, Line 10
Error in TRY, level 11
Test 2 - After GO

วิธีเดียวที่จะทำให้งานนี้คือการเขียนสคริปต์โดยไม่มีGOคำสั่ง บางครั้งมันง่าย บางครั้งมันค่อนข้างยาก (ใช้สิ่งที่ต้องการIF @error <> 0 BEGIN ...)


ไม่สามารถทำได้ด้วย CREATE PROCEDURE เป็นต้นดูคำตอบของฉันสำหรับวิธีแก้ปัญหา
Blorgbeard ออก

ทางออกของ Blogbeard นั้นยอดเยี่ยมมาก ฉันทำงานกับ SQL Server มาหลายปีแล้วและนี่เป็นครั้งแรกที่ฉันได้เห็นสิ่งนี้
Rob Garrison

4

ฉันใช้ RETURNที่นี่ตลอดเวลาทำงานในสคริปต์หรือStored Procedure

ตรวจสอบให้แน่ใจว่าคุณROLLBACKทำธุรกรรมหากคุณเป็นหนึ่งในนั้นมิฉะนั้นRETURNทันทีจะส่งผลให้การทำธุรกรรมเปิดปราศจากข้อผูกมัด


5
ไม่ทำงานกับสคริปต์ที่มีหลายแบทช์ (คำสั่ง GO) - ดูคำตอบของฉันสำหรับวิธีการทำ
Blorgbeard ออก

1
RETURN เพิ่งออกจากกลุ่มคำสั่งปัจจุบัน หากคุณอยู่ในบล็อก IF END การดำเนินการจะดำเนินการต่อหลังจากสิ้นสุด ซึ่งหมายความว่าคุณไม่สามารถใช้ RETURN เพื่อสิ้นสุดการดำเนินการหลังจากทดสอบเงื่อนไขบางอย่างเนื่องจากคุณจะอยู่ใน IF END block เสมอ
cdonner


3

คุณสามารถใช้คำสั่ง GOTO ลองสิ่งนี้ นี่คือการใช้งานเต็มรูปแบบสำหรับคุณ

WHILE(@N <= @Count)
BEGIN
    GOTO FinalStateMent;
END

FinalStatement:
     Select @CoumnName from TableName

GOTO ควรจะเป็นไม่ดีเข้ารหัสปฏิบัติใช้ "TRY..CATCH" ขอแนะนำตามที่มันถูกนำมาใช้ตั้งแต่ SQL Server 2008 ตามด้วยการโยนในปี 2012
เอ็ดดี้มาร์

1

ขอบคุณสำหรับคำตอบ!

raiserror() ทำงานได้ดี แต่คุณไม่ควรลืม returnคำสั่งมิฉะนั้นสคริปต์จะดำเนินต่อไปโดยไม่มีข้อผิดพลาด! (การเพิ่มเรนเดอร์ไม่ใช่ "นักเลง" ;-)) และแน่นอนว่าการทำโรลแบ็คถ้าจำเป็น!

raiserror() ดีใจที่ได้บอกคนที่รันสคริปต์ว่ามีบางอย่างผิดปกติ


1

หากคุณเพียงแค่เรียกใช้งานสคริปต์ใน Management Studio และต้องการหยุดการดำเนินการหรือการย้อนกลับ (ถ้าใช้) ในข้อผิดพลาดครั้งแรกวิธีที่ดีที่สุดที่ฉันคาดไว้คือใช้ try catch block (SQL 2005 เป็นต้นไป) สิ่งนี้ทำงานได้ดีในสตูดิโอการจัดการหากคุณกำลังเรียกใช้งานไฟล์สคริปต์ Proc ที่เก็บไว้สามารถใช้สิ่งนี้ได้เช่นกัน


1
คำตอบของคุณเพิ่มไปยังคำตอบที่ยอมรับด้วย 60+ upvotes อะไร? คุณเคยอ่านไหม ตรวจสอบคำถาม metaSOนี้และJon Skeet: Coding Blogเกี่ยวกับวิธีการให้คำตอบที่ถูกต้อง
Yaroslav

0

ย้อนกลับไปในวันที่เราใช้สิ่งต่อไปนี้ ... ทำงานได้ดีที่สุด:

RAISERROR ('Error! Connection dead', 20, 127) WITH LOG

0

ใส่ในบล็อก catch catch จากนั้นการประมวลผลจะถูกถ่ายโอนไปยัง catch

BEGIN TRY
    PRINT 'This will be printed'
    RAISERROR ('Custom Exception', 16, 1);
    PRINT 'This will not be printed'
END TRY
BEGIN CATCH
    PRINT 'This will be printed 2nd'
END CATCH;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.