◀ 2.

Oracle 19cのDML|SELECT・INSERT・UPDATE・DELETEと確定条件

▶

Oracle Database 19cのDMLの入口です。目的に合う実際の子ページを選び、構文・対象・接続の自動確定設定を確認してください。製品別の比較例は残していますが、全例をOracleへ続けて実行する手順ではありません。

DMLの選択と変更結果・確定の判断を分ける模式図。SQL実測ではない
命令の選択と、実行結果を確認して確定する判断は別です。SQL実測・無停止・復旧成功を示す図ではありません。

本ページの子ページ一覧

個別の構文や手順は、次の子ページから選んでください。現在の実際の親子関係・表示順に並べています。

  1. SELECT文:行の参照と抽出
  2. INSERT:行の追加
  3. UPDATE文:既存値の更新
  4. DELETE文:行の削除と確定前の確認
  5. WHERE句:対象条件
  6. JOIN句:表の結合
  7. 集合演算子:結果集合の演算
  8. インラインビュー:FROM句の副問い合わせ
  9. 副問い合わせ (サブクエリ):SQL内の問合せ

SELECT・INSERT・UPDATE・DELETEの基本形

SELECT・INSERT・UPDATE・DELETEの基本形を比較します。以下は独立した構文例で、同じ既存usersへ順番に送る検証や後片付けではありません。表・列・権限・既存データ・制約と自動確定の条件を確認し、学習用の別環境で扱う例です。Oracle実機では未実行です。

-- SELECT
SELECT id, name FROM users WHERE age >= 20 ORDER BY id;

-- INSERT
INSERT INTO users (id, name, age) VALUES (1, 'Taro', 25);

-- UPDATE
UPDATE users SET name = 'Jiro' WHERE id = 1;

-- DELETE
DELETE FROM users WHERE id = 1;

SQL分類全体は親のSQL、CRUDやJOINなどの総合的な説明は別カテゴリのSQLを参照してください。リンク先にも製品別の構文が含まれます。製品・文・接続設定によって確定や取消の条件が異なるため、構文が似ていることだけで同じ操作として扱いません。

この記事の要点
  • DML (Data Manipulation Language) はデータを「読み・書き・更新・削除」する命令群: SELECT / INSERT / UPDATE / DELETE
  • DDL との違い: DDL はテーブル構造を変える (CREATE/ALTER/DROP)。DMLはデータの参照/変更を扱う。索引・trigger・制約等にも作用し得るため、表の値だけに影響が限定されるという意味ではない
  • INSERT のバリエーション: Oracle 19cの単一行INSERT/INSERT ... SELECT/複数表INSERTと、MySQLのIGNORE/ON DUPLICATE KEY UPDATE・PGのON CONFLICTを区別。MERGEを全製品共通の同じUPSERTとはしない
  • UPDATE / DELETEは対象を明確にする。WHEREのない文も構文上は有効だが全行が対象になり得る。WHEREがあっても誤対象・連鎖・同時更新を防ぐ保証ではない
  • TRUNCATEはDELETEと別操作。Oracle 19c通常表のDDLと、PostgreSQLのtransaction内取消・既定CONTINUE IDENTITY等を区別。無条件の高速化/取消不可/採番resetへ一般化しない

DML とは

DML (Data Manipulation Language / データ操作言語) は、テーブル内のデータを操作する SQL コマンド群です。実務の参照/変更を扱いますが、比率はシステムや集計方法次第です。全クエリの95%という一般的な実測値は示しません。

コマンド役割旧掲載の頻度目安(実測順位ではない)
SELECTデータを取り出す(参照)★★★★★
INSERT新しい行を追加★★★★
UPDATE既存行の値を更新★★★★
DELETE行を削除★★★
MERGE条件に応じた更新/挿入等。製品・版の句と対象条件に依存し、同時作成競合の自動解決や他製品UPSERTとの同義は保証しない★★

DML / DDL / DCL / TCL の整理

分類用途コマンド例自動コミット
DMLデータ操作SELECT/INSERT/UPDATE/DELETEトランザクション可
DDL (Data Definition Language)構造定義CREATE/ALTER/DROP/TRUNCATEOracle 19cの通常表DDLは構文上有効な文の実行前/成功後に暗黙COMMIT。MySQLの対象文・例外や、PGのtransaction内通常CREATE等と分ける
DCL (Data Control Language)権限制御GRANT/REVOKEOracleのGRANT/REVOKE等はDDLの確定条件を確認。他製品の権限文へ一律に適用しない
TCL (Transaction Control Language)トランザクション製品別の開始/COMMIT/ROLLBACK。OracleのPL/SQL BEGINはSQL transaction開始とは別—

INSERT の全パターン

旧掲載の製品別・独立した挿入例です。Oracle19cではカンマ区切り複数行VALUESをそのまま使わず、INSERT ALLやINSERT ... SELECT等を対象に合わせます。IGNORE/ON DUPLICATE KEY UPDATEはMySQL、ON CONFLICTや::dateはPGの比較で、最後のMERGEもOracle構文として連続実行できません。IGNOREは重複以外をwarning/補正とする場合もあり、採用時は警告と実結果を確認します。固定10倍や完全な競合防止は保証せず、全SQLは実機未実行です。

-- パターン1: 単純 INSERT
INSERT INTO users (name, email)
VALUES ('田中', 'tanaka@example.com');

-- パターン2: 複数行 INSERT(パフォーマンスが10倍違うことも)
INSERT INTO users (name, email) VALUES
  ('佐藤', 'sato@example.com'),
  ('鈴木', 'suzuki@example.com'),
  ('高橋', 'takahashi@example.com');

-- パターン3: SELECT 結果を INSERT
INSERT INTO users_backup (id, name, email)
SELECT id, name, email FROM users WHERE created_at < '2025-01-01';

-- パターン4: INSERT IGNORE(MySQL)重複キーは無視
INSERT IGNORE INTO users (id, name) VALUES (1, '田中');
-- → id=1 が既存ならエラーにならず何もしない

-- パターン5: ON DUPLICATE KEY UPDATE(MySQL UPSERT)
INSERT INTO daily_counts (date, count) VALUES ('2025-05-18', 1)
ON DUPLICATE KEY UPDATE count = count + 1;

-- パターン6: PostgreSQL の UPSERT
INSERT INTO daily_counts (date, count) VALUES ('2025-05-18', 1)
ON CONFLICT (date) DO UPDATE SET count = daily_counts.count + 1;

-- パターン7: 標準 SQL の MERGE
MERGE INTO daily_counts t
USING (SELECT '2025-05-18'::date AS d, 1 AS c) s
ON t.date = s.d
WHEN MATCHED THEN UPDATE SET count = t.count + s.c
WHEN NOT MATCHED THEN INSERT (date, count) VALUES (s.d, s.c);

UPDATE — 詳細

旧掲載の製品別更新例です。NOW/INTERVAL 1 YEAR/CURDATEやUPDATE JOINをOracleへそのまま転用しません。PGのUPDATE FROMも別構文で、結合先の一致件数による非決定性を確認します。最後の相関更新はWHEREがなく全usersを対象にし得るため、本番へ一括送信しません。事前SELECTと実UPDATEの対象集合が同じで固定されるとも保証しません。

-- 単純な更新
UPDATE users SET status = 'inactive' WHERE id = 1;

-- 複数列を同時更新
UPDATE users
SET status = 'inactive', updated_at = NOW(), updated_by = 'system'
WHERE last_login_at < NOW() - INTERVAL 1 YEAR;

-- UPDATE JOIN(MySQL): 他テーブルの値で更新
UPDATE orders o
JOIN products p ON o.product_id = p.id
SET o.price_snapshot = p.current_price
WHERE o.created_at >= CURDATE();

-- 同等を PostgreSQL で
UPDATE orders SET price_snapshot = p.current_price
FROM products p
WHERE orders.product_id = p.id
  AND orders.created_at >= CURRENT_DATE;

-- サブクエリで更新
UPDATE users
SET order_count = (SELECT COUNT(*) FROM orders WHERE user_id = users.id);

DELETE — 詳細

旧掲載の削除比較です。NOW()やINTERVAL 90 DAY、MySQL DELETE JOIN、PG USINGはOracle19c共通構文ではありません。最後のLIMIT付きDELETEはMySQL単一表向けで順序も明示していません。各batchが確定すれば全batchを通常ROLLBACKで戻せず、無条件ループやFK解除で処理を通す手順にしません。

-- 条件削除
DELETE FROM logs WHERE created_at < NOW() - INTERVAL 90 DAY;

-- DELETE JOIN(MySQL)
DELETE o FROM orders o
JOIN users u ON o.user_id = u.id
WHERE u.deleted_at IS NOT NULL;

-- PostgreSQL は USING
DELETE FROM orders
USING users
WHERE orders.user_id = users.id AND users.deleted_at IS NOT NULL;

-- LIMIT 付き削除(バッチで小分けに削除する定番)
DELETE FROM logs WHERE created_at < '2024-01-01' LIMIT 1000;
-- ループで回す

DELETE vs TRUNCATE — 似て非なる

項目DELETETRUNCATE
分類DMLDDL
WHERE 句使える使えない(全行削除)
速度対象件数・制約/索引/trigger・競合等で比較全行除去の方式が異なるが、固定倍率・無停止や常時高速は保証しない
ROLLBACK自動確定等がなく未確定のtransactionalな変更が対象Oracle通常表は通常ROLLBACK不可。PGはtransaction内の表データの取消が可能。全製品共通ではない
AUTO_INCREMENTDELETEだけで自動resetするとはしない。Oracleのsequence/identityと製品差を確認MySQL InnoDBはreset。PGは既定CONTINUE IDENTITYで、所有sequenceのRESTART IDENTITY指定とは別。OracleへMySQL用語を転用しない
トリガ定義された対象イベント・行/文等の条件に従うDELETE triggerとは別。PGのON TRUNCATE、OracleのDDL trigger等も区別し、すべて不発火とはしない
外部キー参照ON DELETEと制約・参照行次第。子行削除の影響を別に確認子表が空でも参照定義は残る。製品・対象集合・CASCADE等の別条件を確認し、制約解除で通さない

トランザクションで DML を安全に

旧掲載の送金例は完成した安全実装ではありません。START TRANSACTION/ROW_COUNT()はMySQL向けでOracle共通ではなく、SELECTで件数を表示しても分岐せず後のCOMMITへ進みます。両更新の実件数・残高/通貨等の業務条件を同じ接続の適切な未確定範囲で確認し、不一致やエラーなら確定前に取消/原因確認を選びます。末尾ROLLBACKは既にCOMMITした変更を取り消しません。確定応答が不明なら無条件に再送しません。

-- 本番の更新は必ずトランザクション内で
START TRANSACTION;     -- または BEGIN
  UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
  -- 件数チェック
  SELECT ROW_COUNT();  -- 1 でなければ ROLLBACK
  UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
COMMIT;

-- 失敗時
ROLLBACK;

パフォーマンス Tips

  • 大量INSERTは製品に合う方式で往復回数を減らせる場合がある。Oracle19cへ複数行VALUESを転用せず、固定10〜100倍は保証しない
  • MySQL単一表DELETEのLIMIT等による分割は、件数/一意順序/確定境界を計画する。全体取消・短いlock・完了を保証せず、Oracle/PGへ直接LIMITを転用しない
  • UPDATEは目的の行集合と実計画・制約/索引/競合を確認する。索引の有無だけで適切な条件・行lock/表lock・無待機を決めつけない
  • MySQLのSET autocommit=0をOracle共通の必須準備にしない。接続設定の持越しと未確定範囲、fsync/group commit等を分け、業務上の原子性に合う確定単位を選ぶ
  • ON DUPLICATE KEY UPDATEはMySQL固有。どの一意キーと競合するか、制約・trigger・実件数・同時更新を確認し、Oracle MERGE等と同じ動作や常時高速とは保証しない

FAQ

Q: DELETE で消したデータを戻せるか
A: 未確定で取消可能な変更は同じ接続のROLLBACKを検討します。COMMIT/自動確定/暗黙確定後は通常ROLLBACK不可。backup/PITR・Oracle Flashback等は記録/権限/保持等の条件付きで、完全復旧や全環境で使えることは保証しません。結果不明時に削除を無条件再送しません。

Q: UPDATE と REPLACE の違い
A: REPLACE (MySQL) は「DELETE + INSERT」相当で、対象行を一度消してから挿入します。AUTO_INCREMENT が進む / 外部キーで CASCADE が走る等の副作用に注意。

Q: SELECT は DML?
A: Oracle19cの分類ではSELECTもDMLとして扱います。教材によってDQLと分ける場合がありますが、分類名から取消や自動確定の動作を決めず、製品・文・client設定を確認してください。

一次資料と確認範囲

Oracle19cのSQL文の分類・INSERT・COMMIT、PG18 TRUNCATE、MySQL8.4 DELETE・INSERT/IGNOREで製品別条件を照合しました。Oracle/他DBの旧例・復元基本4文は実機未実行で、実計画・lock・性能・障害復旧の検証結果ではありません。

子ページ
  1. SELECT文
  2. INSERT
  3. UPDATE文
  4. DELETE文
  5. WHERE句
  6. JOIN句
  7. 集合演算子
  8. インラインビュー
  9. 副問い合わせ (サブクエリ)
同階層のページ
  1. DDL
  2. DML
  3. トランザクション制御 (SQL)
  4. データディクショナリ
  5. 動的パフォーマンスビュー (V$ビュー)
  6. 関数

最近更新/作成されたページ