2013-04-05 217 views
4

我在SQL Server 2012中有存储过程,比如说spXample和一个定标器函数fXample。 我从spXample调用函数fXample。 我可以在函数中抛出一个异常,并在存储过程的Catch块中捕获它并重新引发到调用C#代码?从SQL Server函数向存储过程抛出异常

更新:

我写的功能等:

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 

我收到错误

Msg 443, Level 16, State 14, Procedure fXample, Line 46 Invalid use of a side-effecting operator 'THROW' within a function.

我怎样写替代代码来实现上述功能?

+0

抛出一个异常的功能基础上什么样的条件?什么类型的函数,标量,TVF,多语句TVF? – 2013-04-05 14:41:41

+0

尝试RAISERROR:http://msdn.microsoft.com/en-us/library/ms178592.aspx。如果你给它一个较低的严重性,它可以被CATCH捕获。从那里,你可以称它为“严重”的严重性(我认为11+;页面上有例子),它会停止SP的执行并将它踢回到你的应用程序。 – valverij 2013-04-05 14:42:30

+0

Aaron的Scaler价值,异常将基于验证。 – MaxRecursion 2013-04-05 14:45:42

回答

9

您可以通过在验证失败时强制出现错误条件来做到这一点,前提是这不是自然可能发生的错误。当你知道某个错误只能发生在验证失败时,你可以通过检查你的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 

Msg 50001, Level 16, State 1, Procedure spXample, Line 12
Your custom error message.

Msg 220, Level 16, State 2, Procedure spXample, Line 7
Arithmetic overflow error for data type tinyint, value = 256.

+2

谢谢,但是我们必须跳过什么荒谬的箍来做些什么是很简单! 只是表明SQL是一种过去的语言,根本就不是在继续。 :( – NickG 2013-08-09 12:53:19

+1

我只想添加THROW来自Sql Server 2012 – 2015-03-06 12:09:43

+0

@NickG,你可以使用存储过程来代替,函数实际上是一种很好的方式来表示它们没有副作用,当然,它们仍然因为你可以抛出一个内置的错误 - 所以它不是完全没有副作用,它是一种在语言中具有纯函数的优雅方式,SQL是一种远远超过其时间的语言,并且非常令人印象深刻考虑它的年龄,它基本上是基于数据集的DSL,非常棒! – Jon49 2017-03-22 16:15:56