2

id列がIDであるデータベース内の一連の行にいくつかのIDを設定しようとしています。

行をループし、負の数(-1、-2、-3など)をインクリメントしてIDを更新するカーソルを作成しました。

IDENTITY_INSERTをオンにして1行だけを更新すると、正常に機能しましたが、カーソルで使用しようとすると、次のエラーがスローされます。

メッセージ8102、レベル16、状態1、22行目ID列'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

とにかく、これにはカーソルは必要ありません。これらがID列であることを無視すると、このようなものは派生テーブルで機能し、それに結合して、セットベースの方法ですべての行を更新できます。

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

これは、ID挿入をオンに設定してから、そのようにすべてを挿入してから、トランザクションで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 に答える