SQL Server 버전에 따라 RAISERROR 또는 THROW를 선택할 수 있습니까?


11

내 코드는 다음과 같습니다.

BEGIN TRY
INSERT INTO TABLE (F1,F2,F3) 
VALUES ('1','2','3')
END TRY
BEGIN CATCH
;THROW
END CATCH

SQL 2008을 사용하는 컴퓨터에서 실행되지 않는 한 잘 작동합니다. CATCH 블록에서 SQL 버전을 확인하고 2012 이상인 경우 THROW를 실행하고 2008 인 경우 RAISERROR를 실행하고 싶습니다. 구문 오류가 있으며 가능한지 궁금합니다. 이와 같은 간단한조차도 나를 위해 작동하지 않습니다.

BEGIN CATCH
IF ((SELECT SERVERPROPERTY('productversion')) >= 11) ;THROW
END CATCH

조언을 부탁드립니다.

답변:


9

불가능합니다.

이전 버전에서는 잘못된 구문이며 컴파일 오류가 발생합니다.

숨길 수없는 THROW에서이 EXEC매개 변수없는 던져 직접 캐치 안에 포함되어야로 하나 catch 블록 내에서.

배포하려는 SQL Server 버전에 따라 원하는 코드 버전을 배포해야합니다. 불행히도 SSDT 툴링에서이를 잘 지원하지 않습니다. 조건부 컴파일)


4

기술적으로 THROW와 사이를 번갈아 가면서 가능하더라도 RAISERROR실제로는 그렇게하고 싶지 않을 것입니다. 왜? 매개 변수가없는의 아주 멋진 능력 때문에 THROW로 사용하여 오류를 재 - 던져 같은 메시지 번호 (예 : Msg 8134대신의 Msg X경우 X> = 50000)이 그들 사이의 유일한 차이점되지 않습니다 : THROW입니다 일괄 중단 동안은 RAISERROR없습니다. 이것은 아래에 설명 된 중요한 동작 차이 일 수 있습니다.

테스트 설정

--DROP PROC ##Throw;
--DROP PROC ##RaisError;

GO
CREATE PROCEDURE ##Throw
AS
SET NOCOUNT ON;
BEGIN TRY
  SELECT 1/0 AS [DivideByZero];
END TRY
BEGIN CATCH
  THROW;
END CATCH;
SELECT 1 AS [AA];
GO

CREATE PROCEDURE ##RaisError
AS
SET NOCOUNT ON;
BEGIN TRY
  SELECT 1/0 AS [DivideByZero];
END TRY
BEGIN CATCH
  RAISERROR('test, yo!', 16, 1);
  -- RETURN; -- typically at end of CATCH block when using RAISERROR
END CATCH;
SELECT 2 AS [BB];
GO

시험 1

EXEC ##Throw;
SELECT 3 AS [CC];

보고:

"Results" Tab:

DivideByZero
{empty result set}

"Messages" Tab:

Msg 8134, Level 16, State 1, Procedure ##Throw, Line 38
Divide by zero error encountered.

시험 2

EXEC ##RaisError;
SELECT 4 AS [DD];

보고:

"Results" Tab:

DivideByZero
{empty result set}

BB
2

DD
4

"Messages" Tab:

Msg 50000, Level 16, State 1, Procedure ##RaisError, Line 45
test, yo!

공정하게하기 위해 다음을 수행하여이 차이를 숨길 수 있습니다.

  • 항상 구조 THROW내에서 사용하여 코드에 대한 모든 호출을 래핑하십시오 TRY...CATCH(아래에 설명).
  • 결코 장소 코드 후 THROW(물론,를 제외하고 END CATCH;)

시험 3

BEGIN TRY
  EXEC ##Throw;
  SELECT 5 AS [EE];
END TRY
BEGIN CATCH
  SELECT ERROR_NUMBER() AS [ErrorNumber], ERROR_MESSAGE() AS [ErrorMessage];
END CATCH;
SELECT 6 AS [FF];
GO

보고:

"Results" Tab:

DivideByZero
{empty result set}

ErrorNumber     ErrorMessage
8134            Divide by zero error encountered.

FF
6

시험 4

BEGIN TRY
  EXEC ##RaisError;
  SELECT 7 AS [GG];
END TRY
BEGIN CATCH
  SELECT ERROR_NUMBER() AS [ErrorNumber], ERROR_MESSAGE() AS [ErrorMessage];
END CATCH;
SELECT 8 AS [HH];
GO

보고:

"Results" Tab:

DivideByZero
{empty result set}

ErrorNumber     ErrorMessage
50000           test, yo!

HH
8

3

저는 믿습니다 마틴 스미스의 대답은 거의 100 % 권리입니다.

이를 수행하는 유일한 방법은 동적 SQL을 사용하는 것입니다. 모든 try / catch 블록 (또는 모든 버전의 두 가지 버전을 사용하려는 경우 전체 작성 프로 시저 명령문을 랩하여 대량의 코드를 복제해야합니다. 버전에 따라 실행).

그것은 유지하는 악몽 일 것입니다. 하지마

SQL Server 버전을 기반으로 SQL 문을 실행하는 방법이 있습니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.