📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

92行目: 92行目:


== エラーハンドリング ==
== エラーハンドリング ==
基本的なエラーハンドリングの設定を以下に示す。<br>
<br>
  <syntaxhighlight lang="tsql">
  <syntaxhighlight lang="tsql">
/* 基本的なエラーハンドリングの設定 */
  BULK INSERT TargetTable
  BULK INSERT TargetTable
  FROM 'C:\Data\source.txt'
  FROM 'C:\Data\source.txt'
127行目: 127行目:
また、詳細なエラー情報を取得する場合は、TRY-CATCHブロックを使用する。<br>
また、詳細なエラー情報を取得する場合は、TRY-CATCHブロックを使用する。<br>
  <syntaxhighlight lang="tsql">
  <syntaxhighlight lang="tsql">
/* BULK INSERTの基本的なエラーハンドリング設定 */
/* ERRORFILEにエラー内容を出力し、最大10件のエラーまで許容 */
BULK INSERT TargetTable
FROM 'C:\Data\source.txt'
WITH
(
    /* エラー情報を出力するファイルパスを指定 */
    ERRORFILE = 'C:\Errors\error.txt',
    /* 許容するエラーの最大数。この数を超えると処理が中止される */
    MAXERRORS = 10,
    /* ヘッダ行をスキップし、2行目からデータとして取り込む */
    FIRSTROW = 2,
    /* 列の区切り文字をカンマに指定 */
    FIELDTERMINATOR = ',',
    /* 行の区切り文字を改行に指定 */
    ROWTERMINATOR = '\n'
);
/* TRY-CATCHブロックを使用したより詳細なエラーハンドリング */
  BEGIN TRY
  BEGIN TRY
     BULK INSERT TargetTable
     BULK INSERT TargetTable
132行目: 152行目:
     WITH
     WITH
     (
     (
      /* エラー情報の出力先を指定 */
       ERRORFILE = 'C:\Errors\error.txt',
       ERRORFILE = 'C:\Errors\error.txt',
      /* 10件までのエラーを許容 */
       MAXERRORS = 10
       MAXERRORS = 10
     );
     );
  END TRY
  END TRY
  BEGIN CATCH
  BEGIN CATCH
    /* エラー発生時に詳細情報を取得 */
     SELECT  
     SELECT  
      /* エラー番号を取得 */
       ERROR_NUMBER() AS ErrorNumber,
       ERROR_NUMBER() AS ErrorNumber,
      /* エラーメッセージの詳細を取得 */
       ERROR_MESSAGE() AS ErrorMessage,
       ERROR_MESSAGE() AS ErrorMessage,
      /* エラーの重要度を取得 (0-25の値) */
       ERROR_SEVERITY() AS ErrorSeverity,
       ERROR_SEVERITY() AS ErrorSeverity,
      /* エラーの状態コードを取得 */
       ERROR_STATE() AS ErrorState;
       ERROR_STATE() AS ErrorState;
  END CATCH
  END CATCH
154行目: 181行目:
エラー発生時のロールバック動作についても理解が重要である。<br>
エラー発生時のロールバック動作についても理解が重要である。<br>
<code>BATCHSIZE</code>オプションを使用している場合、エラーが発生したバッチのみがロールバックされて、それ以前に正常に取り込まれたデータは保持される。<br>
<code>BATCHSIZE</code>オプションを使用している場合、エラーが発生したバッチのみがロールバックされて、それ以前に正常に取り込まれたデータは保持される。<br>
<br>
<syntaxhighlight lang="tsql">
/* ターゲットテーブルに対するBULK INSERT設定 (NULL値とバッチ処理の制御) */
BULK INSERT TargetTable
FROM 'C:\Data\source.txt'
WITH
(
    /* 空の文字列をNULLとして扱うのではなく、空文字として保持 */
    /* このオプションを指定しない場合、空文字列は自動的にNULLに変換される */
    KEEPNULLS,
    /* 一度に処理する行数を5000行に設定 */
    /* メモリ使用量とパフォーマンスのバランスを取るために使用 */
    /* 大きすぎる値はメモリ消費が増加し、小さすぎる値は処理時間が増加 */
    BATCHSIZE = 5000,
    /* テーブルの制約チェックを有効化 */
    /* 外部キー制約、CHECK制約、一意性制約などのすべての制約を確認 */
    /* パフォーマンスは低下するが、データの整合性が保証される */
    CHECK_CONSTRAINTS,
    /* エラー発生時の情報を出力するファイルを指定 */
    ERRORFILE = 'C:\Errors\error.txt',
    /* 最大エラー数を設定 (この数を超えると処理が中止) */
    MAXERRORS = 10,
    /* データファイルの区切り文字設定 */
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '\n',
    /* ヘッダ行をスキップ */
    FIRSTROW = 2
)
/* エラーハンドリングのためのTRY-CATCHブロック */
BEGIN TRY
    /* 上記のBULK INSERT文を実行 */
    /* 注意: EXEC内のBULK INSERT文は、上記のWITHブロックと同じ設定を使用 */
    EXEC('
      BULK INSERT TargetTable
      FROM ''C:\Data\source.txt''
      WITH
      (
          KEEPNULLS,
          BATCHSIZE = 5000,
          CHECK_CONSTRAINTS,
          ERRORFILE = ''C:\Errors\error.txt'',
          MAXERRORS = 10,
          FIELDTERMINATOR = '','',
          ROWTERMINATOR = ''\n'',
          FIRSTROW = 2
      )
    ');
    /* 正常終了時のログ出力 */
    PRINT 'BULK INSERT successfully completed';
END TRY
BEGIN CATCH
    /* エラー情報の取得と出力 */
    SELECT
      GETDATE() AS ErrorTime,            /* エラー発生時刻 */
      ERROR_NUMBER() AS ErrorNumber,      /* エラー番号 */
      ERROR_SEVERITY() AS ErrorSeverity,  /* エラーの重要度 */
      ERROR_STATE() AS ErrorState,        /* エラーの状態 */
      ERROR_PROCEDURE() AS ErrorProc,    /* エラーが発生したプロシージャ */
      ERROR_LINE() AS ErrorLine,          /* エラーが発生した行番号 */
      ERROR_MESSAGE() AS ErrorMessage;    /* エラーメッセージの詳細 */
    /* エラーのログテーブルへの挿入 (オプション) */
    INSERT INTO ErrorLog (
      ErrorTime,
      ErrorNumber,
      ErrorMessage
    )
    VALUES (
      GETDATE(),
      ERROR_NUMBER(),
      ERROR_MESSAGE()
    );
END CATCH;
</syntaxhighlight>
<br>
ただし、実務では、以下に示すように動的なパラメータを使用することが一般的である。<br>
変数を使用することにより柔軟な運用が可能になり、また、パラメータ化することで再利用性も高まる。<br>
<syntaxhighlight lang="tsql">
/* 動的パラメータの使用 */
DECLARE
    @FilePath NVARCHAR(500)  = 'C:\Data\source.txt',
    @ErrorPath NVARCHAR(500) = 'C:\Errors\error.txt',
    @BatchSize INT = 5000,
    @MaxErrors INT = 10,
    @BulkCmd NVARCHAR(MAX);
/* 動的なBULK INSERT文を構築 */
SET @BulkCmd = '
    BULK INSERT TargetTable
    FROM ''' + @FilePath + '''
    WITH
    (
      KEEPNULLS,
      BATCHSIZE      = ' + CAST(@BatchSize AS NVARCHAR(10)) + ',
      CHECK_CONSTRAINTS,
      ERRORFILE      = ''' + @ErrorPath + ''',
      MAXERRORS      = ' + CAST(@MaxErrors AS NVARCHAR(10)) + ',
      FIELDTERMINATOR = '','',
      ROWTERMINATOR  = ''\n'',
      FIRSTROW        = 2
    )';
BEGIN TRY
    /* 構築したBULK INSERT文を実行 */
    EXEC(@BulkCmd);
    /* 正常終了時のログ出力 */
    PRINT 'BULK INSERT successfully completed';
END TRY
BEGIN CATCH
    /* エラー情報の取得と出力 */
    SELECT
      GETDATE()        AS ErrorTime,      /* エラー発生時刻 */
      ERROR_NUMBER()    AS ErrorNumber,    /* エラー番号 */
      ERROR_SEVERITY()  AS ErrorSeverity,  /* エラーの重要度 */
      ERROR_STATE()    AS ErrorState,    /* エラーの状態 */
      ERROR_PROCEDURE() AS ErrorProc,      /* エラーが発生したプロシージャ */
      ERROR_LINE()      AS ErrorLine,      /* エラーが発生した行番号 */
      ERROR_MESSAGE()  AS ErrorMessage;  /* エラーメッセージの詳細 */
    /* エラーのログテーブルへの挿入 (オプション) */
    INSERT INTO ErrorLog (
      ErrorTime,
      ErrorNumber,
      ErrorMessage
    )
    VALUES (
      GETDATE(),
      ERROR_NUMBER(),
      ERROR_MESSAGE()
    );
END CATCH;
</syntaxhighlight>
<br><br>
<br><br>