Ошибка в миллисекундах при преобразовании из XML в SQL Server datetime


Я столкнулся с проблемой, связанной с преобразованием времени передачи данных из XML (ISO8601: yyyy-mm-ddThh: mi: ss.mmm) в SQL Server 2005 datetime. Проблема заключается в том, что преобразование миллисекунд неверно. Я проверил как неявное, так и явное преобразование с помощью convert (datetime, MyDate, 126) из nvarchar, и результат тот же:

Original                Result
2009-10-29T15:43:12.990 2009-10-29 15:43:12.990
2009-10-29T15:43:12.991 2009-10-29 15:43:12.990
2009-10-29T15:43:12.992 2009-10-29 15:43:12.993
2009-10-29T15:43:12.993 2009-10-29 15:43:12.993
2009-10-29T15:43:12.994 2009-10-29 15:43:12.993
2009-10-29T15:43:12.995 2009-10-29 15:43:12.997
2009-10-29T15:43:12.996 2009-10-29 15:43:12.997
2009-10-29T15:43:12.997 2009-10-29 15:43:12.997
2009-10-29T15:43:12.998 2009-10-29 15:43:12.997
2009-10-29T15:43:12.999 2009-10-29 15:43:13.000

Мое неэквивалентное тестирование показывает, что последняя цифра либо 0, либо 3, либо 7. Является ли это простой проблемой округления? Точность миллисекунд важна, и потерять / получить один или два не вариант.

2 11

2 ответа:

Да, SQL Server Время округления до 3.(3) миллисекунд:

SELECT CAST(CAST('2009-01-01 00:00:00.000' AS DATETIME) AS BINARY(8))
SELECT CAST(CAST('2009-01-01 00:00:01.000' AS DATETIME) AS BINARY(8))

0x00009B8400000000
0x00009B840000012C
Как вы можете видеть, эти DATETIME отличаются на 1 секунды, а их двоичные представления отличаются на 0x12C, то есть 300 в десятичной системе счисления.

Это потому, что SQL Server хранит time Часть DATETIME как число 1/300 вторых тиков от полуночи.

Если вы хотите повысить точность, вам нужно сохранить часть TIME как отдельное значение. Например, хранить время, округленное до секунды как DATETIME, и миллисекунды или любая точность, которая вам нужна в качестве INTEGER в других столбцах.

Это позволит вам использовать сложную арифметику DATETIME, например, добавлять месяцы или находить дни недели на DATETIME, и вы можете просто добавить или вычесть миллисекунды и объединить результат как .XXXXXX+HH:MM, чтобы получить действительное представление XML.

Из-за проблем точности , упомянутых Quassnoi Если у вас есть возможность использовать use SqlServer 2008, Вы можете рассмотреть возможность использования datetime2 datatype или если вас интересует только временная часть, вы можете использовать time datatype

Типы данных даты и времени - перечисляет все типы и их точность

В Sql Server 2005, если бы мне требовалась точность 1 миллисекунда, я бы добавил дополнительный столбец milisecond типа int для хранения числа милисекунды и удалите часть милисекунд из столбца dateTime (установите ее в значение 000). Это при условии, что вам также нужна информация о дате.