Отладка длинного динамического SQL в SQL Server 2008 - PullRequest
2 голосов
/ 02 марта 2010

У меня есть динамический 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 и так далее, а затем собрать эту штуку вместе и, наконец, отладить ее.

Буду признателен за указатели от вас. Спасибо!

Ответы [ 2 ]

5 голосов
/ 02 марта 2010

Когда вы вынуждены использовать динамический sql в хранимых процессах, мы делаем следующее.добавить входную переменную отладки, которая является битовым полем.Если оно равно 0, то exec statment будет обрабатываться, если оно равно 1, вместо этого вы получите оператор печати.Я предлагаю вам сделать что-то похожее на отладку.Вместо выполнения распечатайте результаты вашего SQL или, возможно, вставьте SQl в таблицу, поскольку это, кажется, происходит в цикле.Затем вы можете просмотреть созданный sql и увидеть, где он произошел.

Declare debug bit
set debug = 1

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

В качестве альтернативы

Создайте таблицу с именем mydynamiccode_logging (со столбцом sql такой же длины, что и для max sql).statment, rundatecolumn и любые другие столбцы, которые вы можете счесть необходимыми (я бы посчитал, что входные переменные, используемые для составления SQL-статистики, пользователя, приложения, если этот фрагмент кода используют несколько)

Довы запускаете exec statment и запускаете что-то вроде этого:

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

Теперь вы также можете добавить поле бит отладки и вести журнал только тогда, когда вы изменили его в режим отладки или вы всегда можете войти, зависит от системы исколько дополнительного времени уходит на это и как сильно ударила остальная часть системы. Вы не хотите существенно замедлять продвижение через регистрацию.

1 голос
/ 02 марта 2010

сделать что-то вроде этого, он будет регистрировать только сбои:

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