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

时间:2020-03-06 14:19:09  来源:igfitidea点击:

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

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

解决方案

如果无法尽早检查/发现,可能很难做其他事情。

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

我认为通常来说,如果我们正在从数据库中获取错误,这是一个痛苦的过程,并且不费吹灰之力就很难向用户提供"不错的"反馈,但是有时候我们只是不知道,直到我们插入/更新:P

我会尽量避免使我的存储过程返回"业务相关"消息,因为按照定义,这类消息可能应该在业务逻辑层中进行处理/生成。

受精应该是例外的(很少)。我只会将RAISEERROR用作错误信息(例如,嘿,我尝试导入所有这些数据,并且其中一行包含愚蠢的数据,因此我回滚了事务)。我们还需要非常小心所引发的错误的严重性,这可能会对错误的传播方式以及连接发生什么产生巨大影响。

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

我亵渎的2美分:

基于文本的消息在Web上非常有效,例如HTTP。创建,发送,调试系统很容易,其中消息以易读的文本形式完成。

因此,SQL Server层与其上一层之间的消息传递可能是相同的。将文本用作消息传递的一部分可能使开发更加敏捷,调试也更加容易。也许高级开发人员很务实,我们也许应该放开先入为主的正确性概念。

无需根据正确性概念就设计选择进行辩论。 (软件开发中也有时尚)

我想如果我们不介意检查列,那么我们可以根据发生的情况返回不同的内容。

如果一切正常,请照常返回数据。
如果有问题,则返回带有错误的列的结果,该列描述了错误的内容。在处理数据并采取相应措施之前,请检查此列的列名称。

如果我们真的反对RAISERROR,请放下我的脑海。

我已经做到了,但是通常是传递业务"错误"消息,从本质上来说,无论出于何种原因,都必须采用标准FK约束无法实施的数据配置。

如果它们实际上是"错误",那么我对此并没有太大的问题。如果插入记录并使用RAISERROR引发("我们已成功注册XYZ!"),则说明我们遇到了问题。如果是这样,我可能会提出一个使用参数的团队/部门/公司开发标准。

我已经使用了raiseerror从多个嵌套存储过程的深度中返回,但是存储过程的最后一层在被提升为调用语言之前(在我们的情况下是通过JDBC的Java),总是会捕获异常。最外层的存储过程捕获将转换为XML消息,以传输到JDBC调用,并且根据我们的约定,根元素必须包含feedback属性。 feedback属性的值始终具有ok,alert或者error修饰符。确定意味着继续,这里什么也看不到。警报意味着继续进行,但会将其余反馈显示给用户。错误是指平底船,请致电服务台。

像这样使用RAISERROR确实不是一个好主意。就像使用Exceptions作为流控制逻辑一样,通常对此不屑一顾。

为什么不使用OUT参数呢?那正是他们的目的。我想不出不支持OUT参数的数据库或者客户端API。

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

我将使用存储过程中的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值。

仅当"业务"错误消息是数据库错误消息时,在某种意义上已经违反了数据库约束以满足数据库级别的基本低层业务要求。

它不应用于高级业务逻辑,而应在数据库层中避免使用。数据库层始终是最慢的更改,因此仅应包含非常缓慢的更改和不变的业务逻辑。

因此,对于非活动/禁用客户的订单消息,可能是肯定的,但对于90天之内有余额的客户的订单却不是。第一条规则可能是永久性的,第二条规则可能是可配置的,但要按每月的业务需求进行调整。

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

我们应该使用SQL存储过程的输出参数。

从http://msdn.microsoft.com/zh-cn/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

这么老的问题回答不好吗?谁

对于日常状态消息,这将是一件坏事,我几乎同意上述所有答案。但是,我已经看到它非常有效地用于显示长时间批处理中的进度。有关示例,请参阅Jens K从批处理和存储过程中获取反馈/进度。我们必须有一个相当严格的理由来做到这一点,但是当我们需要它时,就需要它,它很棒。

仅当异常情况且我们没有处理逻辑时,才应引发异常。引发和捕获异常的代价也很高。

避免使用异常,除非

  • 情况很特殊
  • 我们没有特殊情况的处理逻辑

使用输出参数或者返回多个结果集以从存储过程传递信息。