SQLを書いていて、次のような悩みを感じたことはありませんか?
- 別テーブルの値を参照しながらUPDATEしたい
- SELECT結果をもとに、安全かつ効率的にデータを更新したい
- JOINやサブクエリ、どの書き方が正解なのか分からない
- 本番環境でUPDATEを実行するのが怖い(全件更新の事故が不安)
SELECT結果を利用したUPDATE(いわゆる sql update select) は、実務で頻出する一方で、事故やパフォーマンス劣化が起きやすい領域です。
理解が浅いまま使うと、取り返しのつかないデータ更新につながることもあります。
この記事では、
- UPDATE × SELECTの基本構造
- サブクエリ・JOINを使った実践的な書き方
- DBMS(MySQL / PostgreSQL / SQL Server / Oracle)ごとの差異
- 大規模データを扱う際のパフォーマンス最適化
- 実務でよくあるアンチパターンと回避策
までを網羅的に解説します。
初心者でも理解でき、実務経験者が「その通り」と納得できるレベル を目指した完全ガイドです。
UPDATE文の基礎とSELECTとの関係
UPDATE文の基本構文
まずはUPDATE文の基本を整理しましょう。
UPDATE テーブル名
SET 列名 = 新しい値
WHERE 条件;
SET:更新したい列と値を指定
WHERE:更新対象行を限定(※省略は原則NG)
UPDATE文は破壊的操作です。
WHERE句を誤る、あるいは書き忘れると、全行が更新されるため細心の注意が必要です。
なぜSELECTと組み合わせるのか
実務では、単純な固定値更新よりも、
- 他の列の値を使いたい
- 別テーブルのデータを参照したい
- 集計結果や条件抽出結果を反映したい
といったケースが大半です。
そこで登場するのが、SELECT結果を使ったUPDATEです。
代表的な方法は以下の2つです。
以降で、それぞれを詳しく見ていきます。
単一テーブルでSELECT結果を使ってUPDATEする方法
サブクエリを使った基本パターン
同じテーブル内の値を参照して更新する場合、サブクエリがよく使われます。
UPDATE users
SET total_score = (
SELECT SUM(score)
FROM user_scores
WHERE user_scores.user_id = users.id
)
WHERE status = 'active';
このように、SET句の中でSELECTを実行することで、動的な値を更新できます。
単一テーブルUPDATEでの注意点
- サブクエリが1行だけ返すことを保証する
- サブクエリ内で不要な列をSELECTしない
- 条件を厳密に指定する
サブクエリが複数行を返すと、多くのDBMSでエラーになります。
パフォーマンス面での考慮
サブクエリは便利ですが、
になると、フルスキャンが発生しやすくなります。
必ず以下を確認しましょう。
EXPLAIN で実行計画を確認
- WHERE句に適切なインデックスがあるか
JOINを使って複数テーブルをUPDATEする方法
JOIN UPDATEの基本構文
複数テーブルを扱う場合、JOINを使ったUPDATEが有効です。
SQL Server / PostgreSQL
UPDATE orders
SET orders.total_price = products.price * orders.quantity
FROM orders
INNER JOIN products
ON orders.product_id = products.id;
MySQL
UPDATE orders
INNER JOIN products
ON orders.product_id = products.id
SET orders.total_price = products.price * orders.quantity;
JOINを使うことで、
というメリットがあります。
INNER JOINとLEFT JOINの使い分け
- INNER JOIN:両方に存在する行のみ更新
- LEFT JOIN:NULLが発生する可能性あり
LEFT JOINを使う場合は、
WHERE products.id IS NOT NULL
などの条件追加を検討しましょう。
実行前に必ずSELECTで確認する
安全な実務フローは以下です。
SELECT *
FROM orders
INNER JOIN products
ON orders.product_id = products.id
WHERE 条件;
→ 結果を確認
→ 問題なければUPDATEに変更
このワンクッションが、事故を防ぎます。
DBMS別:UPDATE × SELECTの違いと最適解
MySQL
- JOIN UPDATEが書きやすい
ORDER BY / LIMIT がUPDATEで使用可能
公式ドキュメント:https://dev.mysql.com/doc/refman/8.0/en/update.html
PostgreSQL
FROM句を使ったUPDATEが基本
- 標準SQLに近い構文
公式ドキュメント:https://www.postgresql.org/docs/current/sql-update.html
SQL Server
- JOIN UPDATEが明確
- 大規模更新ではロック戦略が重要
公式ドキュメント:https://learn.microsoft.com/sql/t-sql/statements/update-transact-sql
Oracle
- UPDATEよりも
MERGE が主流
- INSERT / UPDATEを同時に制御可能
公式ドキュメント:https://docs.oracle.com/en/database/oracle/oracle-database/
SELECTを使ったUPDATEのパフォーマンス最適化
インデックス設計の重要性
に使う列には、必ずインデックスを検討します。
ただし、
場合、更新コストが跳ね上がる点に注意が必要です。
大量更新時の基本戦略
- 小分けに更新(バッチ処理)
- トランザクションを短く保つ
- 業務時間外に実行
主キー・インデックス更新時の注意
- 主キー更新は極力避ける
- どうしても必要なら一時テーブル経由
よくあるアンチパターンと回避策
WHEREなしUPDATE
UPDATE users SET status = 'inactive';
→ 即事故案件
必ずSELECTで確認しましょう。
SELECT結果が変動する問題
- UPDATE中に参照テーブルが変わる
- 不整合が発生
→ トランザクション分離レベルを適切に設定
一括更新によるロック地獄
→ バッチ分割が基本
まとめ:SELECTを活かした安全で強いUPDATEを書くために
- UPDATE × SELECTは実務必須スキル
- サブクエリとJOINを使い分ける
- DBMSごとの仕様差を理解する
- 実行前SELECT・トランザクション管理を徹底
- パフォーマンスと安全性を常に意識
これらを押さえることで、壊れない・速い・信頼されるSQLが書けるようになります。
次のステップ:実務でSQLを武器にしたい方へ
この記事をここまで読んだあなたは、
- SQLを「書ける」だけでなく
- 安全に運用できるエンジニア視点
を身につけつつあります。
私たちは、SQL・DB設計・パフォーマンスを重視した開発を行うチームとして、
こうした技術に真剣に向き合える仲間を探しています。
「もっと実務でSQLを極めたい」
「データを扱う仕事に本気で向き合いたい」
そう感じた方は、ぜひ私たちの技術発信や採用情報も覗いてみてください。
学び続けるエンジニアが、自然に集まる環境を用意しています。