답변:
RAISERROR의 방법
raiserror('Oh no a fatal error', 20, -1) with log
연결이 종료되어 나머지 스크립트 실행이 중지됩니다.
WITH LOG
이 방법으로 작동 하려면 심각도 레벨 20 이상과 옵션이 모두 필요합니다.
이것은 심지어 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'는 인쇄되지 않습니다.
주의 사항 :
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.
RETURN을 사용하십시오 (저장 프로 시저 내부 및 외부에서 모두 작동 함).
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 모드에 있지 않고 실행되는 것처럼 완전히 방탄하지는 않습니다. 여전히 명령 행에서 실행하고 있다면 괜찮습니다.
RAISERROR- SQL을 사용하지 않습니다. 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
유효성 검사가 더 복잡하더라도 최종 검사에 포함 할 플래그 변수는 몇 개만 있으면됩니다.
RAISERROR
누가 스크립트를 실행할지, 어떤 권한을 가지고 있는지 알지 못하는 경우 보다 훨씬 안정적 입니다.
declare @i int = 0; if @i=0 begin select '1st stmt in IF block' go end else begin select 'ELSE here' end go
SQL 2012+에서는 THROW 를 사용할 수 있습니다 .
THROW 51000, 'Stopping execution because validation failed.', 0;
PRINT 'Still Executing'; -- This doesn't execute with THROW
MSDN에서 :
예외를 발생시키고 실행을 TRY… CATCH 구문의 CATCH 블록으로 전송합니다. TRY… CATCH 구문을 사용할 수 없으면 세션이 종료됩니다. 예외가 발생한 행 번호와 절차가 설정됩니다. 심각도는 16으로 설정되어 있습니다.
트랜잭션을 사용하여 noexec on / off 솔루션을 성공적으로 확장하여 스크립트를 전혀 또는 전혀 실행하지 않았습니다.
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로 설정됩니다. 따라서 트랜잭션을 적절하게 커밋하거나 롤백 할 수 있습니다.
IF (XACT_STATE()) <> 1 BEGIN Set NOCOUNT OFF ;THROW 525600, 'Rolling back transaction.', 1 ROLLBACK TRANSACTION; set noexec on END;
그러나 실행이 멈추지 않았고 결국 "롤링 백 트랜잭션"오류가 발생했습니다. 어떤 아이디어?
SQL 문을 WHILE 루프로 감싸고 필요한 경우 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
DECLARE @ST INT; SET @ST = 1; WHILE @ST = 1; BEGIN; SET @ST = 0; ...; END
더 장황하지만 도대체 그것은 어쨌든 TSQL입니다 ;-)
GOTO 문을 사용하여 실행 플로우를 변경할 수 있습니다 .
IF @ValidationResult = 0
BEGIN
PRINT 'Validation fault.'
GOTO EndScript
END
/* our code */
EndScript:
추가 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-------------
저장 프로 시저입니까? 그렇다면 "Return NULL"과 같은 Return 만 할 수 있다고 생각합니다.
적절한 코드 블록을 try catch 블록으로 감싸는 것이 좋습니다. 그런 다음 원하는 경우 캐치 블록을 해제하기 위해 심각도 11 인 Raiserror 이벤트를 사용할 수 있습니다. 에러를 발생시키고 try 블록 내에서 계속 실행하려면 심각도를 낮추십시오.
말이 되나요?
건배, 존
[BOL 참조를 포함하도록 편집]
http://msdn.microsoft.com/en-us/library/ms175976(SQL.90).aspx
RAISERROR 를 사용할 수 있습니다 .
이 중 어느 것도 '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 ...
.)
나는 RETURN
항상 여기에서 사용 하고 스크립트에서 작동하거나Stored Procedure
ROLLBACK
거래가있는 경우 거래를 확인하십시오 . 그렇지 않으면 RETURN
즉시 커밋되지 않은 미결 거래가 발생합니다.
답변을위한 Thx!
raiserror()
잘 작동하지만 return
문장을 잊지 않아야합니다 . 그렇지 않으면 스크립트가 오류없이 계속됩니다! (건조 오류는 "throwerror"가 아닙니다 ;-)) 물론 필요한 경우 롤백을합니다!
raiserror()
스크립트를 실행하는 사람에게 문제가 있음을 알리는 것이 좋습니다.
Management Studio에서 단순히 스크립트를 실행 중이고 첫 번째 오류에서 실행 또는 롤백 트랜잭션 (사용 된 경우)을 중지하려면 try catch 블록 (SQL 2005 이상)을 사용하는 것이 가장 좋습니다. 스크립트 파일을 실행하는 경우 Management Studio에서 잘 작동합니다. 저장된 proc은 항상 이것을 사용할 수 있습니다.