SQLでデータを更新したあとに、「更新するデータを間違えた」「実行結果を確認してから確定したい」と思うことがあります。

そのような場面で使用するのが、ROLLBACKです。

ROLLBACKを使用すると、トランザクション内で実行したUPDATEやINSERT、DELETEなどの変更を取り消し、処理を実行する前の状態に戻せます。

ただし、通常のUPDATE文をそのまま実行したあとから、いつでも取り消せるわけではありません。事前にBEGIN TRANSACTIONでトランザクションを開始する必要があります。

この記事では、SQL Server LocalDBとSQL Server Management Studioを使用し、テーブルの作成からUPDATE、ROLLBACK、COMMITまでを実際に操作しながら解説します。

この記事でわかること

この記事では、SSMSを使ってROLLBACKの基本的な使い方を確認します。

  • SQL Serverにおけるトランザクションの仕組み
  • BEGIN TRANSACTIONの使い方
  • UPDATEしたデータをROLLBACKで取り消す方法
  • UPDATEしたデータをCOMMITで確定する方法
  • SSMSで更新前後のデータを確認する方法
  • ROLLBACKできないケース
  • トランザクションを閉じ忘れた場合の注意点

ROLLBACKだけでなく、BEGIN TRANSACTION、COMMIT、SELECTを組み合わせた確認手順まで説明します。

動作環境

この記事では、Windows環境でSQL Server LocalDBとSSMSを使う前提で進めます。

バージョンは一例です。環境によって画面表示や細かい操作が異なる場合があります。

項目内容
OSWindows 11
SQL ServerSQL Server LocalDB
管理ツールSQL Server Management Studio(SSMS)
接続先(LocalDB)\MSSQLLocalDB
使用言語SQL

環境構築ができていない場合は、以下を参考にしてください。
また、C#.NETで実行したい方は本記事と以下の記事を見ながら試行してみてください。

完成イメージ

この記事では、商品情報を管理するProductsテーブルを作成し、商品の価格を更新します。

最初に、次のデータを登録します。

ProductIdProductNamePrice
1ノートパソコン100000
2マウス3000
3キーボード5000

その後、ノートパソコンの価格を100000円から120000円に変更します。

ただし、すぐには確定せず、BEGIN TRANSACTIONで更新処理を一時的な状態にするのがポイントです。

処理の流れは次のとおりです。

  1. Productsテーブルを作成する
  2. 初期データを登録する
  3. BEGIN TRANSACTIONを実行する
  4. UPDATEで価格を変更する
  5. SELECTで変更結果を確認する
  6. ROLLBACKで変更を取り消す
  7. 再度SELECTし、価格が元に戻ったことを確認する
  8. 最後にCOMMITで変更を確定する例も確認する

最終的には、更新内容を確認してから取り消すか確定するかを選べる状態を作ります。

ROLLBACKの実践

ここからは、SSMSを使用して実際にROLLBACKの動きを確認します。

上から順番にSQLを実行してください。

学習用データベースを作成する

まずは、ROLLBACKの動作を確認するためのデータベースを作成します。

既存のデータベースを触らず、練習用のデータベースを作ると安全です。

SSMSで新しいクエリを開き、以下のSQLを実行します。

CREATE DATABASE RollBackDB;

実行後、左側のデータベース一覧を更新すると、RollBackDBが表示されます。

RollBackDBの作成画像

作成したデータベースを使うために、以下のSQLも実行します。

USE RollBackDB;

これで、以降のSQLはRollBackDBに対して実行されます。

Productsテーブルを作成する

続いて、RollBackDBの中にProductsテーブルを作成します。

Productsテーブルでは、商品ID、商品名、価格を管理します。

CREATE TABLE Products
(
    ProductId INT NOT NULL PRIMARY KEY,
    ProductName NVARCHAR(100) NOT NULL,
    Price INT NOT NULL
);

各カラムの内容は次のとおりです。

カラム名データ型内容
ProductIdINT商品を識別するID
ProductNameNVARCHAR(100)商品名
PriceINT商品価格

ProductIdにはPRIMARY KEYを設定しています。

PRIMARY KEYは、同じ値を重複して登録できないようにする制約です。

商品ごとに一意のIDを持たせるための設定と考えると分かりやすいです。

テーブル作成画像

サンプルデータを登録する

Productsテーブルに、ROLLBACKの確認で使用するデータを登録します。

次のINSERT文で3件の商品データをまとめて登録します。

INSERT INTO Products
(
    ProductId,
    ProductName,
    Price
)
VALUES
    (1, N'ノートパソコン', 100000),
    (2, N'マウス', 3000),
    (3, N'キーボード', 5000);

日本語の文字列には、文字化けを防ぐためにNを付けています。

テーブルデータの登録

登録したデータを確認するため、次のSELECT文を実行します。

SELECT
    ProductId,
    ProductName,
    Price
FROM Products
ORDER BY ProductId;

実行結果は次のようになり、3件のデータが表示されれば準備完了です。

テーブルデータの確認

すでに同じProductIdのデータが登録されている場合は、PRIMARY KEYの重複エラーが発生します。その場合は、既存のデータを削除するか、ProductIdを変更してください。

ROLLBACKの基本構文を確認する

SQL ServerでROLLBACKを使用する場合は、次の流れで記述します。

BEGIN TRANSACTIONからROLLBACKまでが1つの処理単位になります。

BEGIN TRANSACTION;

-- 更新処理

ROLLBACK TRANSACTION;

BEGIN TRANSACTIONは、トランザクションの開始を表します。

ROLLBACK TRANSACTIONは、BEGIN TRANSACTION以降に実行した変更を取り消します。

省略形として、次の書き方も使用できます。

BEGIN TRAN;

-- 更新処理

ROLLBACK TRAN;

この記事では、処理内容が分かりやすいように、BEGIN TRANSACTIONとROLLBACK TRANSACTIONを省略せずに記述します。

BEGIN TRANSACTIONで更新処理を開始する

ここから、実際に商品の価格を変更します。

まずは、次のSQLをまとめて実行してください。
※この時点ではROLLBACKをまだ実行しません。

BEGIN TRANSACTION;

UPDATE Products
SET Price = 120000
WHERE ProductId = 1;

SELECT
    ProductId,
    ProductName,
    Price
FROM Products
ORDER BY ProductId;

実行すると、ProductIdが1のノートパソコンの価格が120000に変わります。

BEGIN TRANSACTIONで更新処理を開始する画像

ただし、現在の更新はまだCOMMITされていません。
つまり、同じSSMSのセッション内では変更後のデータが見えるものの、まだ確定していない状態です。

ROLLBACKでUPDATEを取り消す

価格が120000に変更されていることを確認したら、次のSQLを実行します。

ROLLBACK TRANSACTIONによって、直前のUPDATEを取り消します

ROLLBACK TRANSACTION;

ROLLBACKを実行しただけでは、結果グリッドに商品データは表示されません。

ROLLBACKでUPDATEを取り消す画像

そのため、続けてSELECT文を実行し、データを確認します。

SELECT
    ProductId,
    ProductName,
    Price
FROM Products
ORDER BY ProductId;

実行結果は次のようになります。

ROLLBACKでUPDATEを取り消したこを確認する画像

ノートパソコンの価格が120000から100000に戻っています。

これで、UPDATEによる変更が正常に取り消されたことを確認できました。

UPDATEからROLLBACKまでをまとめて実行する

実際の確認作業では、BEGIN TRANSACTIONからROLLBACKまでを1つのSQLとして記述することもできます。

次のSQLを実行してください。

更新前、更新後、ROLLBACK後の3段階を確認できるSQLです。

-- 更新前のデータを確認
SELECT
    ProductId,
    ProductName,
    Price
FROM Products
WHERE ProductId = 1;

-- トランザクションを開始
BEGIN TRANSACTION;

-- 価格を変更
UPDATE Products
SET Price = 120000
WHERE ProductId = 1;

-- 更新後のデータを確認
SELECT
    ProductId,
    ProductName,
    Price
FROM Products
WHERE ProductId = 1;

-- 更新を取り消す
ROLLBACK TRANSACTION;

-- ROLLBACK後のデータを確認
SELECT
    ProductId,
    ProductName,
    Price
FROM Products
WHERE ProductId = 1;

結果グリッドには、SELECT文ごとに3つの結果が表示されます。

UPDATEからROLLBACKまでをまとめて実行する画像

この流れを確認すると、ROLLBACKが単純に逆方向のUPDATEを実行しているのではなく、トランザクション内の変更そのものを取り消していることが分かります。

複数のUPDATEをまとめてROLLBACKする

1つのトランザクション内では、複数の更新処理を実行できます。

次のSQLでは、3つの商品の価格を変更したあと、すべての変更をROLLBACKします。ROLLBACKはトランザクション内の複数の変更をまとめて取り消せます

BEGIN TRANSACTION;

UPDATE Products
SET Price = 110000
WHERE ProductId = 1;

UPDATE Products
SET Price = 3500
WHERE ProductId = 2;

UPDATE Products
SET Price = 6000
WHERE ProductId = 3;

SELECT
    ProductId,
    ProductName,
    Price
FROM Products
ORDER BY ProductId;

ROLLBACK TRANSACTION;

SELECT
    ProductId,
    ProductName,
    Price
FROM Products
ORDER BY ProductId;

ROLLBACK前は、次の価格になり、ROLLBACK後は、すべて元の価格に戻ります。

複数のUPDATEをまとめてROLLBACKする画像

一連の処理をまとめてトランザクションにすることで、一部のデータだけが変更された中途半端な状態を防止できます。

COMMITでUPDATEを確定する

ROLLBACKは変更を取り消しますが、変更内容に問題がなければCOMMITで確定します。

次のSQLを実行してください。

BEGIN TRANSACTION;

UPDATE Products
SET Price = 120000
WHERE ProductId = 1;

SELECT
    ProductId,
    ProductName,
    Price
FROM Products
WHERE ProductId = 1;

COMMIT TRANSACTION;

COMMIT TRANSACTIONを実行すると、価格の変更が確定します

COMMITでUPDATEを確定する画像

続けて、次のSELECT文を実行します。

SELECT
    ProductId,
    ProductName,
    Price
FROM Products
WHERE ProductId = 1;

Priceが120000のままであれば、更新は確定されています。

COMMITでUPDATEを確定したことを確認する画像

COMMIT後にROLLBACKを実行しても、この更新は元に戻りません。

※COMMITについてわからない方は以下の記事を参考にしてください。

トランザクションが残っていないか確認する

BEGIN TRANSACTIONを実行したあと、COMMITやROLLBACKを忘れることがあります。

現在のセッションでトランザクションが開始されているかは、@@TRANCOUNTを使用して確認できます。

SELECT @@TRANCOUNT AS TransactionCount;

結果の意味は次のとおりです。

トランザクションが残っていないか確認する画像

通常、作業が完了したあとは0になっている状態が正常です。

TransactionCount状態
0トランザクションは開始されていない
1以上トランザクションが開始されている

1以上の場合は、処理内容を確認したうえでCOMMITまたはROLLBACKを実行します。

安全にUPDATEする基本形を確認する

実務でUPDATEを実行するときは、いきなり更新するのではなく、対象データをSELECTで確認してから実行する方法が安全です。

次のSQLは、UPDATE対象を確認し、トランザクション内で更新したあと、ROLLBACKする基本形です。

WHERE句の対象確認とROLLBACKを組み合わせた安全な実行例です。

-- 更新対象を確認
SELECT
    ProductId,
    ProductName,
    Price
FROM Products
WHERE ProductId = 2;

-- トランザクションを開始
BEGIN TRANSACTION;

-- データを更新
UPDATE Products
SET Price = 4000
WHERE ProductId = 2;

-- 更新件数を確認
SELECT @@ROWCOUNT AS UpdatedRowCount;

-- 更新後のデータを確認
SELECT
    ProductId,
    ProductName,
    Price
FROM Products
WHERE ProductId = 2;

-- 今回は確認用のため取り消す
ROLLBACK TRANSACTION;

-- 元に戻ったことを確認
SELECT
    ProductId,
    ProductName,
    Price
FROM Products
WHERE ProductId = 2;

@@ROWCOUNTでは、直前のSQLによって影響を受けた行数を確認できます。

UpdatedRowCountが1であれば、1件更新されています。

想定より多い件数が表示された場合は、COMMITせずにROLLBACKすることで誤更新を防げます。

よくあるエラー・注意点

ROLLBACKを使用するときは、SQLの書き方だけでなく、トランザクションの開始状態と終了状態にも注意が必要です。

初心者がつまずきやすいエラーと対処方法をまとめます。

エラー・現象主な原因対処方法
ROLLBACKを実行しても元に戻らないBEGIN TRANSACTIONを実行せず、UPDATEがすでに確定されている更新前にBEGIN TRANSACTIONを実行する
COMMIT後にROLLBACKできないCOMMITによって変更が確定済みバックアップからの復元や逆更新を検討する
「対応するBEGIN TRANSACTIONがありません」と表示されるトランザクションが開始されていない状態でROLLBACKを実行した@@TRANCOUNTでトランザクション数を確認する
UPDATE後に別の処理が止まったCOMMITまたはROLLBACKを実行しておらず、ロックが残っているトランザクションを終了する
想定以上のデータが更新されたWHERE句が不足している、または条件が間違っているCOMMITせずにROLLBACKし、WHERE句を修正する
Productsテーブルが見つからない使用中のデータベースがSampleDBではないUSE SampleDBを実行する
PRIMARY KEYの重複エラーが発生する同じProductIdのデータがすでに存在する既存データを確認し、IDを変更する
SSMSからLocalDBに接続できないLocalDBが未導入、停止中、またはインスタンス名が異なるsqllocaldb infoでインスタンス名を確認する
SELECTでは変更後の値が見える同じセッション内では未確定の変更を参照できるCOMMITまたはROLLBACK後に再確認する
クエリウィンドウを閉じられない、警告が出る未完了のトランザクションが残っている可能性がある@@TRANCOUNTを確認し、必要に応じてROLLBACKする

BEGIN TRANSACTIONを実行しないとROLLBACKできない

SQL Serverでは、通常のUPDATE文は1つのトランザクションとして自動的に処理されます。

そのため、次のようにUPDATEだけを実行すると、実行後にROLLBACKしても元に戻せません

UPDATE Products
SET Price = 200000
WHERE ProductId = 1;

安全に確認する場合は、次のようにBEGIN TRANSACTIONを付けます。

BEGIN TRANSACTION;

UPDATE Products
SET Price = 200000
WHERE ProductId = 1;

ROLLBACK TRANSACTION;

更新前にトランザクションを開始することが、ROLLBACKを使用するための前提条件です。

COMMIT後はROLLBACKできない

COMMIT TRANSACTIONを実行すると、トランザクション内の変更が確定します。

確定後にROLLBACK TRANSACTIONを実行しても、COMMIT前の状態には戻りません

BEGIN TRANSACTION;

UPDATE Products
SET Price = 200000
WHERE ProductId = 1;

COMMIT TRANSACTION;

この処理のあとに元へ戻すには、価格を再度UPDATEするなど、別の処理が必要です。

本番環境ではバックアップや監査ログが必要になる場合もあります。復旧方法はシステム構成によって異なるため、事前のバックアップ方針を確認することが重要です。

WHERE句なしのUPDATEに注意する

UPDATE文でWHERE句を省略すると、テーブル内のすべての行が更新されます。

次のSQLは、全商品の価格を120000に変更します。

UPDATE Products
SET Price = 120000;

テスト目的であっても、WHERE句なしのUPDATEは重大な誤更新につながる可能性があります。

実行前に同じWHERE条件でSELECTし、対象件数を確認してください。

SELECT
    ProductId,
    ProductName,
    Price
FROM Products
WHERE ProductId = 1;

ROLLBACKを使える状態にしておくことも重要ですが、まずは誤った条件で更新しないことが最優先です。

トランザクションを長時間放置しない

BEGIN TRANSACTIONを実行したままCOMMITやROLLBACKを行わないと、SQL Server側でロックが保持される場合があります。

その結果、別のクエリや別ユーザーの更新処理が待機することがあります。

トランザクションを開始したあとは、必要な確認を短時間で終えるようにしてください。
作業後は、次のSQLでトランザクション数を確認します。

SELECT @@TRANCOUNT AS TransactionCount;

0以外の場合は、処理内容を確認し、COMMITまたはROLLBACKを実行します。

トランザクションを開始したまま離席しないことも重要です。

SSMSの別タブでは同じトランザクションを操作できない

SSMSで[新しいクエリ]を複数開くと、それぞれが別のセッションとして接続される場合があります。

あるクエリウィンドウでBEGIN TRANSACTIONを実行し、別のクエリウィンドウでROLLBACKを実行しても、別セッションのトランザクションは取り消せません

BEGIN TRANSACTION、UPDATE、SELECT、ROLLBACKは、基本的に同じクエリウィンドウで実行してください。

セッションの状況や接続方法は環境によって異なる場合がありますが、初心者のうちは1つのクエリウィンドウ内で完結させる方法が安全です。

まとめ

この記事では、SQL Server Management Studioを使用し、ROLLBACKでUPDATEを取り消す方法を解説しました。

ROLLBACKは、トランザクション内で実行した変更を取り消す命令です。

重要なポイントは次のとおりです。

  • BEGIN TRANSACTIONでトランザクションを開始する
  • UPDATE後にSELECTで変更内容を確認する
  • 変更を取り消す場合はROLLBACK TRANSACTIONを実行する
  • 変更を確定する場合はCOMMIT TRANSACTIONを実行する
  • COMMIT後の変更はROLLBACKできない
  • WHERE句と更新件数を必ず確認する
  • 作業後は@@TRANCOUNTが0になっていることを確認する
  • トランザクションを長時間放置しない

実務では、SELECTで対象確認、BEGIN TRANSACTION、UPDATE、結果確認、COMMITまたはROLLBACKという流れを習慣にすると、誤更新のリスクを減らせます。

ROLLBACKの使い方を理解したあとは、COMMIT、TRY…CATCH、@@TRANCOUNT、XACT_STATE、SAVE TRANSACTIONなどを学ぶと、より安全なトランザクション処理を作成できるようになります。