【Oracle】データ型完全ガイド|NUMBER・VARCHAR2・DATE・TIMESTAMP・INTERVAL・CLOB・BLOB の選び方と注意点

【Oracle】データ型完全ガイド|NUMBER・VARCHAR2・DATE・TIMESTAMP・INTERVAL・CLOB・BLOB の選び方と注意点 Oracle

Oracle のデータ型を正しく選ぶことは、ストレージ効率・検索性能・型変換エラーの防止につながります。特に NUMBER の精度指定・VARCHAR2 と CHAR の違い・DATE と TIMESTAMP の差・CLOB と VARCHAR2 の選択基準は、設計時に迷いやすいポイントです。この記事でそれぞれの特性と使い分けを整理します。

この記事でわかること

  • NUMBER(p,s) の精度・スケールの意味と設定方法
  • VARCHAR2 と CHAR の違い・NVARCHAR2・CLOB の使い分け
  • DATE と TIMESTAMP の違い・TIMESTAMP WITH TIME ZONE
  • INTERVAL 型で期間(月数・秒数)を格納・演算する方法
  • CLOB・BLOB・BFILE の違いと選択基準
  • Oracle 21c の JSON 型・23ai の BOOLEAN 型
  • 型変換関数(TO_NUMBER・TO_CHAR・TO_DATE・CAST)のまとめ
スポンサーリンク

数値型:NUMBER・FLOAT・BINARY_FLOAT

データ型 説明 推奨用途
NUMBER(p,s) 10進数。p=精度(全桁数)、s=スケール(小数点以下の桁数) 金額・数量など正確な数値。Oracle のデフォルト数値型
NUMBER 精度・スケール未指定。最大38桁 汎用だが精度管理が必要な場合は p,s を指定
INTEGER NUMBER(38,0) の別名 整数値(行IDなど)
FLOAT(b) 2進浮動小数点。b=ビット精度(最大126) 科学計算(正確な10進数が不要な場合)
BINARY_FLOAT 32ビット IEEE 754 浮動小数点 高速な浮動小数点演算が必要な場合(OLAP等)
BINARY_DOUBLE 64ビット IEEE 754 浮動小数点 BINARY_FLOAT より精度が必要な場合
NUMBER(p,s) の精度とスケールの使い方
-- NUMBER(p, s):
--   p = 有効桁数(全体の桁数)
--   s = スケール(小数点以下の桁数)
-- 例:
--   NUMBER(5,2) → 最大 999.99(整数部3桁・小数部2桁)
--   NUMBER(10,0) → 最大 9999999999(整数10桁)
--   NUMBER(6,-2) → スケール負数: 最大 9999900(100の位で丸める)

CREATE TABLE products (
    product_id   NUMBER(10)        PRIMARY KEY,   -- 整数
    unit_price   NUMBER(10, 2)     NOT NULL,       -- 金額(小数2桁)
    weight_kg    NUMBER(6, 3),                     -- 重量(3桁小数)
    tax_rate     NUMBER(5, 4)                      -- 税率(0.1000 など)
);

-- 格納される値と精度の例
-- NUMBER(5,2) に 1234.5 → エラー(整数部が3桁を超える)
-- NUMBER(5,2) に 123.456 → 123.46 に丸められる
-- NUMBER(5,2) に 123.454 → 123.45 に丸められる

-- BINARY_FLOAT / BINARY_DOUBLE は近似値になることに注意
SELECT 0.1 + 0.2 FROM DUAL;               -- NUMBER: 0.3 (正確)
SELECT (0.1 + 0.2) - 0.3 FROM DUAL;       -- NUMBER: 0  (正確)
-- BINARY_FLOAT では 0.300000012 のような近似値になる可能性がある

文字列型:VARCHAR2・CHAR・NVARCHAR2・CLOB

データ型 最大長 説明 推奨用途
VARCHAR2(n) 列: 4000B / 32767B* 可変長文字列。実際の長さ分だけ格納 一般的なテキスト(名前・住所など)
CHAR(n) 2000B 固定長文字列。n未満は空白埋め 固定長コード(都道府県コード・フラグ等)
NVARCHAR2(n) 4000B / 32767B* Unicode 可変長(文字数単位) 多言語対応が必要な場合(Oracle 12c 以降は VARCHAR2 も UTF-8可)
NCHAR(n) 2000B Unicode 固定長(文字数単位) Unicode 固定長コード
CLOB 128TB 文字型大オブジェクト 長い HTML・XML・JSON・テキストなど
NCLOB 128TB Unicode CLOB 多言語対応の大テキスト

* 32767B は MAX_STRING_SIZE=EXTENDED(12c 以降)有効時

VARCHAR2 と CHAR の違い・比較の注意点
-- CHAR(5) は常に5バイトに空白埋めして格納される
-- → 'AB' を格納すると内部的には 'AB   '(空白3個)になる

CREATE TABLE test_types (
    c1 CHAR(5),
    c2 VARCHAR2(5)
);
INSERT INTO test_types VALUES ('AB', 'AB');

-- CHAR は末尾空白を無視して比較するため = では一致するが LENGTH は異なる
SELECT LENGTH(c1), LENGTH(c2) FROM test_types;
-- CHAR: 5, VARCHAR2: 2

-- CHAR 列を WHERE = で比較する場合、空白は無視されるが
-- || で連結すると 'AB   Suffix' のように空白が含まれる
SELECT c1 || 'Suffix' FROM test_types;  -- 'AB   Suffix'(CHAR の空白が残る)
SELECT c2 || 'Suffix' FROM test_types;  -- 'ABSuffix'(VARCHAR2 は空白なし)

-- 実務: CHAR は固定長コードのみに使用。それ以外は VARCHAR2 を使う
VARCHAR2 vs CLOB:4000バイトの壁
標準設定の Oracle では VARCHAR2 の最大長は 4000 バイト(Byte セマンティクス)です。4000 バイトを超えるテキストには CLOB を使います。ただし CLOB は LIKE 検索の制限・インデックスの制限があるため、検索が必要なテキストは VARCHAR2 で設計することを優先してください。Oracle 12c 以降に MAX_STRING_SIZE=EXTENDED を設定すれば VARCHAR2 が最大 32767 バイトになります。

日付型:DATE・TIMESTAMP・INTERVAL

データ型 精度 説明
DATE 年月日・時分秒を格納。ミリ秒は持たない
TIMESTAMP(f) サブ秒 DATE + 小数秒(f=桁数、0〜9。デフォルト6)
TIMESTAMP WITH TIME ZONE サブ秒+TZ タイムゾーン情報込みで格納
TIMESTAMP WITH LOCAL TIME ZONE サブ秒+TZ DB のタイムゾーンに変換して格納・取得時にセッションTZに変換
INTERVAL YEAR TO MONTH 年・月 月単位の期間を格納
INTERVAL DAY TO SECOND 日〜秒 日・時・分・秒単位の期間を格納
DATE と TIMESTAMP の違い・ミリ秒の扱い
-- DATE: 秒単位まで。ミリ秒は切り捨て
-- TIMESTAMP: 小数秒(デフォルト6桁=マイクロ秒)まで格納

CREATE TABLE events (
    event_id     NUMBER          PRIMARY KEY,
    event_date   DATE,           -- 秒単位
    event_ts     TIMESTAMP(3),   -- ミリ秒単位(f=3)
    event_ts_tz  TIMESTAMP(6) WITH TIME ZONE   -- タイムゾーン付き
);

-- DATE に SYSDATE(秒単位)を格納
INSERT INTO events (event_id, event_date) VALUES (1, SYSDATE);

-- TIMESTAMP に SYSTIMESTAMP(マイクロ秒)を格納
INSERT INTO events (event_id, event_ts, event_ts_tz)
VALUES (2, SYSTIMESTAMP, SYSTIMESTAMP);

-- TIMESTAMP(3) に格納すると 123.456789 → 123 にミリ秒で切り捨て
-- TO_TIMESTAMP で文字列から変換
SELECT TO_TIMESTAMP('2024-03-15 10:30:00.123456', 'YYYY-MM-DD HH24:MI:SS.FF')
FROM DUAL;
INTERVAL 型:期間を格納・演算する
-- INTERVAL YEAR TO MONTH: 年・月の期間を格納
-- INTERVAL DAY TO SECOND: 日〜秒の期間を格納

-- INTERVAL リテラル
SELECT
    INTERVAL '1-6' YEAR TO MONTH     AS "1年6ヶ月",
    INTERVAL '5' YEAR                AS "5年",
    INTERVAL '3' MONTH               AS "3ヶ月",
    INTERVAL '2 04:30:00' DAY TO SECOND AS "2日4時間30分",
    INTERVAL '45' MINUTE             AS "45分"
FROM DUAL;

-- DATE との演算(数値の加算は日単位)
SELECT
    SYSDATE + 30            AS "30日後",
    SYSDATE + INTERVAL '3' MONTH AS "3ヶ月後",   -- 月末日処理あり
    SYSDATE + INTERVAL '2:30' HOUR TO MINUTE AS "2時間30分後"
FROM DUAL;

-- 2つの日付の差(INTERVAL で取得)
SELECT
    (TIMESTAMP '2024-12-31 23:59:59' - TIMESTAMP '2024-01-01 00:00:00')
    DAY(3) TO SECOND    AS diff
FROM DUAL;
-- 結果: +365 23:59:59.000000

-- 月数差は MONTHS_BETWEEN
SELECT MONTHS_BETWEEN(DATE '2025-03-31', DATE '2024-09-30') FROM DUAL;  -- 6

ラージオブジェクト型:CLOB・BLOB・BFILE

データ型 最大サイズ 格納場所 用途
CLOB 128TB DB内(行外) 長い文字データ(HTML・XML・JSON・文書)
NCLOB 128TB DB内(行外) Unicode 文字データ
BLOB 128TB DB内(行外) バイナリデータ(画像・PDF・動画)
BFILE OS 依存 DB 外(ファイルシステム) OS ファイルへの参照のみ(DB は参照を格納)
CLOB・BLOB の基本操作
-- CLOB に長文テキストを格納
CREATE TABLE documents (
    doc_id      NUMBER PRIMARY KEY,
    doc_title   VARCHAR2(200),
    doc_content CLOB             -- 長いHTMLや本文
);

-- CLOB に INSERT(4000バイト以内ならリテラルで可)
INSERT INTO documents VALUES (
    1,
    'Oracle入門',
    'これは長い文書の内容です。'
);

-- 4000バイト超の場合は DBMS_LOB.WRITEAPPEND か TO_CLOB() を使う
DECLARE
    v_clob CLOB := EMPTY_CLOB();
    v_chunk VARCHAR2(32767);
BEGIN
    INSERT INTO documents VALUES (2, '大きな文書', v_clob)
    RETURNING doc_content INTO v_clob;

    v_chunk := RPAD('あ', 10000, 'あ');   -- 10000文字
    DBMS_LOB.WRITEAPPEND(v_clob, LENGTH(v_chunk), v_chunk);
    COMMIT;
END;
/

-- CLOB の部分取得
SELECT DBMS_LOB.SUBSTR(doc_content, 100, 1) AS first_100
FROM documents
WHERE doc_id = 2;

-- CLOB の全文検索(LIKE は CLOB にも使えるが大きなデータでは遅い)
SELECT doc_title
FROM documents
WHERE doc_content LIKE '%Oracle%';

Oracle 21c・23ai の追加データ型

バージョン データ型 説明
Oracle 21c JSON ネイティブ JSON 型(OSON 形式でバイナリ格納・パース済みで高速)
Oracle 23ai BOOLEAN 真偽値型(TRUE/FALSE/NULL。従来は NUMBER(1) や CHAR(1) で代用していた)
Oracle 23ai VECTOR AI ベクトル検索用の浮動小数点配列型(次元数指定可)
BOOLEAN 型(Oracle 23ai)
-- Oracle 23ai 以前は NUMBER(1) や CHAR(1 CHAR) で代用していた
-- Oracle 23ai 以降は BOOLEAN 型が使用可能
CREATE TABLE feature_flags (
    flag_id     NUMBER PRIMARY KEY,
    flag_name   VARCHAR2(100),
    is_enabled  BOOLEAN DEFAULT FALSE NOT NULL
);

INSERT INTO feature_flags VALUES (1, 'dark_mode', TRUE);
INSERT INTO feature_flags VALUES (2, 'beta_api', FALSE);

SELECT flag_name, is_enabled
FROM feature_flags
WHERE is_enabled = TRUE;

-- IS TRUE / IS FALSE での比較も可能
SELECT flag_name FROM feature_flags WHERE is_enabled IS TRUE;
SELECT flag_name FROM feature_flags WHERE is_enabled IS NOT TRUE;  -- FALSE or NULL

型変換関数まとめ

関数 変換方向 よく使う書式
TO_NUMBER(str, fmt) 文字列→NUMBER TO_NUMBER('1,234', '9,999')
TO_CHAR(n, fmt) NUMBER→文字列 TO_CHAR(1234567, 'FM9,999,999')
TO_DATE(str, fmt) 文字列→DATE TO_DATE('2024-03-15', 'YYYY-MM-DD')
TO_CHAR(d, fmt) DATE→文字列 TO_CHAR(SYSDATE, 'YYYY/MM/DD HH24:MI:SS')
TO_TIMESTAMP(str, fmt) 文字列→TIMESTAMP TO_TIMESTAMP('2024-03-15 10:30:00.123', 'YYYY-MM-DD HH24:MI:SS.FF')
CAST(expr AS type) 型変換(汎用) CAST('100' AS NUMBER)
暗黙型変換の落とし穴
Oracle は WHERE hire_date = '2024-03-15' のように文字列を DATE に暗黙変換しますが、変換は NLS_DATE_FORMAT に依存するためサーバー設定によって挙動が変わります。本番環境と開発環境で NLS_DATE_FORMAT が異なると、同じ SQL で結果が変わったりエラーになります。日付リテラルは必ず DATE '2024-03-15' または TO_DATE('2024-03-15', 'YYYY-MM-DD') で明示してください。

まとめ

  • NUMBER(p,s):金額・数量は必ず精度を指定。BINARY_FLOAT は近似値になることに注意
  • VARCHAR2 vs CHAR:固定長コード以外は VARCHAR2 を使う。CHAR は空白埋めで比較・連結に注意
  • CLOB:4000バイト超のテキストに。LIKE 検索は遅いため設計段階で考慮
  • DATE vs TIMESTAMP:ミリ秒以下が必要なら TIMESTAMP(3〜6)。ログ記録・API 連携は TIMESTAMP が安全
  • INTERVAL:期間を値として格納・演算できる。数値(日数)加算より意図が明確
  • BOOLEAN(23ai〜):真偽値に使える。それ以前は NUMBER(1) または CHAR(1) で代用

日付の書式変換・NLS_DATE_FORMAT の詳細はTO_CHAR / TO_DATE 日付フォーマット完全ガイドを、NLS 設定の確認・変更方法はNLS設定完全ガイドも参照してください。