バッチ処理で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_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
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 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(タブ区切り)ファイルの読み込み
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 パラメータ |
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 UNLIMITED:エラー行を全てスキップして処理を継続する(開発・検証向け)REJECT LIMIT 0:1行でもエラーがあれば即座にSELECT全体をエラーにする(本番の厳格チェック向け)REJECT LIMIT n:n行までのエラーは許容し、超えたらエラー
ORACLE_DATAPUMP ドライバ
ORACLE_DATAPUMP ドライバを使うと、Data Pump形式のバイナリファイルを外部表で参照・出力できます。テーブルのデータをファイルにアンロードし、別の環境でロードする用途で使います。
-- 書き出し用の外部表を作成する
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形式のファイルに書き出される
-- 読み込み用の外部表を作成する(別の環境で使う場合)
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 */ ヒントを付けてダイレクトパスINSERTにすると高速です。詳しくは「【Oracle】SQLヒント句の使い方完全ガイド」を参照してください。
複数ファイルを1つの外部表で参照する
LOCATION に複数のファイル名を指定すると、全ファイルが結合されて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で高速化- 外部表は読み取り専用でインデックスや制約は使えないため、本テーブルへの取り込み後に適切なインデックスと制約を設定する
