调试存储过程(以及编写易于调试的sprocs)的最佳方法是什么?

时间:2008-09-19 23:57:29

标签: .net sql stored-procedures

创建可以减少调试痛苦的sprocs有哪些好的方法?还有哪些工具用于调试存储过程?

也许最重要的是,有哪些迹象表明错误发生在sproc而不是代码中?我希望我在这里不是太糟糕了。投票回答上述任何一个问题。感谢。

对于它的价值,我在.NET环境中工作,SQL服务器。

13 个答案:

答案 0 :(得分:9)

我在存储过程中使用的一种技术,使SQL Server 2005过程更容易调试(没有IDE或调试器):

我在程序的参数列表的末尾添加了一个名为@Debug = 0的输入参数(默认为0 =关闭)。

然后我添加if(@Debug = 1)print'...';

关键接口代码中的语句,以显示任何有用的内部值等。

是的,这是“旧学校”和让你“走代码”的调试器很棒 - 但这适用于任何SQL工具的任何人(包括任何没有你同一个IDE的人调试)。

罗恩

答案 1 :(得分:8)

我用于简单日志输出和调试的另一种技术是在过程的顶部创建一个表变量:

   --**************************************************************************
   -- 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

在过程结束时 - 这取决于调用应用程序从过程调用中记录输出的程度,但我写的应用程序记录了所有内容。 : - )

答案 2 :(得分:6)

我强烈建议您查看SQL管理工作室中的内置工具。

我在这里写了一篇非常详细的博客文章:

http://www.diaryofaninja.com/blog/2010/11/23/debugging-sql-queries-function-amp-stored-procedures-with-sql-management-studio

基本上它的主旨是你输入sql查询来执行你的存储过程,而不是按F5或按下感叹号,你点击播放按钮并使用F10和F11逐步进入你的存储过程

非常方便 - 似乎没有人使用它。

答案 3 :(得分:3)

TSQLUnit

这是SQL Server的单元测试框架。这不是一个经典的调试工具,但它确实允许您为存储过程编写单元测试,这有助于识别错误并验证预期的行为。

例如,如果您有一个错误的存储过程,那么您可以编写一些单元测试来了解它是如何失败的。此外,如果您对SQL代码进行了更改,则可以验证您的更改是否会破坏其他任何内容,或至少告诉您问题所在。

如果某些内容难以测试,那么这可能是一个很好的迹象,表明您的存储过程可能会做得太多,并且如果将其分解为更多焦点和目标触发,则可能会受益。从长远来看,这些过程应该变得相对容易调试和维护。

答案 4 :(得分:3)

我注意到有很多关于使用不同环境和技术来调试SQL过程的建议,但没有人提到DBFit。如果您不熟悉FitFitNesse,请自己帮个忙看看。使用这三个工具,您可以快速构建一整套验收测试,让您高枕无忧,知道您可以重构而不受惩罚。

DBFit只是一系列可用于锻炼数据库的Fit Fixtures。使用Fitness,您可以在存储过程中编写尽可能多的调用排列,以便为其创建测试。

这本身并不是调试,但是一旦你针对单个存储过程进行了一整套测试,你会惊讶于你能够多快地查明问题。失败的测试将直接引导您解决问题,并为您提供失败的确切上下文,因此无需猜测。最重要的是,您现在可以毫无顾虑地重构存储过程,因为您只需重新运行测试以确保不会破坏任何内容。

答案 5 :(得分:2)

对于工具,您可以使用Visual Studio调试SP。 如果存储过程具有长逻辑,则可以重构它,创建单独的存储过程,并从主存储过程调用它。这将有助于缩小您的测试范围,并使您轻松找到哪些部分查询错误。

答案 6 :(得分:2)

这可能是个人偏好,但我发现读取全部被打到一条长行上的SQL查询非常困难。我更喜欢以下缩进样式:

SELECT
    [Fields]
FROM
    Table
WHERE
    x = x

在为全新的数据库模式编写存储过程时,这种简单的实践帮助了我很多。通过将语句分解为多行,可以更容易地识别查询中的错误的罪魁祸首。例如,在SQL Server Management Studio中,给出了异常的行号,因此您可以更快地定位有问题的代码。

对开发人员来说很容易......不要将一个SQL查询的800个字符塞进一行。如果数据库字段名称或数据类型发生变化且没有人向您发送电子邮件,您将会感谢自己。

答案 7 :(得分:1)

我见过的成功使用的几种模式是“诊断”或“测试”模式和日志记录。

当您执行动态SQL执行时,

测试或诊断模式非常有用。确保您可以看到要执行的内容。如果您有需要(或应该)检查错误的区域,请考虑记录到具有足够详细信息的表,以便您可以诊断发生了什么。

答案 8 :(得分:1)

你可以使用Sql server调试,但是我发现除了最直接的情况(在本地服务器上调试等)之外的任何事情都是痛苦的。我还没有找到比print语句更好的东西,所以我会感兴趣地监视这个帖子。

答案 9 :(得分:1)

以下是我今天重申的一些建议 - 如果您要在生产数据库的重要查询中添加连接,请确保在连接表中有空字段时它是安全的。

LEFT JOIN

我打破了一个重要的页面20分钟,然后才发现这是我的小型仓促程序更改。

确保在进行更改时测试程序。为此,我想在过程的注释中添加一个简单的测试查询。很明显,我今天未能做到这一点: - (

/************************************
  MyProcName

  Test:
  -----
  exec MyProcName @myParam
*************************************/

答案 10 :(得分:1)

这可能不是您正在寻找的答案,但如果您已经在.Net环境中,LINQtoSQL大大减少了我编写/使用/需要调试的存储过程的数量。

调试SQL的难度是LINQ编程业务逻辑是我新的首选实践的原因之一。

答案 11 :(得分:1)

SQL Server 2008 Management Studio的集成调试器逐步调试cinch(比较判断如何让VS2005 + SQL调试所需的柔道)

答案 12 :(得分:1)

与Ron的Logging类似,我们通过所有其他存储过程调用日志记录,以帮助跟踪所有调用。 始终使用常见的BatchId来允许跟踪某个批处理运行。 它可能不是最高效的过程,但它确实有助于追踪故障。 将摘要报告编译到电子邮件管理员也非常简单。

即。

Select * from LogEvent where BatchId = 'blah'

示例通话

EXEC LogEvent @Source='MyProc', @Type='Start'
, @Comment='Processed rows',@Value=50, @BatchId = @batchNum

Main Proc

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端集成到同一基础结构中将是有利的。