2

我有一些动态 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)' could not be evaluated。请帮忙。我希望观察从 0 到 199、从 200 到 399 等等的子串,然后把这个东西拼凑起来,最后调试它。

我会很感激你的指点。谢谢!

4

2 回答 2

6

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

Declare debug bit
set debug = 1

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

或者

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

在运行 exec 语句之前,请运行如下内容:

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

现在您还可以添加调试位字段,并且仅在您将其更改为调试模式时进行记录,或者您可以始终记录,这取决于系统以及这需要多少额外时间以及系统其余部分的撞击程度。您不想通过记录显着减慢 prod。

于 2010-03-01T22:01:09.983 回答
1

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

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
于 2010-03-01T22:12:44.210 回答