繁体   English   中英

从 SQL Server 函数向存储过程抛出异常

[英]Throw exception from SQL Server function to stored procedure

我在 SQL Server 2012 中有存储过程说 spXample 和一个缩放器值函数说 fXample。 我从 spXample 调用函数 fXample。 我可以在函数中抛出异常并在存储过程的Catch块中捕获它并重新抛出到调用 C# 代码吗?

更新:

我写的函数如下:

CREATE FUNCTION dbo.fXample(@i INT)
RETURNS TINYINT
AS
BEGIN
  RETURN (SELECT CASE WHEN @i < 10 
    THEN THROW 51000,'Xample Exception',1;
    ELSE (SELECT @i) 
    END);
END
GO

我收到错误

消息 443,级别 16,状态 14,过程 fXample,第 46 行在函数内无效使用副作用运算符“THROW”。

如何编写替代代码来实现上述功能?

您可以通过在验证失败时强制出现错误条件来做到这一点,前提是这不是可能自然发生的错误。 当您知道某个错误只能在验证失败时发生时,您可以通过检查 catch 块中的 error_number 以自定义方式处理该错误。 tempdb 中的示例:

USE tempdb;
GO

CREATE FUNCTION dbo.fXample(@i INT)
RETURNS TINYINT
AS
BEGIN
  RETURN (SELECT CASE WHEN @i < 10 -- change this to your "validation failed" condition
    THEN 1/0         -- something that will generate an error
    ELSE (SELECT @i) -- (you'd have your actual retrieval code here)
    END);
END
GO

CREATE PROCEDURE dbo.spXample
  @i INT
AS
BEGIN
  SET NOCOUNT ON;
  BEGIN TRY
    SELECT dbo.fXample(@i);
  END TRY
  BEGIN CATCH
    IF ERROR_NUMBER() = 8134 -- divide by zero
    BEGIN
      THROW 50001, 'Your custom error message.', 1;
      -- you can throw any number > 50000 here
    END
    ELSE -- something else went wrong
    BEGIN
      THROW; -- throw original error
    END
  END CATCH
END
GO

现在试试看:

EXEC dbo.spXample @i = 10;  -- works fine
EXEC dbo.spXample @i = 6;   -- fails validation
EXEC dbo.spXample @i = 256; -- passes validation but overflows return

结果:

----
10

消息 50001,级别 16,状态 1,过程 spXample,第 12 行
您的自定义错误消息。

消息 220,级别 16,状态 2,过程 spXample,第 7 行
数据类型 tinyint 的算术溢出错误,值 = 256。

虽然这已经解决了,但我觉得我仍然应该分享这个。 我认为这将是一个更简单的解决方案:

BEGIN TRY
    THROW 60000, 'Error', 1;
END TRY
BEGIN CATCH
    THROW
END CATCH
/*  *** EXAMPLES ***
    SELECT dbo.fnDoSomething(500) -- RETURNS TRUE
    
    SELECT dbo.fnDoSomething(5000) -- THROWS ERROR
        Msg 245, Level 16, State 1, Line 4
        Conversion failed when converting the varchar value 
        'Function Error - [dbo].[fnDoSomething] - Value is greater than 1000' to data type bit.
*/
CREATE FUNCTION dbo.fnDoSomething
(
    @SomeValue      INT
)
RETURNS BIT
AS
BEGIN
    IF @SomeValue > 1000
    BEGIN
        DECLARE @FunctionName AS SYSNAME = QUOTENAME(OBJECT_SCHEMA_NAME(@@PROCID)) + '.' + QUOTENAME(OBJECT_NAME(@@PROCID))
        DECLARE @Error AS VARCHAR(200) = 'Function Error - '+ @FunctionName + ' - Value is greater than 1000'
        RETURN  CONVERT(BIT,@Error)
    END

    RETURN 1
END
GO

如果满足某个条件,您也可以在存储过程中引发错误,但错误严重性必须高于 10 才能抛出 SQL 异常

CREATE PROC test
AS
RAISERROR('the error message', 11, 1);
RETURN

您可以稍后在 catch 块中访问此消息

try {
    testProc.ExecuteNonQuery();
}
catch(SqlException ex)
{
    System.Diagnostics.Debug.WriteLine(ex.Message);
}

输出:“错误信息”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM