SQL Query DataTime значение Вставка дважды в таблицу - PullRequest
0 голосов
/ 15 марта 2011

Я пишу простой синтаксический анализатор CSV, который читает данные из моего CSV и вставляет их в мою таблицу. Программы работают нормально, когда я тестирую с небольшим набором данных. Где, когда я иду для большего, мое значение datatime показывается дважды Строка таблицы. Не знаю, почему ??

Например: на картинке ниже вы можете увидеть, как она печатает дату и время дважды, что должно быть напечатано только один раз. Но мои другие данные столбца были обрядовыми.

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 ]

2 голосов
/ 15 марта 2011

Значения DateTime не работают (или, по крайней мере, очень маловероятно) работают как уникальные идентификаторы. Для достижения уникальности рассмотрите возможность использования интегрального значения со свойством идентичности.

Ожидание даты / времени вставки / обновления для предоставления уникального значения даты / времени для каждой строки - это путь к печали по нескольким причинам.

  • Во-первых, точность значения даты и времени SQL Server равна 1 мс. Внутренне значение даты и времени в SQL Server - это кортеж, содержащий два 32-разрядных целых числа. Первое целое число - количество дней с начала эпохи (для SQL Server, то есть 1 января 1900 года). Второе - это смещение в миллисекундах от начала дня (00: 00: 00.000 или 12:00). В мире современных компьютерных процессоров 1 миллисекунда - это долгое время . Вы, вероятно, получите столкновения, просто по этой причине.

  • Во-вторых, гранулярность значения SQL DateTime составляет приблизительно 3 мс (в действительности значение datetime «округляется» в сегменты 3 мс или 4 мс, что еще больше увеличивает вероятность коллизии.

    • Наконец (и я не знаю, что это на самом деле так), я считаю, что если вы вставляете несколько строк в одну транзакцию (например, insert foo select * from bar) и используете свойство по умолчанию для установки текущей даты / time, вы можете получить все, что помечено тем же значением даты и времени, поскольку транзакция считается завершенной одновременно.

«Округленное» значение также будет кратно 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)

Удачи!

0 голосов
/ 16 марта 2011

Спасибо за ваши ответы. Я определил, что это создает проблему только из-за формата 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();
        }
0 голосов
/ 15 марта 2011

Попробуйте:

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

Это скажет вам, есть ли у вас одно и то же значение DateTime дважды или нет.

0 голосов
/ 15 марта 2011

Вы можете попытаться выполнить запрос внутри области блокировки.Это всего лишь предположение.

...