SQL Server错误处理:异常和数据库 - 客户端合同

时间:2009-04-17 19:42:30

标签: sql-server-2005 tsql sql-server-2008 exception stored-procedures

我们是SQL Server数据库开发人员团队。我们的客户是C#/ ASP.NET,C#和Java Web服务,Java / Unix服务和一些Excel的混合包。

我们的客户开发人员只使用我们提供的存储过程,我们希望(当然,合理的)他们会像Web服务方法一样对待它们。

我们的一些客户端开发人员不喜欢SQL异常。他们用他们的语言理解他们,但他们不理解SQL在如何沟通问题方面受到限制。

我不只是指SQL错误,例如尝试将“bob”插入到int列中。

我还指的是例外,例如告诉他们参考值是错误的,或者数据已经改变,或者他们不能这样做,因为他的聚合不是零。

他们没有任何具体的替代方案:他们提到我们应该输出参数,但我们假设一个例外意味着“处理停止/回滚。

这里的人们如何处理数据库 - 客户合同?通常或DB和客户端代码猴之间存在分离的地方。

编辑:

  • 我们专门使用SQL Server 2005 TRY / CATCH
  • 我们将回滚后的所有错误记录到异常表
  • 我们担心我们的一些客户不会检查输出参数并假设一切正常。我们需要标记错误以供支持查看。
  • 一切都是例外......客户应该做一些消息解析来分离信息与错误。要将我们的异常与数据库引擎和调用错误分开,他们应该使用错误编号(我们当然都是50,000)

4 个答案:

答案 0 :(得分:3)

我是一个客户端代码猴,它经常处理数据库。这是我处理它的方式。

SQL中发生的异常(引发错误)会传播回调用者。这将包括ref约束,唯一索引违规,更严重的问题等。基本上任何不会使数据操作正常发生的事情都应该传播回来。

来电者C#应该有这个:

catch (SQLException sqlEx)

然后根据需要处理异常。它们应该具有特定的SQLException处理程序。这很重要。

我通常远离输出参数,因为我认为那些与传输的数据有关,而不是任何错误消息,另外我可以检查SQL Server错误代码的异常,所以我们需要的所有数据都应该在异常。

此外,在SQL Server的某些情况下,我们的存储过程可能会引发“业务类型的异常”。在这些情况下,我们添加自定义错误号(大于50000)并在需要时在存储过程中引发该错误。一般来说,我们尽量将这些保持在最低限度,因为它增加了复杂性,但在某些情况下,我们发现它们是必要的。

现在,由于客户端正在捕获SQLException,因此他们可以查看SQL Server在异常中返回的错误代码,然后在捕获到异常时采取任何特殊操作(如果需要)并且错误号是特定值。如果自定义错误(> 50000)需要,则允许基于错误代码进行二级错误处理。

这也允许DBA引发自定义错误并使客户端代码具有一致的方式来处理它们。然后,DBA必须告诉客户端代码猴子自定义错误是什么,以便他们可以为它们做好准备。

我通常不会将返回代码用于错误处理目的,虽然我可以看到如何使用它们,但这意味着代码猴层中的更多逻辑可以查看并处理返回代码。如果它们是一个问题,我想要一个例外,因为那样我就可以一直处理它们。如果我还要查看返回代码,现在有多种错误处理途径。

答案 1 :(得分:2)

我通常使用输出参数 - 并定义可能的值。

0 =成功
Postive Integer(在插页上说)= New Row Id(@@ identity)

负整数=已知可能的错误条件
-1 =缺少@LastName(或零长度)
-2 =缺少@FirstName(或零长度)
...等等...

定义变得有点乏味 - 但它可以是可扩展的 - 并且它是一种将有意义的结果反馈给客户并将数据访问层传递回业务对象层的方法,这是失败的确切原因(我在Business Objects层中使用枚举来表示不同的状态条件。)

如果需要,数据访问层也可能抛出异常 - 但我相信从性能角度来看,您最好不要在检查枚举或整数值时抛出错误。

还有其他一些技术 - 这只是我过去使用过的一些技巧。

答案 2 :(得分:2)

这是我的建议:

当一切正常时,

返回0 当逻辑错误发生,数据丢失或无效时,返回负x 发生致命错误,插入失败等时返回正x。

将输出参数ErrorMsg和ErrorLog添加到存储过程中。 ErrorMessage将包含人类可读消息,ErrorLog将包含调试信息 如果返回0,则这些将为NULL 您可以使用ErrorLog记录任何问题,确保将它们插入表中,然后在回滚后执行。

使用TRY - Catch捕获问题,构建自己的消息,并使用上述约定返回信息。

答案 3 :(得分:2)

在我目前的工作中,我们为例外条件保留例外情况。对于诸如错误参数之类的东西,我们有标准的返回码 - 例如,无效的参数值总是返回98。 (为什么98?失去了历史...)

这不一定是理想的b / c,客户端和SP都必须了解特定返回码的含义;这是一个很糟糕的问题分离。

在特殊情况下,我们使用OUT参数返回消息,我们的批处理服务使用标准化的#scratch表设置。

在以前的雇主,我们使用自定义SQL错误用于相同的目的。所以,使用有意义的东西。就个人而言,我更喜欢单一机制,但根据您的环境可能无法实现。

也许你们都应该聚在一起为客户端代码开发标准化的方法来处理它。 Excel中使用的VBA具有明显的限制,C#和Java代码没有,并且与Java和Java类似。 C#是相互的,它们不相同。 如果您要坚持返回异常,那么如果您同意a)已知消息#范围指示“错误”异常和b)标准化消息布局以便可以进行标准化解析,开发人员将完成90%。