2016-06-30 3 views
0

내 목표는 SQL 쿼리에서 오류 메시지를 캐치하거나 로그 또는 인쇄 한 다음 실제 오류를 생성하는 대신 전달하는 것입니다. 그러나 나는 그것이 검사 질의로부터 다중 오류를 잡는 것이 불가능하다는 것을 발견했다; 마지막 오류가 잡힐 것단일 쿼리에서 여러 오류를 반환하는 방법

DECLARE @ErrorMessage varchar(1000) 
BEGIN TRY 
    EXEC('SELECT AA,BB FROM TABLE')--neither column AA nor BB exists 
END TRY 
BEGIN CATCH 
SET @ErrorMessage = 'ERRORMESSAGE: ' + Error_Message() 
PRINT @ErrorMessage 
END CATCH 

쿼리는 열 BB를 찾을 수없는 피드백을 제공하지만, 그 AA 칼럼도 존재하지 않는 표시 할 수 없습니다.

또는 다른 예, TRY 블록이 쿼리를 넣어

EXEC('CREATE SCHEMA abc AUTHORIZATION [dbo]') --schema abc already exists 

그것은 acutally ', 스키마를 만들 수 없습니다 이전 오류를 참조'다음 다른 오류가 먼저 '스키마가 이미 존재'오류가 발생합니다,하지만 지금은 키 정보가 포함 된 첫 번째 키 오류가 '먹었습니다'.

그러면 오류 메시지를 모두 표시하는 방법은 무엇입니까?

+3

사실, 나는 그것이 아니라 마지막 * 첫째 * 오류를 잡는다 생각합니다. 오류에서 복구하지 않으면 엔진이 처리를 계속할 수 없습니다. –

+0

@ GordonLinoff가 정확합니다. 첫 번째 오류가 발생하면 엔진은 더 이상 처리하지 않습니다. 따라서 여러 오류를 포착하는 것에 대해 걱정할 필요가 없습니다. – Sam

+0

@GordonLinoff. 네, 여러 쿼리가 있으면 첫 번째 쿼리에서 중지됩니다; 내 일은 여러 개의 오류를 생성하는 단일 쿼리입니다 (예 : 내 expample, 스키마 생성 또는 SP 또는 EXEC (@query)를 사용하여 포함 된 쿼리가 한 번에 두 개의 잘못된 열을 선택 함). – a4194304

답변

1
    당신은 여전히 ​​권리에 대한 ERROR_MESSAGETRY-CATCH이 쿼리의 강력한 특성을 제거 할 수있는 방법 그러나 이것은 단지 발생

이반이 RAISERROR INSIDE TRY-CATCH 블록을 사용 CAN

  • 때 메시지의 SEVERITY TRY 블록에서 10을 초과합니다. 트릭 (11)

    에서 심각도를 설정하는 것입니다 그래서 RAISERROR가 실행되면 오류가 호출자에게 반환됩니다

    • 어떤 TRY 블록의 범위를 벗어난다.
    • TRY 블록에서 심각도가 10 이하입니다.
    • 심각도가 20 이상이고 데이터베이스가 종료됩니다 ( ). MSDN - RAISERROR

    RAISERROR

  • PRINT 대용으로 사용 및 사용자 정의 메시지를 허용 할 수 있습니다. STATE 다른 숫자로 설정하여 코드에서 유사하지만 다른 오류를 추적 할 수 있습니다.

    치명적인 오류가 발생할 수 있으므로 실행하기 전에 쿼리 및 DDL 명령을 테스트하는 것이 좋습니다.예를 들어, 대신에 맹목적으로 EXEC('CREATE SCHEMA abc AUTHORIZATION [dbo]')을 시도하는 대신이 임시 메시지를 시도 할 수 있습니다 :

    DECLARE @SCHEMA NVARCHAR(10) 
    DECLARE @Message NVARCHAR(255) 
    SET @SCHEMA = N'abc' 
    SET @Message = N'The Schema ' + @SCHEMA + ' already exists.' 
    
    IF SCHEMA_ID(@SCHEMA) IS NOT NULL 
    EXEC('CREATE SCHEMA abc AUTHORIZATION [dbo]') 
    ELSE RAISERROR(@Message, 10, 1) 
    --result: The Schema abc already exists. 
    

    OBJECT_ID 같은 유용한 기능을 포함하여 많은 동적 SQL, DDL의 유효성을 확인하는 방법, 그리고 DMLOBJECT_NAME 있습니다 , DATABASE_ID 등 안전하게 테스트 한 다음 각 오류에 대해 적절한 RAISERROR 메시지를 실행하십시오.

    +0

    글쎄, 아직 스키마로 abc가 없다면,이 스키마는 끝까지 실행됩니다. 그러나 당신은 아이디어를 얻습니다. :) –

    0

    가능한 경우 TRY-CATCH을 제거하십시오. 스크립트 문을 GO과 함께 여러 개의 개별 배치로 나눕니다.

    TRY-CATCH 먼저 예외에 반응하여 TRY 블록의 실행을 중단 : try 블록에서 오류가 발생

    경우, 제어는 CATCH 블록 표로 문 다른 그룹에 전달된다.

    https://msdn.microsoft.com/en-us/library/ms175976.aspx

    그래서 TRY-CATCH의 행동은 당신의 의도에 오히려 반대입니다.

    GO은 배치의 끝을 설정합니다. 대부분의 오류는 low severity을 가지므로 일괄 처리를 중단하지 않기 때문에 스크립트를 여러 배치로 분할 할 필요가없는 경우도 있습니다.

    enter image description here :

    create proc SomeProc as 
    begin 
        exec('select uknown from non_existent') 
    end 
    GO 
    drop table #test1 
    drop table #test2 
    GO 
    drop table #test3 
    GO 
    create table #test1 (id int primary key) 
    
    insert into #test1(id) 
    exec SomeProc 
    
    insert into #test 
    values (1) 
    
    insert into #test1 
    values (1) 
    GO 
    insert into #test1 
    values (11) 
    
    insert into #test1 
    values (11) 
    
    insert into #test 
    values (22) 
    GO 
    select * from #test1 
    GO 
    drop table #test 
    GO 
    drop table #test 
    drop proc SomeProc 
    select object_id('SomeProc', 'P') 
    GO 
    

    은 선택의 출력을 제공 않습니다 여기 예를 들어 테스트 또는 일부 유틸리티 목적을 위해 샘플 더미 스크립트이기 때문에

    은 (하지 물론 생산) 그 많은 오류를 발생

    모든 메시지 :

    메시지 3701, 수준 11, 상태 5, 줄 7 존재하지 않거나 사용 권한이 없기 때문에 '# test2', 테이블을 삭제할 수 없습니다.

    메시지 3701, 수준 11, 상태 5, 줄 9 이 없거나 사용 권한이 없기 때문에 '# test3'테이블을 삭제할 수 없습니다.

    메시지 레벨 208, 상태 1, 줄 11 유효하지 않은 개체 이름 'non_existent'.

    (0 개 행 적용됨)

    메시지 208, 수준 16, 상태 0, 줄 16 잘못된 개체 이름 '#test'.

    (1 개 행 적용됨)

    메시지 2627, 수준 14, 상태 1, 'PK __ #의 test1____3213E83FF35979C1' PRIMARY KEY 제약 조건의 선 (25) 위반. 중복 키를 'dbo. # test1'개체에 삽입 할 수 없습니다. 중복 키 값은 (11)입니다. 명세서가 종료되었습니다.

    msg 208, 수준 16, 상태 0, 줄 28 '#test'개체 이름이 잘못되었습니다. 존재하지 않는 또는 권한이 없으므로

    (1 개 행 적용됨)

    메시지 3701, 수준 11, 상태 5, 줄 33, 테이블 '#test'을 (를) 삭제할 수 없습니다.

    메시지 3701, 수준 11, 상태 5, 줄 35 존재하지 않거나 권한이 없기 때문에 '#test'테이블을 삭제할 수 없습니다.

    "내 목표는 SQL 쿼리, 로그 또는 인쇄에서 오류 메시지를 잡아 내고 실제 오류가 발생하도록하는 대신 전달하는 것입니다." - "print"가 ok이면 TRY-CATCH을 제거하십시오.

    +0

    심각한 치명적인 오류가 발생할 경우 TRY-Block을 사용할 수 있습니다. 오류 수준은 11 이하로 설정할 수 있습니다.이 값은 호출을 catch 블록으로 전송하지 않습니다. [MSDN-RAISERROR] (https://msdn.microsoft.com/en-us/library/ms178592.aspx) –

    +0

    @IvanStarostin 그런 생각을 해주셔서 감사합니다. 그러나 필자가 언급 한 _print_은 실제로 'PRINT @ errormsg' 코드를 의미하므로이 코드를 캡처하고 로그하는 것과 같습니다. 어떤 다른 해결책 – a4194304

    +0

    @clifton_h 나는 이것이 좋은 생각이라고 생각한다. 그러나 11 점 미만의 에러 레벨을 설정하는 방법은 실제로 Lvl 15 또는 16의 일반적인 레벨이다. – a4194304

    관련 문제