Oracle SQLのUPDATEは“WHEREの防御”が命。本記事は、oracle 環境で update を安全に使うための超基礎から、初心者がつまずきやすい罠の回避、そして中級者向けのワンポイント(索引の効かせ方・確認手順)までを、コピペで動くサンプル付きで解説します。
テーブル作成やINSERT文についてはコチラ。
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?
1) 導入(要約)
「UPDATEの基本を確実に、でも現場で困らない程度には踏み込みたい」方向け。UPDATE … SET … WHERE …の型、WHEREを書き忘れない運用、事前SELECT→実行→確認→COMMITの最短手順を、実行可能なスクリプトで説明します。
2) 結論・最短手順(スニペット用)
- 対象確認:同じ
WHEREでSELECTして件数と明細を把握 - 実行:
UPDATE 表 SET 列=値 WHERE 条件;(WHERE必須) - 確認:同じ
WHEREでSELECTして変更を目視確認 - 確定/取消:問題なければ
COMMIT、誤りはROLLBACK - 中級ポイント:WHERE列に索引があると速い/SET列の過剰索引は遅くなる
SQL*Plus/SQLclは
SET FEEDBACK ONで「X rows updated.」が表示されます。
3) 背景と基礎:UPDATEとは?
最小構文(まずはこれだけ)
UPDATE [スキーマ.]テーブル名 [別名]
SET 列1 = 値1[, 列2 = 値2, ...]
WHERE 条件式;
- UPDATE:対象表を指定(別名の活用で可読性UP)
- SET:更新する列と値(リテラル/別列/式/関数/
NULLも可) - WHERE:対象行の絞り込み。省略すると全件更新(最大の事故)
テキスト図(概念)
┌─WHEREで対象行を絞る──────────┐
│ 見つかった行だけSETの新値で更新 │
│ 変更前の像はUNDOへ保存 │
└─────────────────────────┘
alt: Oracle SQL UPDATEの探索→更新→UNDOの流れ
4) 準備:本記事のSQLがそのまま動くサンプル環境
既に
SCOTTスキーマとEMP/DEPTがある場合はスキップ可。以下は管理者→SCOTTの順に実行。
-- 管理者で(例:SQL*Plus で conn / as sysdba)
CREATE USER scott IDENTIFIED BY tiger
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP
QUOTA UNLIMITED ON USERS;
GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE TRIGGER TO scott;
-- SCOTTで接続
CONN scott/tiger
-- サンプル表
CREATE TABLE dept (
deptno NUMBER(2) CONSTRAINT dept_pk PRIMARY KEY,
dname VARCHAR2(14),
loc VARCHAR2(13)
);
CREATE TABLE emp (
empno NUMBER(4) CONSTRAINT emp_pk PRIMARY KEY,
ename VARCHAR2(10),
job VARCHAR2(9),
mgr NUMBER(4),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2),
CONSTRAINT emp_dept_fk FOREIGN KEY (deptno) REFERENCES dept(deptno)
);
-- 初期データ
INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK');
INSERT INTO dept VALUES (20,'RESEARCH','DALLAS');
INSERT INTO dept VALUES (30,'SALES','CHICAGO');
INSERT INTO emp VALUES (7369,'SMITH','CLERK', 7902, DATE '1980-12-17', 800, NULL, 20);
INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698, DATE '1981-02-20', 1600, 300, 30);
INSERT INTO emp VALUES (7521,'WARD','SALESMAN', 7698, DATE '1981-02-22', 1250, 500, 30);
INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,DATE '1981-09-28', 1250, 1400, 30);
COMMIT;
補足
CREATE USER:練習用ユーザーSCOTTを作成。DEFAULT/TEMP表領域やクォータを指定し、領域不足エラーを避けます。GRANT … TO scott:最低限の開発系権限(ログイン・表/ビュー/シーケンス/トリガ作成)を付与。dept/emp:deptnoはPK、emp.deptnoはFKで参照整合性を確保。実務でのUPDATE時に制約違反の学習にも最適です。COMMIT:初期データ投入を確定。以降の実験でROLLBACKしてもここには戻りません。
select 結果
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
SQL> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
5) 基本のUPDATE:コピペで動く例(基礎→中級)
共通:更新件数を表示させるために推奨
SET FEEDBACK ON
補足
SET FEEDBACK ON:SQL*Plus/SQLclにてDML後の「X rows updated.」等を表示。SQL%ROWCOUNTをSELECTする必要はありません。
5.1 単一行・単一列(PKで1行を確実に)
-- 事前確認
SELECT empno, ename, sal FROM scott.emp WHERE empno = 7369;
-- 実行
UPDATE scott.emp SET sal = sal + 100 WHERE empno = 7369;
-- 確認
SELECT empno, ename, sal FROM scott.emp WHERE empno = 7369;
COMMIT;
意図:主キーで1行に固定。sal + 100のような式もSETでOK。
補足
- 事前
SELECT:同じWHEREで対象を目視確認(件数/明細)。UPDATE … WHERE empno = 7369:PK指定で1行限定。誤更新の可能性を最小化。COMMIT:更新の確定。間違えたらCOMMIT前にROLLBACKすれば元に戻せます。- パフォーマンス:
empnoにPK索引があるため探索は索引スキャンで高速です。
コマンド実行結果
SQL> SELECT empno, ename, sal FROM scott.emp WHERE empno = 7369;
EMPNO ENAME SAL
---------- ---------- ----------
7369 SMITH 800
1 row selected.
SQL> UPDATE scott.emp SET sal = sal + 100 WHERE empno = 7369;
1 row updated.
SQL> SELECT empno, ename, sal FROM scott.emp WHERE empno = 7369;
EMPNO ENAME SAL
---------- ---------- ----------
7369 SMITH 900 ★
1 row selected.
SQL> COMMIT;
Commit complete.
5.2 1行で複数列(中級:NULL安全の加算)
-- 事前確認
SELECT empno, job, comm FROM scott.emp WHERE empno = 7499;
-- 実行:役職と歩合を一度に更新
UPDATE scott.emp
SET job = 'SR_SALES',
comm = NVL(comm,0) + 100
WHERE empno = 7499;
-- 確認
SELECT empno, job, comm FROM scott.emp WHERE empno = 7499;
COMMIT;
意図:同じ行はカンマ区切りでまとめて更新。NVLでNULLでも安全。
補足
NVL(comm,0) + 100:commがNULLでも計算可能。NULL + 100のNULL伝播を防ぎます。- 同時更新:複数列を1文で更新すると、往復回数が減り可読性・性能が向上。
- インデックス注意:
SET対象列に多数の索引があると索引更新コストが増え、遅くなります。
コマンド実行結果
SQL> SELECT empno, job, comm FROM scott.emp WHERE empno = 7499;
EMPNO JOB COMM
---------- --------- ----------
7499 SALESMAN 300
1 row selected.
SQL> UPDATE scott.emp
2 SET job = 'SR_SALES',
3 comm = NVL(comm,0) + 100
4 WHERE empno = 7499;
1 row updated.
SQL> SELECT empno, job, comm FROM scott.emp WHERE empno = 7499;
EMPNO JOB COMM
---------- --------- ----------
7499 SR_SALES 400 ★
1 row selected.
SQL> COMMIT;
Commit complete.
5.3 複数行を一括更新(対象の見える化→実行→確認)
-- 事前確認(件数と明細)
SELECT COUNT(*) AS hit_cnt
FROM scott.emp
WHERE deptno = 30 AND sal < 2000;
SELECT empno, ename, sal
FROM scott.emp
WHERE deptno = 30 AND sal < 2000
ORDER BY empno;
-- 実行(該当者を10%アップ)
UPDATE scott.emp
SET sal = sal * 1.10
WHERE deptno = 30
AND sal < 2000;
-- 確認
SELECT empno, ename, sal
FROM scott.emp
WHERE deptno = 30 AND sal < 2200
ORDER BY empno;
COMMIT;
意図:複数行でも1文でセット指向。WHEREが安全弁。
補足
SELECT COUNT(*):影響件数を先に把握し、過剰更新を防ぎます。- 条件分割:
deptno=30(選択性高)+sal<2000のAND条件で対象を明確化。- 検証
SELECTの閾値を<2200にしているのは、10%増後の範囲を確認するため。- パフォーマンス:
deptnoやsalに索引があれば探索が速くなります(ケースによりフルスキャンが有利なことも)。
コマンド実行結果
SQL> SELECT COUNT(*) AS hit_cnt
2 FROM scott.emp
3 WHERE deptno = 30 AND sal < 2000;
HIT_CNT
----------
3
1 row selected.
SQL> SELECT empno, ename, sal
2 FROM scott.emp
3 WHERE deptno = 30 AND sal < 2000
4 ORDER BY empno;
EMPNO ENAME SAL
---------- ---------- ----------
7499 ALLEN 1600
7521 WARD 1250
7654 MARTIN 1250
3 rows selected.
SQL> UPDATE scott.emp
2 SET sal = sal * 1.10
3 WHERE deptno = 30
4 AND sal < 2000;
3 rows updated.
SQL> SELECT empno, ename, sal
2 FROM scott.emp
3 WHERE deptno = 30 AND sal < 2200
4 ORDER BY empno;
EMPNO ENAME SAL
---------- ---------- ----------
7499 ALLEN 1760 ★
7521 WARD 1375 ★
7654 MARTIN 1375 ★
3 rows selected.
SQL> COMMIT;
Commit complete.
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?
5.4 よく使う条件(IN / BETWEEN / LIKE)
-- IN:候補のいずれか
UPDATE scott.emp
SET job = 'CLERK_I'
WHERE job IN ('CLERK','ASSISTANT');
-- BETWEEN:範囲(端点含む)
UPDATE scott.emp
SET sal = sal + 50
WHERE sal BETWEEN 1200 AND 1300;
-- LIKE:前方一致
UPDATE scott.emp
SET ename = ename || '_X'
WHERE ename LIKE 'MA%';
ROLLBACK; -- サンプルは戻す
意図:三種の定番条件。||は文字列連結。
補足
IN:複数の候補値に簡潔にマッチ(OR列挙より読みやすい)。BETWEEN:境界含む点に注意(1200 ≤ sal ≤ 1300)。LIKE 'MA%':大文字小文字は照合設定に依存。必要に応じUPPER()で揃えること。ROLLBACK:練習用の更新は最後に戻してデータを元の状態へ。
コマンド実行結果
SQL> UPDATE scott.emp
2 SET job = 'CLERK_I'
3 WHERE job IN ('CLERK','ASSISTANT');
1 row updated.
SQL> UPDATE scott.emp
2 SET sal = sal + 50
3 WHERE sal BETWEEN 1200 AND 1300;
0 rows updated.
SQL> UPDATE scott.emp
2 SET ename = ename || '_X'
3 WHERE ename LIKE 'MA%';
1 row updated.
SQL> ROLLBACK;
Rollback complete.
5.5 NULLの代入・文字列連結(基礎)
-- 現在値の確認
SELECT empno, comm FROM scott.emp WHERE empno = 7521;
-- 値を消す(NULL代入)
UPDATE scott.emp SET comm = NULL WHERE empno = 7521;
-- 氏名にサフィックスを付与
UPDATE scott.emp SET ename = ename || '_TMP' WHERE empno = 7521;
ROLLBACK;
補足
SET 列 = NULL:値を消す操作。NOT NULL制約がある列には代入不可(ORA-01407)。- 文字列連結:
||で連結。Unicode結合時は長さ制限(VARCHAR2のサイズ)に注意。- 検証パターン:事前SELECT→UPDATE→確認→ROLLBACKの流れを体に覚えさせるのが安全です。
6) トラブルシューティング(基礎〜中級)
| 事象/エラー | 典型原因 | 確認ポイント | 対処 |
|---|---|---|---|
| 思わぬ大量更新 | WHERE漏れ/緩い条件 | 事前SELECT COUNT(*) | PK/UKで固定、条件を厳しく |
| ORA-01407(NULL禁止) | NOT NULL列へNULL | DESC 表で列定義 | NVL/既定値の利用、設計見直し |
| ORA-01722(数値無効) | 文字→数値列更新 | 列型/式の型 | TO_NUMBER等で正規化 |
| ORA-00904(識別子) | 列名/別名の誤記 | 実列名・別名の位置 | スペル修正、別名の適用範囲を見直し |
原則:1つのUPDATE文は原子的(失敗時は全ロールバック)。誤実行に気づいたらCOMMITする前にすぐ
ROLLBACK。
7) 運用と中級ポイント
- WHEREの徹底:実行前に同条件のSELECTで対象を見える化。
- 短いトランザクション:
UPDATE→確認→すぐCOMMIT/ROLLBACK。 - 権限:他スキーマ表は
UPDATE権限が必要。 - 性能の勘所(中級):
- WHERE列に索引→探索が速い。
- SET列に多くの索引→更新コスト増(必要最小限に)。
- 統計が古いと遅くなる→
DBMS_STATSで最新化(運用で実施)。
8) FAQ(よくある質問)
Q1. WHEREを書き忘れたら?
A. 即ROLLBACK。以後は事前SELECT COUNT(*)の運用を必須に。
Q2. 何行更新されたか知る方法は?
A. SET FEEDBACK ONで表示。予測は事前SELECT COUNT(*)で。
Q3. 文字列はどう連結する?
A. ||(連結演算子)。例:ename || '_TMP'。
Q4. NULLを入れたい/防ぎたい
A. 代入はSET 列 = NULL。NULL時はNVL(列, 代替)で置換可能。
Q5. 複数列を一度に更新できる?
A. 可能。SET 列1=…, 列2=…と1文でまとめる方が簡潔かつ効率的。
9) まとめ(要点)
- 形は
UPDATE … SET … WHERE …。WHEREは必須。 - 実行前は同条件SELECTで件数と明細を確認。
- 単一行はPKで固定、複数列は1文でまとめる。
- COMMIT/ROLLBACKで安全に確定/取消。
- 中級の勘所:索引はWHEREに効かせる/SET列の過剰索引は慎重に。
本記事は Oracle Database 19c を対象に解説します(他バージョンは画面や既定値が異なる場合があります)。
[参考]
UPDATE




コメント