SQL尝试捕获目的不清楚

时间:2010-06-10 13:10:09

标签: sql try-catch

假设我想告知应用程序SQL服务器发生了什么/返回了什么。我们有这个代码块:

BEGIN TRY
    -- Generate divide-by-zero error.
    SELECT 1/0;
END TRY
BEGIN CATCH
     SELECT 
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() as ErrorState,
        ERROR_PROCEDURE() as ErrorProcedure,
        ERROR_LINE() as ErrorLine,
        ERROR_MESSAGE() as ErrorMessage;
END CATCH;
GO

让我们有这个代码块:

SELECT 1/0;

我的问题是: 两者都返回除以零错误。我不明白的是,当我在两种情况下都得到错误时,为什么我应该用try catch clausule包围它? 这两个错误都会传播到客户端应用程序,这不是真的吗?

5 个答案:

答案 0 :(得分:3)

是的,尝试捕获的唯一原因(如在普通代码中)是如果您可以“处理”错误,即您可以纠正错误并成功完成该过程被执行的任何功能,或者,如果想在将错误返回给客户端之前对错误做些什么(比如修改消息,或者将其存储在错误日志表中或向某人发送电子邮件等等)(尽管我更愿意做大部分的事情来自DAL层)

但从技术上讲,catch子句不会返回错误。它只是返回一个包含错误信息的结果集。这是非常不同的,因为它不会在客户端代码中导致异常。这就是为什么你的结论是正确的,你应该让原始错误直接传播回客户端代码。

正如您所写的那样,不会向客户端返回任何错误。与普通代码一样,如果您不处理(纠正)catch子句中的错误,则应始终在catch子句中重新抛出它(在sql中表示Raiserror函数)。您上面所做的一般都很糟糕,客户端代码可能有也可能没有任何正确处理的能力 一个完全不同的记录集(一个有错误信息)来自它的期望。某些调用(如插入更新或删除)可能根本不期望或正在寻找返回的记录集...相反,如果您希望或需要在将其返回到客户端之前对过程中的错误执行某些操作,请使用{{ 1}}功能

Raiserror()

答案 1 :(得分:1)

  

两者都将除法返回零   错误。

是的,但使用不同的返回路径。

不同之处在于,在第一个示例中,您正在预测错误并以某种方式处理错误。错误作为常规结果进入应用程序 - 它不会通过错误处理机制传播。实际上,如果应用程序看起来不是特定的结果形状,那么它可能不知道发生了错误。

在第二个实例中,错误通常会通过错误报告机制(例如异常)传播到您的应用程序。这将中止操作。这有多大影响将取决于应用程序的异常处理。也许它会中止当前操作,或者整个应用程序可能会失败,具体取决于应用程序的设计和对异常的容忍度。

您可以选择对您的应用程序有意义的内容。应用程序可以有意义地处理错误 - 如果是这样,传播错误(第二个示例),或者最好在查询(第一个示例)中处理,并通过返回默认结果(例如空行集)来“平滑”错误。

答案 2 :(得分:1)

当try部分中的所有内容都是select时,尝试Catch不是很有用。但是,如果您有一个包含多个步骤的事务,则使用catch块来回滚所有步骤,并可能记录有关在日志中导致问题的原因的详细信息。但最重要的部分是回滚以确保数据完整性。

如果你在Try块中创建动态SQl,那么记录失败的动态SQl变量和传入的任何参数也是有帮助的。这可以帮助解决一些难以捕获的问题,“我们没有任何了解用户实际做了什么导致问题“错误。

答案 3 :(得分:0)

不,通过在TRY / CATCH块中执行Select 1/0,select语句不返回任何内容,catch块中的select语句正常显示错误详细信息。查询成功完成 - 不会抛出任何错误。

如果您自己运行Select 1/0,则查询无法成功完成 - 它会因错误而爆炸。

在SQL中使用catch块使您有机会在那里做一些事情,然后不仅让错误冒泡到应用程序。

您看到错误详细信息的唯一原因是您正在选择它们。如果Catch块中没有代码,您将看不到任何错误信息。

答案 4 :(得分:0)

使用第一种方法,您不会直接从SQL Server获取错误

第二种方法可能会停止执行其后的语句

所以你最好提前发现它