2

我正在尝试为 id 列是标识的数据库中的一堆行设置一些 id。

我创建了一个游标来循环遍历行并使用递增的负数(-1、-2、-3 等)更新 id。

当我只更新打开 IDENTITY_INSERT 的一行时,它工作正常,但是一旦我尝试在游标中使用它,它就会引发以下错误。

消息 8102,级别 16,状态 1,第 22 行无法更新标识列“myRowID”。

DECLARE @MinId  INT;
SET @MinId = (SELECT MIN(myRowId) FROM myTable)-1;

DECLARE myCursor CURSOR
FOR
SELECT myRowId
FROM dbo.myTable
WHERE myRowId > 17095

OPEN myCursor 
DECLARE @myRowId INT

FETCH NEXT FROM myCursor INTO @myRowId
WHILE (@@FETCH_STATUS <> -1)
BEGIN

SET IDENTITY_INSERT dbo.myTable ON;

--UPDATE dbo.myTable
--SET myRowId = @MinId
--WHERE myRowId = @myRowId;

PRINT (N'ID: ' + CAST(@myRowId AS VARCHAR(10)) + N' NewID: ' + CAST(@MinId AS VARCHAR(4)));
SET @MinId = @MinId - 1;
FETCH NEXT FROM myCursor INTO @myRowId
END

CLOSE myCursor 
DEALLOCATE myCursor 
GO
SET IDENTITY_INSERT dbo.myTable OFF;
GO

有谁知道我做错了什么?

4

1 回答 1

6

无论如何,您不需要光标。忽略它们是标识列,这样的东西可以在派生表中工作,然后您可以加入它以基于集合的方式更新所有行

select 0-row_number() over( order by myRowId asc) as myRowId,*
 from dbo.myTable
WHERE myRowId > 17095

如果您最终设置身份插入,然后将它们全部插入,然后在事务中删除 WHERE myRowId > 17095(按该顺序!),这仍然可能是一种有用的方法

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 

BEGIN TRAN
SET IDENTITY_INSERT dbo.myTable ON;

INSERT INTO dbo.myTable
SELECT 0-row_number() OVER( ORDER BY myRowId ASC) AS myRowId, OtherColumns
 FROM dbo.myTable
WHERE myRowId > 17095

DELETE FROM dbo.myTable WHERE myRowId > 17095

SET IDENTITY_INSERT dbo.myTable OFF;
COMMIT
于 2010-05-06T11:34:12.790 回答