【SQL】UPDATE文の書き方|WHERE・複数列更新と安全な実行手順
「社員の名前を直したい」「部署名をまとめて変えたい」。そんなときに使うのがSQLのUPDATE文です。SETで「何を変えるか」、WHEREで「どの行を変えるか」を決めます。まずは1人の名前を変える例から見ていきましょう。
実行前にここだけ確認
WHEREを省略すると全行が更新対象になります。 実行前に同じ条件のSELECTで対象を確認しましょう。この記事の実行例はSQL Server LocalDB+SSMS向けです。
UPDATE文の基本構文:SETとWHEREの役割
UPDATE テーブル名
SET 列名 = 新しい値
WHERE 更新条件;例えば「社員IDが1の氏名だけを変更する」なら、次のように書きます。まだ練習用テーブルがない場合は、後の準備手順から始めてください。
UPDATE dbo.Employees
SET EmployeeName = N'山田一郎'
WHERE EmployeeId = 1;SET:EmployeeName → 氏名の列だけ
ID 2~4の行はそのままです。図は架空データによる説明用で、実際の操作画面ではありません。
| 句 | 決めること | この例 |
|---|---|---|
| UPDATE | どのテーブルか | dbo.Employees |
| SET | どの列を何に変えるか | EmployeeNameを山田一郎へ |
| WHERE | どの行を変えるか | EmployeeIdが1の行 |
UPDATEで変えられるのは、すでにある行の値です。行の追加はINSERT、行の削除はDELETEを使います。UPDATEで列そのものを増やすわけではありません。
複数列の更新と複数行の更新は別の操作
部署・年齢・給与をまとめて変更
SETをカンマで区切る
対象はWHEREで1行に限定
同じ部署名の変更を適用
WHEREに一致する行すべてが対象
1文=1行とは限らない
ここは少し混同しやすいところです。1人の「部署と給与」を変えるのは複数列の更新。「営業部の全員」を変えるのは複数行の更新です。どの項目を変えるのかと、誰を対象にするのかを分けて考えると整理しやすくなります。もちろん、両方を同時に指定することもできます。
SQL Server+SSMSで練習用データを準備する
ここからは練習用のデータベースを用意して進めます。SqlPracticeDBやEmployeesがすでにある場合は、何に使っているか確認し、削除・上書きは避けてください。別名のDBを作る場合は、後に出てくるUSEの名前も合わせます。
Windows 11、SQL Server LocalDB、SSMSを使う前提です。接続先は (LocalDB)\MSSQLLocalDB。未設定の方はLocalDBとSSMSの接続手順を先に確認してください。画面の配置はバージョンによって異なります。
1.データベースとテーブルを作成
SSMSで「新しいクエリ」を開き、次を実行します。GOはSSMSなどが解釈するバッチ区切りで、SQL文そのものではありません。C#から実行するときはGOを送らず、処理を分けます。
CREATE DATABASE SqlPracticeDB;
GO
USE SqlPracticeDB;
GO
CREATE TABLE dbo.Employees
(
EmployeeId INT PRIMARY KEY,
EmployeeName NVARCHAR(50) NOT NULL,
Department NVARCHAR(50) NOT NULL,
Age INT NOT NULL,
Salary INT NOT NULL
);社員IDを主キーにし、日本語の氏名・部署はNVARCHARで保持します。ここで使う社員名・年齢・給与はすべて説明用の架空データです。
2.4行の初期データを登録
INSERT INTO dbo.Employees
(EmployeeId, EmployeeName, Department, Age, Salary)
VALUES
(1, N'山田太郎', N'営業部', 28, 300000),
(2, N'佐藤花子', N'開発部', 32, 380000),
(3, N'鈴木一郎', N'営業部', 40, 450000),
(4, N'高橋美咲', N'総務部', 25, 280000);
SELECT * FROM dbo.Employees ORDER BY EmployeeId;| ID・氏名 | 部署 | 年齢 | 給与 |
|---|---|---|---|
| 1 山田太郎 | 営業部 | 28 | 300000 |
| 2 佐藤花子 | 開発部 | 32 | 380000 |
| 3 鈴木一郎 | 営業部 | 40 | 450000 |
| 4 高橋美咲 | 総務部 | 25 | 280000 |
SQL ServerのUnicode文字列はN付きのシングルクォートで記述します。上の表は初期データの想定結果です。CREATE TABLEとINSERTは初回だけ実行してください。同じIDを再登録すると主キー重複のエラーになります。
UPDATEの実践:1行・複数列・複数行を更新
準備ができたら、例1~5を同じ練習用DBで上から順に1回ずつ試してみましょう。SSMSでは選択した範囲だけを実行できます。まず先頭のSELECTで対象を見て、問題なければUPDATE、その後にもう一度SELECTで結果を見る、という順番です。SELECTの書き方を確認したい方はSELECT文の使い方も参考にしてください。
例1:WHEREで特定の1行を更新する
まずはID 1の人だけ、名前を変えてみましょう。対象を決めるのは主キーのEmployeeIdです。部署・年齢・給与は変えません。冒頭の例をすでに実行していれば、同じ名前をもう一度設定することになります。
-- まず、このSELECTだけを実行して対象を確認
SELECT * FROM dbo.Employees WHERE EmployeeId = 1;
-- 対象が正しければ更新
UPDATE dbo.Employees
SET EmployeeName = N'山田一郎'
WHERE EmployeeId = 1;
-- UPDATEの直後に件数、続いて結果を確認
SELECT @@ROWCOUNT AS UpdatedRows;
SELECT * FROM dbo.Employees WHERE EmployeeId = 1;確認するのは、UpdatedRowsが1になり、氏名が山田一郎に変わっているかどうかです。@@ROWCOUNTが返すのは直前の文の影響行数なので、UPDATEとの間に別のSELECTやPRINTを挟むと、見たい件数ではなくなってしまいます。同じ値を設定した行も数えるため、「実際に値が変わった件数」とは限らない点にも注意してください。
例2:複数カラムをカンマで区切って更新する
次はID 2の部署・年齢・給与をまとめて変えます。SETを何度も書く必要はありません。変更したい列をカンマでつなげれば大丈夫です。最後の列の後にはカンマを付けないようにしましょう。
SELECT * FROM dbo.Employees WHERE EmployeeId = 2;
UPDATE dbo.Employees
SET Department = N'企画部',
Age = 33,
Salary = 400000
WHERE EmployeeId = 2;
SELECT * FROM dbo.Employees WHERE EmployeeId = 2;| ID 2の項目 | 更新前 | 更新後 |
|---|---|---|
| 部署 | 開発部 | 企画部 |
| 年齢 | 32 | 33 |
| 給与 | 380000 | 400000 |
例3:条件に一致する複数行をまとめて更新する
今度は営業部の2人を、まとめて営業企画部へ変更します。ここで気を付けたいのは、最後のSELECTです。更新後には「営業部」という名前では見つからなくなるので、「営業企画部」で確認します。
SELECT * FROM dbo.Employees
WHERE Department = N'営業部';
UPDATE dbo.Employees
SET Department = N'営業企画部'
WHERE Department = N'営業部';
SELECT * FROM dbo.Employees
WHERE Department = N'営業企画部';この例では、ID 1・3の2行が更新対象です。特定のIDを複数指定するなら、WHERE EmployeeId IN (1, 3) という条件でも絞れます。
例4:現在の値に加算して更新する
SELECT EmployeeId, Salary FROM dbo.Employees
WHERE Department = N'営業企画部';
UPDATE dbo.Employees
SET Salary = Salary + 10000
WHERE Department = N'営業企画部';
SELECT EmployeeId, Salary FROM dbo.Employees
WHERE Department = N'営業企画部';1回実行した場合、ID 1は300000→310000、ID 3は450000→460000になります。右辺のSalaryは更新前の値です。ここは名前の変更とは違い、もう一度実行すると、さらに10000増えてしまいます。 結果を見直すときは、最後のSELECTだけを実行しましょう。
例5:AND・ORで更新条件を組み合わせる
営業企画部かつ40歳以上のID 3だけ、給与を20000増やします。ANDは両方の条件を満たす行、ORはどちらかを満たす行を対象にします。混在させるときは括弧で意図を明確にします。
SELECT EmployeeId, Age, Salary FROM dbo.Employees
WHERE Department = N'営業企画部' AND Age >= 40;
UPDATE dbo.Employees
SET Salary = Salary + 20000
WHERE Department = N'営業企画部' AND Age >= 40;
SELECT EmployeeId, Age, Salary FROM dbo.Employees
WHERE Department = N'営業企画部' AND Age >= 40;例4まで進めていれば、ID 3の給与は460000→480000になります。例えば「営業部または開発部、かつ40歳以上」なら、部署のOR条件全体を括弧で囲み、その外側で年齢の条件をANDで結びます。
練習後の結果を一覧で確認
| ID | 氏名・部署 | 年齢 | 給与 |
|---|---|---|---|
| 1 | 山田一郎・営業企画部 | 28 | 310000 |
| 2 | 佐藤花子・企画部 | 33 | 400000 |
| 3 | 鈴木一郎・営業企画部 | 40 | 480000 |
| 4 | 高橋美咲・総務部 | 25 | 280000 |
例1~5を各1回実行した場合の想定結果です。順番を変えたり加算を繰り返したりすると結果が異なります。
全件更新とROLLBACK:取り消せる条件を知る
WHEREを省略したUPDATEは全行を対象にします。自動コミットで確定した更新は、後からROLLBACKを書いても取り消せません。 SQL Serverは既定では自動コミットで動作します。取り消しを練習する場合は、更新前に明示的なトランザクションを開始します。
→ UPDATE
変更を確定する
未確定の変更を戻す
次は全行の給与を一時的に300000にし、同じコード内で取り消す練習です。未完了のトランザクションがない、練習用の新しいクエリ接続で実行してください。
USE SqlPracticeDB;
GO
BEGIN TRANSACTION;
UPDATE dbo.Employees
SET Salary = 300000; -- 練習用:全行が対象
SELECT @@ROWCOUNT AS UpdatedRows;
SELECT EmployeeId, Salary FROM dbo.Employees ORDER BY EmployeeId;
ROLLBACK TRANSACTION; -- この例では必ず取り消す
SELECT EmployeeId, Salary FROM dbo.Employees ORDER BY EmployeeId;最初の結果では給与が全員300000になり、ROLLBACK後の結果では実行前の給与に戻る想定です。例1~5の後なら、最後の一覧は310000・400000・480000・280000になります。
変更を残したい場合は、同じ接続で結果を確認してからCOMMITを実行します。取り消すならROLLBACKです。両方を順番に実行するわけではありません。途中でエラーになってもトランザクションが残る場合があるので、終了しているかを確認し、必要なら取り消してください。
トランザクションを開いたまま席を離れると、ロックで他の処理を待たせる場合があります。本番ではバックアップ・実行権限・同時更新・エラー処理も含めて設計してください。詳しくはROLLBACKの使い方とCOMMITの使い方を参照してください。
応用:行ごとに別の値を設定するCASE
ID 1と3で異なる給与を設定する例です。WHEREで対象を絞り、CASEで行ごとの設定値を分けます。練習後のデータを残せるよう、この例も最後にROLLBACKします。
BEGIN TRANSACTION;
UPDATE dbo.Employees
SET Salary = CASE EmployeeId
WHEN 1 THEN 320000
WHEN 3 THEN 490000
ELSE Salary
END
WHERE EmployeeId IN (1, 3);
SELECT EmployeeId, Salary FROM dbo.Employees
WHERE EmployeeId IN (1, 3);
ROLLBACK TRANSACTION;CASEは「どの値にするか」を分けるもので、対象の行を絞る役目はWHEREです。また、ELSEを省略すると、どの条件にも当てはまらない場合はNULLになります。この例ではELSE Salaryとして、元の給与を残す形にしています。
更新できない・0件になるときの確認表
| 現象 | まず確認すること |
|---|---|
| 0行更新 | 同じWHERE条件でSELECT。前の例で部署名を変えていないか、接続先DBが正しいかを確認。 |
| 全行・想定以上の行が更新 | WHEREの省略、ORの括弧、条件の広さを確認。未確定なら同じ接続でROLLBACK。確定後は管理者と復旧手順を検討。 |
| Invalid object name | DB・スキーマ・テーブル名を確認。練習例はSqlPracticeDBのdbo.Employees。 |
| Invalid column name | 列名の綴りを確認。テーブル名ではなく列名をSETに書く。 |
| Conversion failed | 数値列に文字を渡していないか、値と列の型を確認。 |
| Cannot insert the value NULL | NOT NULL列にはNULLを設定できない。エラー回避だけのために制約を外さず、設計に合う値を使う。 |
| 処理が長く終わらない | 別接続のトランザクション、ロック待ち、対象件数を確認。原因不明のまま繰り返し実行しない。 |
| 権限エラー | 対象へのUPDATE権限などを確認。必要な権限は管理者に相談。 |
NULLは「= NULL」ではなく「IS NULL」で判定
NULLを含む行の検索にはIS NULLを使います。NULLを設定する際も、文字列の「’NULL’」とは区別します。本記事のEmployeesは全列NOT NULLなので、NULLの更新例をそのまま当てはめないでください。
| 目的 | 書き方の考え方 |
|---|---|
| NULLの行を対象にする | WHERE 対象列 IS NULL |
| NULLでない行を対象にする | WHERE 対象列 IS NOT NULL |
| 値をNULLにする | SET 対象列 = NULL(NULL許可列のみ) |
よくある質問
別テーブルの値を使って更新できますか?
できます。SQL ServerならUPDATE…FROMやサブクエリを使います。ただし、JOINを使う書き方はDB製品によって違います。また、更新する1行に参照元の複数行が対応すると、どの値が使われるか決まらない場合があります。先にSELECTで結合結果を見て、1行に絞れているか確認しておくと安心です。
MySQL・PostgreSQLでも同じコードを使えますか?
単純なUPDATE・SET・WHEREの考え方は共通ですが、本記事のN付き文字列、dbo、GO、@@ROWCOUNT、トランザクション例はSQL Server向けです。他のDBへはそのまま貼り付けず、各製品の構文を確認してください。
UPDATE後にROLLBACKすれば必ず元に戻せますか?
いいえ。ROLLBACKで取り消せるのは、まだ確定していないトランザクション内の変更です。自動コミットやCOMMITで確定した変更を、通常のROLLBACKで戻すことはできません。
まとめ:実行前の対象確認と実行後の件数確認
まずは「SETで何を変えるか、WHEREでどの行を変えるか」を押さえれば大丈夫です。実行前にSELECTで対象を確認し、更新後に件数と値を見直す。このひと手間を習慣にしておくと、意図しない更新に気付きやすくなります。慣れてきたら、複数列の更新やCASEの例も試してみてください。
参考:SQL Server公式資料
UPDATEの構文 / @@ROWCOUNT / トランザクション / CASE式
図・表は架空のデータによる説明用です。結果は公式資料とコードをもとにした想定で、SQL Server・SSMSでの実行確認はしていません。
サイトアイコン-2-150x150.png)