2010-06-10 53 views
1

假设我想告诉应用程序发生了什么/返回了SQL服务器。我们有这样的代码块:SQL尝试catch目的不清楚

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来包围它? 是不是这个错误会在两种情况下传播到客户端应用程序?

回答

3

是的,Try Catch的唯一原因是(如在普通代码中),如果您可以“处理”错误,即,你可以纠正错误并成功地完成程序的任务功能,或者如果想在错误返回给客户端之前做一些事情(比如修改消息,或者将它存储在错误日志表中或者发送给别人一封电子邮件等(尽管我更喜欢从DAL层中完成大部分工作)

然而,从技术上说,catch子句并没有返回错误,它只是返回带有错误信息的结果集。这是非常不同的,因为它不会导致客户端代码中的异常。这就是为什么你的结论是正确的,ou应该让原始错误直接传播回客户端代码

正如你所写,没有错误将被返回给客户端。如在普通代码中,如果哟你不要在catch子句中处理(纠正)错误,你应该总是在catch子句中重新抛出它(在sql中意味着Raiserror函数)。上面所做的一般情况是不好的,客户端代码可能会或可能没有任何能力来正确处理与预期完全不同的记录集(一个带有错误信息的记录集)。某些调用(如插入更新或删除)可能根本没有预期或正在查找返回的记录集......而是,如果您希望或需要在将过程中的错误返回给客户端之前对其进行处理,请使用Raiserror()函数

BEGIN TRY 
    -- Generate divide-by-zero error. 
    SELECT 1/0; 
END TRY 
BEGIN CATCH 
    -- Other code to do logging, whatever ... 
    Raiserror(ERROR_MESSAGE(), ERROR_NUMBER(), ERROR_STATE()) 
END CATCH; 
+0

好的,你已经非常清楚地解释了..另一个问题:为什么你更喜欢在DAL中完成所有这些'捕捉函数'? – 2010-06-10 14:59:35

+0

,因为通常这些类型的事件(记录错误,仪表,追踪,操作人员的某些问题的通知等)被称为“交叉问题”,可能发生在任何系统模块中,而不仅仅是数据库..因此,从整体系统的角度来看,将这种功能置于可从系统中的任何地方访问的代码模块中,而不仅仅是从数据库中更有意义... – 2010-06-10 15:11:25

+0

如果我想要某个方面导致记录被保存在数据库中,我会将该模块的代码写回数据库作为它的一个任务... – 2010-06-10 15:12:19

0

不,通过在TRY/CATCH块中执行Select 1/0,select语句不会返回任何内容,并且catch块中的select语句将优雅地显示错误详细信息。查询成功完成 - 不会引发错误。

如果您自己运行Select 1/0,则查询无法成功完成 - 它会弹出一个错误消息。

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

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

1

两者都返回零除 错误。

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

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

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

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

0

使用第一种方法,你不会从SQL Server得到的错误直接

第二种方法可以提前

停止它后面

所以最好的语句,你抓住它的执行

1

尝试抓住是不是有用的,当你所有的尝试部分是一个选择。但是,如果您有多个步骤的事务,则使用catch块将所有步骤回滚并可能记录有关导致日志中问题的原因的详细信息。但最重要的部分是确保数据完整性的回滚。

如果您要在Try块中创建动态SQl,那么记录动态SQl变量失败并传入任何参数也会有帮助。这可以帮助解决一些难以捕捉的问题,“我们没有任何想法是什么用户实际上造成的问题“的错误。