2014-11-28 1 views
0

SQL Server 저장 프로 시저의 CATCH 절에서 데이터베이스 오류로 구성된 결과 집합을 반환해야하지만 그 문제가 있습니다. 커서를 사용하여 결과 집합을 반환해야합니까? 그렇다면 .NET 응용 프로그램의 OUTPUT 매개 변수에 대한 형식 선언은 무엇입니까? ObjectVariant을 시도했지만 작동하지 않았습니다. SQL Server에서 VB.NET 응용 프로그램으로 결과 집합을 반환하십시오.

은 또한 단지 반환하는 SELECT 문을 사용하여 간단한 방법을 시도하고 내 CATCH 절에 같은 따라서가 아니라 또 다른 하나의 저장 프로 시저와 함께 작동 : 하나의 저장 프로 시저 때와

while (@I <= @count) 
begin  
    BEGIN TRY  
     -- delete all previous rows inserted in @customerRow for previous counts @I  
     delete from @customerRow 

     -- this is inserting the current row that we want to save in database 
     insert into @customerRow 
      SELECT 
       [id],[firstname], [lastname], [street], [city], 
       [phone],[mobile],[fax], [email], [companyName], 
       [licence],[brn], [vat], [companyStreet], [companyCity], [status] 
      FROM 
       (SELECT 
        ROW_NUMBER() OVER (ORDER BY id ASC) AS rownumber, 
        [id], [firstname], [lastname], [street], [city], 
        [phone], [mobile], [fax], [email], [companyName], 
        [licence], [brn], [vat], [companyStreet], [companyCity], [status] 
       FROM  
        @registerDetails) AS foo 
      WHERE 
      rownumber = @I            

     -- this stored procedure handles the saving of the current customer row just defined above 
     -- if there is any error from that sproc, it will jump to CATCH block 
     --save the error message in the temp table and continue 
     --with the next customer row in the while loop. 
     exec dbo.sp_SaveCustomer @customerRow 
    END TRY 
    BEGIN CATCH 
     IF @@TranCount = 0 
     -- Transaction started in procedure. 
     -- Roll back complete transaction. 
     ROLLBACK TRANSACTION; 
     if XACT_STATE()= -1 rollback transaction 

     DECLARE @ErrorMessage NVARCHAR(4000); 
     DECLARE @ErrorSeverity INT; 
     DECLARE @ErrorState INT; 


     SELECT @ErrorMessage = ERROR_MESSAGE() + ' ' + (select firstname from @registerDetails where [email protected]) 
     SELECT @ErrorSeverity = ERROR_SEVERITY(); 
     SELECT @ErrorState = ERROR_STATE() 

     INSERT INTO #registrationResults (error,id) 
     SELECT @ErrorMessage, @I 

    END CATCH  

    set @I = @I +1    
end 
COMMIT TRANSACTION registerTran 

select * from #registrationResults 

위의 작품

ta.Fill(registrationErrors, clientDetailsDT) 

registrationErrorsclientDetailsDT 강하게 데이터 테이블을 입력있다 : 나는 나의 vb.net 코드를 호출합니다.

이 사람은하지 않습니다 :

begin catch 
    IF @@TranCount > 0 or XACT_STATE()= -1 ROLLBACK TRANSACTION; 
    DECLARE @ErrorMessage NVARCHAR(4000); 
    DECLARE @ErrorSeverity INT; 
    DECLARE @ErrorState INT; 
    DECLARE @ErrorLine INT; 


    SELECT @ErrorMessage = ERROR_MESSAGE(); 
    SELECT @ErrorSeverity = ERROR_SEVERITY(); 
    SELECT @ErrorState = ERROR_STATE(); 
    SELECT @ErrorLine = ERROR_Line(); 

    ****ERROR -- THIS SELECT WAS MESSING ALL UP as it was this select that was being  returned to the .NET and not the select of the desired #temp table after, hence returning 0 resultset as this select was EMPTY. !! 
    select status_indicator from InsertInvoiceTriggerData where session_GUID = guid** 
    delete from InsertInvoiceTriggerData where session_GUID = @guid** 

    INSERT INTO #registrationResults (error,id) 
    SELECT @ErrorMessage, NULL 

    select * from #registrationResults 

end catch 

모든 제안 방법 결과 집합을 반환?

답변

1

데이터베이스 코드를 보지 못했지만 제 경험상 catch이라는 첫 번째 오류가 발생하면 전체 트랜잭션을 롤백해야합니다. 다른 것들과 별개로, 그것은 주어진 상황에서 돌아 오기 위해 하나 이상의 오류가 결코 없다는 것을 의미합니다.

@Error int = null output, 
@Message nvarchar(2048) = null output 

그리고는 다른 출력 변수처럼 그들을 검색 할 수 있습니다 이와 같이

, 내 저장 프로 시저에서 2 개 스칼라 출력 매개 변수를 사용하여, 즉.

UPD : 일부 코드를 추가 한 후에도 여전히 문제가 무엇인지 정확히 이해하지 못합니다. 그러나 코드에 몇 가지 문제가 있으므로이를 지적하고 그 중 하나가 문제를 해결할 가능성이 있습니다. 마지막 스 니펫이 너무 불완전하기 때문에 첫 번째 스 니펫 만 주석 처리합니다.

  • 루프보다 어딘가에서 가장 바깥 쪽 트랜잭션을 시작 했어야합니다. 그렇지 않으면 코드가 실패합니다.
  • 올바르게 추측 한 경우 dbo.sp_SaveCustomer 저장된 프로 시저 내에 모든 세이브 포인트 논리를 구현했습니다. 그렇지 않은 경우 표시 한 코드에 save tran 또는 rollback @savepoint 문이 없으므로 전체 토론이 무의미합니다.
  • 첫 번째 catch 성명 - IF @@TranCount = 0 ROLLBACK TRANSACTION은 모두 잘못되었습니다. 조건이 성공하면 존재하지 않는 트랜잭션을 롤백하려고하는 중 오류가 발생합니다. 세이브 포인트에 의존한다면 여기에 있으면 안됩니다. 그것은 무조건 휴식 발생한다 후
  • 다음 : 롤백뿐만 아니라 그들에 영향을 미칠 것이기 때문에 INSERT INTO @registrationResults (error, id) SELECT error_message() + ' ' + firstname, id from @registerDetails where [email protected];는 또한
  • ,이 목적을 위해 임시 테이블을 사용하지 않습니다 : 당신의 catch 코드의 나머지 부분이 교체 할 수 있습니다 if XACT_STATE()= -1 begin rollback transaction; break; end;
  • . 이것을 위해 항상 테이블 변수를 사용하십시오. 다른 변수와 마찬가지로 트랜잭션이 아닙니다.당신이 커밋 트랜잭션 (transaction)이 시점에서 끝날 수 있기 때문에
  • commit는 조건부해야한다 : 아니지만 if @@trancount > 0 commit tran;
  • commit 성명에서 세이브 포인트 이름을 지정 아무 문제가 없다, 그것은 단지 (혼란을 초래 오류로 간주). 또한이 모듈에는 세이브 포인트가 없어야합니다 (루프 전에 정의하지 않은 경우).

사실상 dbo.SaveCustomer 저장 프로 시저 내부에서 어떤 일이 발생하는지 전혀 알지 못하기 때문에 이것이 빙산의 일각이라고 생각합니다. UPD2

: 여기 내가 저장 프로 시저에서 레코드를 수신하는 데 사용하는 내 VB.NET 코드의 샘플입니다

Private Function SearchObjectsBase(_ 
    SearchMode As penum_SEARCH_MODE, SearchCriteria As String 
) As DataSet 

Dim Cmd As DbCommand, Pr As DbParameter, dda As DbDataAdapter 

' Initialise returning dataset object 
SearchObjectsBase = New DataSet() 

Cmd = MyBase.CreateCommand(String.Format("dbo.{0}", SearchMode)) 

With Cmd 

    ' Parameter definitions 
    Pr = .CreateParameter() 
    With Pr 
     .ParameterName = "@SearchCriteria" 
     .DbType = DbType.Xml 
     .Value = SearchCriteria 
    End With 
    .Parameters.Add(Pr) 

    ' Create data adapter to use its Fill() method 
    dda = DbProviderFactories.GetFactory(.Connection).CreateDataAdapter() 
    ' Assign the prepared DbCommand as a select method for the adapter 
    dda.SelectCommand = Cmd 

    ' A single resultset is expected here 
    dda.Fill(SearchObjectsBase) 

End With 

' Set error vars and get rid of it 
Call MyBase.SetErrorOutput(Cmd) 

' Check for errors and, if any, discard the dataset 
If MyBase.ErrorNumber <> 0 Then SearchObjectsBase.Clear() 

End Function 

을 나는 자동으로 선택하는 아주 좋은 방법이있는 .NET 4.5을 사용 실제 연결을 기반으로하는 가장 적합한 데이터 어댑터 여기

Dim XDoc As New XElement("Criteria"), DS As DataSet = Nothing, DT As DataTable 
... 
DS = .SearchPatients(XDoc.ToString(SaveOptions.None)) 
' Assign datasource to a grid 
Me.dgr_Search.DataSource = DS.Tables.Item(0) 

, SearchPatients() 인 SearchObjectsBase 위에 래퍼() 그리고 여기 이 함수를 호출한다.

+0

언급 한대로 스칼라 매개 변수가 단일 출력으로 정상적으로 작동하지만 내 경우에는 트랜잭션이 while 루프에서 진행되고 트랜잭션이 성공하지 않을 때마다 저장된 지점으로 롤백되고 오류 메시지가 저장됩니다 위와 같이 임시 테이블에. 루프가 완료되면 결과 집합을 반환합니다. 그러나 CATCH 블록의 임시 테이블에서 언급 한 매개 변수를 반환하려는 경우 어떻게 구현합니까? – user2043688

+0

음, 오류 결과 집합을 XML로 변환하고 XML 출력 매개 변수를 통해 반환 할 수 있습니다. 왜냐하면 2014 년이 되더라도 테이블 변수 매개 변수는 여전히 읽기 전용입니다. –

+0

원본 게시물을 다시 한 번 살펴 보겠습니다. 데이터베이스 코드가 포함되어 있습니다. 또한 MSDN 설명서에 따르면이 방법은 저장 프로 시저간에 작동하지만 .NET에서 커서를 읽는 방법은 무엇입니까? http://msdn.microsoft.com/en-us/library/ms188655.aspx – user2043688

관련 문제