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 が可能です。