我试图看看它是否可以在游标循环中执行更新,并且这个更新的数据会在循环的第二次迭代中反映出来。
DECLARE cur CURSOR
FOR SELECT [Product], [Customer], [Date], [Event] FROM MyTable
WHERE [Event] IS NULL
OPEN cur
FETCH NEXT INTO @Product, @Customer, @Date, @Event
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT * FROM MyTable WHERE [Event] = 'No Event' AND [Date] < @DATE
-- Now I update my Event value to 'No Event' for records whose date is less than @Date
UPDATE MyTable SET [Event] = 'No Event' WHERE [Product] = @Product AND [Customer] = @Customer AND [Date] < @DATE
FETCH NEXT INTO @Product, @Customer, @Date, @Event
END
CLOSE cur
DEALLOCATE cur
假设当sql执行时,所有记录的Event列都为NULL 在上面的sql中,我在游标循环内部进行选择以查询MyTable,其中Event值为“No Event”,但即使我在下一行中进行更新,查询也不返回任何值。 所以,我在想是否有可能更新一个表,更新的数据会反映在游标循环的下一次迭代中。
感谢您的帮助, Javid
答案 0 :(得分:4)
首先,你不需要光标。类似下面的内容将具有相同的语义(从所有Event
为NULL
的起始位置)并且效率更高。
WITH T
AS (SELECT [Event],
RANK() OVER (PARTITION BY [Product], [Customer]
ORDER BY [Date] DESC) AS Rnk
FROM MyTable)
UPDATE T
SET [Event] = 'No Event'
WHERE Rnk > 1
其次,关于标题中提交游标循环内的问题与其他任何地方相同。您只需要一个COMMIT
语句。但是,如果您未在更大的事务中运行此事件,则UPDATE
语句仍将自动提交。
第三,你真正的问题似乎并不是关于提交。它是关于反映后续迭代数据更新的光标。对于问题中的情况,您需要DYNAMIC
光标
定义一个游标,该游标反映对行中所做的所有数据更改 滚动光标时的结果集。数据值, 订单,行的成员资格可以在每次获取时更改。
并非所有查询都支持动态游标。问题中的代码但是如果没有ORDER BY
,那么处理行的顺序是不确定的,因此是否会看到可见的结果。我添加了一个ORDER BY
和一个索引来支持它,以允许使用动态游标。
如果您尝试以下操作,您将看到光标只提取一行,因为日期按降序处理,当处理第一行时,表格会更新,以便不再有行符合下一次提取的条件。如果注释掉游标循环中的UPDATE
,则会获取所有三行。
CREATE TABLE MyTable
(
[Product] INT,
[Customer] INT,
[Date] DATETIME,
[Event] VARCHAR(10) NULL,
PRIMARY KEY ([Date], [Product], [Customer])
)
INSERT INTO MyTable
VALUES (1,1,'20081201',NULL),
(1,1,'20081202',NULL),
(1,1,'20081203',NULL)
DECLARE @Product INT,
@Customer INT,
@Date DATETIME,
@Event VARCHAR(10)
DECLARE cur CURSOR DYNAMIC TYPE_WARNING FOR
SELECT [Product],
[Customer],
[Date],
[Event]
FROM MyTable
WHERE [Event] IS NULL
ORDER BY [Date] DESC
OPEN cur
FETCH NEXT FROM cur INTO @Product, @Customer, @Date, @Event
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @Product,
@Customer,
@Date,
@Event
-- Now I update my Event value to 'No Event' for records whose date is less than @Date
UPDATE MyTable
SET [Event] = 'No Event'
WHERE [Product] = @Product
AND [Customer] = @Customer
AND [Date] < @Date
FETCH NEXT FROM cur INTO @Product, @Customer, @Date, @Event
END
CLOSE cur
DEALLOCATE cur
DROP TABLE MyTable
答案 1 :(得分:0)
即使这样做有效,但由于您错过了查询中的ORDER BY
子句,因此无法保证正确的结果。
根据这一点,可以更新所有记录,无记录或任何随机记录子集。
请您用简单的英语解释一下您的存储过程应该做什么?