如何根据DB中的现有条目快速减少数据表

Tho*_*mas 5 c# sql sql-server datatable sql-server-2012

我目前正试图将数据表插入到数据库中.它工作得很好,速度很快.如果数据库中已存在任何行(重复键),则会出现唯一的问题.

为了解决这个问题,我修改了我的程序,以便我首先检查每个新条目是否已存在于数据库中.这是.......慢(在目前的情况下,我没有很多条目,但后来我需要检查的超过200k条目和那几次).因此,我需要让它变得更快(如果可能的话).

数据表的结构如下:

DataTable transactionTable.Columns.Add("DeviceId", typeof(Int32));
transactionTable.Columns.Add("LogDate", typeof(DateTime));
transactionTable.Columns.Add("LogType", typeof(Int32));
transactionTable.Columns.Add("LogText", typeof(String));

transactionTable.PrimaryKey = new DataColumn[3] {
    transactionTable.Columns[0],
    transactionTable.Columns[1],
    transactionTable.Columns[2]
};
Run Code Online (Sandbox Code Playgroud)

到目前为止我所拥有的是以下内容:

DataTable insertTable = transactionTable.Copy();
insertTable.Clear();
using (SqlConnection sqlcon = new SqlConnection(this.GetConnString()))
{
    sqlcon.Open();
    foreach (var entry in transactionTable.AsEnumerable())
    {
        using (SqlCommand sqlCom = sqlCon.CreateCommand())
        {
            sqlCom.Parameters.Clear();
            sqlCom.CommandText = "SELECT 1 FROM myTable WHERE"
                    + " DeviceId = @DeviceId AND LogDate = @LogDate"
                    + " AND LogType = @LogType"
            sqlCom.Parameters.AddWithValue("@DeviceId", entry.Field<Int32>("DeviceId"));
            sqlCom.Parameters.AddWithValue("@LogDate", entry.Field<DateTime>("LogDate"));
            sqlCom.Parameters.AddWithValue("@LogType", entry.Field<Int32>("LogType"));

            using (SqlDataREader myRead = sqlCon.ExecuteReader()
            {
                myRead.Read();

                if (myRead.HasRows == false)
                {
                    insertTable.Rows.Add(entry.ItemArray);
                }
            }

        }
    }
}

// And afterwards the bulkinsert which I think is out of scope for the question itself 
// (I use the insertTable there)
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:有没有办法更快地做到这一点,以免得到密钥违规问题?

Gio*_*uri 2

在这种情况下,我将使用一些临时表。以下是一些步骤:

  1. 批量插入临时表(使用SqlBulkCopy
  2. 使用带有左连接的存储过程插入基表以消除现有行
  3. 截断暂存表

因此,您需要删除代码中的 foreach 语句,添加用于插入基表的存储过程,添加用于截断的存储过程。或者您可以将最后 2 个步骤合二为一。