1.

Oracle 19cのCREATE TABLE|型・制約・外部キーとCTASの注意点

▶

Oracle Database 19cで表を作るための案内です。型・制約・既定値を分け、後半の製品比較をOracleへそのまま転用しないでください。同名エラーを解消するために既存表をDROPする手順ではありません。

Oracleの表作成で、型・既定値とNULL禁止・一意性・参照整合性を別に確認する模式図
通常DEFAULTやCHECK(amount >= 0)だけではNULLを禁止できません。CHECK(列 IS NOT NULL)とは条件が異なります。これは制約の役割を整理した図であり、実SQLや性能を試験した結果ではありません。

表関連の一覧から操作を選べます。既存表の列追加はカラムの追加、型・属性の変更はカラムの定義変更、削除の注意は表の削除を参照してください。

この記事の要点
  • CREATE TABLE 文で新しい表(テーブル)を作成する
  • 基本構文は CREATE TABLE 表名 ( 列名 データ型 [制約], ... [表制約] )
  • 列の型、制約(NOT NULL/UNIQUE/PRIMARY KEY/CHECK等)と既定値を分ける。DEFAULTはOracleの整合性制約ではない
  • 主キー / 外部キーは複数列の場合表制約として末尾に書く
  • IF NOT EXISTSの対応版を確認する。Oracle 19cは19.28以降で、存在する表の定義一致や移行完了を保証する指定ではない

CREATE TABLE とは

Oracle 19cの通常表DDLは構文上正しいDDLの実行前と成功後に暗黙COMMITがあります。CREATEが失敗すれば先行DMLも取り消せるとは保証しません。利用者の通常ROLLBACKで表作成を戻す手順ではなく、別作業の未確定変更と分けて計画します。DDLの説明も確認してください。

SQL で新しい表(テーブル)を作成するには CREATE TABLE 文を使います。列の名前、データ型、制約をまとめて指定し、データ格納の枠組みを定義します。

基本構文

保存した構文表記です。角括弧や省略記号をそのまま実行しないでください。Oracle通常の永続表CREATEはDDL前/成功後の暗黙COMMITがあり、同名エラーを含め失敗時に先行DMLが戻る保証はありません。既存の表や権限・quotaを先に確認してください。

CREATE TABLE 表名 (
    列名1 データ型1 [列制約],
    列名2 データ型2 [列制約],
    ...
    [表制約 (主キー / 外部キー / CHECK / UNIQUE)]
);

基本例

Oracle 19c向けの親子表の例

次は他の例と独立した通常の永続表です。専用の検証schemaで、2つの表名と制約名が未使用か、既存のCREATE TABLE権限・表領域quota・主キー用索引を作る前提があるかを確認します。権限を自動付与したり、同名表を消して作り直したりしないでください。親を先に定義しますが、2文をtransactionで囲んでもOracle通常DDLを一括ROLLBACKできるわけではありません。Oracle実機では未実行です。

-- Oracle Database 19c, ordinary permanent tables in a separate test schema.
-- Confirm both object names are unused. Do not DROP an existing object to retry.
CREATE TABLE cq_customers (
    customer_id NUMBER(10) CONSTRAINT cq_customers_pk PRIMARY KEY,
    display_name VARCHAR2(100 CHAR) NOT NULL
);

CREATE TABLE cq_orders (
    order_id NUMBER(10) CONSTRAINT cq_orders_pk PRIMARY KEY,
    customer_id NUMBER(10) NOT NULL,
    amount NUMBER(12,2) NOT NULL,
    status VARCHAR2(10 CHAR) DEFAULT 'NEW' NOT NULL,
    CONSTRAINT cq_orders_amount_ck CHECK (amount >= 0),
    CONSTRAINT cq_orders_customer_fk
        FOREIGN KEY (customer_id) REFERENCES cq_customers(customer_id)
);

NUMBERで数値、VARCHAR2のCHAR指定で文字数の長さ意味を表します。文字集合・byte上限まで無制限になる指定ではありません。主キーはNULLと重複を禁止し、NOT NULL付き外部キーは親のキーと対応する値を要求します。amountはNOT NULLとCHECKを組み合わせており、CHECKだけでNULLを禁止した例ではありません。通常DEFAULTは値省略時等の既定値で、明示NULLを自動的にNEWへ置き換えません。この例のstatusはNOT NULLなので明示NULLを拒否します。

この外部キーにはON DELETEを指定していません。子行が参照する親行のDELETEは拒否される条件になります。ON UPDATE CASCADEはOracle 19cの参照句ではサポートされず、後の比較例をそのまま転用できません。制約も参照してください。

保存した基本比較例

保存した型・制約の比較例です。OracleのINT/DECIMALはNUMBER系に対応し、VARCHARは現在VARCHAR2と同義でもVARCHAR2が推奨です。salaryのCHECKだけではNULLを禁止せず、emailの単一UNIQUEもNULLを許します。CURRENT_DATE/CURRENT_TIMESTAMPの型やsession time zoneは製品別に確認し、Oracle実行済みと扱わないでください。

CREATE TABLE employees (
    emp_id      INT          PRIMARY KEY,
    emp_name    VARCHAR(100) NOT NULL,
    email       VARCHAR(255) UNIQUE,
    hire_date   DATE         DEFAULT CURRENT_DATE,
    salary      DECIMAL(10,2) CHECK (salary >= 0),
    dept_id     INT,
    created_at  TIMESTAMP    DEFAULT CURRENT_TIMESTAMP
);

主なデータ型

次表は製品をまたぐ型名の比較です。すべてがOracle 19cの同名型という意味ではありません。Oracleの通常表ではNUMBER/VARCHAR2/DATE/TIMESTAMP/CLOB/BLOB等の仕様と、長さ意味・精度・文字集合を確認します。

用途代表的な型備考
整数INT / BIGINT / SMALLINT製品別に範囲を確認。OracleのINT/SMALLINTはNUMBER(38)への対応で、MySQL等の記憶サイズ別整数と同一視しない。BIGINTをOracle同名型と扱わない
小数DECIMAL(p,s) / NUMERIC十進の精度/scaleを設計する。OracleはDECIMAL/NUMERICをNUMBERへ対応させる。型名だけで全製品の範囲や丸めを同一視しない
浮動小数FLOAT / DOUBLE / REALOracleのFLOATはNUMBERのsubtypeで、BINARY_FLOAT/BINARY_DOUBLEとは別。DOUBLE等の他製品名をそのまま移植しない
文字列(固定長)CHAR(n)Oracle CHARは固定長だがBYTE/CHARの長さ意味と文字集合を確認。常にn文字という製品共通の定義ではない
文字列(可変長)VARCHAR(n)OracleはVARCHAR2を推奨。VARCHARは現在同義だが将来の意味変更に備え区別する。BYTE/CHARとbyte上限を確認
長文TEXT / CLOBOracleではCLOB等。TEXTは他製品の型名であり同名のOracle SQL型とはしない
日付DATE / TIME / TIMESTAMP / DATETIMEOracle DATEは時刻も持つ。TIMESTAMP/TIME ZONEの有無を選び、TIMEやDATETIME等の他製品名と分ける
真偽BOOLEAN / BITOracle 19cのSQL表列はBOOLEAN型を持たない。NUMBER(1)を使うだけでは0/1に限定されず、値域/NULLを別に設計する
バイナリBLOB / VARBINARYOracleはBLOB/RAW等。VARBINARY等の他製品型名と分け、容量・保存方式を確認

列制約

この表には比較のため既定値も残していますが、OracleではDEFAULTは制約ではありません。NOT NULLはinlineの列定義で宣言し、他の制約をout-of-lineにできることからNOT NULLも表末尾に書けるとは一般化しません。

制約意味
NOT NULLNULL を許さない
UNIQUEOracleの単一列UNIQUEは複数NULLを許す。複合キーのNULL条件は別に確認し、NULL禁止にはNOT NULLを使う
PRIMARY KEY主キー(NOT NULL + UNIQUE)
DEFAULT 値通常DEFAULTはINSERTの値省略時等に使う。既存NULLの埋戻しや明示NULLの置換ではない。DEFAULT ON NULLは別指定
CHECK (条件)OracleのCHECKはTRUEだけでなくNULLによるUNKNOWNでも満たす。NULL禁止が必要ならNOT NULLを別に付ける
REFERENCES 親表(列)参照可能な親のPRIMARY KEY/UNIQUE制約、列対応・型・権限を確認。nullableな単一FKはNULLも許すため、必須関係ならNOT NULLを別に設計する

表制約(複数列にまたがる制約)

列単位の制約とは別に、テーブル末尾にまとめて書く表制約があります。複合主キーや複数列の外部キーで使います。

保存した複合キー例です。orders/productsの参照可能な親キー、列/型・権限が必要で、これだけで一括実行できる検体ではありません。NOT NULLは列に指定し、CHECKと参照制約の効果を分けてください。

CREATE TABLE order_items (
    order_id  INT NOT NULL,
    item_no   INT NOT NULL,
    product_id INT NOT NULL,
    quantity   INT NOT NULL,
    -- 表制約
    PRIMARY KEY (order_id, item_no),
    FOREIGN KEY (order_id)   REFERENCES orders(order_id),
    FOREIGN KEY (product_id) REFERENCES products(product_id),
    CONSTRAINT chk_qty CHECK (quantity > 0)
);

主キーの書き方 2 通り

主キー2通りの独立例です。t1とt2は別表で、OracleではNUMBER/VARCHAR2の型・長さ意味を選びます。既存同名表をDROPして繰り返す手順ではありません。

-- 列制約として
CREATE TABLE t1 (
    id INT PRIMARY KEY,
    name VARCHAR(50)
);

-- 表制約として(複合主キー時もこちら)
CREATE TABLE t2 (
    id    INT,
    sub   INT,
    name  VARCHAR(50),
    PRIMARY KEY (id, sub)
);

外部キー(FOREIGN KEY)

Oracle 19cの外部キーは、非NULL値を参照可能な親キーへ対応させます。Oracleの参照句はON DELETE CASCADE/SET NULLを区別し、ON UPDATE CASCADEやSET DEFAULTをサポートしません。ON DELETE CASCADEは親行DELETEに伴う子行の削除であり、DROP TABLEのCASCADE CONSTRAINTSによる参照制約の削除とは別です。

保存した他製品比較例です。ON UPDATE CASCADEはOracle 19c非対応なのでこのまま実行できません。customersと親キー等の定義も省略されています。ON DELETE CASCADEは子行を削除するため、エラーの自動回避策として選ばないでください。

CREATE TABLE orders (
    order_id  INT PRIMARY KEY,
    customer_id INT NOT NULL,
    FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE CASCADE  -- 親が消えたら子も消す
        ON UPDATE CASCADE  -- 親のキーが変わったら子も追随
);
動作意味
CASCADEOracle 19cのON DELETE CASCADEは参照する子行の削除。ON UPDATE CASCADEはOracle非対応で、他製品の動作と分ける
SET NULLOracleのON DELETE SET NULLは参照する子側をNULLへ変える。NULLを許す設計かを確認し、NOT NULLを外す自動対処にはしない
SET DEFAULT製品別の比較項目。Oracle 19cのON DELETE SET DEFAULTは非対応
RESTRICT / NO ACTIONOracleではON DELETE指定を省略した通常の参照制約で、検査時に参照行が残る親のDELETE等を拒否する。RESTRICT/NO ACTIONという明示構文・遅延検査は製品別に確認

自動採番(IDENTITY / SERIAL / AUTO_INCREMENT)

次は製品別の列定義断片です。採番とPRIMARY KEY/UNIQUEによる保護は別で、採番だけでは無欠番・時系列順・全製品で1から開始を保証しません。PostgreSQLのIDENTITY例にはこの断片だけでは主キー制約がありません。SQLiteのINTEGER PRIMARY KEYと追加のAUTOINCREMENTの役割も分けて確認してください。

DBMS書き方
MySQLid INT NOT NULL AUTO_INCREMENT PRIMARY KEY
PostgreSQLid SERIAL PRIMARY KEY または id INT GENERATED ALWAYS AS IDENTITY
SQL Serverid INT IDENTITY(1,1) PRIMARY KEY
Oracleid NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
SQLiteid INTEGER PRIMARY KEY AUTOINCREMENT

IF NOT EXISTS(既存ならスキップ)

同名の存在を扱う指定で、既存表の列/制約が意図した定義と一致するかは確認しません。schemaやtable/view等の実体を調べ、同名エラーの対処として既存表をDROPしないでください。

保存したIF NOT EXISTS比較例です。Oracle 19cは19.28以降というRU条件があり、対応しても既存表の定義確認や差分移行にはなりません。usersが実業務の表名であればそのまま実行しないでください。

CREATE TABLE IF NOT EXISTS users (
    id    INT PRIMARY KEY,
    name  VARCHAR(50) NOT NULL
);

MySQL/PostgreSQL/SQLiteの比較に加え、Oracle 19cの公式資料では19.28以降に対応します。それ以前の19c RUへ一律に使えるとはしません。USER_TABLESの事前判定は定義照合でも同時作成競合の防止でもなく、EXECUTE IMMEDIATEはSQLを実行する機能で読取診断ではありません。

既存テーブルからコピー(CTAS)

OracleのCTASはSELECT結果に基づく新表で、元の全定義/保護/依存を複製する機能ではありません。PK/UNIQUE/FK/CHECK・索引・DEFAULT等は引き継がれません。明示したNOT NULLはNOT DEFERRABLE/VALIDATE状態と列を直接選ぶ等の条件付きで、主キー由来の暗黙NOT NULLは継承されません。backupという名前や0行SELECTだけで復元可能な完全backupとは扱わないでください。

保存したCTAS例です。「構造とデータ」「構造だけ」は全定義/制約/索引/既定値の完全複製を意味しません。employees_backupという名前だけで復元可能なbackupにはならず、DDLのCOMMITや同時利用も別に確認します。

-- 構造とデータをまとめてコピー
CREATE TABLE employees_backup AS
SELECT * FROM employees;

-- 構造だけ(WHERE で 0 件にする)
CREATE TABLE employees_empty AS
SELECT * FROM employees WHERE 1 = 0;

一時テーブル / グローバル一時テーブル

OracleのGLOBAL TEMPORARYは共有する定義とsession固有の行を分けます。ON COMMIT DELETE ROWSならCOMMIT後に行を消し、PRESERVE ROWSならsession終了まで行を保ちます。PRIVATE TEMPORARYは定義の寿命も別で、transaction-specificのDROP DEFINITION作成は既存transactionをCOMMITしませんが、session-specificのPRESERVE DEFINITION作成は暗黙COMMITします。一時表ならすべて同じ取消規則とはしません。

保存したMySQL等の一時表構文の比較です。CREATE TEMPORARY TABLEだけではOracle 19cのGLOBAL/PRIVATE TEMPORARY構文になりません。定義と行の寿命・COMMITの作用を製品別に確認し、全一時表がsession内だけ同じように生きるとは扱わないでください。

-- セッション内だけ生きる一時表
CREATE TEMPORARY TABLE tmp_log (
    id INT, msg VARCHAR(200)
);

テーブル作成後によくやること

  • インデックス追加: CREATE INDEX idx_emp_name ON employees(emp_name);
  • コメント付与(PostgreSQL): COMMENT ON COLUMN employees.emp_name IS '従業員名';
  • テーブル変更: 保存した他製品比較のALTER TABLE employees ADD COLUMN phone VARCHAR(20);はOracleのADD構文とは別です。OracleではADD (phone VARCHAR2(20 CHAR))等を対象条件に合わせ、既存データ・依存を確認します
  • 削除: DROP TABLE employees;は表/データを失う独立した破壊的操作です。作成後の必須手順や同名エラー解消にはせず、DDL/復旧条件を別に確認します

よくあるトラブル

症状原因
「table already exists」接続先・所有schema・同名objectの種類/定義を確認する。既存表をDROPしない。IF NOT EXISTSで処理を省略しても意図した定義一致は保証されない
「invalid identifier」列名/実名・予約語・大文字小文字を確認。Oracleの引用付き識別子は二重引用符で、MySQLのバッククオートを転用しない。引用すればすべての予約名問題を解決できるとはしない
外部キーで作成失敗親の実在・参照可能なPRIMARY KEY/UNIQUE制約・列対応/型・REFERENCES権限を確認。索引単独をOracleの参照キーと同一視せず、制約解除で通す手順にはしない
NOT NULL で INSERT 失敗値省略と明示NULL、通常DEFAULTとDEFAULT ON NULLを区別し、入力と業務要件を確認。DEFAULT追加だけで既存NULLや明示NULLが直るとはしない

FAQ

Q: 列の順序は重要?
A: 論理的には任意ですが、INSERT 値の暗黙的な順序や、人間が読む際の自然さに影響します。主キーを先頭にまとめる慣習が一般的。

Q: 型は後から変えられる?
A: Oracle 19cではALTER TABLE ... MODIFY等を使い、型/既存値・長さ/精度・依存/DDLのCOMMIT境界を確認します。全変更が可能でも全行rewriteでもありません。他製品のALTER COLUMNと混ぜず、カラムの定義変更を参照してください。

Q: 複合主キーと代理キー、どちらがいい?
A: 複合キー/代理キーは安定性・業務上の一意性・参照側・変更頻度等で設計します。AUTO_INCREMENTはMySQLの構文でOracleへ転用しません。代理キーを採っても必要な業務UNIQUE/NOT NULL/FKが不要になるわけではありません。

関連

  • 表関連 — 親カテゴリ
  • ALTER TABLE / DROP TABLE
  • CREATE INDEX — 索引
  • 主キー / 外部キー / NOT NULL / UNIQUE
  • 正規化 / データ型設計

公式資料と確認範囲

Oracle Database 19cの一次資料で、通常表の作成・型・制約・CTAS・一時表とRelease Updateの条件を確認しています。旧例と新Oracle例の実行、他DBの全互換性、処理時間・復旧は実証していません。次のSQLiteだけは合成検体で限定的に実測しています。

2026-10-27、ローカルSQLite 3.49.1の新しいメモリ内DBで6検体を確認しました。CHECK(x >= 0)とNULL、通常DEFAULTと値省略/明示NULL、NOT NULLとの組合せ、有効な単一FKのNULL/親キー対応、IF NOT EXISTSで元定義が変わらないこと、既存行へのDEFAULTなしNOT NULL列追加の拒否をそれぞれ比較しています。SQLiteでの合成例であり、上のOracleソースや旧例を実行した証明ではありません。Oracle・MySQL・PostgreSQL等や丸め・長さ意味・移行/ロック/性能を検証した意味にもなりません。本番・既存DB・ファイルDBには接続していません。

子ページ

子ページはありません

同階層のページ
  1. 表の作成
  2. カラムの追加
  3. カラムの定義変更
  4. カラムの削除
  5. 表の削除
  6. TRUNCATE文

最近更新/作成されたページ