【Oracle】CREATE TABLE 完全ガイド|テーブル作成・CTAS・列制約・ストレージオプションまで解説

Oracle でデータを格納するには CREATE TABLE でテーブルを作成します。列のデータ型・制約(PRIMARY KEY・NOT NULL・UNIQUE・CHECK)・デフォルト値・ストレージオプションなど、テーブル作成時に設定できる項目は多岐にわたります。また CREATE TABLE AS SELECT(CTAS)を使うと、既存クエリの結果構造をそのままテーブルとして保存できます。

この記事でわかること

  • CREATE TABLE の基本構文と主要なデータ型
  • NOT NULL / DEFAULT / UNIQUE / CHECK 制約のインライン定義
  • 複合主キーなどテーブルレベルの制約定義
  • CREATE TABLE AS SELECT(CTAS)でクエリ結果からテーブルを作成する方法
  • STORAGE 句・PCTFREE・TABLESPACE などのストレージオプション
  • TRUNCATE TABLE と DELETE の違い
スポンサーリンク

CREATE TABLE の基本構文

CREATE TABLE の基本的な書き方
-- 最もシンプルな例
CREATE TABLE products (
    product_id   NUMBER(10)     NOT NULL,
    product_name VARCHAR2(200)  NOT NULL,
    price        NUMBER(12, 2)  DEFAULT 0 NOT NULL,
    category     VARCHAR2(50),
    created_at   DATE           DEFAULT SYSDATE NOT NULL,
    description  CLOB,
    CONSTRAINT products_pk PRIMARY KEY (product_id),
    CONSTRAINT products_name_uk UNIQUE (product_name),
    CONSTRAINT products_price_chk CHECK (price >= 0)
);

-- 主なデータ型の選び方
-- NUMBER(p, s): 数値。p=精度(有効桁数)、s=スケール(小数点以下桁数)
--   NUMBER(10):     整数 10桁
--   NUMBER(12, 2):  小数点2桁(金額など)
--   NUMBER:         精度未指定(38桁まで)
-- VARCHAR2(n):      可変長文字列。n はバイト数(BYTE)または文字数(CHAR)
--   VARCHAR2(200 CHAR): 200文字(マルチバイト文字も200文字として数える)
--   VARCHAR2(200 BYTE): 200バイト(3バイト文字は約66文字)
-- CHAR(n):          固定長文字列(未使用部分はスペースパディング)
-- DATE:             日付+時刻(秒まで)
-- TIMESTAMP:        日付+時刻(ミリ秒・タイムゾーン対応)
-- CLOB:             大量テキスト(最大 128TB)
-- BLOB:             バイナリデータ(最大 128TB)
-- BOOLEAN:          真偽値(Oracle 23ai 以降)

-- テーブル作成後の確認
DESCRIBE products;              -- 列定義を確認する
SELECT * FROM USER_TABLES WHERE table_name = 'PRODUCTS';  -- テーブル情報を確認する

制約の定義(インライン vs テーブルレベル)

制約の定義方法と命名規則
-- ① インライン制約(列の定義と同じ行に書く)
-- シンプルな制約に適している
CREATE TABLE orders (
    order_id    NUMBER(10)    CONSTRAINT orders_pk PRIMARY KEY,   -- インライン PK
    customer_id NUMBER(10)    NOT NULL,                           -- NOT NULL
    status      VARCHAR2(20)  DEFAULT 'PENDING'                   -- DEFAULT 値
                              CHECK (status IN ('PENDING','SHIPPED','CANCELLED')),
    order_date  DATE          DEFAULT SYSDATE NOT NULL,
    amount      NUMBER(12, 2) NOT NULL
);

-- ② テーブルレベル制約(複合主キー・複合 UNIQUE に必須)
CREATE TABLE order_items (
    order_id    NUMBER(10) NOT NULL,
    item_seq    NUMBER(5)  NOT NULL,
    product_id  NUMBER(10) NOT NULL,
    quantity    NUMBER(10) NOT NULL,
    unit_price  NUMBER(12, 2) NOT NULL,
    -- テーブルレベルの複合主キー
    CONSTRAINT order_items_pk PRIMARY KEY (order_id, item_seq),
    -- テーブルレベルの外部キー
    CONSTRAINT oi_order_fk  FOREIGN KEY (order_id) REFERENCES orders (order_id) ON DELETE CASCADE,
    CONSTRAINT oi_product_fk FOREIGN KEY (product_id) REFERENCES products (product_id),
    -- テーブルレベルの UNIQUE(複合 UNIQUE)
    CONSTRAINT oi_order_prod_uk UNIQUE (order_id, product_id),
    -- テーブルレベルの CHECK
    CONSTRAINT oi_qty_chk CHECK (quantity > 0)
);

-- 制約の命名規則(例):
-- テーブル名_PK: 主キー
-- テーブル名_カラム名_UK: UNIQUE
-- テーブル名_カラム名_FK: 外部キー
-- テーブル名_カラム名_CHK: CHECK
-- テーブル名_カラム名_NN: NOT NULL(CHECK 制約として定義する場合)

-- DEFERRABLE 制約(トランザクション内での制約チェックの延期が可能)
-- 相互参照がある場合や大量データロード時に使用
CONSTRAINT orders_cust_fk FOREIGN KEY (customer_id)
    REFERENCES customers (customer_id)
    DEFERRABLE INITIALLY DEFERRED   -- デフォルトで遅延評価
-- DEFERRABLE INITIALLY IMMEDIATE: デフォルトは即時評価(SET CONSTRAINTS DEFERRED で変更可)

CREATE TABLE AS SELECT(CTAS)の使い方

CTAS(Create Table As Select)は既存テーブルのデータとその構造をコピーして新しいテーブルを作成する方法です。バックアップコピーの作成・テーブルの再構成・集計結果の保存などに使われます。

CTAS でテーブルを作成する
-- 既存テーブルの全データをコピーして新テーブルを作成する
CREATE TABLE employees_backup AS
    SELECT * FROM employees;
-- ※ 制約(PRIMARY KEY・NOT NULL 以外)はコピーされない
-- ※ インデックスもコピーされない → 必要なら別途作成する

-- 特定列・条件でフィルタしてコピーする
CREATE TABLE high_salary_employees AS
    SELECT employee_id, last_name, salary, department_id
    FROM employees
    WHERE salary > 8000;

-- 列名を変更して CTAS する(AS で別名指定)
CREATE TABLE dept_salary_summary AS
    SELECT department_id,
           COUNT(*) AS emp_count,
           AVG(salary) AS avg_salary,
           MAX(salary) AS max_salary
    FROM employees
    GROUP BY department_id;

-- 構造だけコピーしてデータはコピーしない(WHERE 1=2 で 0件)
CREATE TABLE orders_template AS
    SELECT * FROM orders WHERE 1 = 2;
-- → テーブル定義(列・データ型)はコピーされるが行データは0件

-- CTAS でタブルスペースを指定する
CREATE TABLE employees_backup
    TABLESPACE data_ts
AS
    SELECT * FROM employees;

-- NOLOGGING で高速 CTAS(大量データ向け・REDO ログを減らす)
CREATE TABLE large_table_copy
    NOLOGGING
AS
    SELECT * FROM large_source_table;
-- NOLOGGING はバックアップ後のリカバリ性に注意(バックアップ後に実行推奨)

ストレージオプション(PCTFREE・TABLESPACE・STORAGE)

ストレージオプションを指定した CREATE TABLE
-- ストレージオプションを指定した本番テーブルの作成例
CREATE TABLE transactions (
    txn_id      NUMBER(15)   NOT NULL,
    account_id  NUMBER(10)   NOT NULL,
    txn_date    DATE         DEFAULT SYSDATE NOT NULL,
    amount      NUMBER(15, 2) NOT NULL,
    txn_type    VARCHAR2(20) NOT NULL,
    CONSTRAINT transactions_pk PRIMARY KEY (txn_id)
)
-- 表領域の指定(テーブルを格納する表領域)
TABLESPACE data_ts
-- インデックスは別表領域に作成(USING INDEX で指定する場合)
-- USING INDEX TABLESPACE index_ts

-- PCTFREE: 将来の UPDATE のために各ブロックに残す空き容量(%)
-- デフォルト 10。UPDATE が多いテーブルは大きめに設定
PCTFREE 20

-- PCTUSED: ブロックに新しい行を挿入できる最低使用率(%)(デフォルト 40)
-- ASSM(Automatic Segment Space Management)を使う場合は無視される
-- PCTUSED 40

-- INITRANS: 各ブロックの初期トランザクションスロット数(デフォルト 1)
-- 並列 DML が多い場合は大きめに設定(最大 255)
INITRANS 4

-- STORAGE: エクステントのサイズ設定(ASSM ではほぼ不要)
STORAGE (
    INITIAL     1M         -- 最初のエクステントサイズ
    NEXT        1M         -- 2番目以降のエクステントサイズ
    MINEXTENTS  1          -- 最小エクステント数
    MAXEXTENTS  UNLIMITED  -- 最大エクステント数(UNLIMITED: 無制限)
)

-- COMPRESS: データブロックを圧縮する(ストレージ節約)
-- COMPRESS FOR OLTP や COMPRESS FOR QUERY HIGH などもある(EE 機能)
-- COMPRESS

-- CACHE / NOCACHE: バッファキャッシュへの優先度
-- CACHE: バッファキャッシュの先頭に配置(小テーブルの高速アクセス)
-- NOCACHE: バッファキャッシュを使わない(大テーブルのシーケンシャルスキャン向け)
NOCACHE
;

-- ストレージパラメータを確認する
SELECT table_name, tablespace_name, pct_free, pct_used,
       ini_trans, max_trans, initial_extent, next_extent,
       min_extents, max_extents, compression
FROM USER_TABLES
WHERE table_name = 'TRANSACTIONS';

TRUNCATE TABLE と DELETE の違い

項目 TRUNCATE TABLE DELETE(WHERE なし)
分類 DDL(ロールバック不可) DML(COMMIT 前にロールバック可)
処理速度 高速(ハイウォーターマークをリセット) 低速(行ごとに処理・UNDO ログ生成)
UNDO/REDO 最小限 すべての削除行の UNDO ログを生成
トリガー 発動しない DELETE トリガーが発動する
外部キー参照 参照されている場合はエラー CASCADE オプションがあれば子行も削除
ストレージ ハイウォーターマークがリセット(容量が返却される) ハイウォーターマークは変わらない
TRUNCATE TABLE の使い方
-- テーブルのすべての行を削除する(高速・ロールバック不可)
TRUNCATE TABLE orders;

-- ストレージを保持したまま削除する(REUSE STORAGE: デフォルト DROP STORAGE)
TRUNCATE TABLE orders REUSE STORAGE;
-- DROP STORAGE(デフォルト): エクステントを解放してハイウォーターマークをリセット
-- REUSE STORAGE: エクステントを保持(次の INSERT が速くなるが容量は返却しない)

-- カスケード削除(12c 以降: 外部キーで参照されている場合も削除可)
-- 通常は外部キー制約があると TRUNCATE できない
-- → 外部キー制約を一時的に DISABLE して TRUNCATE するか、子テーブルを先に TRUNCATE する

-- DROP TABLE と TRUNCATE の違い
-- DROP TABLE: テーブル定義ごと削除(PURGE を付けるとゴミ箱にも入らない)
DROP TABLE old_logs PURGE;  -- テーブルを完全に削除する
-- TRUNCATE: テーブル定義を残してデータのみ削除(再利用可能)
TRUNCATE TABLE temp_data;

まとめ

  • データ型の選び方:数値は NUMBER(p, s)、可変長文字は VARCHAR2(n CHAR)(文字数指定を推奨)、日時は DATE(秒まで)または TIMESTAMP(ミリ秒・タイムゾーン対応)
  • 制約の定義:単一列の制約はインラインで、複合主キー・複合 UNIQUE はテーブルレベルで定義する。制約名を必ず指定する(デバッグ・ALTER TABLE でのメンテナンスが容易になる)
  • CTAS:CREATE TABLE … AS SELECT で既存テーブルのコピーを高速作成。WHERE 1=2 で定義のみコピー、NOLOGGING で大量データの高速コピーができる
  • PCTFREE:UPDATE が多いテーブルは 20〜30 に設定する。挿入専用で更新しないテーブルは 0 に設定するとブロック効率が上がる
  • TRUNCATE vs DELETE:全件削除なら TRUNCATE が高速・UNDO 不要。ただし DDL なのでロールバック不可。トリガーが必要な場合や外部キーがある場合は DELETE

テーブルに後から列・制約・ストレージオプションを追加・変更する方法についてはOracle ALTER TABLE 完全ガイドを参照してください。主キー・外部キー・CHECK 制約の詳細はOracle 制約(CONSTRAINT)完全ガイドも参照してください。