4

我有个问题。我正在研究游标。每次,在获取最后一条记录并打印其数据后,游标会打印一个附加行。要理解我的意思,请考虑以下示例:我只想打印关于 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)

4

5 回答 5

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
于 2010-08-31T12:26:45.720 回答
3

您提到您使用的是 SQL Server 2008。使用 SQL Server 2005 或更高版本,您根本不需要游标来执行您想要的操作。

select top 10 left(cast(row_number() over(order by ContactName) as varchar)+ '      ', 6) + ContactName
    from Customers
于 2010-08-31T13:39:39.557 回答
1

看看你是如何复制打印逻辑的?这是一个指向哪里出了问题的指针。您的循环应如下所示:

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

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

于 2010-08-31T12:26:45.020 回答
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 不是绝对必要的,因为游标变量将在批处理结束时超出范围。但是,它仍然是一种很好的形式,因为您稍后可能会在最后添加更多代码,并且您应该尽早释放资源。

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

于 2010-08-31T13:32:12.773 回答
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
于 2010-08-31T12:27:05.797 回答