解决游标问题

发布于 2024-09-16 15:51:03 字数 1039 浏览 6 评论 0原文

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

I have a question. I am working on cursors. Each time, after fetching the last records and printing its data’s, the cursor prints an addition line. To understand what I mean please consider the following sample example:
I want to print the information about only 10 customers.

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

Now look at the output:

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      

The row number 11 also has been printed. Is it a problem in a cursor or it always occurs?
Is there any way not to print this addition data? Thanks
(i use sql erver 2008)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

好菇凉咱不稀罕他 2024-09-23 15:51:03

要么……

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

Either...

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

    FETCH NEXT FROM myCursor INTO @ContactName
END

Or...

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

Or...

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

    -- do stuff
END
喜你已久 2024-09-23 15:51:03

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

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

You mentioned you're using SQL Server 2008. With SQL Server 2005 or greater, you don't need a cursor at all to do what you want.

select top 10 left(cast(row_number() over(order by ContactName) as varchar)+ '      ', 6) + ContactName
    from Customers
微暖i 2024-09-23 15:51:03

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

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

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

See how you have the printing logic duplicated? That's a pointer to what's going wrong. Your loop should look like this:

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

The only duplicated code should be the FETCH NEXT itself - the way you have it now, the last FETCH happens, but you PRINT a line before the WHILE can exit.

千纸鹤带着心事 2024-09-23 15:51:03

记录集末尾的 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

A FETCH at the end of the record set sets @@FETCH_STATUS to not 0.

The FETCH NEXT command should be the last line in the 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
行至春深 2024-09-23 15:51:03

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

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

对于额外的点,使用游标变量并声明 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)。

This is an off-by-one error. Here's a better way to iterate through a cursor, w/ less code duplication:

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

For extra points, use a cursor variable and declare w/ FAST_FORWARD and TYPE_WARNING, or STATIC for small datasets. eg:

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

CLOSE and DEALLOCATE are not strictly necessary, as the cursor variable will go out of scope at the end of the batch. It is still good form, however, as you might add more code at the end later on, and you should free up resources as early as possible.

TYPE_WARNING tells you when SQL Server implicitly converts the requested cursor type (FAST_FORWARD) to another type (typically STATIC), if the requested type is incompatible w/ your SELECT statement.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文