Oracle SQL INSERT 徹底解説

Oracle Master Bronze

導入

データベースに新しい行(レコード)を入れる基本操作が oracle insert です。本記事では insert oracle の正しい使い方を、やさしい言葉と“そのまま動く実行例”で解説します。ユーザー作成 → 表(テーブル)作成 → INSERT → 確認 → エラー対処まで。

テーブルの作成についてはコチラ。

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

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


このページのゴール(3分で把握)

  • INSERT文の安全な書き方(列名を明示)を理解する。
  • 日付・時刻・数値の入れ方をミスなく書ける。
  • IDENTITY と SEQUENCE の違い・使い分けを説明できる。
  • 代表的なエラー原因と直し方を自分で判断できる。

基本からスタート:insert oracle の考え方

INSERT 文は「どの表に」「どの列へ」「どんな値を入れるか」を指定して書きます。将来の変更に強くするため、列(カラム)名は必ず明示しましょう。

例:基本の書き方

-- 推奨:列名を明示(安全・読みやすい)
INSERT INTO 表名 (列1, 列2, ...) VALUES (値1, 値2, ...);

-- 非推奨:全列に順番通り(将来、列が増えると壊れやすい)
INSERT INTO 表名 VALUES (値1, 値2, ...);

ポイント

  • 省略した列には DEFAULT の値が入る(設定がなければ NULL)。
  • NOT NULL の列を省略するとエラー(ORA-01400)。
  • 日付・時刻は TO_DATE / TO_TIMESTAMP書式を明示すると安心。

補足:列名の省略と NULL の指定

  • すべての列に値を入れる場合は、列名リストを省略して書けます(ただし将来の列追加に弱いため、実務では列名の明示を推奨)。
  • 値を入れない列に NULL を入れたい場合は、VALUES 内で NULL を書きます(列を省略した場合は DEFAULT が適用され、DEFAULT がなければ NULL が入ります)。
-- 列名省略(全列に値を入れる)※テーブル定義の列順に合わせる
INSERT INTO customers
VALUES (DEFAULT, 'Foo', 'foo@example.com', SYSDATE, 'A');

-- 値を入れない列に NULL を明示(joined_on と email を NULL にする例)
INSERT INTO customers (name, email, joined_on, status)
VALUES ('Bar', NULL, NULL, 'A');

テキスト図:INSERT のながれ

┌──── クライアント(SQL*Plus / SQLcl / アプリ) ────┐
│ INSERT INTO T(colA,colB) VALUES(:A,:B);                  │
└───────────────────↓────────────────────┘
┌────────── Oracleサーバ ──────────┐   ┌── テーブル領域 ──┐
│ ①文法チェック ②制約チェック(NOT NULL/一意/外部キー)│→│ 行を書き込む     │
│ ③必要なら索引も更新                                   │   │ 索引も更新       │
└──────────────────────────────┘   └──────────────┘

データ型ごとの安全な書き方(暗黙変換を避ける)

Oracle が自動で型を変える「暗黙変換」は思わぬミスの原因です。狙った型で入れましょう。

-- 文字列(シングルクォートで囲む)
INSERT INTO t(c_vc2) VALUES ('山田太郎');

-- 日付(書式を明示)
INSERT INTO t(c_date) VALUES (TO_DATE('2025-08-01','YYYY-MM-DD'));

-- タイムスタンプ(ミリ秒まで)
INSERT INTO t(c_ts) VALUES (
  TO_TIMESTAMP('2025-08-01 10:20:30.123','YYYY-MM-DD HH24:MI:SS.FF3')
);

-- 数値(クォート不要)
INSERT INTO t(c_num) VALUES (12345);

自動採番は2つ:IDENTITY と SEQUENCE の使い分け

「主キーを自動で増やしたい」——そんなときは IDENTITY 列SEQUENCE を使います。どちらも“番号を発行する”仕組みですが、設計や運用で向き不向きがあります。

まず結論(選び方の早見表)

┌─────────────┬──────────────────────────────┐
│ やりたいこと       │ おすすめ                                   │
├─────────────┼──────────────────────────────┤
│ いちばん簡単に自動採番 │ IDENTITY 列(テーブルの列定義に付ける)          │
│ 細かく挙動を調整したい │ SEQUENCE(開始値/間隔/キャッシュ等を個別設定) │
│ 既存アプリでNEXTVAL使用│ SEQUENCE                                 │
└─────────────┴──────────────────────────────┘

IDENTITY 列(シンプルで学習向き)

何か? テーブルの列に「自動で番号をふる」性質をつける機能。内部的にはシーケンスに近い仕組みを使います。

主な指定

  • GENERATED ALWAYS AS IDENTITY … 常にDBが採番(手動で値を入れるとエラー)
  • GENERATED BY DEFAULT AS IDENTITY … ふだんはDBが採番。必要なら手動指定も可能
  • (応用)BY DEFAULT ON NULL … 値が NULL のときだけDBが採番

基本例

CREATE TABLE demo_customers (
  id        NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name      VARCHAR2(50)  NOT NULL,
  email     VARCHAR2(255) UNIQUE,
  joined_on DATE          DEFAULT SYSDATE,
  status    CHAR(1)       DEFAULT 'A' CHECK (status IN ('A','I'))
);

-- id はDBが自動採番
INSERT INTO demo_customers (name, email)
VALUES ('Sato Ichiro','s.ichiro@example.com');
コマンド実行例

SQL> CREATE TABLE demo_customers (
2 id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
3 name VARCHAR2(50) NOT NULL,
4 email VARCHAR2(255) UNIQUE,
5 joined_on DATE DEFAULT SYSDATE,
6 status CHAR(1) DEFAULT 'A' CHECK (status IN ('A','I'))
7 );

Table created.

SQL> INSERT INTO demo_customers (name, email)
2 VALUES ('Sato Ichiro','s.ichiro@example.com');

1 row created.

SQL> set lin 1000
SQL> col name for a15
SQL> col email for a25
SQL> select * from demo_customers;

ID NAME EMAIL JOINED_ON S
---------- --------------- ------------------------- --------- -
1 Sato Ichiro s.ichiro@example.com 23-AUG-25 A

よくあるQ&A

  • Q: 間違えて入れたので ROLLBACK したら番号は戻る?戻りません。 採番は消費され、番号には“飛び番(欠番)”が出ます。
  • Q: 次回の採番開始値を変えたい? → 列を変更します。
ALTER TABLE demo_customers MODIFY
  (id GENERATED BY DEFAULT AS IDENTITY START WITH 1000);
  • Q: 手動で値を入れたい?BY DEFAULT を使っているときだけ可能です。

メリット/注意

  • 追加のオブジェクト管理が不要でシンプル。
  • ただし 欠番が出る ことは普通(トランザクション取り消し/同時実行/障害時など)。

SEQUENCE(自由度が高いプロ向け)

何か? 独立した「番号発行機」オブジェクト。NEXTVAL で次の番号、CURRVAL で今の番号を取得します。

作成と利用の基本

-- 作成
CREATE SEQUENCE demo_customers_seq START WITH 1 INCREMENT BY 1 CACHE 20 NOCYCLE;

-- シーケンスを使う表
CREATE TABLE demo_customers_seqver (
  id         NUMBER PRIMARY KEY,
  name       VARCHAR2(50) NOT NULL,
  created_at DATE DEFAULT SYSDATE
);

-- 挿入時にNEXTVALを使う
INSERT INTO demo_customers_seqver (id, name)
VALUES (demo_customers_seq.NEXTVAL, 'Tanaka Hanako');

-- 同じセッションなら直後にCURRVALで最後の番号を参照
SELECT demo_customers_seq.CURRVAL FROM dual;
コマンド実行例

SQL> CREATE SEQUENCE demo_customers_seq START WITH 1 INCREMENT BY 1 CACHE 20 NOCYCLE;

Sequence created.

SQL> CREATE TABLE demo_customers_seqver (
2 id NUMBER PRIMARY KEY,
3 name VARCHAR2(50) NOT NULL,
4 created_at DATE DEFAULT SYSDATE
5 );

Table created.

SQL> INSERT INTO demo_customers_seqver (id, name)
2 VALUES (demo_customers_seq.NEXTVAL, 'Tanaka Hanako');

1 row created.

SQL> select * from demo_customers_seqver;

ID NAME CREATED_A
---------- --------------- ---------
1 Tanaka Hanako 23-AUG-25

SQL> SELECT demo_customers_seq.CURRVAL FROM dual;

CURRVAL
----------
1

主なオプション(よく使うもの)

  • START WITH n:初期値
  • INCREMENT BY n:増分
  • CACHE n / NOCACHE:番号をメモリにキャッシュ(高速化。ただし障害時は欠番が出やすい)
  • CYCLE / NOCYCLE:最大値まで行ったら最小値に戻るか

メリット/注意

  • 振る舞いを細かく調整でき、複数テーブルでも使い回せる。
  • CURRVAL は同じセッションで NEXTVAL を一度実行してからでないと参照できません。
  • こちらも 欠番は普通 に発生します(キャッシュ/ロールバック/並列挿入等)。

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

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


IDENTITY と SEQUENCE の違い(かんたん図)

┌────────────┬───────────────────────────┐
│ IDENTITY 列     │ 列に“自動採番”の性質を付与。表の一部。    │
├────────────┼───────────────────────────┤
│ SEQUENCE       │ 独立オブジェクト。NEXTVAL/ CURRVALで取得。│
├────────────┼───────────────────────────┤
│ 初期設定の容易さ │ ◎(作成が簡単)                         │
│ 調整の自由度     │ △(限定的)                             │
│                  │ ◎(開始値/間隔/キャッシュ等を調整可)   │
└────────────┴───────────────────────────┘

すぐに採番値を受け取る:RETURNING 句

RETURNING ... INTO は、INSERT/UPDATE/DELETE 直後に、その行の列値をプログラム側に返す文法です。単一行の操作でよく使います。

何が便利?

  • 新しく入った行の ID(主キー) をすぐ受け取れる。
  • デフォルト値(SYSDATE など)や 生成列 の値も一度で取得。

注意(SQL*Plus)VARIABLE コマンドは DATE 型をサポートしません。日時を受け取るときは VARCHAR2 変数を用意し、RETURNING 側で TO_CHAR で文字列化して受け取ります。

使い方(SQL*Plus/SQLcl の例)

VARIABLE v_new_id NUMBER
VARIABLE v_when   VARCHAR2(32)

INSERT INTO demo_customers (name, email)
VALUES ('Yamada Taro','yamada.taro@example.com')
RETURNING id, TO_CHAR(joined_on,'YYYY-MM-DD HH24:MI:SS')
INTO :v_new_id, :v_when;

PRINT v_new_id
PRINT v_when
コマンド実行例

SQL> VARIABLE v_new_id NUMBER
SQL> VARIABLE v_when VARCHAR2(32)
SQL> INSERT INTO demo_customers (name, email)
2 VALUES ('Yamada Taro','yamada.taro@example.com')
3 RETURNING id, TO_CHAR(joined_on,'YYYY-MM-DD HH24:MI:SS')
4 INTO :v_new_id, :v_when;

1 row created.

SQL> select * from demo_customers;

ID NAME EMAIL JOINED_ON S
---------- --------------- ------------------------- --------- -
1 Sato Ichiro s.ichiro@example.com 23-AUG-25 A
1000 Yamada Taro yamada.taro@example.com 23-AUG-25 A

SQL> PRINT v_new_id

V_NEW_ID
----------
1000

SQL> PRINT v_when

V_WHEN
---------------------------------
2025-08-23 00:59:52

もし joined_on が TIMESTAMP 列なら

RETURNING id, TO_CHAR(joined_on,'YYYY-MM-DD HH24:MI:SS.FF3')
INTO :v_new_id, :v_when;

よくあるパターン

  • IDENTITY と組み合わせて、発行された id を受け取る。
  • SEQUENCE を使う場合NEXTVAL でID自体は分かりますが、RETURNING同時に他の列SYSDATE など)も受け取ると便利。

UPDATE/DELETE でも使える(参考)

-- UPDATE で変わった行の主キーを受け取る
VARIABLE v_id NUMBER
UPDATE demo_customers SET status='I' WHERE email='s.ichiro@example.com'
RETURNING id INTO :v_id;

-- DELETE で消した行の主キーを受け取る
VARIABLE v_del NUMBER
DELETE FROM demo_customers WHERE id=1
RETURNING id INTO :v_del;
コマンド実行例

SQL> VARIABLE v_id NUMBER
SQL> UPDATE demo_customers SET status='I' WHERE email='s.ichiro@example.com'
2 RETURNING id INTO :v_id;

1 row updated.

SQL> select * from demo_customers;

ID NAME EMAIL JOINED_ON S
---------- --------------- ------------------------- --------- -
1 Sato Ichiro s.ichiro@example.com 23-AUG-25 I
1000 Yamada Taro yamada.taro@example.com 23-AUG-25 A

SQL> PRINT v_id

V_ID
----------
1

SQL> VARIABLE v_del NUMBER
SQL> DELETE FROM demo_customers WHERE id=1
2 RETURNING id INTO :v_del;

1 row deleted.

SQL> select * from demo_customers;

ID NAME EMAIL JOINED_ON S
---------- --------------- ------------------------- --------- -
1000 Yamada Taro yamada.taro@example.com 23-AUG-25 A

SQL> PRINT v_del

V_DEL
----------
1

メモ

  • 基本は1行対象のDMLで使います。複数行を一度に処理する場合は、PL/SQL の RETURNING BULK COLLECT INTO(上級)などを検討します。
  • アプリ(JDBC 等)では SQL 文の RETURNING を使わず、getGeneratedKeys などで受け取る方法もあります。

代表的なエラーと直し方(ミニ逆引き)

-- 一意制約違反(同じメールを入れた 等)
ORA-00001: 一意制約(string.string)に反しています
→ 入力前に重複チェック。ユニーク制約+索引で防ぐ。

-- NOT NULL違反(必須列がNULL)
ORA-01400: (string)にはNULLは挿入できません。
→ DEFAULT 設定/アプリ側の入力チェック/列リストの見直し。

-- 外部キー違反(親がないのに子を入れた)
ORA-02291: 整合性制約(string.string)に違反しました - 親キーがありません
→ 先に親レコードを入れる/順番を直す。

トランザクションの基本(確定=COMMIT/取り消し=ROLLBACK)

INSERT はCOMMIT するまで確定しません。やり直したいときは ROLLBACK を使います。

SAVEPOINT sv1;  -- 途中の目印
INSERT INTO demo_customers (name) VALUES ('Temp User');
ROLLBACK TO sv1;  -- その目印まで戻す
COMMIT;           -- ここで確定


トランザクションについてはコチラ。


実行手順(19c/Oracle Linux 7.9 で確認済み)

以下は実機で動く最小手順です。表領域やパスワード規則は環境に合わせて調整してください。

1) ユーザー(スキーマ)を作る(SYSDBA)

-- CDB なら対象 PDB へ切り替えてから
-- sqlplus / as sysdba で接続
CREATE USER appuser IDENTIFIED BY "Str0ng#Pass"
  DEFAULT TABLESPACE users QUOTA UNLIMITED ON users;
GRANT CREATE SESSION, CREATE TABLE, CREATE SEQUENCE TO appuser;

2) ログインして表を作る(APPUSER)

-- sqlplus appuser/Str0ng#Pass
CREATE TABLE customers (
  id         NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name       VARCHAR2(50)  NOT NULL,
  email      VARCHAR2(255) UNIQUE,
  joined_on  DATE          DEFAULT SYSDATE,
  status     CHAR(1)       DEFAULT 'A' CHECK (status IN ('A','I'))
);

3) 1行入れてみる(列名を明示)

INSERT INTO customers (name, email, status)
VALUES ('Suzuki Jiro','suzuki.jiro@example.com','A');

-- 省略した列は DEFAULT(joined_on = SYSDATE)
INSERT INTO customers (name, email)
VALUES ('Kato Miki','kato.miki@example.com');

4) 日付や時刻を安全に入れる

INSERT INTO customers (name, email, joined_on)
VALUES (
  'Shimizu Kana',
  'shimizu.kana@example.com',
  TO_DATE('2025-08-23','YYYY-MM-DD')
);

5) 新しい ID をその場で受け取る

VARIABLE new_id NUMBER
INSERT INTO customers (name) VALUES ('Nagasawa Mei')
  RETURNING id INTO :new_id;
PRINT :new_id;
COMMIT;  -- 確定

6) 動作確認用の SQL

-- 件数を確認
SELECT COUNT(*) FROM customers;

-- 直近の行を確認
SELECT * FROM customers ORDER BY id DESC FETCH FIRST 5 ROWS ONLY;

-- メールの一意索引(UNIQUE)を確認
SELECT index_name, uniqueness
  FROM user_indexes
 WHERE table_name = 'CUSTOMERS';

実務で気をつけること(要点)

  • 列名は必ず書くINSERT INTO T VALUES(...) は将来の列追加で壊れやすい。
  • DEFAULT と NULL は別:集計や監査で意味が変わることがある。
  • 日付/時刻は書式を明示TO_DATETO_TIMESTAMP を使う。
  • 採番方法の混在は最小限:手動 ID と IDENTITY/SEQUENCE の併用は避ける。
  • コミット間隔を設計:大量 INSERT で入れすぎても少なすぎても NG。

INSERT ... SELECT は別記事で詳しく

  • 片方の表からもう片方へまとめて取り込むときに使う文です。
  • データ量が多いときは 実行計画・索引・ロック が重要。実機例は別記事で扱います。

まとめ

  • 列名を明示して安全に INSERT する。
  • IDENTITY は簡単、SEQUENCE は自由度。要件で選ぶ。
  • RETURNING で新 ID をすぐ取得できる。
  • 日付/時刻は書式を明示して暗黙変換を避ける。
  • COMMIT/ROLLBACK で確実にコントロールする。

本記事は Oracle Database 19c を対象に解説します(他バージョンは画面や既定値が異なる場合があります)。


[参考]
INSERT

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

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

コメント

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