【问题标题】:How to check for duplicate records before inserting them to DB(2 Primary Keys)如何在将重复记录插入 DB 之前检查重复记录(2 个主键)
【发布时间】:2017-06-13 18:11:25
【问题描述】:

我在检查数据库中同一行的 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 个参数....

【问题讨论】:

    标签: c# sql database duplicates


    【解决方案1】:

    首先,不清楚此表中的内容或您的数据类型。假设您的数据类型是 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,从而消除 @Date 参数中的 time 部分。但是,这将要求您确保数据是干净的,并且必须重建表。

    最后一个选择是在查询中将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】:

      这应该在 SQL 端完成。将您的参数传递给存储过程,以检查表中是否已存在记录,如果存在,则返回错误或丢弃记录。如果不存在,则将其插入表中。您无法在客户端执行此操作,因为您不会在内存中拥有完整的表。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 2013-10-23
          • 1970-01-01
          • 2017-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多