문제

"break"또는 "exit"명령과 같이 SQL Server에서 SQL 스크립트의 실행을 즉시 중지하는 방법이 있습니까?

인서트를 시작하기 전에 유효성 검사 및 조회를 수행하는 스크립트가 있으며 유효성 검사 또는 조회가 실패하면 중지하기를 원합니다.

도움이 되었습니까?

해결책

그만큼 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.

'호'는 인쇄되지 않았습니다.

경고 :

  • 관리자 ( 'Sysadmin'역할)로 로그인 한 경우에만 작동하며 데이터베이스 연결이없는 경우에도 작동합니다.
  • admin으로 로그인하지 않은 경우 RainError () 호출 자체가 실패합니다. 그리고 스크립트는 계속 실행됩니다.
  • sqlcmd.exe로 호출되면 Exit Code 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.

다른 팁

반품 만 사용하십시오 (저장된 절차 내부와 외부에서 작동 함).

SQLCMD 모드를 사용할 수 있다면 Incantation

: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 모드에 있지 않고 실행되는 것처럼 완전히 방탄은 아닙니다. 그래도 명령 줄에서 실행하는 경우 괜찮습니다.

나는이 목적으로 사용할 수있는 진술을 사용하지 않는다. 유효성 검사 및 조회를 수행하고 로컬 변수를 설정 한 다음 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

유효성 검사가 더 복잡하더라도 최종 확인에 포함하려면 몇 가지 플래그 변수 만 있으면됩니다.

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

분명히 컴파일러는 오류가 있고 실행이 비활성화 되더라도 IF의 @finished 변수를 "이해"합니다. 그러나 실행이 비활성화되지 않은 경우에만 값이 1로 설정됩니다. 따라서 그에 따라 거래를 잘 커밋하거나 롤백 할 수 있습니다.

SQL 명령문을 중간 루프로 래핑하고 필요한 경우 브레이크를 사용할 수 있습니다.

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

SQL 2012+에서는 사용할 수 있습니다 던지다.

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

MSDN에서 :

예외를 제기하고 실행을 시도의 캐치 블록으로 전송합니다… 캐치 구조물 ... 시도해 보면… 캐치 구조를 사용할 수 없으면 세션이 종료됩니다. 예외가 제기되는 줄 번호와 절차가 설정됩니다. 심각도는 16으로 설정됩니다.

이것은 저장된 절차입니까? 그렇다면 "return null"과 같은 반품을 할 수 있다고 생각합니다.

추가 Refinig Sglasses 방법, 위의 선은 SQLCMD 모드의 사용을 강제하고 SQLCMD 모드를 사용하지 않거나 사용하지 않으면 SCIRPT를 발효시킵니다. :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-------------

시도 캐치 블록에 적절한 코드 블록을 감싸는 것이 좋습니다. 그런 다음 원하는 경우 캐치 블록으로 나누기 위해 11 인 Raiserror 이벤트를 사용할 수 있습니다. 오버러를 원하지만 시도 블록 내에서 계속 실행하려면 심각도를 낮추십시오.

이해가 되나요?

건배, 존

BOL 참조를 포함하도록 편집

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

사용을 사용하여 실행 흐름을 변경할 수 있습니다 이동 진술 :

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

/* our code */

EndScript:

당신이 사용할 수있는 Raiserror.

이 중 어느 것도 'GO'진술과 함께 작동하지 않습니다. 이 코드에서 심각도가 10 또는 11인지 여부에 관계없이 최종 인쇄 문을 얻습니다.

테스트 스크립트 :

-- =================================
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 ....)

이것은 내 해결책이었습니다.

...

BEGIN
    raiserror('Invalid database', 15, 10)
    rollback transaction
    return
END

GOTO 문을 사용할 수 있습니다. 이 시도. 이것은 당신을 위해 가득 차 있습니다.

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

FinalStatement:
     Select @CoumnName from TableName

나는 사용한다 RETURN 여기서 항상 스크립트로 작동합니다 Stored Procedure

당신을 확인하십시오 ROLLBACK 당신이 하나, 그렇지 않으면 거래 RETURN 즉시 공개 커밋되지 않은 트랜잭션이 발생합니다

대답을 위해 thx!

raiserror() 잘 작동하지만 잊지 말아야합니다 return 문장은 그렇지 않으면 스크립트가 오류없이 계속됩니다! (Raiserror는 "Thowerror"가 아닙니다 ;-)) 물론 필요한 경우 롤백을합니다!

raiserror() 스크립트를 실행 한 사람에게 무언가 잘못되었다고 말하는 것이 좋습니다.

단순히 관리 스튜디오에서 스크립트를 실행하고 첫 번째 오류에서 실행 또는 롤백 트랜잭션 (사용 된 경우)을 중지하려는 경우, 내가 생각하는 가장 좋은 방법은 시도 캐치 블록 (SQL 2005 이후)을 사용하는 것입니다. 스크립트 파일을 실행하는 경우 관리 스튜디오에서 잘 작동합니다. 저장된 Proc는 항상 이것을 사용할 수 있습니다.

우리가 다음을 사용하는 날에 ... 가장 잘 작동했습니다.

RAISERROR ('Error! Connection dead', 20, 127) WITH LOG
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top