如下边的例子
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Test](
[ID] [int] NOT NULL) ON [PRIMARY]
GO
INSERT INTO Test VALUES(1)
GO
DECLARE C$Cursor Cursor LOCAL FAST_FORWARD
FOR
SELECT ID From Test Where ID < 10
DECLARE @id INT
OPEN C$Cursor
Fetch C$Cursor INTO @id
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE Test SET ID = ID + 1 WHERE id = @id
Fetch C$Cursor INTO @id
END
CLOSE C$Cursor
DEALLOCATE C$Cursor
按照MSDN的说明,如果不指定的话,默认游标应该是动态的游标,那么我更新数据后应该反映在游标中,所以最后结果应该是10,但是执行结果确是2,为什么?
当然是2了你游标提取的数据只有一条,然后这一条数据的ID为1,你将ID的字段加1后更新,当然是二了,那个10是你的筛选条件而已,并不是你要循环多少次。
如果是动态的话,它的更新应该反映到游标里,这样就能一直读取到刚刚更新数据,直到数据变更10不再满足条件。这是我理解。
@Silade: 因为你的数据只有一条,游标提取完毕之后,游标就结束了,sql语句也有个执行的顺序,你放在前面 就是指执行一次,你放在循环里面就是多次。搞明白顺序
@az235: 那我请问,下边的执行为啥是10
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Test](
[ID] [int] NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED ([ID] ASC)) ON [PRIMARY]
GO
INSERT INTO Test VALUES(1)
GO
DECLARE C$Cursor Cursor
FOR
SELECT ID From Test Where ID < 10
DECLARE @id INT
OPEN C$Cursor
Fetch C$Cursor INTO @id
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE Test SET ID = ID + 1 WHERE id = @id
Fetch C$Cursor INTO @id
END
CLOSE C$Cursor
DEALLOCATE C$Cursor
@Silade: 上面的我说错了点东西,没有注意到你用了这几个关键字 Local FAST_FORWARD STATIC,你自己写的为静态游标,而下面的为动态游标,静态游标是以游标打开时刻的当时状态显示结果集的游标。静态游标在游标打开时不反映对基础数据进行的更新、删除或插入。有时称它们为快照游标。动态游标是可以在游标打开时反映对基础数据进行的修改的游标。用户所做的更新、删除和插入在动态游标中加以反映。
为我上面的错误道歉,谢谢。
@az235: 我的第一个例子也没有STATIC 关键字,而且FAST_FORWARD 也不能与STATIC 同时存在,所以两个游标都是动态游标。
@Silade: FAST_FORWARD 与Static不是互斥的参见这里http://shikonglaike.iteye.com/blog/1001161
@az235:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Test](
[ID] [int] NOT NULL) ON [PRIMARY]
GO
INSERT INTO Test VALUES(1)
GO
DECLARE C$Cursor Cursor FAST_FORWARD STATIC
FOR
SELECT ID From Test Where ID < 10
DECLARE @id INT
OPEN C$Cursor
Fetch C$Cursor INTO @id
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE Test SET ID = ID + 1 WHERE id = @id
Fetch C$Cursor INTO @id
END
CLOSE C$Cursor
DEALLOCATE C$Cursor
以上代码会报错。