SQL Serverで始めるループ処理入門

データベース操作において、同じ処理を繰り返し実行したい場面は少なくありません。

SQL Serverでは、T-SQLのWHILE文やCURSORを使ってループ処理を実現できます。

本記事では、初心者向けに基本的なループ処理の使い方をわかりやすく解説します。最後に演習問題と解答例も用意しているので、学んだ内容をすぐに試してみましょう。


ループ処理の概要

プログラミング言語ではforやwhileといった繰り返し構文が一般的ですが、T-SQLでは主にWHILECURSORが用いられます。

  • 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による制御

ループ内で途中終了や次の繰り返しへスキップしたい場合、BREAKCONTINUEを使います。

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. 問題1
    WHILE文を使い、1から10までの偶数のみを出力するスクリプトを作成してください。
  2. 問題2
    テーブルdbo.Products(ProductID INT, Price DECIMAL(10,2))から、価格が1000円以上の商品だけをカウントし、その数を変数に格納するWHILEループを作成してください。
  3. 問題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による制御、実践的な連番更新例も解説しました。演習問題でしっかり手を動かし、ループ処理をマスターしましょう!