【问题标题】:IDENTITY_INSERT ON inside of cursor does not allow inserted idIDENTITY_INSERT ON 游标内部不允许插入 id
【发布时间】:2010-05-06 11:09:30
【问题描述】:

我正在尝试为 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

有谁知道我做错了什么?

【问题讨论】:

    标签: sql-server tsql cursor identity-insert


    【解决方案1】:

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

    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
    

    【讨论】:

    • +1,正是我的想法,如果可以的话,+10000,因为使用基于集合的方法而不是光标!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-30
    • 2014-05-23
    • 2016-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多