Oracle SQL UPDATE基礎から中級:安全な書き方

Oracle Master Bronze

Oracle SQLのUPDATEは“WHEREの防御”が命。本記事は、oracle 環境で update を安全に使うための超基礎から、初心者がつまずきやすい罠の回避、そして中級者向けのワンポイント(索引の効かせ方・確認手順)までを、コピペで動くサンプル付きで解説します。

テーブル作成やINSERT文についてはコチラ。

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?


1) 導入(要約)

「UPDATEの基本を確実に、でも現場で困らない程度には踏み込みたい」方向け。UPDATE … SET … WHERE …の型、WHEREを書き忘れない運用事前SELECT→実行→確認→COMMITの最短手順を、実行可能なスクリプトで説明します。


2) 結論・最短手順(スニペット用)

  1. 対象確認:同じWHERESELECTして件数と明細を把握
  2. 実行UPDATE 表 SET 列=値 WHERE 条件;WHERE必須
  3. 確認:同じWHERESELECTして変更を目視確認
  4. 確定/取消:問題なければCOMMIT、誤りはROLLBACK
  5. 中級ポイント: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/empdeptnoは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) + 100commNULLでも計算可能。NULL + 100NULL伝播を防ぎます。
  • 同時更新:複数列を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<2000AND条件で対象を明確化。
  • 検証SELECTの閾値を<2200にしているのは、10%増後の範囲を確認するため。
  • パフォーマンス:deptnosalに索引があれば探索が速くなります(ケースによりフルスキャンが有利なことも)。
コマンド実行結果

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列へNULLDESC 表で列定義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

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?

コメント

タイトルとURLをコピーしました