C# 我应该在T-SQL中设置错误处理吗?

C# 我应该在T-SQL中设置错误处理吗?,c#,.net,sql-server,tsql,C#,.net,Sql Server,Tsql,作为开发人员,错误处理和try/catch是我编写的代码中非常重要的一部分 但是,在SQL Server存储过程中,在SP中写入错误处理是否是最佳做法?如果没有(这似乎是常见情况),异常是否会传播到.NET代码?我问这个问题是因为我觉得T-SQL的行为就像C#错误处理 在T-SQL中编写错误处理的最佳方法是什么?是的,在TSQL代码中使用。在这种情况下,该异常不会传播给客户端 无论何时使用或处理未处理的SQL异常,都会发生传播 BEGIN TRY SELECT Foo FROM MyL

作为开发人员,错误处理和try/catch是我编写的代码中非常重要的一部分

但是,在SQL Server存储过程中,在SP中写入错误处理是否是最佳做法?如果没有(这似乎是常见情况),异常是否会传播到.NET代码?我问这个问题是因为我觉得T-SQL的行为就像C#错误处理

在T-SQL中编写错误处理的最佳方法是什么?

是的,在TSQL代码中使用。在这种情况下,该异常不会传播给客户端

无论何时使用或处理未处理的SQL异常,都会发生传播

BEGIN TRY
     SELECT Foo FROM MyLinkedServer.dbo.SomeTable; --what if the remote server is down?

     DECLARE @Baz uniqueidentifier  = 15/2; --oops        
END TRY
BEGIN CATCH
    SELECT @Baz = NEWID();
    ROLLBACK TRAN; 
    --whatever business logic you have for handling your exception.
END CATCH

我喜欢在我的SQL和代码库中保留尽可能多的逻辑。涉及“如果发生此异常,我希望执行此操作”的逻辑听起来像是我希望在代码中包含的逻辑

因此,我通常会让异常传播到代码中,并在那里处理它


另一方面,根据我的经验,人们使用try/catch的次数太多了。只有在出现错误的情况下,您确实需要采取不同的措施时,才能尝试/捕获。如果您只想应用一般的错误日志类型代码,那么让它一直传播到顶部,并在一个地方处理它。更糟糕的是,当人们在代码中乱扔try/catch时,这些try/catch会毫无理由地吞下异常

我不知道有黑白两种选择。总是有权衡的

除非有明确的恢复行动,否则我看不出有什么意义

如果数据库由多个客户机共享,这可能是有意义的。否则将迫使每个客户机实现错误处理逻辑。在这种情况下,问题是应该将什么发送回客户机?当然,他们应该知道发生了什么以及为什么

答案将取决于您是DBA还是中间层开发人员。每个人都可能认为责任最好留给他们。

视情况而定

通常情况下,如果它是一个非常包容的存储过程,可以处理几乎所有的逻辑分支工作,那么我肯定会捕获错误,并在该存储过程中相应地处理它们


但有时,如果只是一个快速调用或查询,我会让错误浮出水面,让应用程序“轻松”地读取错误并处理应用程序代码。

我的首选是让数据库针对“坏”数据进行自我保护。(有一次,一位设计自动化机器的控制工程师建议我应该针对10%的坏数据进行设计。Oy。)因此,我尝试使用索引、外键、约束和触发器来捕获我能捕获的数据。所有访问都是通过存储过程进行的,可以让或让向导玩SSM

在存储过程中,我不太担心语句失败,而是担心发生的事情是否有意义。输入验证非常常见,通常包括:

-- Validate the input.
if @Serial is NULL
    begin
    rollback transaction
    RaIsError( '@Serial   cannot be   NULL .', 13, 0 )
    return
    end
set @TelephoneNumber = LTrim( RTrim( @TelephoneNumber ) )
if @TelephoneNumber is NULL or @TelephoneNumber = ''
    begin
    RaIsError( '@TelephoneNumber   must be supplied.', 13, 0 )
    return
    end
(旁白:当使用Sun god boo boo,RaIsError时,严重性需要大于等于11才能将SQL异常抛出到.NET。也许我们都可以插手,为微软买一个元音。)


同样,我会根据需要检查中间结果。例如,如果我应该查找一些现存的和唯一的内容,但发现行数不是一,那么我会退出。

只有在适当的情况下才“应该”。请阅读这篇由Erland Sommarskog撰写的文章,SQL Server MVP:@p.campbell我同意-也许是适当(而不是)的一个很好的解释案例场景会很有帮助。这样做可能有什么好处?除非你真的在处理这个错误(也就是说,它不是SQL中的一个bug),否则我觉得还是让这个(未处理的)错误爆炸调用者为好。@Kirk我愚蠢的演示代码没有多大意义。也许您想回滚事务。也许你想发送一些SQLMail。也许您想在另一个链接服务器中查找一些数据。也许你想把它记录在审计表中。谢谢你的回复,很公平。(虽然我真的同意Dylan的说法,业务逻辑不属于这里)业务逻辑可能属于也可能不属于,但处理实际的SQL Server错误(即使是数据类型不匹配、数学错误等)肯定属于这里。通常,我使用
TRY…CATCH
块来记录数据库端需要发生的其他事情,如日志记录、回滚等,然后说“嘿,这里发生了什么事!“。我们捕获错误,然后将错误报告给调用方,并让他们以自己的方式处理它。@Wil,IMO,您提到的所有内容最好在调用站点上实现,而不是在SQL中实现。我宁愿在调用站点上登录。我宁愿在调用站点上回滚。无论调用方如何处理错误,都会返回错误,为什么在运输过程中?