第3章 データロード・アンロードと接続 / 想定学習時間:30〜40分 / 最終確認:2026年8月

3-2. COPY INTOによるバルクロード(検証・エラー処理・ロードメタデータ)

🎯 この節の学習目標

1. COPY INTO の基本:ステージからテーブルへ

ステージに置いたファイルをテーブルにロードする中心的なコマンドが COPY INTO <table> です。これはバルクロード(bulk load)と呼ばれる、まとまったデータを一括で取り込む方式です。

-- 最も基本的な形:ステージのファイルをテーブルへロードする
COPY INTO sales
  FROM @my_stage
  FILE_FORMAT = (FORMAT_NAME = 'my_csv_format');

-- 対象ファイルを絞り込む2つの方法
COPY INTO sales FROM @my_stage
  FILES = ('sales_01.csv.gz', 'sales_02.csv.gz');  -- ファイル名を列挙

COPY INTO sales FROM @my_stage
  PATTERN = '.*sales_2026.*[.]csv[.]gz';           -- 正規表現で指定

COPY INTO の実行には、実行中の仮想ウェアハウスが必要です(ここが 3-3 のサーバーレスな Snowpipe との大きな違いです)。ウェアハウスのサイズは「大きいほど速い」と単純には言えず、並列処理できるのはファイル数までなので、ファイル数に応じたサイズを選ぶのが基本です。ファイルが1つしかなければ、ウェアハウスを大きくしてもそのファイルのロードは速くなりません。

ステージ上のファイル@my_stage(内部 / 外部)
VALIDATION_MODE でロードせずに事前検証(任意)
COPY INTO <table>ロードメタデータ(64日)で同一ファイルをスキップ
エラー発生時は ON_ERROR の設定で分岐
ABORT_STATEMENT既定:ロード全体を中止
CONTINUEエラー行を飛ばして続行
SKIP_FILEエラーを含むファイルを丸ごとスキップ
成功した行がテーブルへ
テーブル結果は COPY_HISTORY / LOAD_HISTORY で確認

図:COPY INTO によるバルクロードの流れ。検証・重複防止・エラー処理の各ポイントを押さえる

2. ロードメタデータ:64日間の再ロード防止

COPY INTO は、どのファイルをいつロードしたかというメタデータをテーブルごとに 64日間保持します。このおかげで、同じ COPY 文を誤って再実行しても、ロード済みのファイルは自動的にスキップされ、データが二重に入ることを防げます。

📝 試験のポイント

「COPY INTO のロードメタデータは64日」「Snowpipe のロード履歴は14日」という日数の対比は、試験で定番の論点です(3-3 で再度整理します)。また「同じファイルを強制的に再ロードするオプションは何か」と問われたら FORCE = TRUE と即答できるようにしましょう。

3. ON_ERROR:エラー行に出会ったときの振る舞い

ロード中に形式不正な行などのエラーに遭遇したとき、どう振る舞うかを決めるのが ON_ERROR オプションです。

設定値動作向いている場面
ABORT_STATEMENTエラーを検出した時点でロード全体を中止する。COPY INTO の既定値不正データを1行も入れたくない、原因を調べてからやり直したい場合
CONTINUEエラー行だけをスキップして、残りの行のロードを続行する多少の不正行より、ロードを止めないことを優先する場合
SKIP_FILEエラーを含むファイル単位で丸ごとスキップし、他のファイルは続行するファイル単位で完全性を保ちたい場合
SKIP_FILE_n / SKIP_FILE_n%エラーが n 件(または n%)以上になったファイルだけをスキップする少数のエラーは許容し、壊れ方がひどいファイルだけ除外したい場合

4. VALIDATION_MODE:ロードせずに検証する

本番のロードを実行する前に「このファイルはエラーなくロードできるか」を確かめたいことがあります。VALIDATION_MODE を指定した COPY INTO は、データを一切ロードせずに検証だけを行います

-- ファイルの先頭10行を解析し、変換結果を表示する(ロードはしない)
COPY INTO sales FROM @my_stage
  VALIDATION_MODE = 'RETURN_10_ROWS';

-- すべてのファイルを検証し、見つかったエラーを一覧で返す(ロードはしない)
COPY INTO sales FROM @my_stage
  VALIDATION_MODE = 'RETURN_ERRORS';

-- 過去に実行した COPY のエラーを後から確認する VALIDATE 関数
SELECT * FROM TABLE(VALIDATE(sales, JOB_ID => '_last'));

5. ロード時の基本変換:できること・できないこと

COPY INTO は、FROM 句に SELECT を書くことで、ロードと同時に簡単な変換を行えます。ただし、できる変換は限定的です。

できることできないこと
列の並べ替え・省略CAST による型変換、SUBSTR などの単純な関数適用、定数列の追加結合(JOIN)集約(GROUP BY)、FLATTEN のような複雑な変換(必要ならいったんロードしてから変換する)

💡 具体例:ロード時の列選択と変換

-- ステージファイルの1列目と3列目だけを、型変換しながらロードする
COPY INTO sales (sale_id, amount)
  FROM (
    SELECT t.$1, CAST(t.$3 AS NUMBER(10,2))
    FROM @my_stage t
  )
  FILE_FORMAT = (FORMAT_NAME = 'my_csv_format');

-- 列名でマッピングする(Parquet などの列名付き形式で便利)
COPY INTO sales FROM @my_stage
  FILE_FORMAT = (TYPE = 'PARQUET')
  MATCH_BY_COLUMN_NAME = CASE_INSENSITIVE;

-- ロード成功後にステージのファイルを自動削除する
COPY INTO sales FROM @my_stage PURGE = TRUE;

$1, $2, ... はファイル内の列位置を指します。MATCH_BY_COLUMN_NAME は、ファイル内の列名とテーブルの列名を突き合わせてロードするオプションです。PURGE = TRUE はロード成功後にステージからファイルを削除し、後片付けを自動化します。

6. ロード履歴の確認:COPY_HISTORY と LOAD_HISTORY

「どのファイルがいつ、何行ロードされ、エラーは何件だったか」は、次の手段で確認できます。

手段場所特徴
COPY_HISTORY(テーブル関数)INFORMATION_SCHEMA指定テーブルへのロード履歴を確認。COPY と Snowpipe の両方の履歴を含む
LOAD_HISTORY(ビュー)INFORMATION_SCHEMA / ACCOUNT_USAGECOPY INTO によるロード履歴。INFORMATION_SCHEMA 版には Snowpipe の履歴は含まれない
-- 直近のロード状況をテーブル関数で確認する
SELECT file_name, row_count, error_count, last_load_time
FROM TABLE(INFORMATION_SCHEMA.COPY_HISTORY(
  TABLE_NAME => 'SALES',
  START_TIME => DATEADD(hour, -24, CURRENT_TIMESTAMP())
));

✅ この節のまとめ

練習問題

問1. 先週ロードしたファイルと同じファイルに対して COPY INTO を再実行した。既定の動作として正しいものはどれか。

  1. ファイルが再ロードされ、テーブルに重複データが入る
  2. ロードメタデータに基づき、ロード済みファイルは自動的にスキップされる
  3. エラーが発生して COPY 文全体が失敗する
  4. テーブルの既存データが削除されてから再ロードされる
解答と解説を見る

正解:B

COPY INTO はテーブルごとに64日間のロードメタデータを保持しており、ロード済みと判定されたファイルは自動的にスキップされます。Aが起きるのは FORCE = TRUE を指定した場合や、64日を超えてメタデータが期限切れになった場合です。Cのようなエラーにはならず、スキップされるだけです。Dのような既存データの削除(TRUNCATE 相当)を COPY が勝手に行うことはありません。

問2. ON_ERROR オプションを何も指定せずに COPY INTO を実行した場合の、エラー発生時の既定動作はどれか。

  1. エラー行をスキップしてロードを続行する(CONTINUE)
  2. エラーを含むファイルだけをスキップする(SKIP_FILE)
  3. ロード全体を中止する(ABORT_STATEMENT)
  4. エラー行を自動的に修正してロードする
解答と解説を見る

正解:C

COPY INTO の ON_ERROR の既定値は ABORT_STATEMENT で、エラーを検出するとロード全体が中止されます。AとBは明示的に指定した場合の動作です。Dのような自動修正機能はありません。なお、Snowpipe では既定値が異なり SKIP_FILE である点が 3-3 で登場します。

問3. 本番ロードの前に、ステージ上の全ファイルをロードせずに検証し、含まれるエラーを一覧で確認したい。最も適切な方法はどれか。

  1. VALIDATION_MODE = 'RETURN_ERRORS' を指定して COPY INTO を実行する
  2. FORCE = TRUE を指定して COPY INTO を実行する
  3. ON_ERROR = 'CONTINUE' を指定して COPY INTO を実行する
  4. PURGE = TRUE を指定して COPY INTO を実行する
解答と解説を見る

正解:A

VALIDATION_MODE = 'RETURN_ERRORS' は、データをロードせずに対象ファイルを検証し、すべてのエラーを返します。Bはロード済みファイルの強制再ロードで、検証とは無関係です。Cは実際にロードを行いながらエラー行をスキップする設定なので、「ロードせずに」という要件を満たしません。Dはロード成功後にステージのファイルを削除するオプションです。

問4. COPY INTO のロード時変換(FROM 句での SELECT)でできる操作はどれか。

  1. 複数のステージファイルとテーブルを JOIN して結果をロードする
  2. GROUP BY で集約した結果をロードする
  3. 列の並べ替え・省略や CAST による型変換を行ってロードする
  4. ウィンドウ関数で行番号を振り、直前行と比較しながらロードする
解答と解説を見る

正解:C

COPY INTO のロード時変換でサポートされるのは、列の並べ替え・省略、CAST、SUBSTR のような単純な関数適用など、行単位で完結する軽い変換に限られます。A の結合、B の集約、D のウィンドウ関数はサポートされません。複雑な変換が必要な場合は、いったんテーブルにロードしてから SQL(INSERT ... SELECT や Streams / Tasks、Dynamic Tables)で変換します。