解决游标问题

时间:2010-08-31 12:19:28

标签: sql-server sql-server-2008 cursors

我有一个问题。我正在研究游标。每次在获取最后的记录并打印其数据后,光标都会打印一条附加行。要理解我的意思,请考虑以下示例示例:  我想打印仅有10位客户的信息。

USE Northwind
GO

DECLARE myCursor CURSOR 
FOR SELECT TOP(10) ContactName FROM Customers
DECLARE @RowNo int,@ContactName nvarchar(30)
SET @RowNo=1
OPEN myCursor
FETCH NEXT FROM myCursor INTO @ContactName
PRINT  LEFT(CAST(@rowNo as varchar) + '      ',6)+'  '+ @ContactName
SET @RowNo=@RowNo+1
SET @ContactName=''
WHILE @@FETCH_STATUS=0
  BEGIN
        FETCH NEXT FROM myCursor INTO @ContactName
        PRINT + LEFT(CAST(@rowNo as varchar) + '      ',6)+'  '+ @ContactName
        SET @RowNo=@RowNo+1
        SET @ContactName=''
  END
CLOSE myCursor
DEALLOCATE myCursor

现在看一下输出:

1       Maria Anders
2       Ana Trujillo
3       Antonio Moreno
4       Thomas Hardy
5       Christina Berglund
6       Hanna Moos
7       Frédérique Citeaux
8       Martín Sommer
9       Laurence Lebihan
10      Elizabeth Lincoln
11      

行号11也已打印。它是光标中的问题还是总是发生? 有没有办法不打印这些添加数据?谢谢 (我使用sql erver 2008)

5 个答案:

答案 0 :(得分:5)

要么...

FETCH NEXT FROM myCursor INTO @ContactName
WHILE @@FETCH_STATUS = 0
BEGIN
    -- do stuff

    FETCH NEXT FROM myCursor INTO @ContactName
END

或者...

WHILE @@FETCH_STATUS = 0
BEGIN
    FETCH NEXT FROM myCursor INTO @ContactName
    IF @@FETCH_STATUS = 0
    BEGIN
        -- do stuff
    END
END

或者...

WHILE (1 = 1)
BEGIN
    FETCH NEXT FROM myCursor INTO @ContactName
    IF @@FETCH_STATUS <> 0
        BREAK

    -- do stuff
END

答案 1 :(得分:3)

您提到您正在使用SQL Server 2008.对于SQL Server 2005或更高版本,您根本不需要光标来执行您想要的操作。

select top 10 left(cast(row_number() over(order by ContactName) as varchar)+ '      ', 6) + ContactName
    from Customers

答案 2 :(得分:1)

了解如何重复打印逻辑?这是指出错误的指针。你的循环应如下所示:

FETCH NEXT INTO @working_variables
WHILE @@FETCH_STATUS = 0
    -- process @working_variables
    FETCH NEXT INTO @working_variables

唯一重复的代码应该是FETCH NEXT本身 - 现在的方式,最后FETCH发生,但是PRINT WHILE之前的一行退出。

答案 3 :(得分:0)

记录集末尾的FETCH将@@ FETCH_STATUS设置为不为0.

FETCH NEXT命令应该是WHILE BLOCK中的最后一行。

USE Northwind
GO

DECLARE myCursor CURSOR 
FOR SELECT TOP(10) ContactName FROM Customers
DECLARE @RowNo int,@ContactName nvarchar(30)
SET @RowNo=0
OPEN myCursor
FETCH NEXT FROM myCursor INTO @ContactName
WHILE @@FETCH_STATUS=0
  BEGIN

        SET @RowNo=@RowNo+1
        SET @ContactName=''
        PRINT + LEFT(CAST(@rowNo as varchar) + '      ',6)+'  '+ @ContactName
        FETCH NEXT FROM myCursor INTO @ContactName
  END
CLOSE myCursor
DEALLOCATE myCursor

答案 4 :(得分:0)

这是一个错误的错误。这是迭代游标的更好方法,减少代码重复:

USE Northwind
GO

DECLARE myCursor CURSOR 
FOR SELECT TOP(10) ContactName FROM Customers
DECLARE @RowNo int,@ContactName nvarchar(30)
SET @RowNo=0 -- initialize counters at zero, increment after the fetch/break
OPEN myCursor
WHILE 1=1 BEGIN -- start an infinite loop
  FETCH NEXT FROM myCursor INTO @ContactName
  IF @@FETCH_STATUS <> 0 BREAK
  SET @RowNo=@RowNo+1
  PRINT  LEFT(CAST(@rowNo as varchar) + '      ',6)+'  '+ @ContactName
END
CLOSE myCursor
DEALLOCATE myCursor

对于额外的点,使用游标变量并为小数据集声明w / FAST_FORWARD和TYPE_WARNING或STATIC。例如:

DECLARE @cursor CURSOR
SET @cursor = CURSOR FAST_FORWARD TYPE_WARNING FOR
  SELECT TOP (10) ContactName FROM Customers
OPEN @cursor 
......
CLOSE @cursor
DEALLOCATE @cursor

CLOSE和DEALLOCATE不是绝对必要的,因为游标变量将在批处理结束时超出范围。但是,它仍然是一个很好的形式,因为您可能会在稍后添加更多代码,并且您应该尽早释放资源。

TYPE_WARNING告诉您SQL Server隐式将请求的游标类型(FAST_FORWARD)转换为另一种类型(通常是STATIC),如果请求的类型与SELECT语句不兼容。