【Oracle】NOT NULL制約を削除・追加する方法(ALTER TABLE MODIFY)

OracleデータベースでカラムのNOT NULL制約を削除・追加したいと思ったことはありませんか?

テーブル設計の変更やデータ移行の際に、NOT NULL制約の操作は頻繁に必要になります。しかし、構文を間違えると ORA-01451ORA-02296 などのエラーが発生し、意図しないデータ不整合を招く恐れもあります。

この記事では、NOT NULL制約の削除・追加の基本構文から、複数カラムの一括変更DEFAULT制約との組み合わせ制約の確認方法他RDBMS(MySQL・PostgreSQL・SQL Server)との構文比較まで、実務で使える知識を網羅的に解説します。

スポンサーリンク

NOT NULL制約とは

NOT NULL制約は、カラムに NULL(値なし)を格納することを禁止する制約です。

ポイント:NOT NULL制約が設定されたカラムには、INSERT時に必ず値を指定する必要があります。DEFAULT値が設定されている場合は、省略してもDEFAULT値が格納されます。

テーブル作成時にNOT NULL制約を設定する例を見てみましょう。

SQL
CREATE TABLE employees (
  emp_id    NUMBER       NOT NULL,
  emp_name  VARCHAR2(100) NOT NULL,
  email     VARCHAR2(200),
  dept_id   NUMBER
);

この例では emp_idemp_name にNOT NULL制約が設定されています。emaildept_id はNULLを許可しています。

NOT NULL制約を削除する方法(基本構文)

OracleでNOT NULL制約を削除するには、ALTER TABLE ... MODIFY 文を使います。

構文
ALTER TABLE テーブル名 MODIFY (カラム名 NULL);

注意:OracleではMySQLやSQL Serverと異なり、ALTER TABLE ... ALTER COLUMN 構文は使えません。必ず MODIFY を使用してください。

実行例:emp_nameのNOT NULLを削除

SQL
-- emp_nameカラムからNOT NULL制約を削除
ALTER TABLE employees MODIFY (emp_name NULL);

実行結果

Table altered.

これで emp_name カラムにNULLを格納できるようになります。

変更前後の確認

制約が正しく削除されたか確認するために、変更前後で DESCRIBE を実行しましょう。

SQL*Plus
DESC employees;

変更前

Name      Null?    Type
--------- -------- -------------
EMP_ID    NOT NULL NUMBER
EMP_NAME  NOT NULL VARCHAR2(100)
EMAIL              VARCHAR2(200)
DEPT_ID            NUMBER

変更後

Name      Null?    Type
--------- -------- -------------
EMP_ID    NOT NULL NUMBER
EMP_NAME           VARCHAR2(100)
EMAIL              VARCHAR2(200)
DEPT_ID            NUMBER

EMP_NAME の Null? 欄から NOT NULL が消えていれば成功です。

複数カラムのNOT NULLを一括削除する

複数のカラムからNOT NULL制約を同時に削除できます。カラムをカンマで区切って指定します。

SQL
-- 複数カラムのNOT NULLを一括削除
ALTER TABLE employees MODIFY (
  emp_name NULL,
  email    NULL
);

ポイント:1つの ALTER TABLE 文で複数カラムを同時に変更できるため、カラムごとに個別のSQLを実行する必要はありません。DDLの実行回数を減らすことでパフォーマンスにも有利です。

NOT NULL制約を追加する方法

逆に、NULLを許可しているカラムにNOT NULL制約を追加する方法です。

構文
ALTER TABLE テーブル名 MODIFY (カラム名 NOT NULL);

実行例:emailにNOT NULLを追加

SQL
-- emailカラムにNOT NULL制約を追加
ALTER TABLE employees MODIFY (email NOT NULL);

注意:カラムに既にNULLデータが存在する場合、NOT NULL制約の追加は ORA-02296 エラーで失敗します。事前にNULLデータを更新または削除してください。

NULLデータが存在する場合の対処法

SQL
-- 手順1: NULLデータを確認
SELECT COUNT(*) FROM employees WHERE email IS NULL;

-- 手順2: NULLデータをデフォルト値で更新
UPDATE employees SET email = 'unknown@example.com'
WHERE email IS NULL;

-- 手順3: NOT NULL制約を追加
ALTER TABLE employees MODIFY (email NOT NULL);

DEFAULT制約との組み合わせ

NOT NULL制約は DEFAULT 値と組み合わせて使うことが多いです。DEFAULT値を設定しておくことで、INSERT時にカラムを省略してもNOT NULL違反を防げます。

NOT NULL + DEFAULT の設定

SQL
-- DEFAULT値とNOT NULLを同時に設定
ALTER TABLE employees MODIFY (
  status DEFAULT 'active' NOT NULL
);

NOT NULL削除時のDEFAULTの扱い

NOT NULL制約を削除しても、DEFAULT値はそのまま残ります。

SQL
-- NOT NULLだけを削除(DEFAULT値は維持される)
ALTER TABLE employees MODIFY (status NULL);

-- DEFAULT値も削除したい場合
ALTER TABLE employees MODIFY (status DEFAULT NULL NULL);

DEFAULT値の確認方法

  • USER_TAB_COLUMNSDATA_DEFAULT カラムで確認できます
  • NOT NULL制約を削除してもDEFAULT値は独立して保持されます
  • DEFAULT値の変更は ALTER TABLE ... MODIFY (カラム名 DEFAULT 新しい値) で行います

制約の確認方法

NOT NULL制約の状態を確認する方法はいくつかあります。

方法1:DESCRIBEコマンド

最もシンプルな確認方法です。SQL*PlusやSQL Developerで使用できます。

SQL*Plus
DESCRIBE employees;
-- または省略形
DESC employees;

実行結果

Name      Null?    Type
--------- -------- -------------
EMP_ID    NOT NULL NUMBER
EMP_NAME  NOT NULL VARCHAR2(100)
EMAIL              VARCHAR2(200)
DEPT_ID            NUMBER

方法2:USER_TAB_COLUMNSビュー

SQLで制約を確認する場合は USER_TAB_COLUMNS(または ALL_TAB_COLUMNS)を使います。

SQL
-- 特定テーブルのカラムのNULL許可状態を確認
SELECT column_name,
       data_type,
       nullable,
       data_default
FROM user_tab_columns
WHERE table_name = 'EMPLOYEES'
ORDER BY column_id;

実行結果

COLUMN_NAME  DATA_TYPE     NULLABLE  DATA_DEFAULT
-----------  ------------  --------  ------------
EMP_ID       NUMBER        N
EMP_NAME     VARCHAR2      N
EMAIL        VARCHAR2      Y
DEPT_ID      NUMBER        Y
NULLABLEの値 意味
N NOT NULL制約あり(NULLを許可しない)
Y NULL許可(NOT NULL制約なし)

方法3:USER_CONSTRAINTSビュー

名前付きのNOT NULL制約を確認する場合は、制約ビューを使います。

SQL
-- NOT NULL制約(CHECK制約として登録される)を確認
SELECT c.constraint_name,
       cc.column_name,
       c.search_condition
FROM user_constraints c
JOIN user_cons_columns cc
  ON c.constraint_name = cc.constraint_name
WHERE c.table_name = 'EMPLOYEES'
  AND c.constraint_type = 'C'
ORDER BY cc.column_name;

NOT NULL制約はCHECK制約の一種

  • OracleではNOT NULL制約は内部的に CHECK (column IS NOT NULL) として管理されます
  • USER_CONSTRAINTS では constraint_type = 'C'(CHECK制約)として表示されます
  • 制約名はシステムが自動生成(例: SYS_C00xxxx)されます

名前付きNOT NULL制約の操作

NOT NULL制約に名前を付けて定義することもできます。名前付き制約は管理がしやすくなります。

名前付き制約の作成

SQL
-- テーブル作成時に名前付きNOT NULL制約を定義
CREATE TABLE products (
  product_id   NUMBER CONSTRAINT pk_product_nn NOT NULL,
  product_name VARCHAR2(200) CONSTRAINT name_nn NOT NULL,
  price        NUMBER
);

-- 既存テーブルに名前付きNOT NULL制約を追加
ALTER TABLE products MODIFY (
  price CONSTRAINT price_nn NOT NULL
);

名前付き制約の削除

名前付きの場合は、DROP CONSTRAINT でも削除できます。

SQL
-- 方法1: MODIFY NULL で削除(推奨)
ALTER TABLE products MODIFY (price NULL);

-- 方法2: 制約名を指定して削除
ALTER TABLE products DROP CONSTRAINT price_nn;

ポイント:MODIFY NULL のほうが制約名を調べる必要がなくシンプルです。DROP CONSTRAINT は、制約名がわかっている場合やスクリプトで管理している場合に使います。

他のRDBMSとの構文比較

NOT NULL制約の削除構文はRDBMSによって異なります。

RDBMS NOT NULL削除の構文
Oracle ALTER TABLE t MODIFY (col NULL)
MySQL ALTER TABLE t MODIFY col データ型 NULL
PostgreSQL ALTER TABLE t ALTER COLUMN col DROP NOT NULL
SQL Server ALTER TABLE t ALTER COLUMN col データ型 NULL

各RDBMSのサンプルコード

MySQL の場合
MySQL
-- MySQLではデータ型の再指定が必要
ALTER TABLE employees MODIFY emp_name VARCHAR(100) NULL;

-- NOT NULLの追加
ALTER TABLE employees MODIFY emp_name VARCHAR(100) NOT NULL;
PostgreSQL の場合
PostgreSQL
-- PostgreSQLではALTER COLUMN ... DROP NOT NULLを使う
ALTER TABLE employees ALTER COLUMN emp_name DROP NOT NULL;

-- NOT NULLの追加
ALTER TABLE employees ALTER COLUMN emp_name SET NOT NULL;
SQL Server の場合
SQL Server
-- SQL ServerではALTER COLUMNを使う
ALTER TABLE employees ALTER COLUMN emp_name NVARCHAR(100) NULL;

-- NOT NULLの追加
ALTER TABLE employees ALTER COLUMN emp_name NVARCHAR(100) NOT NULL;

Oracle固有の注意点

  • Oracleでは MODIFY を使い、括弧 () でカラムを囲みます
  • MySQL / SQL Server のように データ型の再指定は不要 です
  • PostgreSQLのような DROP NOT NULL / SET NOT NULL 構文はありません

よくあるエラーと対処法

NOT NULL制約の操作で発生しやすいエラーを整理します。

エラー 原因 対処法
ORA-02296 NULLデータが存在する状態でNOT NULLを追加しようとした NULLデータを更新または削除してから実行
ORA-01451 既にNULL許可のカラムに対して NULL を再指定した 先にNULLABLEを確認してから実行
ORA-01400 NOT NULLカラムにNULLをINSERTしようとした 値を指定するか、DEFAULT値を設定
ORA-01407 NOT NULLカラムをNULLにUPDATEしようとした NULL以外の値を指定
ORA-00942 テーブルが存在しない、またはアクセス権がない テーブル名・スキーマを確認

ORA-02296 の詳細と対処

NOT NULLを追加する際に最も多いエラーです。

エラー再現と対処
-- NULLデータが入っている状態でNOT NULLを追加
ALTER TABLE employees MODIFY (email NOT NULL);
-- ORA-02296: (SCOTT.) の使用可能化 - NULLが見つかりました

-- 対処1: NULLの件数を確認
SELECT COUNT(*) AS null_count
FROM employees
WHERE email IS NULL;

-- 対処2: NULLデータを適切な値で埋める
UPDATE employees
SET email = 'N/A'
WHERE email IS NULL;
COMMIT;

-- 対処3: 再度NOT NULLを追加
ALTER TABLE employees MODIFY (email NOT NULL);

ORA-01451 の詳細と対処

既にNULLを許可しているカラムに再度 NULL を指定すると発生します。

エラー再現と対処
-- 既にNULL許可のカラムにNULLを指定
ALTER TABLE employees MODIFY (email NULL);
-- ORA-01451: 列はすでにNULL可能です

-- 対処: 事前にNULLABLEを確認
SELECT column_name, nullable
FROM user_tab_columns
WHERE table_name = 'EMPLOYEES'
  AND column_name = 'EMAIL';

実務での注意点

本番環境でNOT NULL制約を操作する際は、以下の点に注意してください。

1. 既存データへの影響

注意:NOT NULL制約を削除する場合、既存データには影響しません。しかし、削除後に新規INSERTでNULLが入る可能性があるため、アプリケーション側のバリデーションを確認してください。

2. ALTER TABLE は DDL(暗黙コミット)

注意点
-- ALTER TABLEはDDLのため、暗黙的にCOMMITされる
-- 以下のようなトランザクション内での使用に注意

UPDATE employees SET salary = 50000 WHERE emp_id = 1;
-- ↓ この時点でUPDATEも一緒にCOMMITされる
ALTER TABLE employees MODIFY (email NULL);
-- ROLLBACKしてもUPDATEは取り消せない
ROLLBACK; -- 効果なし

3. ロックへの影響

ALTER TABLE実行時のロック

  • ALTER TABLE ... MODIFY は対象テーブルに排他ロック(DDLロック)をかけます
  • 他のセッションからの DML(INSERT/UPDATE/DELETE)はブロックされます
  • 大量レコードのテーブルでは、メンテナンスウィンドウで実行することを推奨します
  • Oracle 11g以降では DBMS_REDEFINITION を使ったオンライン変更も可能です

4. 本番運用でのベストプラクティス

手順 内容
1. 事前確認 対象カラムの現在のNULL許可状態を確認
2. データ確認 NULLデータの有無と件数を確認(NOT NULL追加時)
3. バックアップ テーブルのバックアップを取得
4. テスト環境で検証 本番適用前にテスト環境で動作確認
5. 本番実行 メンテナンスウィンドウ中に実行
6. 事後確認 制約変更後のテーブル構造を確認
本番運用のサンプルスクリプト
本番用スクリプト例
-- ============================================
-- NOT NULL制約 変更スクリプト
-- 対象: employees.email
-- 変更内容: NOT NULL → NULL許可
-- ============================================

-- 1. 変更前の状態を確認
SELECT column_name, nullable, data_default
FROM user_tab_columns
WHERE table_name = 'EMPLOYEES'
  AND column_name = 'EMAIL';

-- 2. NOT NULL制約を削除
ALTER TABLE employees MODIFY (email NULL);

-- 3. 変更後の状態を確認
SELECT column_name, nullable, data_default
FROM user_tab_columns
WHERE table_name = 'EMPLOYEES'
  AND column_name = 'EMAIL';

よく使う操作のまとめ

操作 SQL構文
NOT NULL削除 ALTER TABLE t MODIFY (col NULL)
NOT NULL追加 ALTER TABLE t MODIFY (col NOT NULL)
一括削除 ALTER TABLE t MODIFY (col1 NULL, col2 NULL)
DEFAULT付きNOT NULL ALTER TABLE t MODIFY (col DEFAULT '値' NOT NULL)
名前付き制約で削除 ALTER TABLE t DROP CONSTRAINT 制約名
NULL状態の確認 SELECT nullable FROM user_tab_columns WHERE ...

まとめ

項目 内容
NOT NULL削除 ALTER TABLE テーブル名 MODIFY (カラム名 NULL)
NOT NULL追加 ALTER TABLE テーブル名 MODIFY (カラム名 NOT NULL)
NULLデータに注意 NOT NULL追加前にNULLデータが存在しないことを確認
DDLの暗黙コミット ALTER TABLE は自動コミットされるため、ROLLBACKできない
確認方法 DESC テーブル名 または USER_TAB_COLUMNS ビュー

NOT NULL制約の操作はOracleの基本スキルですが、本番環境では暗黙コミットロックの影響を理解した上で慎重に実行しましょう。変更前のバックアップと事後確認を忘れずに行うことが大切です。