存储过程 - 将消息传递回用户应用程序的最佳方法

时间:2008-09-17 22:12:27

标签: sql sql-server tsql raiserror

我想知道人们在存储过程中使用RAISERROR将用户消息(即与业务相关的消息,而不是错误消息)传递给应用程序的想法。

我公司的一些高级开发人员一直在使用这种方法并在我们的C#代码中捕获SqlException以获取消息并将其显示给用户。我对这种方法不满意,并想知道其他人如何处理来自存储过程的这些类型的用户消息。

14 个答案:

答案 0 :(得分:6)

我已经完成了这项工作,但通常会传递业务“错误”消息,实际上必须存在一个数据配置,无论出于何种原因,都无法使用标准FK约束强制执行。

如果它们实际上是“错误”,我没有太大的问题。如果它正在插入一条记录并使用RAISERROR投掷(“你已成功注册XYZ!”),那么你就遇到了问题。如果是这种情况,我可能会提出一个团队/部门/公司开发标准来使用参数。

答案 1 :(得分:4)

像这样使用RAISERROR真的不是一个好主意。这就像使用Exceptions作为流控制逻辑一样,这通常是不受欢迎的。

为什么不使用OUT参数?这正是它们的用途。我想不出不支持OUT参数的数据库或客户端API。

答案 2 :(得分:2)

使存储过程返回2组数据。第一个可以包含实际返回的数据,然后第二个可以返回文本消息。然后,您的应用程序代码可以使用所需的数据,然后显示返回的任何消息。

答案 3 :(得分:1)

回答这么久的问题是不好的形式? Anywho ...

对于你的日常状态信息,这将是一个坏事,我几乎同意上面的每一个答案。然而,我已经看到这非常有效地用于显示长批次中的进展。有关示例,请参阅Jens K的Getting feedback / progress from batches and stored procedures。你必须有一个非常聪明的理由这样做,但是当你需要它时,你需要它并且很棒。

答案 4 :(得分:1)

只有在情况异常并且您没有处理逻辑时才应抛出异常。提高和捕捉异常也很昂贵。

除非

,否则请避免使用例外
  1. 情况异常
  2. 您没有特殊情况的处理逻辑
  3. 使用输出参数或返回多个结果集来传递存储过程中的信息。

答案 5 :(得分:0)

我会尽量避免让我的存储过程返回与业务相关的消息,因为根据定义,这些消息可能应该在业务逻辑层中处理/生成。

例外应该是例外(不常见)。我只会将RAISEERROR用于错误(比如嘿我试图导入所有这些数据,其中一行有愚蠢的数据,所以我回滚了事务)。您还需要非常小心所引发的错误的严重性,这会对错误传播的方式以及连接发生的情况产生巨大影响。

如果这还不够,请尝试使用返回值或输出变量。

答案 6 :(得分:0)

我想如果你不介意检查列,那么你可以根据发生的事情返回不同的东西。

如果一切正常,请正常返回数据。 如果出现问题,请返回一个名为Error的列的结果,该列描述了什么是坏的。在处理数据之前检查此列的列名称并采取相应措施。

如果你真的反对RAISERROR,请离开我的头顶。

答案 7 :(得分:0)

我已经使用raiseerror从多个嵌套存储过程的深度返回,但是存储过程的最后一层总是在被引发到调用语言之前捕获异常(在我们的例子中是Java via JDBC)。最外层的存储过程catch被转换为XML消息以传输到JDBC调用,根据我们的约定,根元素必须包含反馈属性。反馈属性的值始终具有ok,alert或error的装饰器。好的意思是继续,没有什么可看的。警报意味着继续,但向用户显示其余的反馈。错误意味着平底船,请致电服务台。

答案 8 :(得分:0)

我将使用存储过程中的RETURN值,如下所示:

CREATE PROCEDURE checkReturnValue
AS
BEGIN
    DECLARE @err AS INT
    SET @err = 0

    IF (rand() < 0.5)
    BEGIN
        SET @err = 1
    END

    SELECT * FROM table

    PRINT @err

    RETURN @err
END

检查调用存储过程的应用程序中的RETURN值。

答案 9 :(得分:0)

仅当“业务”错误消息是数据库错误消息时,才会违反为满足数据库级别的基本低级业务需求而实施的数据库约束。

它不应该用于高级业务逻辑,应该在数据库层中避免使用。数据库层总是最慢的变化,因此只有非常缓慢变化和不变的业务逻辑应该存在。

对于有关非活动/已停用客户的订单的消息,可能是肯定的,但对于在90天内有余额的客户的订单则不行。第一条规则可能是永久性的,第二条规则可能是可配置的,可以按月进行业务调整。

答案 10 :(得分:0)

我们在发生错误时引发错误,并在输出变量或返回值中返回状态信息。

答案 11 :(得分:0)

您应该使用SQL存储过程输出参数。

来自http://msdn.microsoft.com/en-us/library/ms378108.aspx

CREATE PROCEDURE GetImmediateManager
   @employeeID INT,
   @msg varchar(50) OUTPUT
AS
BEGIN
   SELECT ManagerID 
   FROM HumanResources.Employee 
   WHERE EmployeeID = @employeeID

   SELECT @msg = 'here is my message'
END

答案 12 :(得分:-1)

如果之前无法检查/抓住,可能很难做其他任何事情。

我必须在我编写的过程中编写一个raiseerror,并将其用作插入/更新表的约束,因为它是数据的“最后一站”,我必须在那里检查它。

我认为一般来说,如果你从数据库中收到错误......它很难对付并且更难以给用户提供“好的”反馈而不需要付出很多努力,但有时候你只是不知道直到你插入/更新:P

答案 13 :(得分:-2)

我亵渎2美分:

基于文本的消息在Web上运行得非常好,例如HTTP。通过人类可读的文本完成消息传递,可以轻松创建,发送和调试系统。

因此,SQL Server层与其上层之间的消息传递可能相同。使用文本作为消息传递的一部分可能会使您的开发更加灵活,并且您的调试更容易。也许高级开发人员是务实的,你应该愿意放弃预先设想的正确概念。

根据自身的优点对设计选择进行辩论,而不是基于正确性的概念。 (软件开发也有时尚)