テーブル値パラメータのSQLを実行すると 「オブジェクト 'dbo.[テーブル値パラメータ変数]' には重複するキーを挿入できません。」のエラーが発生する

テーブル値パラメータのSQLを実行すると 「オブジェクト 'dbo.[テーブル値パラメータ変数]' には重複するキーを挿入できません。」のエラーが発生する現象の紹介です。

現象

テーブル値パラメータのSQLを実行すると以下の例外が発生します。

エラーメッセージ
Microsoft.Data.SqlClient.SqlException: '制約 'PK__#....' の PRIMARY KEY 違反。 オブジェクト 'dbo.[テーブル値パラメータ変数]' には重複するキーを挿入できません。重複するキーの値は ([値]) です。


英語では以下のメッセージとなります。

Error message
Violation of PRIMARY KEY constraint 'PK__#....'. Cannot insert duplicate key in object 'dbo.[TVP variable]'. The duplicate key value is ([value]).

原因

テーブル値パラメータに重複した値が挿入されています。

現象が発生するコード

UI

下図のフォームを作成します。

テーブル値パラメータのSQLを実行すると 「オブジェクト 'dbo.[テーブル値パラメータ変数]' には重複するキーを挿入できません。」のエラーが発生する:画像1

コード

using Microsoft.Data.SqlClient;
using static System.ComponentModel.Design.ObjectSelectorEditor;
using System.Windows.Forms;
using System.Data;

namespace TableValuedParametersQuery
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      List<string> qList = new List<string>() { "X-XD05", "R-D400", "B-250", "NC-208", "R-D400" };

      string constr = @"Data Source=192.168.64.48;Initial Catalog=iPentecSandBox;Connect Timeout=60;Persist Security Info=True;Encrypt=False;User ID=sa;Password=adelieC#8851SQL";

      using (SqlConnection con = new SqlConnection(constr)) {
        try {
          con.Open();
          string sqlstr = "SELECT * FROM ProductsF WHERE model IN(SELECT Model FROM @TVPParam)";
          SqlCommand com = new SqlCommand(sqlstr, con);

          // テーブル値型のデータを作成
          DataTable table = new DataTable();
          table.Columns.Add("Model", typeof(string));
          foreach (string q in qList) {
            table.Rows.Add(q);
          }

          // テーブル値パラメータを追加
          SqlParameter tvpParam = com.Parameters.AddWithValue("@TVPParam", table);
          tvpParam.SqlDbType = SqlDbType.Structured;
          tvpParam.TypeName = "dbo.ModelList";

          //exec
          SqlDataReader sdr = com.ExecuteReader();

          while (sdr.Read() == true) {
            string model = (string)sdr["model"];
            string name = (string)sdr["name"];
            string category = (string)sdr["category"];
            decimal price = (decimal)sdr["price"];
            textBox1.Text += string.Format("{0} / {1} / {2} : {3:g} \r\n", model.Trim(), name.Trim(), category.Trim(), price);

          }
        }

        finally {
          con.Close();
        }
      }
    }
  }
}

実行結果

プロジェクトを実行し、[button1]をクリックすると、以下のエラーが発生します。

エラーメッセージ
Microsoft.Data.SqlClient.SqlException: '制約 'PK__#AD0AAF0__FB104C127F888355' の PRIMARY KEY 違反。 オブジェクト 'dbo.@TVPParam' には重複するキーを挿入できません。重複するキーの値は (R-D400) です。


テーブル値パラメータのSQLを実行すると 「オブジェクト 'dbo.[テーブル値パラメータ変数]' には重複するキーを挿入できません。」のエラーが発生する:画像2

対処法

テーブル値パラメータに挿入するリストの値を確認します。 R-D400 の値が2つあり、テーブル値パラメーターに重複した値を挿入しています。

List<string> qList = new List<string>() { "X-XD05", "R-D400", "B-250", "NC-208", "R-D400" };


以下に修正します。

List<string> qList = new List<string>() { "X-XD05", "R-D400", "B-250", "NC-208" };


AuthorPortraitAlt
著者
iPentec.com の代表。ハードウェア、サーバー投資、管理などを担当。
Office 365やデータベースの記事なども担当。
作成日: 2025-02-25
Copyright © 1995–2025 iPentec all rights reserverd.