SQL Query DateTime值在表中插入两次

时间:2011-03-15 15:48:59

标签: c# sql-server sql-server-2005 sql-server-2008

我正在编写一个简单的csv解析器,它从我的csv中读取数据并将其插入到我的表中。程序工作正常当我使用小数据集进行测试时。当我选择较大的数据集时,我的数据时间值仅显示两次表格行。不知道为什么??

例如:在下面的图片中,您可以看到它打印两次的日期时间,只能打印一次。但我的其他列数据是仪式。

enter image description here

CREATE TABLE [dbo].[SAMPLE](
    [Number] [int] NULL,
    [DateTime] [datetime] NULL,
    [Value] [decimal](9, 2) NULL
) ON [PRIMARY]

我正在运行一个运行近45000次的简单查询。

string sqlQuery = "insert into Sample values ( " + number+ ",'" + row.dateT + "'," + value + ");"; 
SqlCommand sqlComm  = new SqlCommand(sqlQuery, dbcon);

要测试我的输入值,我已将“sqlquery”写入文本文件,这是完美的,我100%确定我没有将相同的日期时间写入表格

4 个答案:

答案 0 :(得分:2)

DateTime值不起作用(或者至少不太可能起作用)作为唯一标识符。考虑使用带有标识属性的整数值来实现唯一性。

由于一些原因,期望插入/更新的日期/时间为每行提供唯一的日期时间值是悲伤的途径。

  • 首先,SQL Server日期时间值的精度为1毫秒。在内部,SQL Server日期时间值是包含两个32位整数的元组。第一个整数是自纪元以来的天数(对于SQL Server,即1900年1月1日)。第二个是从一天开始(00:00:00.000也称为12:00 am)的毫秒数偏移量。在现代计算机处理器的世界中,1毫秒是 loooong 时间。出于这个原因,你很可能会发生碰撞。

  • 其次,SQL DateTime值的粒度约为3ms(实际上,datetime值被“舍入”为3ms或4ms桶,进一步增加了碰撞的可能性。

    • 最后(我不知道这实际上是真的),我相信如果你在一个事务中插入多行(例如insert foo select * from bar)并使用默认属性来设置当前的日期/时间,您最终可能会被标记为具有相同日期时间值的所有内容,因为该交易被视为同时完成。

“舍入”值也将是0,3或7毫秒的倍数。请考虑以下脚本。它创建一个临时表,插入一些日期/时间字符串并将它们转换为日期时间值:

drop table #temp
go
create table #temp
(
  value       varchar(32) not null primary key clustered ,
  dtConverted as convert(datetime,value,121)
)
go
set nocount on

insert #temp (value) values( '2011-01-31 23:59:59.000' )
insert #temp (value) values( '2011-01-31 23:59:59.001' )
insert #temp (value) values( '2011-01-31 23:59:59.002' )
insert #temp (value) values( '2011-01-31 23:59:59.003' )
insert #temp (value) values( '2011-01-31 23:59:59.004' )
insert #temp (value) values( '2011-01-31 23:59:59.005' )
insert #temp (value) values( '2011-01-31 23:59:59.006' )
insert #temp (value) values( '2011-01-31 23:59:59.007' )
insert #temp (value) values( '2011-01-31 23:59:59.008' )
insert #temp (value) values( '2011-01-31 23:59:59.009' )
insert #temp (value) values( '2011-01-31 23:59:59.010' )

insert #temp (value) values( '2011-01-31 23:59:59.990' )
insert #temp (value) values( '2011-01-31 23:59:59.991' )
insert #temp (value) values( '2011-01-31 23:59:59.992' )
insert #temp (value) values( '2011-01-31 23:59:59.993' )
insert #temp (value) values( '2011-01-31 23:59:59.994' )
insert #temp (value) values( '2011-01-31 23:59:59.995' )
insert #temp (value) values( '2011-01-31 23:59:59.996' )
insert #temp (value) values( '2011-01-31 23:59:59.997' )
insert #temp (value) values( '2011-01-31 23:59:59.998' )
insert #temp (value) values( '2011-01-31 23:59:59.999' )

set nocount off
go
select * from #temp
go

运行上面的脚本时,结果可能不是您所期望的。这些值不仅舍入为3毫秒或4毫秒间隔,而且毫秒值大于997的任何日期时间值都会向上舍入到第二天(在本例中为月份)。这是一个边界条件,会在真实场景中咬你(不要问我怎么知道这个)。这是结果,你会得到:

value                   dtConverted
----------------------- -----------------------
2011-01-31 23:59:59.000 2011-01-31 23:59:59.000
2011-01-31 23:59:59.001 2011-01-31 23:59:59.000
2011-01-31 23:59:59.002 2011-01-31 23:59:59.003
2011-01-31 23:59:59.003 2011-01-31 23:59:59.003
2011-01-31 23:59:59.004 2011-01-31 23:59:59.003
2011-01-31 23:59:59.005 2011-01-31 23:59:59.007
2011-01-31 23:59:59.006 2011-01-31 23:59:59.007
2011-01-31 23:59:59.007 2011-01-31 23:59:59.007
2011-01-31 23:59:59.008 2011-01-31 23:59:59.007
2011-01-31 23:59:59.009 2011-01-31 23:59:59.010
2011-01-31 23:59:59.010 2011-01-31 23:59:59.010
2011-01-31 23:59:59.990 2011-01-31 23:59:59.990
2011-01-31 23:59:59.991 2011-01-31 23:59:59.990
2011-01-31 23:59:59.992 2011-01-31 23:59:59.993
2011-01-31 23:59:59.993 2011-01-31 23:59:59.993
2011-01-31 23:59:59.994 2011-01-31 23:59:59.993
2011-01-31 23:59:59.995 2011-01-31 23:59:59.997
2011-01-31 23:59:59.996 2011-01-31 23:59:59.997
2011-01-31 23:59:59.997 2011-01-31 23:59:59.997
2011-01-31 23:59:59.998 2011-01-31 23:59:59.997
2011-01-31 23:59:59.999 2011-02-01 00:00:00.000

(21 row(s) affected)
祝你好运!

答案 1 :(得分:0)

您可以尝试在锁定范围内执行查询。这只是猜测。

答案 2 :(得分:0)

试试这个:

select datetime, count(1) as countDT 
from SAMPLE
group by datetime
having count(1) > 1

这将告诉您两次是否具有相同的DateTime值。

答案 3 :(得分:0)

感谢您的回答。我已经确定它的创建问题只是因为DataTime格式我们将其转换为字符串以进行格式更改。我将datatime插入为SqldbType.DateTime。下面给出了我的代码片段,它解决了我的所有问题。

using (SqlCommand cmd = new SqlCommand(query, conn))
        {
          int 123;

          cmd.Parameters.Add(new SqlParameter(@"Number", SqlDbType.int)).Value = 123;
          cmd.Parameters.Add(new SqlParameter(@"aDateTime", SqlDbType.DateTime)).Value = mydate;
cmd.Parameters.Add(new SqlParameter(@"aDateTime", SqlDbType.decimal)).Value = value;
          cmd.ExecuteNonQuery();
        }