SQL Server で VALUES 句を使って一度に 1000 件以上のレコードを INSERT する

SQL Server で VALUES 句を使って一度に 1000 件以上のレコードを INSERT する

こんばんは、じゅんじゅんです。

普段、業務で SQL Server をよく使用しています。

プログラムに不具合が発生したので調べてみると、SQL で「INSERT ステートメントの行値式の数が、1000 行値の許容最大数を超えています。」というエラー (エラーコード: 10738) が発生していました。

今回はこのエラーを回避し、一度に 1000 件以上のレコードを INSERT する方法について紹介します。

エラーが発生する SQL

まずはエラーが発生する SQL の例を紹介します。以下のように Visual Basic で 1001 行の VALUES 句が書かれた INSERT 文を作成します。

valueExpressions(@Name1, @Value1) から (@Name1001, @Value1001) の文字列が格納された配列だとします。

エラーが発生する SQL 文作成するプログラム
Dim sqlText = $"
-- サンプルテーブルを作成
CREATE TABLE TargetTable (
  ID INT IDENTITY(1,1) PRIMARY KEY,
  NAME NVARCHAR(100),
  VALUE INT
);

-- 一時テーブルに全件挿入
INSERT INTO TargetTable (NAME, VALUE)
VALUES
  {String.Join(vbCrLf + ", ", valueExpressions)}
;"

INSERT 部分の SQL は以下のようになります。

エラーが発生する INSERT 文
INSERT INTO TargetTable (NAME, VALUE)
VALUES
  (@Name1, @Value1),
  (@Name2, @Value2),
  (@Name3, @Value3),
  -- 省略: 998行分のデータ
  (@Name1000, @Value1000),
  (@Name1001, @Value1001) -- この行でエラーが発生します
;

この SQL を実行すると制限に引っかかり「INSERT ステートメントの行値式の数が、1000 行値の許容最大数を超えています。」のエラーが発生します。

エラーを回避する方法

INSERT INTO … SELECT 構文を使用し、VALUES のデータを派生テーブルとして扱うことでこのエラーを回避できます。

エラーが発生しない SQL 文作成するプログラム
Dim sqlText = $"
-- サンプルテーブルを作成
CREATE TABLE TargetTable (
  ID INT IDENTITY(1,1) PRIMARY KEY,
  NAME NVARCHAR(100),
  VALUE INT
);

-- 一時テーブルに全件挿入
INSERT INTO TargetTable (NAME, VALUE)
SELECT
  targetData.NAME, targetData.VALUE
FROM (
  VALUES
    {String.Join(vbCrLf + ", ", valueExpressions)}
  ) AS targetData(
    NAME
  , VALUE
);"

INSERT 部分の SQL は以下のようになります。

エラーが発生しない INSERT 文
INSERT INTO TargetTable (NAME, VALUE)
SELECT
  targetData.NAME, targetData.VALUE
FROM (
  VALUES
    (@Name1, @Value1),
    (@Name2, @Value2),
    (@Name3, @Value3),
    -- 省略: 998行分のデータ
    (@Name1000, @Value1000),
    (@Name1001, @Value1001)
  ) AS targetData(
    NAME
  , VALUE
);

この書き方であればエラーなく 1000 件以上の INSERT が可能です。

参考

junya-gera