エラーファイルを使用した Transact-SQL 取り込みエラーのトラブルシューティング

適用対象:✅ Warehouse in Microsoft Fabric

この記事では、T-SQL インジェスト パターンでのインジェスト エラーのトラブルシューティング方法について説明します。

COPY INTOBULK INSERTOPENROWSET、およびCTASステートメントのINSERTUPDATEMERGE関数を使用したウェアハウスへのインジェストは、いくつかの理由で失敗する可能性があります。 ソース ファイルの値がテーブル スキーマと一致しない可能性があります。 必要な値が見つからない可能性があります。 インジェスト オプションも正しく構成されていない可能性があります。

このトラブルシューティング ガイドでは、拒否された行の診断情報を使用してエラーを解決し、行レベルのエラーをキャプチャし、エラー メタデータを使用して拒否された行を検査します。

COPY INTOやその他のインジェスト コマンドによって生成されたエラー ファイルを調べることで、取り込みに失敗した行とその理由を正確に特定できます。 この情報は、データ品質の問題を特定したり、インジェスト設定を調整したり、ソース データを修正したり、負荷を確実に再実行したりするのに役立ちます。

Important

これらの手順は、Transact-SQL コマンド (COPY INTOBULK INSERT、および DML と OPENROWSET 関数) を使用した CSV または JSONL ファイルの取り込みにのみ適用されます。 拒否された行の出力ファイルは、外部インジェスト ツール ( パイプライン など)、 Parquet ファイル、または SQL 分析エンドポイントからデータを取り込む場合には生成されません。

ターゲット テーブルを作成する

インジェスト コマンドを実行する前に、変換とデータ品質の問題を早期にキャッチできるように、厳密な型と NOT NULL 制約を持つ変換先テーブルを作成します。

  1. ウェアハウスワークスペースで、ウェアハウスを開きます。

  2. [ ホーム ] タブで、[ 新しい SQL クエリ] を選択します。

    [新しい SQL クエリ] ボタンのある、ユーザーのワークスペースの上段セクションのスクリーンショット。

  3. 次のステートメントを実行します。

    DROP TABLE IF EXISTS dbo.TaxiTrips;
    GO
    CREATE TABLE dbo.TaxiTrips
    (
        vendorID         int    NOT NULL,
        startLat         float  NOT NULL,
        startLon         float  NOT NULL,
        endLat           float  NOT NULL,
        endLon           float  NOT NULL,
        passengerCount   int    NOT NULL,
        tripDistance     float  NOT NULL,
        fareAmount       float  NOT NULL,
        mtaTax           float  NOT NULL,
        totalAmount      float  NOT NULL
    );
    

COPY INTO での取り込みやTransact-SQL での取り込みなど、サポートされている複数の方法を使用できます。 データ ソース、形式、自動化の要件に最適なインジェスト方法を選択します。 次の COPY INTO の例は、外部ファイルからテーブルにデータを読み込むための一般的なインジェスト パターンを示しています。

COPY INTO [dbo].[TaxiTrips]
FROM 'https://{storage-path}.blob.core.windows.net/Files/yellow/'
WITH ( FILE_TYPE = 'CSV' );

ソース ファイルが変換先テーブル スキーマと一致しない場合、このステートメントはデータの取り込みに失敗する可能性があります。 一般的な原因としては、列数の不一致、互換性のないデータ型、ターゲット テーブルに格納できない値などがあります。 インジェストで変換先スキーマに変換できない値が検出された場合、ステートメントは次のようなエラーを返します。

Msg 13812, Level 16, State 1, Line 2
Bulk load data conversion error (type mismatch or invalid character for the specified codepage)
for row starting at byte offset 0, column 1 (vendorID).
Underlying data description:
file 'https://....blob.core.windows.net/Files/yellow/tripdata.csv'.

このエラーは、1 つ以上の行を変換先の列の種類に変換できないことを示します。

MAXERRORS と ERRORFILE を使用してエラーを調査する

行レベルのエラーの数が定義されたしきい値を下回った場合にインジェストを続行し、指定した場所に診断の詳細を格納するには、次のオプションを使用します。

  • MAXERRORS は、インジェスト中に許容される行レベルのエラーの最大数を設定します。
  • ERRORFILE は、拒否された行とエラーの詳細をデータベースが書き込む場所を指定します。
COPY INTO [dbo].[TaxiTrips]
FROM 'https://{storage-path}.blob.core.windows.net/Files/yellow/'
WITH (
    FILE_TYPE = 'CSV',
    MAXERRORS = 10,
    ERRORFILE = 'https://{storage-path}.blob.core.windows.net/Files/yellow/'
);

Important

別のストレージ アカウントではなく、ソース ファイルの読み取りに使用されるのと同じストレージの場所に ERRORFILE を構成します。 ソース データへのアクセスに使用される ID には、構成されたエラー パスにフォルダーとファイルを作成するためのアクセス許可も必要です。

読み込み操作は、拒否された行の数が MAXERRORSよりも小さい場合にのみ成功します。 エラーがキャプチャされると、インジェスト操作は次のように書き込みます。

  • error.jsonl 構造化診断用
  • row.csv 拒否されたソース行の場合

拒否された行を検索してクエリを実行する

データベースは、構成されたエラーの場所の下にある構造化フォルダー階層にエラー情報を書き込みます。 これらのフォルダーは、特定の実行をトレースし、診断を 1 つのインジェスト ステートメントに関連付けるのに役立ちます。

ERRORFILE/
+-- _rejectedrows/
    +-- <timestamp>/
        +-- <statement_id>/
            +-- error.jsonl
            +-- row.csv or rows.jsonl

OPENROWSETを使用して、error.jsonlの構造化診断を読み取り、失敗した値、影響を受けた宛先列、および失敗した行の発生場所を特定できます。

SELECT *
FROM OPENROWSET(
    BULK 'https://{storage-path}.blob.core.windows.net/Files/yellow/_rejectedrows/*/*/error.jsonl'
);

通常、結果セットには、拒否されたレコードごとに 1 行が含まれます。次に例を示します。

エラー コラム カラム名 Value IsOutputted ファイル ErrorRowLocation
データ変換エラー 1 vendorID vendorID 1 https://.../yellow/tripdata.csv 0
NULLを許可しない列にNULL 1 vendorID NULL 1 https://.../yellow/ytripdata.csv 399
データ変換エラー 6 passengerCount N/A 1 https://.../yellow/yellow_tripdata.csv 519

error.jsonl ファイルには、1 行に 1 つの JSON オブジェクトが含まれています。 各オブジェクトには、前の表に示したプロパティが含まれています。 次の表では、各プロパティについて詳しく説明します。

コラム 説明
Error インジェスト中に値が拒否された理由を説明するエラー メッセージを提供します。
Column 取り込むことができなかった値を含むソース CSV ファイル内の列のインデックスを指定します。 列のインデックス作成は、最初の列の 1 から開始されます。
ColumnName 値を格納できなかった変換先テーブル列の名前を指定します。
Value 変換または検証できなかったソース値。
IsOutputted 報告されたエラーを含むソース ファイルの行が、拒否された行出力ファイル (row.csv または row.jsonl) にも書き込まれるかどうかを示します。 1 (または JSONL ファイル内のtrue) の値は、行がerror.csvで書き込まれたことを意味し、0 (または JSONL ファイル内のfalse) の値は、そうでないことを意味します。
File 拒否された行の発生元のソース ファイルを識別します。 この値は、拒否されたデータを調査のために元の入力ファイルにトレースするのに役立ちます。
ErrorRowLocation エラーが発生したソース ファイル内のバイト オフセット位置。

拒否された行を確認する

構造化された診断情報を確認したら、データベースが取り込めなかった元のソース データを調べることができます。 拒否された行の出力には、ソース レコードのコピーが含まれています。入力ファイルに表示されたとおりに保持されます。 拒否された行の診断では、インジェストに失敗したレコードのみを含むファイルが生成されます。

  • COPY INTO (FILE_TYPE = 'CSV')を使用して CSV ファイルを取り込む場合、拒否された出力にはrow.csv ファイルが含まれます。 このファイルはソース ファイルの構造と一致し、無効な値を持つ元の CSV 行が含まれています。
  • OPENROWSET(FORMAT = 'JSONL')を使用して JSONL ファイルを取り込む場合、拒否された出力にはrow.jsonl ファイルが含まれます。 このファイルは、インジェストエラーの原因となった元の JSON オブジェクトを保持します。

これらのファイルを使用して、正しくない値、予期しない NULL 値、データとして誤って解析されたヘッダー行など、エラーの根本原因を検証します。

SELECT *
FROM OPENROWSET(
    BULK 'https://{storage-path}.blob.core.windows.net/Files/yellow/_rejectedrows/*/*/row.csv'
);

row.csv スキーマはソース CSV 図形と一致し、インジェストに失敗した行のみが含まれます。

「rejected-row」行の出力例:

C1 C2 C3 C4 C5 C6 C7 C8 C9 C10
vendorID startLat startLon endLat endLon passengerCount tripDistance fareAmount mtaTax totalAmount
NULL 40.7484 -73.9857 40.7549 -73.9840 2 1.40 9.00 0.50 13.20
1 40.7216 -74.0047 40.7359 -74.0036 N/A 1.80 11.00 0.50 15.90

この診断情報に基づいて、次のインジェストの問題を特定できます。

  • ソース ファイル内のヘッダー行が誤ってデータ行として解析されます。 解決するには、 COPY INTO ステートメントで FIRSTROW = 2 オプションを使用する必要があります。
  • vendorID列 (C1) のソース ファイル内の行にはNULL値が含まれていますが、変換先TaxiTripsテーブル内の対応する列はNOT NULLとして定義されます。
  • passengerCount列のソース ファイルの行に、変換先の N/A 列に変換できない無効な値 () が含まれています。

Note

JSONL 入力から拒否された行を調べる場合も、同じプロセスが適用されます。 row.jsonl ファイルを使用して、拒否されたレコードを検査します。

インジェストの問題を修正し、データを再取り込みする

インジェスト エラーの原因を特定したら、問題を修正し、影響を受けるデータを再取り込みます。 修復方法は、エラーの発生元によって異なります。

変換先テーブルのスキーマを修正する

ソース データが宛先テーブル スキーマに準拠していない場合は、テーブル定義を更新します。 一般的な修正には、列データ型の変更や、 NOT NULLなどの制限付き制約の削除が含まれます。

一部のシナリオでは、データを再取り込みする前に、コピー先テーブルを削除して再作成することが必要になる場合があります。

ソース データの修正とファイルの再取り込み

ソース ファイル内の無効な値または一貫性のない値が原因でインジェストが失敗した場合は、それらの値を修正し、データを再取り込みします。 たとえば、 N/A などのプレースホルダー値を空の値や有効な既定値に置き換えます。

COPY INTO [dbo].[TaxiTrips]
FROM 'https://{storage-path}.blob.core.windows.net/Files/yellow/tripdata_corrected.csv'
WITH ( FILE_TYPE = 'CSV' );

修正されたデータを再取り込みする場合は、元のファイルを参照するフォルダー パスではなく、修正されたデータのみを含む新しいファイルを指す明示的なファイル パスを使用します。 この方法では、以前に正常に読み込まれた行を再取り込みできなくなり、重複するデータが回避されます。

ステージング テーブルを使用して拒否された行を再処理する

拒否された行をステージング テーブルに読み込み、Transact-SQL データ変更ステートメントを使用してデータを修正してから、修正された行を再取り込みできます。

次の CREATE TABLE AS SELECT ステートメントは、拒否された行をテーブルに読み込み、さらに処理します。

CREATE TABLE TaxiTrip_RejectedRows AS
SELECT *
FROM OPENROWSET(
    BULK 'https://{storage-path}.blob.core.windows.net/Files/yellow/_rejectedrows/*/*/row.csv'
);

データを修正したら、消去された行をコピー先テーブルに挿入します。