有什么好的方法可以创建可减少调试痛苦的存储过程?有哪些工具可用于调试存储过程?
也许最重要的是,有哪些迹象表明错误发生在存储过程中而不是代码中?我希望我在这里不是太糟糕了。投票选出以上任何一项的答案。谢谢。
对于它的价值,我在 .NET 环境中工作,SQL 服务器。
有什么好的方法可以创建可减少调试痛苦的存储过程?有哪些工具可用于调试存储过程?
也许最重要的是,有哪些迹象表明错误发生在存储过程中而不是代码中?我希望我在这里不是太糟糕了。投票选出以上任何一项的答案。谢谢。
对于它的价值,我在 .NET 环境中工作,SQL 服务器。
我在存储过程中使用的一种技术可以使它们更易于为 SQL Server 2005 过程调试(无需 IDE 或调试器):
我在过程的参数列表末尾添加了一个名为 @Debug = 0(默认为 0 = off)的输入参数。
然后我添加 if (@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
在过程结束时 - 这取决于调用应用程序记录您的过程调用输出的程度,但我编写的应用程序会记录所有内容。:-)
我强烈建议您查看 SQL 管理工作室中的内置工具。
我在这里写了一篇非常详细的博客文章:
基本上它的要点是你输入你的sql查询来执行你的存储过程,而不是按F5或点击感叹号,你点击播放按钮并使用F10和F11单步执行并进入你的存储过程。
非常非常方便 - 似乎没有人使用它。
这是 SQL Server 的单元测试框架。不完全是经典的调试工具,但它确实允许您为存储过程编写单元测试,这可以极大地帮助识别错误并验证预期的行为。
例如,如果您有一个有问题的存储过程,那么您可以编写一些单元测试来了解它是如何失败的。此外,如果您对 SQL 代码进行更改,您可以验证您的更改没有破坏其他任何内容,或者至少告诉您问题出在哪里。
如果某些东西很难测试,那么这可能是一个很好的迹象,表明您的存储过程可能做的太多,如果将其分解为更多焦点和目标的过程,可能会受益。从长远来看,这些过程应该变得相对更容易调试和维护。
我注意到很多关于使用不同环境和技术来调试 SQL procs 的建议,但没有人提到DBFit。如果您不熟悉Fit和FitNesse,请帮自己一个忙,然后查找它们。使用这三个工具,您可以快速为自己构建一整套验收测试,让您高枕无忧,因为您知道您可以毫无顾忌地进行重构。
DBFit 只是一系列 Fit Fixtures,可用于练习数据库。使用 Fitness,您可以将尽可能多的调用排列写入存储的过程中,因为您想为其创建测试。
这本身并不是调试,但您会惊讶于一旦您针对单个存储过程进行了整组测试,您可以多快地查明问题。失败的测试将直接引导您解决问题,并为您提供失败的确切上下文,因此无需猜测。最重要的是,您现在可以毫无畏惧地重构您的存储过程,因为您只需重新运行测试以确保您没有破坏任何东西。
这可能是个人喜好,但我发现阅读全部放在一条长线上的 SQL 查询非常困难。我更喜欢以下缩进样式:
SELECT
[Fields]
FROM
Table
WHERE
x = x
在为全新的数据库模式编写存储过程时,这个简单的实践帮助了我很多。通过将语句分成多行,可以更容易地识别查询中错误的罪魁祸首。例如,在 SQL Server Management Studio 中,给出了异常的行号,因此您可以更快地定位有问题的代码。
对您的开发人员同行要轻松...不要将 800 个字符的 SQL 查询塞到一行中。如果数据库字段名称或数据类型更改并且没有人给您发送电子邮件,您稍后会感谢自己。
对于工具,您可以使用 Visual Studio 来调试 SP。如果存储过程的逻辑很长,你可以重构它,创建单独的存储过程,然后从你的主存储过程中调用它。这也将有助于缩小您的测试范围,并让您轻松找到查询的哪一部分是错误的。
这是今天向我重申的一些建议 - 如果您要向生产数据库上的重要查询添加连接,请确保连接表中有空字段时它是安全的。
LEFT JOIN
在我们发现这是我的小而仓促的存储过程更改之前,我打破了一个重要页面 20 分钟。
并确保在进行更改时测试您的程序。为此,我喜欢在过程的注释中放置一个简单的测试查询。Obvisouly,我今天没能做到这一点:-(
/************************************
MyProcName
Test:
-----
exec MyProcName @myParam
*************************************/
这可能不是您正在寻找的答案,但如果您已经在 .Net 环境中,LINQtoSQL 已经大大减少了我编写/使用/需要调试的存储过程的数量。
调试 SQL 的困难是在 LINQ 中编写业务逻辑是我新的首选实践的原因之一。
SQL Server 2008 Management Studio 的集成调试器使逐步调试变得轻而易举(与弄清楚如何让 VS2005 + SQL 调试所需的柔道相比)
我看到成功使用的几种模式是“诊断”或“测试”模式和日志记录。
执行动态 SQL 执行时,测试或诊断模式很有用。确保您可以看到您将要执行的操作。如果您有需要(或应该)检查错误的区域,请考虑将日志记录到具有足够详细信息的表中,以便诊断正在发生的事情。
您可以使用 Sql 服务器调试,但我发现除了最直接的情况(在本地服务器上调试等)之外,这在任何情况下都是一种痛苦。我还没有找到比打印语句更好的东西,所以我会感兴趣地监视这个线程。
与 Ron 的日志记录类似,我们通过所有其他存储过程调用日志记录过程,以帮助跟踪所有调用。始终使用一个通用的 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 端集成到相同的基础架构中将是有利的。