Я пытаюсь получить Datediff
между GETDATE()
и SYSDATETIME()
в миллисекундах.
SELECT DATEDIFF(ms, GETDATE() , SYSDATETIME());
В результате я получаю 0
или 1
или 2
или 3
. В чем причина этой разницы?
Я пытаюсь получить Datediff
между GETDATE()
и SYSDATETIME()
в миллисекундах.
SELECT DATEDIFF(ms, GETDATE() , SYSDATETIME());
В результате я получаю 0
или 1
или 2
или 3
. В чем причина этой разницы?
Это два разных вызова функций, которые могут возвращаться два раза в разное время.
Кроме того, GETDATE
возвращает тип данных datetime
с точностью всего 3-4 мс, тогда как SYSDATETIME()
возвращает тип данных datetime2(7)
.
Даже если оба вызова должны были вернуться в одно и то же время, вы могли бы увидеть проблему, с которой вы столкнулись из-за округления.
DECLARE @D1 DATETIME2 = '2012-08-18 10:08:40.0650000'
DECLARE @D2 DATETIME = @D1 /*Rounded to 2012-08-18 10:08:40.067*/
SELECT DATEDIFF(ms, @D1 , @D2) /*Returns 2*/
Другой ответ неверен: если вы подставите GETDATE()
, функция будет вызываться только один раз, как показано ниже.
WHILE DATEDIFF(ms, GETDATE() , GETDATE()) = 0
PRINT 'This will not run in an infinite loop'
При запуске цикла на моем рабочем столе Windows XP с GETDATE()
и SYSDATETIME
я также вижу результаты, указывающие на то, что может происходить что-то еще. Возможно, вызов другого API.
CREATE TABLE #DT2
(
[D1] [DATETIME2](7),
[D2] [DATETIME2](7)
)
GO
INSERT INTO #DT2
VALUES(Getdate(), Sysdatetime())
GO 100
SELECT DISTINCT [D1],
[D2],
Datediff(MS, [D1], [D2]) AS MS
FROM #DT2
DROP TABLE #DT2
Пример результатов ниже
+-----------------------------+-----------------------------+-----+
| D1 | D2 | MS |
+-----------------------------+-----------------------------+-----+
| 2012-08-18 10:16:03.2500000 | 2012-08-18 10:16:03.2501680 | 0 |
| 2012-08-18 10:16:03.2530000 | 2012-08-18 10:16:03.2501680 | -3 |
| 2012-08-18 10:16:03.2570000 | 2012-08-18 10:16:03.2501680 | -7 |
| 2012-08-18 10:16:03.2600000 | 2012-08-18 10:16:03.2501680 | -10 |
| 2012-08-18 10:16:03.2630000 | 2012-08-18 10:16:03.2501680 | -13 |
| 2012-08-18 10:16:03.2630000 | 2012-08-18 10:16:03.2657914 | 2 |
| 2012-08-18 10:16:03.2670000 | 2012-08-18 10:16:03.2657914 | -2 |
| 2012-08-18 10:16:03.2700000 | 2012-08-18 10:16:03.2657914 | -5 |
| 2012-08-18 10:16:03.2730000 | 2012-08-18 10:16:03.2657914 | -8 |
| 2012-08-18 10:16:03.2770000 | 2012-08-18 10:16:03.2657914 | -12 |
| 2012-08-18 10:16:03.2800000 | 2012-08-18 10:16:03.2814148 | 1 |
+-----------------------------+-----------------------------+-----+
Интересующие строки
| 2012-08-18 10:16:03.2600000 | 2012-08-18 10:16:03.2501680 | -10 |
| 2012-08-18 10:16:03.2630000 | 2012-08-18 10:16:03.2501680 | -13 |
Это несоответствие слишком велико, чтобы быть проблемой округления, и не может быть просто проблемой синхронизации с задержкой между вызовом двух функций, поскольку проблема существует более чем в одной строке, которая GETDATE
сообщает 10:16:03.26X
, тогда как SYSDATETIME
сообщает 10:16:03.250
datetime
имеет точность только 300 тиков в секунду. то есть до 3 цифр точности с последней цифрой 0
, 3
или 7
. Более новый тип данных datetime2
может представлять до 7 десятичных цифр точности.
- person Martin Smith; 19.08.2012
Они отличаются тем, что две функции не могут быть вызваны одновременно (в одно и то же время). Другие запущенные процессы могут повлиять на тайминги. Есть десятки причин, по которым они могут отличаться на разную величину.
Если вы сделаете то же самое с двумя вызовами GetDate()
вместо этого, они не приведут к никакой разнице, потому что механизм базы данных достаточно умен, чтобы понять, что это одно и то же, и повторно использовать результаты. Однако использование GetDate()
и SysDateTime()
отличается, потому что это не один и тот же путь кода (они делают разные вещи).
Подумайте об этом так: если вы видите 1 + 2
и 1 + 2
, легко увидеть, что первое выражение и второе совпадают, и поэтому вам нужно выполнить вычисление только один раз. Если вы измените его на 1 + Rand()
и 1 + Rand()
, вы не сможете узнать, что вернут два разных вызова Rand()
, поэтому вам придется выполнять вычисления отдельно.
Эта разница является хорошим примером разницы между ТОЧНОСТЬЮ и РАЗРЕШЕНИЕМ (на данный момент оставим ТОЧНОСТЬ в стороне). GETDATE() возвращает DATETIME с (очевидно) ТОЧНОСТЬЮ до миллисекунды, но, если вы поместите его в плотный цикл, вы обнаружите, что следующее возвращаемое значение будет через несколько миллисекунд; он может возвращать только около 300 различных значений каждую секунду, так как его РАЗРЕШЕНИЕ составляет всего около 3 или 4 миллисекунд. подробнее об этом читайте здесь Это конструктивная особенность/компромисс типа данных DATETIME.
SELECT DATEDIFF(ms, GETDATE(), GETDATE());
? - person Waleed Khan   schedule 18.08.2012SELECT DATEDIFF(ms, GETDATE(), GETDATE())
, будет ли GetDate() выполняться дважды или один раз? - person Himanshu Jansari   schedule 18.08.20120
. - person Himanshu Jansari   schedule 18.08.2012