如何在将重复记录插入数据库之前检查重复记录(2个主键)

时间:2017-01-27 23:11:47

标签: c# sql database duplicates

我在同一行同时检查数据库中的2个值时遇到问题,在我的表中我有2个主键(DateTagNumber),而且在我之前插入我要检查重复记录的任何新数据。

我需要检查我没有插入具有相同date和相同tagnumber的任何新数据。

例如:当前记录

Date: 25/03/2015 
TagNumber:111

当新数据可用时,我需要检查另一条记录上是否已存在DateTagNumber(因为这将是重复的)。

所以如果新数据是

Date:25/03/2015
TagNumber:111

此记录已存在并将跳过插入新记录。但是,如果新数据是:

Date:27/03/2015 
TagNumber:111

这将是一条新记录,并将继续插入数据。

代码:

foreach (DataGridViewRow row in dataGridView1.Rows)
        {

            string constring = @"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\koni\Documents\Visual Studio 2015\Projects\t\Project\DB.mdf;Integrated Security=True";
            using (SqlConnection con = new SqlConnection(constring))
            {

                using (SqlCommand sqlCommand = new SqlCommand("SELECT * from ResultsTable where TagNumber=@TagNumber AND Date=@Date", con))
                {
                    con.Open();
                    string smdt1 = row.Cells["Exposure Date"].Value.ToString();
                    string format1 = "dd.MM.yyyy";
                    DateTime dt1 = DateTime.ParseExact(smdt1, format1, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);

                    sqlCommand.Parameters.AddWithValue("@Date", dt1);
                    sqlCommand.Parameters.AddWithValue("@TagNumber", row.Cells["Device #"].Value);

                }
            }
        }

我已经尝试过ExecuteScalar()命令并且它不好 - 它仅适用于1个参数....

3 个答案:

答案 0 :(得分:0)

这应该在SQL端完成。将参数传递给存储过程,该过程检查表中是否已存在记录,如果存在,则返回错误或丢弃记录。如果它不存在,请将其插入表中。你不能在客户端这样做,因为你不会在内存中有完整的表。

答案 1 :(得分:0)

首先,它在这个表或您的数据类型中不是很清楚。假设您的数据类型为TagNumber: intDate: datetime

接下来你的问题可能是日期字段。

DateTime dt1 = DateTime.ParseExact(smdt1, format1, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);

将按预期解析日期。然而,这也将返回时间。因此,在您的查询中,参数@Date还会自动将时间部分添加到结果中(放置断点并查看)。现在,当您提供DateTimeStyles.AssumeUniversal时,时间设置为00:00:00 UTC时间,该时间将转换为当前时区。 (在澳大利亚,请到10:30:00)。

sqlCommand.Parameters.AddWithValue("@Date", dt1.Date); //parsed date at midnight 00:00:00

现在恕我直言,使用存储过程将是您最好的选择,因为您可以使用单个查询来查询和插入。

示例程序,例如。

CREATE PROCEDURE InsertNewRecord
    @TagNumber int,
    @Date datetime
AS
BEGIN
    SET NOCOUNT ON;
    IF NOT EXISTS (SELECT TOP 1 1 FROM ResultsTable WHERE [Date] = @Date AND TagNumber = @TagNumber)
        INSERT INTO ResultsTable (TagNumber, [Date]) VALUES (@TagNumber, @Date)
END
GO

接下来你可以轻松地调用它(注意只使用测试数据)。

var tagNumber = "111";
var date = DateTime.ParseExact("28.01.2017", "dd.MM.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);

using(var con = new SqlConnection(connectionString))
{
    using(var cmd = new SqlCommand("EXEC InsertNewRecord @TagNumber, @Date", con))
    {
        cmd.Parameters.AddWithValue("@TagNumber", tagNumber);
        cmd.Parameters.AddWithValue("@Date", date.Date);

        con.Open();
        cmd.ExecuteNonQuery();
        con.Close();
    }

}

正如您从存储过程中看到的那样,我们只是先查询(使用NOT EXISTS并选择一个真正的结果限制为单行以获得性能。SELECT TOP 1 1 FROM ..如果两者都返回单行1标签号和日期存在于记录中。

现在,您还可以将数据类型从datetime更改为date,从而消除time参数的@Date部分。但是,这将要求您确保数据干净,并且必须重建表。

最后一个选项是将您的datetime字段转换为查询中的date,并将@Date参数更改为date类型,然后检查它们是否相等比如。

ALTER PROCEDURE InsertNewRecord
    @TagNumber int,
    @Date date
AS
BEGIN
    SET NOCOUNT ON;
    IF NOT EXISTS (SELECT TOP 1 1 FROM ResultsTable WHERE cast([Date] as date) = @Date AND TagNumber = @TagNumber)
        INSERT INTO ResultsTable (TagNumber, [Date]) VALUES (@TagNumber, @Date)
END
GO

对于完整性,如果由于某种原因你不想使用存储过程,则以下将检查记录是否存在(注意使用.Date属性)。

using (var con = new SqlConnection(connectionString))
{
    bool exists = false;
    using(var cmd = new SqlCommand("SELECT TOP 1 1 FROM ResultsTable WHERE TagNumber=@TagNumber AND [Date]=@Date", con))
    {
        cmd.Parameters.AddWithValue("@TagNumber", tagNumber);
        cmd.Parameters.AddWithValue("@Date", date.Date);

        con.Open();
        var result = cmd.ExecuteScalar(); //returns object null if it doesnt exist
        con.Close();

        exists = result != null; //result will be one or null.
    }
    if (exists)
    {
        //INSERT RECORD
    }
}

无论哪种方式,我都会说问题在于数据的时间部分,但是没有我们只能猜测的更多信息。

答案 2 :(得分:0)

正如@Nico所解释的那样,创建存储过程是更好的方法。