SQL 中的 CURSOR 在只有 1 条记录时运行多次
CURSOR in SQL runs multiple times when there is only 1 record in it
我遇到了一个 CURSOR 问题,在某些情况下,它只填充了一个值,但它并没有立即存在,而是一直持续到我的情况崩溃为止。
这是代码:
DECLARE @positionID as INT
DECLARE position_cursor CURSOR FOR
SELECT positionUniqueNumber
FROM position
WHERE position.EmployeeID = @EmployeeID
OPEN position_cursor
FETCH NEXT FROM position_cursor INTO @positionID
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE position
SET positionFromDate = DATEADD(day,@days, positionFromDate)
WHERE position.positionUniqueNumber = @positionID
FETCH NEXT FROM position_cursor INTO @positionID
END
CLOSE position_cursor
DEALLOCATE position_cursor
如果 'position_cursor' 只有一个值,我希望光标在一个 运行 之后存在,而不是继续下去,直到它试图设置一个高于 9999 的日期并崩溃。
对我来说,一个解决方法是检查 table 中有多少符合条件的记录,仅当超过 1 条时才使用光标,但我想找到更好的方法。想法?
谢谢
这是一个修复被注释掉的重现。大多数人 期望 游标的 STATIC 语义,但这不是默认设置。如果您的更新导致行在游标读取的索引中移动,它可以读取同一行两次。
只需始终将游标声明为 LOCAL STATIC 即可避免这些问题。
drop table if exists position
go
create table position(positionuniquenumber int primary key nonclustered, EmployeeId int, positionFromDate DateTime)
create unique clustered index cix_position on position(employeeid,positionFromDate,positionuniquenumber)
insert into position(positionuniquenumber,EmployeeId,positionFromDate) values (1,1,getdate())
go
DECLARE @EmployeeID int = 1
declare @Days int = 1
DECLARE @positionID as INT
DECLARE position_cursor CURSOR /*LOCAL STATIC*/ FOR
SELECT positionUniqueNumber
FROM position
WHERE position.EmployeeID = @EmployeeID
OPEN position_cursor
FETCH NEXT FROM position_cursor INTO @positionID
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE position
SET positionFromDate = DATEADD(day,@days, positionFromDate)
WHERE position.positionUniqueNumber = @positionID
FETCH NEXT FROM position_cursor INTO @positionID
END
CLOSE position_cursor
DEALLOCATE position_cursor
我遇到了一个 CURSOR 问题,在某些情况下,它只填充了一个值,但它并没有立即存在,而是一直持续到我的情况崩溃为止。
这是代码:
DECLARE @positionID as INT
DECLARE position_cursor CURSOR FOR
SELECT positionUniqueNumber
FROM position
WHERE position.EmployeeID = @EmployeeID
OPEN position_cursor
FETCH NEXT FROM position_cursor INTO @positionID
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE position
SET positionFromDate = DATEADD(day,@days, positionFromDate)
WHERE position.positionUniqueNumber = @positionID
FETCH NEXT FROM position_cursor INTO @positionID
END
CLOSE position_cursor
DEALLOCATE position_cursor
如果 'position_cursor' 只有一个值,我希望光标在一个 运行 之后存在,而不是继续下去,直到它试图设置一个高于 9999 的日期并崩溃。 对我来说,一个解决方法是检查 table 中有多少符合条件的记录,仅当超过 1 条时才使用光标,但我想找到更好的方法。想法? 谢谢
这是一个修复被注释掉的重现。大多数人 期望 游标的 STATIC 语义,但这不是默认设置。如果您的更新导致行在游标读取的索引中移动,它可以读取同一行两次。
只需始终将游标声明为 LOCAL STATIC 即可避免这些问题。
drop table if exists position
go
create table position(positionuniquenumber int primary key nonclustered, EmployeeId int, positionFromDate DateTime)
create unique clustered index cix_position on position(employeeid,positionFromDate,positionuniquenumber)
insert into position(positionuniquenumber,EmployeeId,positionFromDate) values (1,1,getdate())
go
DECLARE @EmployeeID int = 1
declare @Days int = 1
DECLARE @positionID as INT
DECLARE position_cursor CURSOR /*LOCAL STATIC*/ FOR
SELECT positionUniqueNumber
FROM position
WHERE position.EmployeeID = @EmployeeID
OPEN position_cursor
FETCH NEXT FROM position_cursor INTO @positionID
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE position
SET positionFromDate = DATEADD(day,@days, positionFromDate)
WHERE position.positionUniqueNumber = @positionID
FETCH NEXT FROM position_cursor INTO @positionID
END
CLOSE position_cursor
DEALLOCATE position_cursor