source

SQL Server - SQL 스크립트 실행 중지 또는 중단

manysource 2023. 5. 15. 22:20

SQL Server - SQL 스크립트 실행 중지 또는 중단

SQL 서버에서 "브레이크" 또는 "종료" 명령과 같은 SQL 스크립트 실행을 즉시 중지할 수 있는 방법이 있습니까?

삽입을 시작하기 전에 검증 및 조회를 수행하는 스크립트가 있는데, 검증 또는 조회가 실패할 경우 해당 스크립트가 중지되기를 원합니다.

상승 오차 방법

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' 역할)로 로그인한 경우에만 작동하며 데이터베이스 연결이 없는 상태로 유지됩니다.
  • admin으로 로그인하지 않은 경우 RAISEERROR() 호출 자체가 실패하고 스크립트가 계속 실행됩니다.
  • sqlcmd.exe를 사용하여 호출하면 종료 코드 2745가 보고됩니다.

참조: http://www.mydatabasesupport.com/forums/ms-sqlserver/174037-sql-server-2000-abort-whole-script.html#post761334

noexec 방법

하는 또 은 GO 문으작는또동다방같다다습니음과법은른하로▁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

(콜론을 포함하여) Raise 오류가 발생하여 스크립트가 실제로 중지됩니다.예.,

: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 Management Studio는 구문 분석 시간 오류도 바로 지나갑니다.그래도 명령줄에서 실행하는 경우에는 문제가 없습니다.

저는 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

검증이 더 복잡하더라도 최종 검사에 포함할 몇 개의 플래그 변수만 있으면 됩니다.

SQL 2012+에서는 SLOW를 사용할 수 있습니다.

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

MSDN에서:

예외를 발생시키고 실행을 TRI의 CATCH 블록으로 전송합니다.CATCH 구성...시도한 경우...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로 설정됩니다.따라서 그에 따라 트랜잭션을 적절하게 커밋하거나 롤백할 수 있습니다.

GOTO 문을 사용하여 실행 흐름을 변경할 수 있습니다.

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

/* our code */

EndScript:

필요한 경우 SQL 문을 WHIN 루프로 묶고 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

method를 하며, 하지 않을 하거나 Sglass를 합니다. 위의 라인은 SQLCMD 모드를 사용하도록 강제하며, SQLCMD 모드를 사용하지 않거나 사용할 경우 스크립트를 제거합니다.:on error exit실수가 있을 경우 종료합니다.
컨텍스트_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항상 여기서, 스크립트로 작동하거나.Stored Procedure

잘부탁다니립드!다▁sure!ROLLBACK이 한 거래, 그렇지 않으면 거래, 즉 입니다.RETURN 않은 합니다.

저장 프로시저입니까?그렇다면 "Return NULL"과 같은 Return을 수행하면 될 것 같습니다.

적절한 코드 블록을 시도 캐치 블록으로 감싼다.그런 다음 원하는 경우 탐지 블록으로 나누기 위해 심각도가 11인 상승 오류 이벤트를 사용할 수 있습니다.오류만 발생시키고 시도 블록 내에서 실행을 계속하려면 심각도를 낮춰야 합니다.

TRY...CATCH(트랜잭션-SQL)

이 중 '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 ....)

RAISEROR를 사용할 수 있습니다.

이것이 제 해결책이었습니다.

...

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

GOTO 문을 사용할 수 있습니다.이거 먹어봐요.이것은 당신에게 충분히 쓸모가 있습니다.

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

FinalStatement:
     Select @CoumnName from TableName

정답은 thx!

raiserror()잘 작동하지만 잊어서는 안 됩니다.return문 그렇지 않으면 스크립트가 오류 없이 계속됩니다! (따라서 상승 오류는 "잘못된 오류"가 아닙니다;-)) 그리고 물론 필요한 경우 롤백을 수행합니다!

raiserror()대본을 실행하는 사람에게 뭔가 잘못되었다고 말하는 것은 좋은 일입니다.

Management Studio에서 단순히 스크립트를 실행하는 경우 첫 번째 오류 시 실행 또는 롤백 트랜잭션(사용되는 경우)을 중지하려면 try catch block(SQL 2005 이후)을 사용하는 것이 가장 좋습니다.스크립트 파일을 실행하는 경우 Management Studio에서 잘 작동합니다.저장 프로시저도 항상 이 기능을 사용할 수 있습니다.

시도 캐치 블록에 묶으면 실행이 전달되어 캐치됩니다.

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;

예전에 우리가 사용했던 것은...가장 잘 작동함:

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

여기 있는 다른 모든 사람들과 제가 읽은 다른 게시물들에 감사드립니다.하지만 @jaraics가 대답하기 전까지는 어떤 것도 제 모든 요구를 충족시키지 못했습니다.

제가 본 대부분의 답변은 여러 배치가 있는 스크립트를 무시합니다.그리고 그들은 SSMS와 SQLCMD의 이중 사용을 무시합니다. 제 스크립트는 SSMS에서 완전히 실행 가능합니다. 하지만 저는 F5 방지를 원합니다. 그들이 사고로 인해 기존의 객체 세트를 제거하지 않도록 말입니다.

SET PARSEONLY ON원치 않는 F5를 막을 수 있을 정도로 잘 작동했습니다.하지만 SQLCMD로는 실행할 수 없습니다.

제가 잠시 주춤했던 또 다른 이유는 오류가 있을 때 배치가 추가 명령을 건너뛸 수 있다는 것입니다.SET NOCOUNT ON건너뛰는 중이었기 때문에 스크립트가 계속 실행되었습니다.

어쨌든, 저는 jaraics의 답변을 조금 수정했습니다: (이 경우, 저는 또한 명령줄에서 활성화될 데이터베이스가 필요합니다.)

-----------------------------------------------------------------------
-- Prevent accidental F5
-- Options:
--     1) Highlight everything below here to run
--     2) Disable this safety guard
--     3) or use SQLCMD
-----------------------------------------------------------------------
set NOEXEC OFF                             -- Reset in case it got stuck ON
set CONTEXT_INFO  0x1                      -- A 'variable' that can pass batch boundaries
GO                                         -- important !
if $(SQLCMDDBNAME) is not null
    set CONTEXT_INFO 0x2                   -- If above line worked, we're in SQLCMD mode
GO                                         -- important !
if CONTEXT_INFO()<>0x2 
begin
    select 'F5 Pressed accidentally.'
    SET NOEXEC ON                          -- skip rest of script
END
GO                                         -- important !
-----------------------------------------------------------------------

< rest of script . . . . . >


GO
SET NOEXEC OFF
print 'DONE'

저는 다음 스크립트를 사용해 왔으며 여기에서 제 답변에서 더 자세한 내용을 볼 수 있습니다.

RAISERROR ( 'Wrong Server!!!',18,1) WITH NOWAIT RETURN
    
    print 'here'
    
    select [was this executed]='Yes'

언급URL : https://stackoverflow.com/questions/659188/sql-server-stop-or-break-execution-of-a-sql-script