ORA-01400: cannot insert NULL into (“スキーマ”.”テーブル”.”列”)は、NOT NULL 制約または主キー制約がある列に NULL を挿入しようとしたときに発生します。
エラーメッセージにはスキーマ名・テーブル名・列名が含まれるため、どの列が原因かは一目でわかりますが、INSERT 文で列を省略した場合の暗黙的な NULL 挿入や、ALTER TABLE で NOT NULL を追加しようとした際のエラーなど、発生パターンは複数あります。
この記事でわかること
- ORA-01400 が発生する主なパターン
- INSERT 文で列を省略した場合の暗黙的な NULL 挿入
- DEFAULT 値の設定と DEFAULT ON NULL(12c 以降)の使い方
- ALTER TABLE で既存テーブルに NOT NULL 制約を追加する正しい手順
- USER_TAB_COLUMNS で NOT NULL 制約と DEFAULT 値を確認する方法
ORA-01400 が発生する主なパターン
代表的な発生パターン
-- パターン①: NOT NULL 列を INSERT で省略している
CREATE TABLE orders (
order_id NUMBER PRIMARY KEY, -- NOT NULL(主キー)
customer_id NUMBER NOT NULL, -- NOT NULL 制約
order_date DATE DEFAULT SYSDATE, -- DEFAULT 値あり
status VARCHAR2(20) NOT NULL
);
-- NG: customer_id が省略されている → 暗黙的に NULL が挿入される → ORA-01400
INSERT INTO orders (order_id, order_date, status) VALUES (1, SYSDATE, 'PENDING');
-- ORA-01400: ("MYSCHEMA"."ORDERS"."CUSTOMER_ID") に NULL は挿入できません
-- OK: すべての NOT NULL 列に値を指定する
INSERT INTO orders (order_id, customer_id, order_date, status)
VALUES (1, 100, SYSDATE, 'PENDING');
-- パターン②: 明示的に NULL を挿入しようとしている
INSERT INTO orders (order_id, customer_id, order_date, status)
VALUES (2, NULL, SYSDATE, 'PENDING'); -- customer_id に NULL を明示 → ORA-01400
-- パターン③: SELECT INSERT で SELECT 結果が NULL になる
INSERT INTO orders (order_id, customer_id, order_date, status)
SELECT o.order_id, c.customer_id, SYSDATE, 'COPY'
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.customer_id; -- 対応するcustomerがなければNULL
-- パターン④: UPDATE で NOT NULL 列を NULL に更新しようとする
UPDATE orders SET customer_id = NULL WHERE order_id = 1;
-- ORA-01407: ("MYSCHEMA"."ORDERS"."CUSTOMER_ID") を NULL に更新できません
-- ※ UPDATE の場合は ORA-01400 ではなく ORA-01407 になる(混同に注意)
DEFAULT 値と DEFAULT ON NULL(Oracle 12c 以降)
通常の DEFAULT は列を省略したときに適用されますが、DEFAULT ON NULL は NULL を明示的に渡した場合にも DEFAULT 値を適用します(12c 以降)。
DEFAULT と DEFAULT ON NULL の違い
-- 通常の DEFAULT: 列を省略した場合にのみ適用される
CREATE TABLE logs (
log_id NUMBER PRIMARY KEY,
message VARCHAR2(500),
log_time DATE DEFAULT SYSDATE -- 列省略時のみ SYSDATE
);
INSERT INTO logs (log_id, message) VALUES (1, 'test'); -- OK: log_time = SYSDATE
INSERT INTO logs (log_id, message, log_time) VALUES (2, 'x', NULL); -- ORA-01400(もし NOT NULL 制約あれば)
-- DEFAULT ON NULL(Oracle 12c 以降): NULL を明示しても DEFAULT 値を使う
CREATE TABLE orders_v2 (
order_id NUMBER PRIMARY KEY,
status VARCHAR2(20) DEFAULT ON NULL 'PENDING' NOT NULL
-- NULL を明示しても 'PENDING' が使われる → NOT NULL 制約と組み合わせやすい
);
INSERT INTO orders_v2 (order_id) VALUES (1); -- status = 'PENDING'(省略)
INSERT INTO orders_v2 (order_id, status) VALUES (2, NULL); -- status = 'PENDING'(NULL → DEFAULT 適用)
INSERT INTO orders_v2 (order_id, status) VALUES (3, 'SHIPPED'); -- status = 'SHIPPED'
-- NOT NULL 制約の確認: USER_TAB_COLUMNS で確認する
SELECT column_name, nullable, data_default
FROM USER_TAB_COLUMNS
WHERE table_name = 'ORDERS_V2'
ORDER BY column_id;
-- nullable = N: NOT NULL 制約あり
-- data_default: デフォルト値(DEFAULT ON NULL は DATA_DEFAULT_ON_NULL=YES に追加列で確認)
ALTER TABLE で既存テーブルに NOT NULL 制約を追加する
既存テーブルに NOT NULL 制約を追加する場合、対象列に NULL 値がある行が1件でも存在すると ORA-02296 が発生します。また全行に DEFAULT 値をバックフィルしてから制約を追加する必要があります。
既存テーブルへの NOT NULL 追加手順
-- 既存テーブル(一部の行に NULL がある可能性がある)
ALTER TABLE employees ADD salary_grade NUMBER; -- NULL 許可で追加
-- NG: NULL 値がある状態で NOT NULL を追加しようとすると ORA-02296
ALTER TABLE employees MODIFY salary_grade NOT NULL;
-- ORA-02296: (HR.SYS_C00xxxx) を使用可能にできません - NULL 値があります
-- 手順①: まず全行に DEFAULT 値を設定する
UPDATE employees SET salary_grade = 0 WHERE salary_grade IS NULL;
COMMIT;
-- 手順②: NOT NULL 制約を追加する
ALTER TABLE employees MODIFY salary_grade NOT NULL;
-- または DEFAULT ON NULL を使って1ステップで追加する(12c 以降)
ALTER TABLE employees ADD monthly_bonus NUMBER DEFAULT ON NULL 0 NOT NULL;
-- 既存行には DEFAULT 値 0 が設定される → NULL 行が発生しないため制約追加が成功する
-- NULL 値の件数を確認してから作業する
SELECT COUNT(*) FROM employees WHERE salary_grade IS NULL;
-- NULL 値がある列を特定する
SELECT column_name, COUNT(*) AS null_count
FROM (
SELECT column_name, table_name
FROM USER_TAB_COLUMNS
WHERE table_name = 'EMPLOYEES' AND nullable = 'Y'
) cols
CROSS APPLY (
SELECT COUNT(*) AS null_rows
FROM employees
WHERE CASE columns.column_name WHEN 'SALARY_GRADE' THEN salary_grade END IS NULL
)
GROUP BY column_name
HAVING null_count > 0;
-- ※ 上記は例示。実際はテーブルの列を確認してから個別に COUNT する
まとめ
- ORA-01400 の主な原因:INSERT で NOT NULL 列を省略(暗黙的 NULL)・明示的な NULL 挿入・LEFT JOIN による NULL の混入
- UPDATE の場合は ORA-01407:UPDATE で NOT NULL 列を NULL に変更しようとした場合は ORA-01407 になる(ORA-01400 ではない)
- DEFAULT 値の活用:列にデフォルト値を設定することで省略時の NULL 挿入を防ぐ。12c 以降の DEFAULT ON NULL は NULL を明示しても DEFAULT を適用する
- 既存テーブルへの NOT NULL 追加:①UPDATE で NULL 行をなくす → ②ALTER TABLE MODIFY NOT NULL の2ステップ。または 12c 以降は DEFAULT ON NULL + NOT NULL で1ステップで追加できる
- USER_TAB_COLUMNS で確認:nullable=’N’ の列が NOT NULL 制約あり。data_default でデフォルト値を確認できる
主キー・外部キー・CHECK など制約全般については Oracle 制約(CONSTRAINT)完全ガイドを参照してください。INSERT / UPDATE / DELETE の基本的な操作については Oracle DML 完全ガイドも参照してください。