是否可以根据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版本进行检查,如果THROW等于或高于2012,则运行THROW,如果它等于或高于2012,则运行RAISERROR。语法错误,我想知道是否有可能。即使像这样简单的事情也对我不起作用。

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

任何建议表示赞赏。

Answers:


9

不,这是不可能的。

在早期版本中,这是无效的语法,将导致编译错误。

不能将其隐藏THROWEXECcatch块内部,因为必须将无参数的抛出直接包含在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!

公平地说,可以通过以下操作掩盖这种差异:

  • 始终THROWTRY...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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.