データベース操作において、同じ処理を繰り返し実行したい場面は少なくありません。
SQL Serverでは、T-SQLのWHILE文やCURSORを使ってループ処理を実現できます。
本記事では、初心者向けに基本的なループ処理の使い方をわかりやすく解説します。最後に演習問題と解答例も用意しているので、学んだ内容をすぐに試してみましょう。
ループ処理の概要
プログラミング言語ではforやwhileといった繰り返し構文が一般的ですが、T-SQLでは主にWHILEとCURSORが用いられます。
- WHILE: 条件を満たす間、処理を繰り返す
- CURSOR: 結果セットの各行に対して順番に処理を実行する
どちらも状況に応じて使い分けることで、効率よくデータ操作ができます。
WHILEループの基本
WHILEは条件をチェックし、TRUEの間はブロック内のSQLを繰り返し実行します。
DECLARE @i INT = 1;
WHILE @i <= 5
BEGIN
PRINT CONCAT('現在のカウント: ', @i);
SET @i = @i + 1;
END;
上記の例では、@iが1から5まで増加しながら、メッセージを5回出力します。
ポイント
- ループ変数(ここでは@i)の初期化を忘れない
- 条件を必ずFALSEにできるように、変数の更新を行う
BREAK/CONTINUEによる制御
ループ内で途中終了や次の繰り返しへスキップしたい場合、BREAKやCONTINUEを使います。
DECLARE @i INT = 1;
WHILE @i <= 10
BEGIN
IF @i = 4
BREAK; -- ループを抜ける
IF @i % 2 = 0
BEGIN
SET @i = @i + 1;
CONTINUE; -- 次の繰り返しへ
END;
PRINT @i;
SET @i = @i + 1;
END;
この例では、@iが4になったらループを抜け、偶数はスキップして奇数のみを表示します。
CURSORを使った行単位ループ
CURSORは、SELECT結果の各行に対して繰り返し処理を行えます。大量データには不向きですが、行ごとに個別処理が必要なときに便利です。
DECLARE user_cursor CURSOR FOR
SELECT UserID, UserName FROM dbo.Users;
DECLARE @uid INT;
DECLARE @uname NVARCHAR(50);
OPEN user_cursor;
FETCH NEXT FROM user_cursor INTO @uid, @uname;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT CONCAT('処理中ユーザー: ', @uname, ' (ID=', @uid, ')');
-- ここに各行に対する処理を記述
FETCH NEXT FROM user_cursor INTO @uid, @uname;
END;
CLOSE user_cursor;
DEALLOCATE user_cursor;
注意点
- 使用後は必ずCLOSEとDEALLOCATEを実行する
- 大量データの場合、パフォーマンスに注意する
実践例:連番レコードの更新
テーブルdbo.Sequencesに連番を振り直す例です。
-- サンプルテーブル作成
CREATE TABLE dbo.Sequences (
SeqID INT IDENTITY(100,1) PRIMARY KEY,
Value NVARCHAR(100)
);
-- ダミーデータ挿入
INSERT INTO dbo.Sequences (Value)
VALUES (N'ItemA'), (N'ItemB'), (N'ItemC');
-- 連番更新用変数
DECLARE @newSeq INT = 1;
-- WHILEで更新
WHILE EXISTS (SELECT 1 FROM dbo.Sequences WHERE SeqID <> @newSeq)
BEGIN
UPDATE dbo.Sequences
SET SeqID = @newSeq
WHERE SeqID = (SELECT MIN(SeqID) FROM dbo.Sequences WHERE SeqID <> @newSeq);
SET @newSeq = @newSeq + 1;
END;
このコードは、SeqIDを1から順に振り直します。
演習問題
- 問題1
WHILE文を使い、1から10までの偶数のみを出力するスクリプトを作成してください。 - 問題2
テーブルdbo.Products(ProductID INT, Price DECIMAL(10,2))から、価格が1000円以上の商品だけをカウントし、その数を変数に格納するWHILEループを作成してください。 - 問題3
CURSORを使って、テーブルdbo.Orders(OrderID, OrderDate)の各行をループ処理し、OrderDateが休日(土日)であればコンソールに「休日注文: OrderID」を出力するスクリプトを作成してください。
解答例
解答1
DECLARE @i INT = 1;
WHILE @i <= 10
BEGIN
IF @i % 2 = 0
PRINT @i;
SET @i = @i + 1;
END;
解答2
DECLARE @count INT = 0;
DECLARE @i INT = 1;
DECLARE @maxId INT;
SELECT @maxId = MAX(ProductID) FROM dbo.Products;
WHILE @i <= @maxId
BEGIN
IF EXISTS (SELECT 1 FROM dbo.Products WHERE ProductID = @i AND Price >= 1000)
SET @count = @count + 1;
SET @i = @i + 1;
END;
PRINT CONCAT('1000円以上の商品数: ', @count);
解答3
DECLARE order_cursor CURSOR FOR
SELECT OrderID, OrderDate FROM dbo.Orders;
DECLARE @oid INT;
DECLARE @odate DATE;
OPEN order_cursor;
FETCH NEXT FROM order_cursor INTO @oid, @odate;
WHILE @@FETCH_STATUS = 0
BEGIN
IF DATEPART(WEEKDAY, @odate) IN (1, 7)
PRINT CONCAT('休日注文: ', @oid);
FETCH NEXT FROM order_cursor INTO @oid, @odate;
END;
CLOSE order_cursor;
DEALLOCATE order_cursor;
まとめ
本記事では、SQL Serverにおける基本的なループ処理であるWHILE文とCURSORの使い方を紹介しました。
BREAKやCONTINUEによる制御、実践的な連番更新例も解説しました。演習問題でしっかり手を動かし、ループ処理をマスターしましょう!