我在同一行同时检查数据库中的2个值时遇到问题,在我的表中我有2个主键(Date
和TagNumber
),而且在我之前插入我要检查重复记录的任何新数据。
我需要检查我没有插入具有相同date
和相同tagnumber
的任何新数据。
例如:当前记录
Date: 25/03/2015
TagNumber:111
当新数据可用时,我需要检查另一条记录上是否已存在Date
和TagNumber
(因为这将是重复的)。
所以如果新数据是
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个参数....
答案 0 :(得分:0)
这应该在SQL端完成。将参数传递给存储过程,该过程检查表中是否已存在记录,如果存在,则返回错误或丢弃记录。如果它不存在,请将其插入表中。你不能在客户端这样做,因为你不会在内存中有完整的表。
答案 1 :(得分:0)
首先,它在这个表或您的数据类型中不是很清楚。假设您的数据类型为TagNumber: int
和Date: 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所解释的那样,创建存储过程是更好的方法。