[SQL Server] カーソル(CURSOR)の使い方
カーソル(CURSOR)について簡単に例文と説明をしたいと思います。
個人的に「CURSOR」はあまり使いません。
でも、どうしてもという場合は使います。
まず、「CURSOR」を使う時の基本的なテンプレートは下記の通りです。
下記の部分で茶色になっている部分だけ修正して使えばいいです。
DECLARE @UserID varchar(25) -- #### 説明1
DECLARE @UserName nvarchar(20)
DECLARE DB_Cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT UserID, UserName FROM dbo.TempData1 -- #### 説明2
OPEN DB_Cursor
FETCH NEXT FROM DB_Cursor
INTO @UserID, @UserName -- #### 説明3
WHILE @@FETCH_STATUS = 0
BEGIN
-- #### 説明4 #### Start ####
UPDATE dbo.UserInfo
SET UserName = @UserName
WHERE UserID = @UserID
-- #### 説明4 #### End ####
FETCH NEXT FROM DB_Cursor
INTO @UserID, @UserName -- #### 説明5
END
CLOSE DB_Cursor
DEALLOCATE DB_Cursor
まずは「説明2」部分に「CURSOR」で使う原本データを準備します。
「説明2」は「SELECT UserID, UserName FROM dbo.TempData1」になっています。
例えば、「dbo.TempData1」テーブルに3件のデータがあれば3件データに対して処理を行います。
100件があるとしたら100件のデータを処理することになります。
ここで「dbo.TempData1」テーブルから「UserID」, 「UserName」カラムのデータのみ使用しています。
そしたらこのカラム数に合わせて「説明3」、「説明5」にも変数をしてする必要があります。
もし、カラム数と変数の数が一致しなかったら下記のようなエラーが発生します。
「カーソル フェッチ: INTO リストで宣言する変数の数は、選択される列の数と一致させてください。」
変数名はカラム名と違っても問題ありません。
「説明3」、「説明5」部分で変数を使うためには変数を指定する必要がありますので、
「説明1」で変数を指定しています。
「説明4」部分では「説明2」のデータを利用して「説明4」で処理を行うことです。
上記のSQLの動作を簡単にすると。。
「dbo.TempData1」テーブルにあるUserID, UserNameデータを元に
「dbo.UserInfo」テーブルに「dbo.TempData1」テーブルにある同じUserIDを持つデータのUserNameを変更する。
では、実際にテストしてみましょう。
下記にテスト用のSQLを準備しまいた。
1)UserInfoテーブルを作成及びデータを登録
USE tempdb
GO
-- テーブル作成
CREATE TABLE dbo.UserInfo
(
UserID varchar(25)
, UserName nvarchar(20)
, RegDate datetime
)
GO
-- データ登録
INSERT INTO dbo.UserInfo (UserID, UserName, RegDate)
SELECT 'test01', N'テスト01', '2010-01-01 00:00:00' UNION ALL
SELECT 'test02', N'テスト02', '2011-01-01 00:00:00' UNION ALL
SELECT 'test03', N'テスト03', '2012-01-01 00:00:00' UNION ALL
SELECT 'test04', N'テスト04', '2013-01-01 00:00:00' UNION ALL
SELECT 'test05', N'テスト05', '2014-01-01 00:00:00'
GO
-- データ確認
SELECT * FROM dbo.UserInfo
GO
2)カーソルで使う原本データTempData1テーブルを作成及びデータを登録
-- テーブル作成
CREATE TABLE dbo.TempData1
(
UserID varchar(25)
, UserName nvarchar(20)
)
GO
-- データ登録
INSERT INTO dbo.TempData1 (UserID, UserName)
SELECT 'test02', N'山田' UNION ALL
SELECT 'test03', N'鈴木' UNION ALL
SELECT 'test04', N'木村'
GO
-- データ確認
SELECT * FROM dbo.TempData1
GO
3)「CURSOR」で「dbo.TempData1」テーブルにある
UserIDのtest02, test03, test04のUserNameデータを元に
「dbo.UserInfo」テーブルから一致するUserIDのUserNameデータを修正する。
DECLARE @UserID varchar(25)
DECLARE @UserName nvarchar(20)
DECLARE DB_Cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT UserID, UserName FROM dbo.TempData1
OPEN DB_Cursor
FETCH NEXT FROM DB_Cursor
INTO @UserID, @UserName
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE dbo.UserInfo
SET UserName = @UserName
WHERE UserID = @UserID
FETCH NEXT FROM DB_Cursor
INTO @UserID, @UserName
END
CLOSE DB_Cursor
DEALLOCATE DB_Cursor
それではデータを確認してみましょう。
SELECT * FROM dbo.UserInfo
GO
どうですか?
「dbo.UserInfo」テーブルのtest02, test03, test04のUserNameは変更されたのが確認できましたか?
こういう感じで「CURSOR」が使える範囲は広いです。
だが、使い間違えると処理時間がかかり過ぎたり、負荷がかかり過ぎますので注意して使いましょう。
ここまでが「CURSOR」の説明で、上記の例文を「CURSOR」を使わないで同じ結果がでる処理方法を紹介したいと思います。
UPDATE dbo.UserInfo
SET UserName = B.UserName
FROM dbo.UserInfo AS A
JOIN dbo.TempData1 AS B
ON A.UserID = B.UserID
これで終わりです。
SQLは簡単でしょう??
このSQLが上記の「CURSOR」と同じ処理結果が出ます。
こっちの方が負荷もかからないし、処理速度も速いです。
今回は「CURSOR」について基本テンプレートと簡単な例文と一緒に説明をしました。