执行存储过程参数验证的“正确”方式

我有一个存储过程,它执行一些参数验证,如果参数无效,应该会失败并停止执行。

我的第一个错误检查方法如下所示:

create proc spBaz
(
  @fooInt int = 0,
  @fooString varchar(10) = null,
  @barInt int = 0,
  @barString varchar(10) = null
)
as
begin
  if (@fooInt = 0 and (@fooString is null or @fooString = ''))
    raiserror('invalid parameter: foo', 18, 0)

  if (@barInt = 0 and (@barString is null or @barString = ''))
    raiserror('invalid parameter: bar', 18, 0)

  print 'validation succeeded'
  -- do some work
end

这并没有做到这一点,因为严重性18不会停止执行,并且“验证成功”与错误消息一起打印。

我知道我可以简单地在每次增加错误后添加一个回报,但是这对我来说很丑陋:

  if (@fooInt = 0 and (@fooString is null or @fooString = ''))
  begin
    raiserror('invalid parameter: foo', 18, 0)
    return
  end

  ...

  print 'validation succeeded'
  -- do some work

由于严重级别为11和更高的错误在try / catch块中被捕获,我测试的另一种方法是在这样的try / catch块内封装错误检查。 问题在于错误被吞噬了,根本没有发送给客户端。 所以我做了一些研究并找到了重新抛出错误的方法:

  begin try
    if (@fooInt = 0 and (@fooString is null or @fooString = ''))
      raiserror('invalid parameter: foo', 18, 0)

    ...
  end try
  begin catch
    exec usp_RethrowError
    return
  end catch

  print 'validation succeeded'
  -- do some work

我对这种方法仍然不满意,所以我问你:

你的参数验证是怎样的? 做这种检查有没有某种“最佳做法”?


我不认为有这样一个“正确”的方法。

我自己的偏好与第二个例子类似,但是对于每个参数和更明确的错误消息都有单独的验证步骤。

正如你所说,这有点繁琐和丑陋,但代码的意图对于阅读它的任何人都是显而易见的,而且它可以完成工作。

IF (ISNULL(@fooInt, 0) = 0)
BEGIN
    RAISERROR('Invalid parameter: @fooInt cannot be NULL or zero', 18, 0)
    RETURN
END

IF (ISNULL(@fooString, '') = '')
BEGIN
    RAISERROR('Invalid parameter: @fooString cannot be NULL or empty', 18, 0)
    RETURN
END

我们通常会避免raiseerror()并返回一个表示错误的值,例如负数:

if <errorcondition>
    return -1

或者将结果传递给两个输出参数:

create procedure dbo.TestProc
    ....
    @result int output,
    @errormessage varchar(256) output
as
set @result = -99
set @errormessage = null
....
if <errorcondition>
    begin
    set @result = -1
    set @errormessage = 'Condition failed'
    return @result
    end

正如你从这个答案历史中看到的,我遵循了这个问题并接受了答案,然后继续“发明”一个与第二种方法基本相同的解决方案。

咖啡因是我的主要能量来源,因为我花了大半生的时间,因为我花了太多时间编码; 因此,我没有意识到我的假人,直到你正确地指出了它。

因此,为了记录,我更喜欢第二种方法:使用SP来提高当前错误,然后在参数验证周围使用TRY / CATCH。

它减少了所有IF / BEGIN / END块的需求,因此减少了线数,并将焦点放回到验证。 阅读SP代码时,能够看到正在参数上执行的测试很重要; 在我看来,所有额外的语法松散来满足SQL解析器都会妨碍我们。

链接地址: http://www.djcxy.com/p/71579.html

上一篇: The "right" way to do stored procedure parameter validation

下一篇: What is a stored procedure?