DML(データ操作文)とは
データを操作・変更するSQL文の総称。INSERT / UPDATE / DELETE の3種類がある。
DML文はトランザクションを構成し、COMMIT または ROLLBACK を実行するまで変更が確定しない。
また、DML 実行後に DDL文(CREATEなど)を実行すると、直前のDML変更が暗黙的にコミットされる点に注意。
INSERT
表に新しい行を追加する。
列リスト指定あり
INSERT INTO <表名> (<列名1>, <列名2>, ...)
VALUES (<値1>, <値2>, ...);
- 表名に続けて、値を設定したい列を列リストに指定する
- 列リストに指定した列の数だけ、VALUES 句に値を指定する
- 列リストに指定しなかった列には、定義済みのデフォルト値 が設定される。デフォルト値がなければ NULL が設定される
列リスト指定なし
INSERT INTO <表名>
VALUES (<値1>, <値2>, ...);
- 表のすべての列に対して値を指定する必要がある
- 指定する値は表の列の定義順に合わせる
- 将来の列追加に弱いため、実務では列名の明示を推奨
主なエラーケース
| エラー原因 | 説明 |
|---|---|
| 列と値の数の不一致 | 列リストの列数と VALUES の値の数が合わない |
| データ型の不一致 | 列のデータ型と挿入する値のデータ型が異なる |
| 主キー制約違反 | すでに存在するキー値を挿入しようとした |
| NOT NULL 制約違反 | NOT NULL 列に NULL を指定した(列リスト指定なしで省略した場合も含む) |
UPDATE
表の行データを更新する。
UPDATE <表名>
SET <列名1> = <値1> [, <列名2> = <値2>, ...]
[WHERE <条件>];
- SET 句に更新したい列名と新しい値を指定する
- カンマ区切りで複数列を一度に更新できる
- WHERE 句を省略すると、表の全行が更新されるため注意
- SET 句に計算式・スカラー副問合せを使用可能
- 副問合せで複数列を同時に更新する場合は、左辺を
(列名1, 列名2)のようにカッコで囲む
DELETE
表の行データを削除する。
DELETE [FROM] <表名>
[WHERE <条件>];
-
FROMは省略可能(省略してもエラーにならない) - WHERE 句で条件を絞って削除可能
- WHERE 句を省略すると全行削除される(TRUNCATE と異なりロールバック可能)
DML における副問合せ
| DML文 | 副問合せの位置 | 種別 |
|---|---|---|
| INSERT | VALUES 句内 | スカラー副問合せ |
| UPDATE | SET 句の右辺 | スカラー副問合せ または 複数列副問合せ |
| DELETE | WHERE 句内 | スカラー / 非スカラー副問合せ |
| UPDATE | SET 句(複数列同時更新) |
(列1, 列2) = (副問合せ) の形式 |
補足:UPDATE の複数列副問合せの注意点
SET (列名1, 列名2) = (副問合せ)の形式では、SET 句の左辺の列の数・データ型と副問合せが返す列の数・データ型が一致する必要がある。
DML における相関副問合せ
-
UPDATEの WHERE 句・SET 句で相関副問合せを使用できる -
DELETEの WHERE 句で相関副問合せを使用できる - 相関副問合せでは、主問合せの現在処理中の行の値を副問合せ内で参照する
マルチテーブル INSERT
副問合せが返す複数の行を、同時に複数の表に追加できる機能。
INSERT 先はビューではなく表のみ。
マルチテーブル INSERT の構文では、末尾に必ずサブクエリ(SELECT 文)が必要である。サブクエリの結果を利用しない場合は SELECT * FROM DUAL と書くのが慣例。
① 無条件 INSERT ALL
副問合せから返された行データを、INTO 句で指定したすべてのターゲット表に追加する。
INSERT ALL
INTO <ターゲット表名> [(<列名>, ...)] VALUES (<値>, ...)
[INTO <ターゲット表名> [(<列名>, ...)] VALUES (<値>, ...)]
SELECT ... FROM ...;
- 複数の INTO 句を指定できる
- 副問合せが返す列数とターゲット表の列数が等しい場合、VALUES 句を省略できる
-
INSERT ALLはすべての INTO 句に無条件でデータを追加する
② 条件付き INSERT ALL
WHEN 句の条件を満たしたすべての INTO 句にデータを追加する。1 行が複数の WHEN 句を満たす場合、複数のターゲット表に追加される点が INSERT FIRST との最大の違い。
INSERT ALL
WHEN <条件1> THEN INTO <ターゲット表名> VALUES (...)
[INTO <ターゲット表名> VALUES (...)]
[WHEN <条件2> THEN INTO <ターゲット表名> VALUES (...)]
[ELSE INTO <ターゲット表名> VALUES (...)]
SELECT ... FROM ...;
- 1 つの WHEN 句の中に複数の INTO 句を指定できる
- すべての WHEN 句の条件を満たさない行は、ELSE 句のターゲット表に追加される。ELSE 句は省略可能
- 副問合せが返す列数とターゲット表の列数が等しい場合、VALUES 句の指定を省略できる
③ 条件付き INSERT FIRST
WHEN 句の条件を評価し、最初に真となった WHEN 句の INTO 句のみにデータを追加する。以降の WHEN 句は評価されない。
INSERT FIRST
WHEN <条件1> THEN INTO <ターゲット表名> VALUES (...)
[WHEN <条件2> THEN INTO <ターゲット表名> VALUES (...)]
[ELSE INTO <ターゲット表名> VALUES (...)]
SELECT ... FROM ...;
INSERT ALL と INSERT FIRST の比較
| INSERT ALL | INSERT FIRST | |
|---|---|---|
| WHEN 評価 | すべての WHEN 句を評価 | 最初に真となった WHEN 句のみ実行 |
| 複数条件に合致する場合 | 複数の表に追加される | 最初の条件の表にのみ追加される |
| ELSE 句の動作 | すべての条件を満たさない行が対象 | 同左 |
データベースリンク
あるOracle Databaseから別のOracle Databaseにある表(リモート表)にアクセスできるようにする仕組み。
表名@データベースリンク名 の形式でリモート表を参照できる。
マルチテーブル INSERT や DML 文でもリモート表を利用できる。
MERGE
指定した表(ソース表)から行を取得し、その行をもとにして別の表(ターゲット表)に対して更新(UPDATE)または追加(INSERT)を行う文。
1 つの SQL 文で「存在すれば更新、なければ追加」という処理を実現できる。
MERGE INTO <ターゲット表名> [<表別名>]
USING <ソース表名 | ビュー | 副問合せ> [<表別名>]
ON (<結合条件>)
WHEN MATCHED THEN
UPDATE SET <列名1> = <値1> [, <列名2> = <値2>, ...]
[WHERE <条件>]
[DELETE WHERE <条件>]
WHEN NOT MATCHED THEN
INSERT [(<列名1> [, <列名2>, ...])]
VALUES (<値1> [, <値2>, ...])
[WHERE <条件>];
MERGE の主なルール
| ルール | 説明 |
|---|---|
| USING 句 | ソースには表・ビュー・副問合せを指定できる |
| ON 句の列は更新不可 | ON 句で指定した列を WHEN MATCHED の UPDATE で更新しようとすると ORA-38104 エラーになる |
| WHEN MATCHED 省略可 | UPDATE / DELETE 処理を実行しない場合は省略できる |
| WHEN NOT MATCHED 省略可 | INSERT 処理を実行しない場合は省略できる。ただし少なくともどちらか一方は指定する必要がある |
| WHEN MATCHED の WHERE 句 | 条件を指定した場合、条件を満たす行のみ UPDATE される |
| WHEN MATCHED の DELETE WHERE | UPDATE 後の値で条件を評価し、条件を満たす行を削除する |
| WHEN NOT MATCHED の WHERE 句 | 条件を指定した場合、条件を満たす行のみ INSERT される |
| ソース表に同一キーが複数存在 | UPDATE 時は ORA-30926、INSERT 時は ORA-00001(主キー制約違反)が発生する |
| MERGE は決定的な文 | 同一の MERGE 文でターゲット表の同じ行を複数回更新することはできない |
【試験ポイント】INSERT 句の列名と括弧
WHEN NOT MATCHED の INSERT 句で列名リストを指定する場合、INSERT (列名1, 列名2)のようにカッコで列名を囲む。列名を省略した場合はターゲット表のすべての列に VALUES の値が挿入される。
MERGE の使用例(WHEN MATCHED のみ)
MERGE INTO target_table t
USING source_table s
ON (t.id = s.id)
WHEN MATCHED THEN
UPDATE SET t.salary = s.salary
WHERE s.active = 1
DELETE WHERE s.active = 0;
この例では、ON 条件を満たす行に対して、active = 1 の行は UPDATE し、UPDATE 後に active = 0 の行は DELETE する。