【Oracle】外部表(External Table)の使い方完全ガイド|CSVファイルをSQLで直接読み込む方法・ORACLE_LOADER・エラー処理

バッチ処理でCSVファイルを定期的にOracleに取り込みたい、外部システムからのデータ連携ファイルをSQLで直接参照したい――そんな場面で活躍するのが外部表(External Table)です。通常のテーブルと同じくSELECT文でデータを読み取れますが、データの実体はデータベース外のOSファイル(CSV, TSV等)に存在します。SQL*Loaderの制御ファイルを書かずに、SQLだけでファイルを読み込めるのが最大のメリットです。本記事ではディレクトリオブジェクトの作成から、ORACLE_LOADERドライバの設定、エラー処理、本テーブルへの取り込みまで体系的に解説します。

この記事でわかること

  • 外部表の仕組みとメリット
  • ディレクトリオブジェクトの作成と権限設定
  • ORACLE_LOADER ドライバで CSV/TSV ファイルを読み込む方法
  • 日付・数値の型変換とNULL処理
  • BADファイル・LOGファイル・REJECTリミットによるエラー処理
  • ORACLE_DATAPUMP ドライバで Data Pump 形式ファイルを参照する方法
  • INSERT INTO … SELECT で本テーブルにデータを取り込む方法
  • PARALLEL による読み込み高速化
スポンサーリンク

外部表とは

外部表はOracleのデータディクショナリに定義される読み取り専用のテーブルです。通常テーブルとの主な違いは次のとおりです。

比較項目 通常テーブル 外部表
データの保存先 データベース内(表領域) OSファイル(CSV, TSV等)
DML INSERT/UPDATE/DELETE 可能 SELECT のみ(読み取り専用)
インデックス 作成可能 作成不可
統計情報 DBMS_STATSで収集 収集可能(アクセス最適化に有効)
主な用途 通常のデータ格納 ファイルデータのSQL参照・ETL

ディレクトリオブジェクトの作成

外部表を作成する前に、ファイルが置かれているOSディレクトリを「ディレクトリオブジェクト」としてOracleに登録する必要があります。

ディレクトリオブジェクトの作成と権限付与
-- DBA権限でディレクトリオブジェクトを作成する
CREATE OR REPLACE DIRECTORY ext_data_dir
    AS '/data/external_files';
-- Windows の場合: AS 'C:\data\external_files'

-- 外部表を使うユーザーに読み取り権限を付与する
GRANT READ ON DIRECTORY ext_data_dir TO hr;

-- 書き込み権限(LOGファイル・BADファイルの出力先に必要)
GRANT WRITE ON DIRECTORY ext_data_dir TO hr;

-- ディレクトリ一覧を確認する
SELECT directory_name, directory_path
FROM all_directories
ORDER BY directory_name;
注意:ディレクトリオブジェクトのパスはOracleサーバー上のパスです。クライアントPCのパスではありません。ファイルはサーバー上の指定パスに配置してください。

ORACLE_LOADER ドライバで CSV ファイルを読み込む

最も一般的な使い方です。ORACLE_LOADER はSQL*Loaderと同じエンジンを使い、CSVやTSVファイルをSQLで参照できます。

CSV ファイルの例

emp_id,name,department,salary,hire_date
1001,佐藤太郎,営業部,350000,2020-04-01
1002,鈴木花子,開発部,420000,2019-07-15
1003,田中一郎,総務部,310000,2021-01-10
1004,中村美咲,開発部,480000,2018-03-20
外部表の作成 ── CSV ファイルを読み込む
CREATE TABLE emp_csv_ext (
    emp_id      NUMBER,
    name        VARCHAR2(100),
    department  VARCHAR2(50),
    salary      NUMBER,
    hire_date   DATE
)
ORGANIZATION EXTERNAL (
    TYPE ORACLE_LOADER
    DEFAULT DIRECTORY ext_data_dir         -- ディレクトリオブジェクト名
    ACCESS PARAMETERS (
        RECORDS DELIMITED BY NEWLINE       -- 行区切り
        CHARACTERSET UTF8                  -- 文字コード
        SKIP 1                             -- ヘッダー行をスキップ
        FIELDS TERMINATED BY ','           -- カンマ区切り
        OPTIONALLY ENCLOSED BY '"'         -- ダブルクォート囲み(任意)
        MISSING FIELD VALUES ARE NULL      -- 不足フィールドはNULL
        (
            emp_id,
            name,
            department,
            salary,
            hire_date DATE 'YYYY-MM-DD'    -- 日付フォーマット指定
        )
    )
    LOCATION ('employees.csv')             -- ファイル名
)
REJECT LIMIT UNLIMITED;                    -- エラー行の許容数(UNLIMITEDで全件許容)
外部表をSELECTで参照する
-- 通常のテーブルと同じように SELECT できる
SELECT emp_id, name, department, salary
FROM emp_csv_ext
WHERE department = '開発部'
ORDER BY salary DESC;

-- 集計もJOINもそのまま使える
SELECT department, COUNT(*) AS cnt, AVG(salary) AS avg_salary
FROM emp_csv_ext
GROUP BY department
ORDER BY avg_salary DESC;

TSV(タブ区切り)ファイルの読み込み

TSV ファイル用の外部表
CREATE TABLE log_tsv_ext (
    log_date    DATE,
    log_level   VARCHAR2(10),
    message     VARCHAR2(500)
)
ORGANIZATION EXTERNAL (
    TYPE ORACLE_LOADER
    DEFAULT DIRECTORY ext_data_dir
    ACCESS PARAMETERS (
        RECORDS DELIMITED BY NEWLINE
        CHARACTERSET UTF8
        FIELDS TERMINATED BY '\t'         -- タブ区切り
        MISSING FIELD VALUES ARE NULL
        (
            log_date DATE 'YYYY-MM-DD HH24:MI:SS',
            log_level,
            message
        )
    )
    LOCATION ('app.log')
)
REJECT LIMIT UNLIMITED;

エラー処理(BADファイル・LOGファイル・REJECT LIMIT)

データ品質が不安定なファイルを読み込む場合、エラー行の取り扱いが重要です。外部表はエラーに関するファイルを自動生成します。

ファイル種別 内容 指定方法
BADファイル 型変換エラー等で読み込めなかった行 BADFILE パラメータ
LOGファイル 読み込み処理のログ(件数・エラー詳細) LOGFILE パラメータ
DISCARDファイル WHERE条件で除外された行 DISCARDFILE パラメータ
BADファイルとLOGファイルを明示指定する
CREATE TABLE emp_csv_ext (
    emp_id      NUMBER,
    name        VARCHAR2(100),
    salary      NUMBER
)
ORGANIZATION EXTERNAL (
    TYPE ORACLE_LOADER
    DEFAULT DIRECTORY ext_data_dir
    ACCESS PARAMETERS (
        RECORDS DELIMITED BY NEWLINE
        BADFILE ext_data_dir:'emp_bad.log'     -- エラー行の出力先
        LOGFILE ext_data_dir:'emp_load.log'    -- 処理ログの出力先
        SKIP 1
        FIELDS TERMINATED BY ','
        MISSING FIELD VALUES ARE NULL
        (emp_id, name, salary)
    )
    LOCATION ('employees.csv')
)
REJECT LIMIT 10;   -- エラー行が10件を超えたらSELECT全体がエラーになる
REJECT LIMIT の使い分け
REJECT LIMIT UNLIMITED:エラー行を全てスキップして処理を継続する(開発・検証向け)
REJECT LIMIT 0:1行でもエラーがあれば即座にSELECT全体をエラーにする(本番の厳格チェック向け)
REJECT LIMIT n:n行までのエラーは許容し、超えたらエラー

ORACLE_DATAPUMP ドライバ

ORACLE_DATAPUMP ドライバを使うと、Data Pump形式のバイナリファイルを外部表で参照・出力できます。テーブルのデータをファイルにアンロードし、別の環境でロードする用途で使います。

ORACLE_DATAPUMP ── テーブルデータをファイルに書き出す
-- 書き出し用の外部表を作成する
CREATE TABLE emp_dump_ext
    ORGANIZATION EXTERNAL (
        TYPE ORACLE_DATAPUMP
        DEFAULT DIRECTORY ext_data_dir
        LOCATION ('emp_dump.dmp')
    )
AS SELECT employee_id, name, salary FROM employees;
-- CREATE TABLE AS SELECT で外部表を作成すると、
-- SELECT結果がData Pump形式のファイルに書き出される
ORACLE_DATAPUMP ── ファイルからデータを参照する
-- 読み込み用の外部表を作成する(別の環境で使う場合)
CREATE TABLE emp_load_ext (
    employee_id NUMBER,
    name        VARCHAR2(100),
    salary      NUMBER
)
ORGANIZATION EXTERNAL (
    TYPE ORACLE_DATAPUMP
    DEFAULT DIRECTORY ext_data_dir
    LOCATION ('emp_dump.dmp')
);

-- 通常テーブルと同様にSELECTできる
SELECT * FROM emp_load_ext WHERE salary > 400000;

本テーブルへのデータ取り込み(INSERT INTO … SELECT)

外部表は読み取り専用ですが、INSERT INTO ... SELECT で本テーブルにデータを取り込めます。CSVファイルから本テーブルへのロードパイプラインとして広く使われるパターンです。

外部表から本テーブルにデータを取り込む
-- 本テーブルが既に存在する場合
INSERT /*+ APPEND PARALLEL(e, 4) */ INTO employees e
SELECT emp_id, name, department, salary, hire_date
FROM emp_csv_ext;
COMMIT;

-- 本テーブルを新規作成して一括取り込み(CTAS)
CREATE TABLE employees_new AS
SELECT * FROM emp_csv_ext;
APPEND ヒントとの併用
大量データを取り込む場合は /*+ APPEND */ ヒントを付けてダイレクトパスINSERTにすると高速です。詳しくは「【Oracle】SQLヒント句の使い方完全ガイド」を参照してください。

複数ファイルを1つの外部表で参照する

LOCATION に複数のファイル名を指定すると、全ファイルが結合されて1つのテーブルとして参照されます。

複数ファイルを1つの外部表にまとめる
CREATE TABLE sales_csv_ext (
    sale_date   DATE,
    product     VARCHAR2(100),
    amount      NUMBER
)
ORGANIZATION EXTERNAL (
    TYPE ORACLE_LOADER
    DEFAULT DIRECTORY ext_data_dir
    ACCESS PARAMETERS (
        RECORDS DELIMITED BY NEWLINE
        CHARACTERSET UTF8
        SKIP 1
        FIELDS TERMINATED BY ','
        (sale_date DATE 'YYYY-MM-DD', product, amount)
    )
    LOCATION ('sales_2025_01.csv', 'sales_2025_02.csv', 'sales_2025_03.csv')
)
REJECT LIMIT UNLIMITED;
-- 3ファイルが結合されて SELECT * FROM sales_csv_ext で全件取得できる

PARALLEL による読み込み高速化

外部表の並列読み込み
-- 外部表にデフォルト並列度を設定する
ALTER TABLE emp_csv_ext PARALLEL 4;

-- または SELECT 時にヒントで指定する
SELECT /*+ PARALLEL(e, 4) */ emp_id, name, salary
FROM emp_csv_ext e
WHERE salary > 300000;

外部表の制限事項

制限 説明
DML不可 INSERT / UPDATE / DELETE はできない(SELECT のみ)
インデックス不可 インデックスは作成できない
制約不可 PRIMARY KEY, UNIQUE, CHECK 等の制約は定義できない
パーティション不可 外部表自体のパーティション化はできない
ファイルの場所 ファイルはOracleサーバー上に配置する必要がある(クライアントPCではない)
トランザクション 外部表のSELECTは読み取り一貫性が保証されない(ファイル内容がSELECT中に変わると結果が不定)

まとめ

外部表はCSVやTSVファイルをSQLで直接参照できる、OracleのETL基盤として非常に便利な機能です。

  • ORACLE_LOADER:CSV/TSVファイルをSQL*Loaderエンジンで読み込む。ヘッダースキップ・日付変換・NULLハンドリング等が可能
  • ORACLE_DATAPUMP:Data Pump形式のバイナリファイルを参照・出力する。環境間のデータ移行に適している
  • ディレクトリオブジェクトの作成と READ/WRITE 権限の付与が前提
  • BADFILE/LOGFILE/REJECT LIMIT でエラー行の処理を制御できる
  • LOCATION に複数ファイルを指定すると結合して1テーブルとして参照可能
  • INSERT INTO ... SELECT で本テーブルへの取り込みが可能。APPEND + PARALLEL で高速化
  • 外部表は読み取り専用でインデックスや制約は使えないため、本テーブルへの取り込み後に適切なインデックスと制約を設定する