この例では:
DECLARE @KeyField INT, @ValueField INT
DECLARE CursorName CURSOR FAST_FORWARD
FOR SELECT T1.KeyField, T1.ValueField
FROM Table1 AS T1
LEFT JOIN Table2 AS T2
ON T1.ValueField = T2.ValueField
WHERE T2.KeyField IS NULL -- Filter out any records that have the same value in T2 as T1
OPEN CursorName FETCH NEXT FROM CursorName
INTO @KeyField, @ValueField
WHILE (@@FETCH_STATUS = 0)
BEGIN
INSERT INTO Table2 (KeyField, ValueField)
SELECT @KeyField, @ValueField
FETCH NEXT FROM CursorName
INTO @KeyField, @ValueField
END
CLOSE CursorName
DEALLOCATE CursorName;
(カーソルをどれだけ「気に入った」か忘れてしまいました。)
カーソルループボディ内でTable2を更新すると、ループの次の反復でデータセットからその値が除外されますか?...つまり、Table2を更新すると、元のカーソル定義にTable2を使用するデータセットが変更されます。
つまり、Table2を更新すると、元のカーソル定義にTable2を使用するデータセットが変更されます。
table2
にデータを挿入していて、STATIC
キーワードを指定しない限り、これらのデータ変更が表示される可能性があります。
カーソルが最初に開かれたときと同じようにカーソルが常に結果セットを表示し、カーソルが使用するデータの一時的なコピーを作成することを指定します。カーソルへのすべての要求は、tempdbのこの一時テーブルから応答されます
カーソルの宣言によっては、どのデータがカーソルに表示されるかについて他の影響があります。
KEYSET、DYNAMIC、FAST_FORWARD、FORWARD_ONLY などのキーワードは、この動作に影響を与えます。
FORWARD_ONLY に関するドキュメントの例
...現在のユーザーが行った(または他のユーザーがコミットした)結果セットの行に影響するすべての挿入、更新、削除ステートメントは、行がフェッチされるときに表示されます。ただし、カーソルを後方にスクロールすることはできないため、行がフェッチされた後にデータベース内の行に加えられた変更は、カーソルを通して表示されません...
FORWARD_ONLY
を使用すると、カーソルが置かれている行によってはデータが表示される場合があります。
しかし、あなたの例では、使用されているフィルターのために:
WHERE T2.KeyField IS NULL -- Filter out any records that have the same value in T2 as T1
新しい行が追加された場合でも、ヌル以外がTable2
に挿入されるため、挿入されたデータは除外されます。
このクエリの適応をテストして、無限ループカーソルを作成できます。
DROP TABLE dbo.Table1;
DROP TABLE dbo.Table2;
CREATE TABLE dbo.Table1(KeyField int,ValueField int);
INSERT INTO dbo.Table1
SELECT TOP(10) ROW_NUMBER() OVER( ORDER BY(SELECT NULL)),
ROW_NUMBER() OVER( ORDER BY(SELECT NULL))
FROM MASTER..spt_values;
CREATE TABLE dbo.Table2(KeyField int,ValueField int)
INSERT INTO dbo.Table2
SELECT TOP(10) ROW_NUMBER() OVER( ORDER BY(SELECT NULL)),
ROW_NUMBER() OVER( ORDER BY(SELECT NULL))
FROM MASTER..spt_values;
DECLARE @KeyField INT, @ValueField INT;
DECLARE @counter int = 0;
DECLARE CursorName CURSOR
FOR SELECT T1.KeyField, T1.ValueField
FROM Table1 AS T1
LEFT JOIN Table2 AS T2
ON T1.ValueField = T2.ValueField
WHERE T2.KeyField IS NOT NULL; -- CHANGED TO NOT NULL
OPEN CursorName FETCH NEXT FROM CursorName
INTO @KeyField, @ValueField
WHILE (@@FETCH_STATUS = 0)
BEGIN
INSERT INTO Table2 (KeyField, ValueField)
SELECT @KeyField, @ValueField
SELECT @KeyField, @ValueField
FETCH NEXT FROM CursorName
INTO @KeyField, @ValueField
SET @counter += 1
END
CLOSE CursorName
DEALLOCATE CursorName;
SELECT @counter;