调试存储过程(以及编写易于调试的sproc)的最佳方法是什么?
有什么好的方法可以创建可减轻调试麻烦的存储过程?还有哪些工具可用于调试存储过程?
也许最重要的是,有什么迹象可以表明错误是在存储过程中发生的,而不是在代码中发生的?我希望我在这方面不会太糟糕了。投票给以上任何一个答案。谢谢。
对于它的价值,我在.NET环境中工作,即SQL服务器。
解决方案
我已经看到成功使用的两种模式是"诊断"或者"测试"模式以及日志记录。
在执行动态SQL执行时,测试或者诊断模式非常有用。确保我们可以看到要执行的内容。如果我们有需要(或者应该)检查错误的区域,请考虑将日志记录到具有足够详细信息的表中,以便我们可以诊断正在发生的情况。
我们可以使用Sql服务器调试,但是我发现,除了最直接的情况(在本地服务器上调试等)之外,这在任何情况下都是一个痛苦。我还没有找到比打印语句更好的东西,因此我将有兴趣地监视此线程。
对于工具,可以使用Visual Studio调试SP。
如果存储过程具有较长的逻辑,则可以对其进行重构,创建单独的存储过程,然后从主存储过程中调用它。这也将有助于缩小测试范围,并简化查找错误查询部分的过程。
TSQLUnit
这是SQL Server的单元测试框架。不完全是经典的调试工具,但它确实允许我们为存储过程编写单元测试,这可以极大地识别错误并验证预期的行为。
例如,如果存储过程中有错误,则可以编写一些单元测试来了解它是如何失败的。另外,如果我们对SQL代码进行了更改,则可以验证所做的更改没有破坏其他内容,或者至少告诉我们问题出在哪里。
如果某项内容很难测试,则可能很好地表明我们存储的proc可能做得太多,并且可以将其分解为更多的关注和目标proc来受益。从长远来看,这些proc应该会变得相对更容易调试和维护。
如果要将联接添加到生产数据库中的重要查询中,今天向我重申了一些建议,请确保在联接表中存在空字段时该联接是安全的。
LEFT JOIN
我弄断了重要页面20分钟,然后才发现这是我匆忙进行的小型存储过程更改。
并确保在进行更改时测试程序。为此,我想在过程注释中添加一个简单的测试查询。显然,我今天没有做到这一点:-(
/************************************ MyProcName Test: ----- exec MyProcName @myParam *************************************/
我在存储过程中使用的一种技术使它们更易于调试(没有IDE或者调试器)以用于SQL Server 2005过程:
我在该过程的参数列表的末尾添加了一个名为@Debug = 0(默认为0 = off)的输入参数。
然后添加(@Debug = 1)print'...';
关键时刻代码中的语句,以显示任何有用的内部值等。
是的,它是"老派",并且允许我们"遍历代码"的调试器很棒,但这适用于使用任何SQL工具的任何人(包括使用相同IDE进行调试的任何人)。
罗恩
我用于简单日志输出和调试的另一种技术是在过程顶部创建一个表变量:
--************************************************************************** -- Create a log table variable to store messages to be returned to the -- calling application. --************************************************************************** declare @log as table ( msg varchar(MAX) ); then insert into @log values ('Inserted a new DVO Order into IRMA, order id: [' + convert(varchar(10), @@IDENTITY ) + ']'); etc. then ... select msg from @log; end
在过程结束时,这取决于调用应用程序记录过程调用输出的情况,但是我编写的应用程序记录了全部过程。 :-)
这可能不是我们要寻找的答案,但是如果我们已经处于.Net环境中,则LINQtoSQL大大减少了我编写/使用/需要调试的存储过程的数量。
调试SQL的困难是我在LINQ中编程业务逻辑是我的新首选做法的原因之一。
我注意到有关使用不同的环境和技术调试SQL proc的许多建议,但是没有人提到DBFit。如果我们不熟悉Fit和FitNesse,请帮个忙,看看他们。使用这三个工具,我们可以快速构建一套完整的验收测试,让我们放心地知道自己可以不受惩罚地进行重构。
DBFit只是一系列健身器材,可用于练习数据库。使用Fitness,我们可以为要创建测试的呼叫在存储的proc上写入尽可能多的调用排列。
这本身并不是调试,但是一旦对单个存储的proc进行了完整的测试,我们会以多快的速度查明问题,我们会感到惊讶。测试失败会直接导致我们遇到问题,并为我们提供失败的确切背景,因此我们无法进行猜测。最重要的是,我们现在可以不用担心就可以重构存储的proc,因为我们只需要重新运行测试以确保我们没有破坏任何东西即可。
SQL Server 2008 Management Studio的集成调试器使逐步调试变得容易(比较柔道以确定如何获取VS2005 + SQL进行调试)
这可能是个人喜好,但是我发现读取全部排成一行的SQL查询非常困难。我更喜欢以下缩进样式:
SELECT [Fields] FROM Table WHERE x = x
当为全新的数据库模式编写存储过程时,这种简单的实践对我有很大帮助。通过将语句分成多行,可以更轻松地确定查询中错误的元凶。例如,在SQL Server Management Studio中,给出了异常的行号,因此我们可以更快地定位有问题的代码。
对其他开发人员要容易一点……不要将SQL查询的800个字符填入一行。如果数据库字段名称或者数据类型更改并且没有人通过电子邮件发送给我们,稍后我们将感激不尽。
与Ron的日志记录类似,我们通过所有其他存储过程调用日志记录proc,以帮助跟踪所有调用。
整个过程中都使用通用的BatchId,以允许跟踪特定的批处理运行。
它可能不是性能最高的过程,但确实有助于跟踪故障。
将摘要报告编译为电子邮件管理员也非常简单。
IE。
Select * from LogEvent where BatchId = 'blah'
样品电话
EXEC LogEvent @Source='MyProc', @Type='Start' , @Comment='Processed rows',@Value=50, @BatchId = @batchNum
主程序
CREATE PROCEDURE [dbo].[LogEvent] @Source varchar(50), @Type varchar(50), @Comment varchar(400), @Value decimal = null, @BatchId varchar(255) = 'BLANK' AS IF @BatchId = 'BLANK' SET @BatchId = NEWID() INSERT INTO dbo.Log (Source, EventTime, [Type], Comment, [Value],BatchId) VALUES (@Source, GETDATE(), @Type, @Comment, @Value,@BatchId)
继续前进,可以利用CLR并希望通过SQL调用Log4Net之类的东西。由于我们的应用程序代码使用Log4Net,因此将进程的SQL端集成到同一基础结构中将是有利的。
我强烈建议我们看一下SQL Management Studio中的内置工具。
我在这里写了一篇非常详细的博客文章:
http://www.diaryofaninja.com/blog/2010/11/23/debugging-sql-queries-function-amp-stored-procedures-with-sql-management-studio
基本上,要点是我们输入sql查询来执行存储过程,而不是按F5或者单击感叹号,而是单击播放按钮并使用F10和F11逐步进入存储过程。
非常非常方便,似乎没有人使用它。