У меня была хранимая процедура, сравнивающая две даты. Из логики моего приложения я ожидал, что они будут равны. Однако сравнение не удалось. Причиной этого было то, что одно из значений было сохранено как DATETIME
и должно быть CONVERT
-ed до DATETIME2
перед тем, как его сравнить с другим DATETIME2
. По-видимому, это изменило его ценность. Я проверил это небольшое испытание:
DECLARE @DateTime DATETIME='2018-01-18 16:12:25.113'
DECLARE @DateTime2 DATETIME2='2018-01-18 16:12:25.1130000'
SELECT @DateTime, @DateTime2, DATEDIFF(NANOSECOND, @DateTime, @DateTime2)
Это дало мне следующий результат:
Почему существует разница 333333ns между этими значениями? Я думал, что DATETIME2
, как более точный тип, должен иметь возможность точно представлять все значения, которые могут быть сохранены в DATETIME
? В документации DATETIME2 указано только:
Когда преобразование происходит из даты и времени, копируются дата и время. Дробная точность увеличивается до 7 цифр.
Никаких предупреждений о преобразовании, добавляющем или вычитающем 333333ns, к значению или от него! Так почему это происходит?
Я использую SQL Server 2016.
edit: Странно, на другом сервере я получаю нулевую разницу. Оба являются SQL Server 2016, но тот, где у меня проблема, имеет уровень совместимости, установленный в 130, тот, где у меня нет его 120. Переключение между ними меняет это поведение.
edit2: DavidG предложил в комментариях, что значение, которое я использую, может быть представлено как DATETIME2
, но не DATETIME
. Поэтому я изменил свой тест, чтобы убедиться, что значение, присваиваемое @DateTime2
, является допустимым значением DATETIME
:
DECLARE @DateTime DATETIME='2018-01-18 16:12:25.113'
DECLARE @DateTime2 DATETIME2=CONVERT(DATETIME2, @DateTime)
SELECT @DateTime, @DateTime2, DATEDIFF(NANOSECOND, @DateTime, @DateTime2)
Это немного помогает, потому что разница меньше, но все равно не равна нулю: