2010-03-01 3 views
1

특정 조건에서 폭탄을 사용하는 일부 동적 SQL 문이 있으므로 디버깅하려고합니다. 그것과 같이 내장됩니다 :SQL Server 2008에서 긴 동적 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까지 보는 것을 희망하고 있었다. 그리고 나서이 것을 하나로 모아서 마침내 디버깅하기를 바랬다.

나는 당신에게서 포인터를 평가할 것입니다. 감사!

+3

을 당신이 동적 SQL은 종종 나쁜 생각 하나의 이유를 발견보세요! – HLGEM

+0

분명히 그런 식으로 보일지 모르지만 틀림없이 경직된 SQL은 읽기가 더 어려울 때가 있습니다 :) - SQL 테이블에 쌓인 다양한 모양의 나무와 같은 것들로 작업하는 것을 상상해보십시오. –

+0

나는 그다지 읽을 수 없다는 것을 의미하지 않았다. 단지 디버깅하는 데 어려움이 있었고 가능한 모든 조건에서 디버깅하는 것이 불가능하다는 것을 의미했다. – HLGEM

답변

4

저장 프로 시저에서 동적 SQL을 사용하도록 강제 할 때 다음을 수행합니다. 비트 필드 인 디버그의 입력 변수를 추가하십시오. 0이면 exec 명령이 1이면 처리하고 대신 print 문을 얻습니다. 나는 당신이 simliar 디버깅을 할 것을 제안한다. 실행하는 대신 SQL의 결과를 인쇄하거나 SQl을 루프에 삽입하는 것처럼 보이는 테이블에 삽입 할 수 있습니다. 그런 다음 빌드 된 SQL을 살펴보고 잘못 된 위치를 볼 수 있습니다. 또한

는 SQL 열 당신이 필요 찾을 수있는 최대의 SQL 한 Statment하는 rundatecolumn 및 어떤 다른 컬럼과 동일한 길이의 테이블라는 mydynamiccode_logging을 (만들기 (내가 생각 하는데요 입력 변수를 사용

Declare debug bit 
set debug = 1 

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

하나 이상이 코드 조각)

를 사용하는 경우는 SQL 한 Statment, 사용자, 응용 프로그램을 만들려면이 같은 것을 실행 간부 한 Statment 실행하기 전에 :

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

이제 디버그 비트 필드를 추가하여 디버그 모드로 변경하거나 시스템에 따라 로그 할 수있는 시간과 로그의 남은 시간 및 시스템의 나머지 부분이 . 로깅을 통해 생산성을 크게 떨어 뜨리고 싶지는 않습니다.

+0

아, 아주 멋지다! 환경을 감지 할 수있는 기회가 있습니까? #if 디버그 ... #endif, 또는 __name__ == '__main__'(파이썬)과 유사합니까? 동적 SQL을 실행하기 전에 print 문을 추가하고 싶습니다. "in debug"에서 "in production"과 반대되는 경우. 이 일을 할 수있는 방법이 있습니까? –

+1

'PRINT'문제는 프로덕션 환경에서 캡처하는 것이므로 재현하기 어려운 문제에서 중요합니다. –

+0

프로덕션 환경에서 인쇄를 실행하지 않습니다. 나는 찌르다가 디버그하려고하지 않을 것이다. @sql을 테이블 (입력 변수와 datetime으로 exec를 실행하기 전에 항상 보내도록 코드를 추가한다고 가정 해 보겠습니다. 그러면 보낸 모든 내용이 자동으로 기록되며 문제를 찾기 위해 테이블을 살펴볼 수 있습니다. 오류가 발생하면 실행 시간에 어떤 영향을 미치는지보아야합니다. – HLGEM

1

이 같은 것을 할, 그것은 단지 실패를 기록합니다

BEGIN TRY 

    DECLARE @LogString varchar(max) 

    --record input parameters 
    SET @LogString='@Param1='+COALESCE(''''[email protected]+'''','null') 
        [email protected]='+COALESCE(''''[email protected]+'''','null') 
        [email protected]='+COALESCE(''''+CONVERT(varchar(23),@ParamDate,121)+'''','null') 
        [email protected]='+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 
+0

흥미 롭습니다 ... 우리는 가능한 한 빨리 SQL을 유지하려고 노력합니다.이 특정 수정의 영향은 무엇입니까? –

+1

거기에는 INSERT가 실패 할 때만 문자열 연결이 몇 개 있습니다. 나는 그것이 그렇게 많이 상처를 줄 것이라고 상상할 수 없다. 폭파중인 절차에 포함 시키면 문제를 디버그하는 데 필요한 모든 정보를 얻을 수 있습니다. 그런 다음 주석을 달 수 있습니다. –

+0

느린 코드는 항상 깨진 코드보다 빠릅니다. – BradC

관련 문제