为什么我的T-SQL游标执行两次?

时间:2017-09-11 03:17:22

标签: sql sql-server tsql cursor

SQL-Server代码:

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)已成功完成'。

请帮助。 感谢。

2 个答案:

答案 0 :(得分:2)

它运行两次的原因是你在之后你已经检查过@@fetch_status之后才进行提取。

步骤如下:

  1. 检查@@fetch_status,该值为零,因为未提取任何内容。
  2. 获取结果
  3. 运行您的子字符串代码
  4. 再次检查@@fetch_status,这仍然为零,因为在上一步中提取了一条记录
  5. 获取另一个结果,该结果失败但光标仍然指向与之前相同的行
  6. 再次运行您的子字符串代码,结果相同
  7. 再次检查@@fetch_status,现在返回-1,因为之前的提取失败。
  8. 出于同样的原因,你得到两次运行它的结果,你第二次得不到任何结果,因为@@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 :(得分: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 = ';'+@value
        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;