2017-09-11 3 views
1

SQL-서버 코드 :T-SQL 커서가 두 번 실행되는 이유는 무엇입니까?

Declare @offers VARCHAR(100) 
Declare @offers_seq VARCHAR(100) 

Declare Result Cursor 
    For Select Top 1 Offers,Offers_seq From [REZJQWB01]..ActiveBooking_OffersDetails_Seq 
Open Result 
While @@fetch_status=0 
Begin 
    Fetch Next From Result Into @offers, @offers_seq 
    Declare @value VARCHAR(100) = @offers 
    While len(@value) >= 1 
    Begin 
     Set @value = substring(@value,charindex(';',@value)+1,len(@value)) 
     Print @value 
    End 
End 
Close Result 
Deallocate Result 

내가 여기 달성 노력하고있어 하나 개의 셀에 존재하고 전체 열에 대한 커서를 만드는 구분 된 값의 집합을 분할하는 것입니다.

2;6;7;8;9;12;13;14;17;19;21; 
6;7;8;9;12;13;14;17;19;21; 
7;8;9;12;13;14;17;19;21; 
8;9;12;13;14;17;19;21; 
9;12;13;14;17;19;21; 
12;13;14;17;19;21; 
13;14;17;19;21; 
14;17;19;21; 
17;19;21; 
19;21; 
21; 

2;6;7;8;9;12;13;14;17;19;21; 
6;7;8;9;12;13;14;17;19;21; 
7;8;9;12;13;14;17;19;21; 
8;9;12;13;14;17;19;21; 
9;12;13;14;17;19;21; 
12;13;14;17;19;21; 
13;14;17;19;21; 
14;17;19;21; 
17;19;21; 
19;21; 
21; 

가 이상적으로 그것은 단지 한 번 인쇄해야하지만 루프가 두 번 실행되는 이유를 잘 모르겠어요 : 나는이 코드를 실행 처음은 아래의 출력을 제공합니다. 두 번째로이 명령을 실행하면 출력이 'Command (s) completed successfully'로 표시됩니다.

친절히 도움. 감사합니다. .

답변

2

을 확인한 후 다음에 까지 가져 오기를 수행하지 않는 이유는 두 번 실행되는 이유입니다.

단계는 다음과 같다 : 제로

  1. 확인 @@fetch_status를, 아무것도 가져온 없었다 때문이다. 기록은 이전 단계
  2. 실패 다른 결과를 가져 오기에서 가져온했지만 커서가 가리키는 때문에
  3. , 여전히 제로, 이는 다시 문자열 코드 실행
  4. 확인 @@fetch_status
  5. 결과를 가져옵니다 이전과 같은 행
  6. 하위 문자열 코드를 다시 실행하십시오. 동일한 결과
  7. @@fetch_status을 다시 확인하십시오. 그러면 이전 페치가 실패했기 때문에 -1이 반환됩니다. @@fetch_status이기 때문에 -1 이전 실행에서 같은 이유로

당신이 한 번 실행이 개 결과를 얻을로, 당신은 아무것도에게 두 번째 시간을 얻을 수 없습니다. 두 가지 문제를 모두 해결하려면 상태를 확인하기 전에 가져와야합니다. 일반적으로 다음 방법 중 하나가 사용됩니다 (구현할 수있는 연습으로 남아 있습니다). 일반적으로 나는 첫 번째 옵션을 사용하지만, 일부는 두 번째 읽기 쉽게 찾을 수 있습니다 :

-- (declare and open cursor) 
while 1=1 begin 
    fetch next from cursor 
    if @@fetch_status <> 0 break; 
    -- (do stuff) 
end 

또는

-- (declare and open cursor) 
fetch next from cursor 
while @@fetch_status = 0 begin 
    -- (do stuff) 
    fetch next from cursor 
end 
+1

제쳐두고, 나는 또한 커서를 피하려고 노력해야한다고 언급해야한다. 가능하다면. 오버 헤드가 많이 발생하므로 일반 루프를 사용하거나 단일 쿼리를 더 효과적으로 수행 할 수 있다면 항상 커서보다 우선적으로 수행하십시오. 좋은 대안을 찾기 위해 "t-sql 커서 사용 안함"에 대한 Google 검색을 수행하십시오. – pcdev

+0

답변을 주셔서 감사합니다 @ pcdev. 내 문제를 해결하는 데 도움이되었습니다. 나는 @@ fetchstatus를 잘못 사용하려고한다는 것을 이해했습니다. 또한 가능한 경우 커서를 피하려고 노력할 것입니다. 아래에 올바른 코드를 붙여 넣으십시오. – funnyguy

0

올바른 코드 :

Declare @offers VARCHAR(100) 
Declare @offers_seq VARCHAR(100) 

Declare Result Cursor 
    For Select Top 1 Offers,Offers_seq From [REZJQWB01]..ActiveBooking_OffersDetails_Seq 
Open Result 
While 1=1 
Begin 
    Fetch Next From Result Into @offers, @offers_seq 
    If @@fetch_status <> 0 Break; 
    Declare @value VARCHAR(100) = @offers 
    While len(@value) > 1 
    Begin 
     Set @value = substring(@value,charindex(';',@value,2)+1,len(@value)) 
     Set @value = ';'[email protected] 
     If len(@value) <= 1 Break; 
     Print @value 
    End 
End 
Close Result 
Deallocate Result 

결과 :

;6;7;8;9;12;13;14;17;19;21; 
;7;8;9;12;13;14;17;19;21; 
;8;9;12;13;14;17;19;21; 
;9;12;13;14;17;19;21; 
;12;13;14;17;19;21; 
;13;14;17;19;21; 
;14;17;19;21; 
;17;19;21; 
;19;21; 
;21;