在 SQL Server 2008 中调试长动态 sql

发布于 2024-08-23 18:25:44 字数 641 浏览 9 评论 0原文

我有一些动态 sql 语句在某些条件下会崩溃,所以我正在尝试调试它。它是这样构建的:

declare @sql varchar(4000);
...
select @sql = '<part1>';
...
select @sql = @sql + '<part2>';
...
select @sql = @sql + '<part3>';
...
begin 
execute(@sql);
select @ec__errno = @@error
    if @ec__errno != 0
    begin
    if @@trancount != 0
    begin
    rollback;
    end
return @ec__errno;
end;
... 

正如我所说,它在循环的特定迭代中爆炸(不要问我为什么这样实现,我只是修复一个错误)并且我很难显示监视窗口中的字符串。我想我只得到前 255 个字符。监视 substring(@sql, 0, 200) 会导致无法评估“substring(@sql,0,200)”。请帮忙。我希望观察从 0 到 199、从 200 到 399 等的子字符串,然后将这个东西拼凑在一起,最后调试它。

我将不胜感激你的指点。谢谢!

I have some dynamic sql statement which bombs under certain conditions, so I am trying to debug it. it gets built like so:

declare @sql varchar(4000);
...
select @sql = '<part1>';
...
select @sql = @sql + '<part2>';
...
select @sql = @sql + '<part3>';
...
begin 
execute(@sql);
select @ec__errno = @@error
    if @ec__errno != 0
    begin
    if @@trancount != 0
    begin
    rollback;
    end
return @ec__errno;
end;
... 

As I said, it bombs in a particular iteration of a loop (don't ask me why it is implemented like this, I am just fixing a bug) and I am having a hard time displaying the contents of the string in a watch window. I think I am getting the first 255 characters only. Watching for substring(@sql, 0, 200) results in 'substring(@sql,0,200)' could not be evaluated. Please help. I was hoping to watch substrings from 0 to 199, from 200 to 399 and so on, and then piece this thing together and finally debug it.

I would appreciate pointers from you. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

北座城市 2024-08-30 18:25:44

当被迫在存储过程中使用动态 sql 时,我们执行以下操作。添加一个 debug 输入变量,它是一个位字段。如果它是 0,则 exec 语句将继续执行;如果它是 1,那么您将得到一条 print 语句。我建议你做一些类似的调试。不要执行,而是打印 SQL 的结果,或者可能将 SQl 插入到表中,因为它似乎是在循环中发生的。然后你可以查看构建的sql,看看哪里出了问题。

Declare debug bit
set debug = 1

...
if debug = 1 Begin     Print @SQL End
Else 
Begin Exec (@sql) End

或者

创建一个名为 mydynamiccode_logging 的表(其中一个 sql 列的长度与最大 sql 语句相同,一个 rundatecolumn 以及您可能认为必要的任何其他列(我会考虑用于组成 sql 语句的输入变量、用户、应用程序(如果多个应用程序使用这段代码)

在运行 exec 语句之前运行如下所示:

insert mydynamiccode_logging (sql, rundate)
values (@sql, getdate()) 

现在您还可以添加调试位字段,并且仅在将其更改为调试模式时才记录,或者您可以始终记录,具体取决于系统以及这需要多少额外时间以及系统的其余部分有多么严重,您不想通过日志记录显着减慢生产速度。

When forced to use dynamic sql in a stored proc, we do the following. add an input variable of debug which is a bit field. If it is 0, the exec statment will proces if it is 1 then you will get a print statement instead. I suggest you do something simliar to debug. Instead of executing, print the results of your SQL or possibly insert the SQl to a table since it seems to be happening in a loop. Then you can look over the sql that was built and see where it went wrong.

Declare debug bit
set debug = 1

...
if debug = 1 Begin     Print @SQL End
Else 
Begin Exec (@sql) End

Alternatively

Create a table called mydynamiccode_logging (with a sql column the same length as the max sql statment, a rundatecolumn and whatever other columns you might find necessary (I'd consider the input variables used to make up the sql statment, the user, the application if more than one uses this piece of code)

Before you run the exec statment run something like this:

insert mydynamiccode_logging (sql, rundate)
values (@sql, getdate()) 

Now you could also add the debug bit field and only log when you have changed it to debug mode or you could always log, depends on the system and how much extra time this takes to do and how slammed the rest of the system is. You don't want to slow prod down significantly by logging.

挽你眉间 2024-08-30 18:25:44

做这样的事情,它只会记录失败:

BEGIN TRY

    DECLARE @LogString   varchar(max)

    --record input parameters
    SET @LogString='@Param1='+COALESCE(''''+@Param1+'''','null')
                   +@Param2='+COALESCE(''''+@Param2+'''','null')
                   +@ParamDate='+COALESCE(''''+CONVERT(varchar(23),@ParamDate,121)+'''','null')
                   +@ParamInt='+COALESCE(''''+CONVERT(varchar(10),@Paramint)+'''','null')

    --build @SQL_String String here
    --repeat as necessary
    SET @LogString=ISNULL(@LogString)+'; '+.... --every logic twist record what is going on

    EXEC (@SQL_String)

END TRY
BEGIN CATCH

    IF XACT_STATE()!=0
    BEGIN
        ROLLBACK TRANSACTION
    END

    SET @LogString=ISNULL(@LogString,'')+'; '
                 +CASE WHEN ERROR_NUMBER()     IS NOT NULL THEN 'Msg '         +CONVERT(varchar(30),   ERROR_NUMBER()     ) ELSE '' END
                 +CASE WHEN ERROR_SEVERITY()   IS NOT NULL THEN ', Level '     +CONVERT(varchar(30),   ERROR_SEVERITY()   ) ELSE '' END
                 +CASE WHEN ERROR_STATE()      IS NOT NULL THEN ', State '     +CONVERT(varchar(30),   ERROR_STATE()      ) ELSE '' END
                 +CASE WHEN ERROR_PROCEDURE()  IS NOT NULL THEN ', Procedure ' +                       ERROR_PROCEDURE()    ELSE '' END
                 +CASE WHEN ERROR_LINE()       IS NOT NULL THEN ', Line '      +CONVERT(varchar(30),   ERROR_LINE()       ) ELSE '' END
                 +CASE WHEN ERROR_MESSAGE()    IS NOT NULL THEN ', '           +                       ERROR_MESSAGE()      ELSE '' END

    INSERT INTO ErrorLog Values (@SQL_String)
    INSERT INTO ErrorLog Values (@LogString)

    --will echo back the complete original error message for the calling application
    DECLARE @ErrorMessage nvarchar(400), @ErrorNumber int, @ErrorSeverity int, @ErrorState int, @ErrorLine int
    SELECT @ErrorMessage = N'Error %d, Line %d, Message: '+ERROR_MESSAGE(),@ErrorNumber = ERROR_NUMBER(),@ErrorSeverity = ERROR_SEVERITY(),@ErrorState = ERROR_STATE(),@ErrorLine = ERROR_LINE()
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine)

    RETURN 9999

END CATCH

do something like this, it will only log failures:

BEGIN TRY

    DECLARE @LogString   varchar(max)

    --record input parameters
    SET @LogString='@Param1='+COALESCE(''''+@Param1+'''','null')
                   +@Param2='+COALESCE(''''+@Param2+'''','null')
                   +@ParamDate='+COALESCE(''''+CONVERT(varchar(23),@ParamDate,121)+'''','null')
                   +@ParamInt='+COALESCE(''''+CONVERT(varchar(10),@Paramint)+'''','null')

    --build @SQL_String String here
    --repeat as necessary
    SET @LogString=ISNULL(@LogString)+'; '+.... --every logic twist record what is going on

    EXEC (@SQL_String)

END TRY
BEGIN CATCH

    IF XACT_STATE()!=0
    BEGIN
        ROLLBACK TRANSACTION
    END

    SET @LogString=ISNULL(@LogString,'')+'; '
                 +CASE WHEN ERROR_NUMBER()     IS NOT NULL THEN 'Msg '         +CONVERT(varchar(30),   ERROR_NUMBER()     ) ELSE '' END
                 +CASE WHEN ERROR_SEVERITY()   IS NOT NULL THEN ', Level '     +CONVERT(varchar(30),   ERROR_SEVERITY()   ) ELSE '' END
                 +CASE WHEN ERROR_STATE()      IS NOT NULL THEN ', State '     +CONVERT(varchar(30),   ERROR_STATE()      ) ELSE '' END
                 +CASE WHEN ERROR_PROCEDURE()  IS NOT NULL THEN ', Procedure ' +                       ERROR_PROCEDURE()    ELSE '' END
                 +CASE WHEN ERROR_LINE()       IS NOT NULL THEN ', Line '      +CONVERT(varchar(30),   ERROR_LINE()       ) ELSE '' END
                 +CASE WHEN ERROR_MESSAGE()    IS NOT NULL THEN ', '           +                       ERROR_MESSAGE()      ELSE '' END

    INSERT INTO ErrorLog Values (@SQL_String)
    INSERT INTO ErrorLog Values (@LogString)

    --will echo back the complete original error message for the calling application
    DECLARE @ErrorMessage nvarchar(400), @ErrorNumber int, @ErrorSeverity int, @ErrorState int, @ErrorLine int
    SELECT @ErrorMessage = N'Error %d, Line %d, Message: '+ERROR_MESSAGE(),@ErrorNumber = ERROR_NUMBER(),@ErrorSeverity = ERROR_SEVERITY(),@ErrorState = ERROR_STATE(),@ErrorLine = ERROR_LINE()
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine)

    RETURN 9999

END CATCH
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文