Подтвердить что ты не робот

Будет ли GETUTCDATE() возвращать одно и то же значение, если оно используется дважды в одном выражении?

У меня есть триггер, который автоматически устанавливает CreationDate и ModifiedDate из данной записи в текущее время UTC всякий раз, когда вводится значение. (CreationDate останется таким же после этого, а ModifiedDate будет обновляться при каждом обновлении через другой триггер).

Я хочу убедиться, что вставляемые и никогда обновленные элементы будут иметь точно такое же значение для CreationDate и ModifiedDate, поэтому я использовал переменную вроде этого:

DECLARE @currentTime DATETIME
SELECT @currentTime = GETUTCDATE()
UPDATE dbo.MyTable SET CreationDate = @currentTime, ModifiedDate = @currentTime
    ...

В моем менталитете ментального программирования я предполагаю, что это предотвращает вызов GETUTCDATE() из двух раз и потенциально дает несколько разные результаты. Это действительно необходимо? Если нет, было бы это дороже, дешевле или точно так же, как в следующем коде?

UPDATE dbo.MyTable SET CreationDate = GETUTCDATE(), ModifiedDate = GETUTCDATE()
    ...
4b9b3361

Ответ 1

DECLARE @Counter INT = 1

WHILE (1 = (SELECT 1 WHERE GETUTCDATE()  = GETUTCDATE()))
SET @Counter = @Counter+1

SELECT @Counter /*Returns almost immediately with a number in the 000s for me.*/

И только для того, чтобы это произошло, также в списке SELECT.

DECLARE @T TABLE 
(
rownum INT IDENTITY(1,1) PRIMARY KEY,
d1 datetime,
d2 datetime
)

WHILE (NOT EXISTS(SELECT * FROM @T WHERE d1 <> d2))
    BEGIN
    DELETE FROM @T
    INSERT INTO @T 
    SELECT GETUTCDATE(),GETUTCDATE()
    END

SELECT * FROM @T

BTW: ЕСЛИ по какой-то причине вы хотите оценить GETUTCDATE() для каждой строки, вы можете обернуть ее в скалярный UDF.

CREATE FUNCTION dbo.GETUTCDATE()
RETURNS DATETIME
WITH SCHEMABINDING
AS
BEGIN
RETURN GETUTCDATE()
END
GO

SELECT GETUTCDATE(),dbo.GETUTCDATE()
FROM master..spt_values

Ответ 2

Благодаря ссылкам, предоставленным gbn, я верю, что отвечает на мой вопрос:

Совсем с rand() Он оценивается один раз за столбец, но после его оценки остается неизменным для всех строк.... посмотрите на свойства оператора ComputeScalar в фактическом плане выполнения, вы увидите, что GetDate() оценивается дважды.

Я проверил, и похоже, что это все равно происходит в SQL Server 2008: GetUtcDate() дважды оценивается в плане выполнения. Он не будет производить разные результаты для каждой строки, но вполне возможно, что он может привести к другому результату на один столбец, если синхронизация закончится именно так.

Изменить

Я могу доказать это! Попробуйте следующее:

select GETUTCDATE(), RAND(), RAND(), ...[~3000 RAND()s]..., RAND(), GETUTCDATE()
from [TableOfYourChoice]

В моем эксперименте я закончил с 2011-05-17 20:47:34.247 в первом столбце и 2011-05-17 20:47:34.250 в последнем столбце, показывая разницу в три миллисекунды в результате оценки всего RAND() между первым и вторым вызывает GETUTCDATE().

Ответ 3

Это будет одно и то же значение.

GETDATE и GETUTCDATE - некоторые из функций, которые оцениваются один раз для каждого запроса: не для каждой строки или столбца в этом запросе. Оптимизатор гарантирует, что они будут одинаковыми, поскольку он одновременно обновляет значения.

Другой вариант - определить ограничения DEFAULT, чтобы вы могли сделать это и меньше беспокоиться об этом.

UPDATE dbo.MyTable
SET CreationDate = DEFAULT, ModifiedDate = DEFAULT, ...
...

У меня есть таблицы с похожими столбцами с ограничениями DEFAULT и никогда не возникало проблем. Это также означает, что мне никогда не нужно думать о том, какую функцию я использую в коде.

Edit:

Я мог ошибаться: SQL Server: заинтригован GETDATE()

Или я мог бы быть прав: Выбор функции GETDATE() дважды в списке выбора - то же значение для обоих?

Статья: Конор Куннигам упоминает это поведение

Edit2: Я демонстративно ошибаюсь: см. сам ответ StriplingWarrior. Он оценивался за столбец (не за строку, а не за запрос)

Ответ 4

Сохранение GETUTCDATE() в переменной является лучшим вариантом, поскольку он гарантирует, что CreationDate и ModifiedDate остаются такими же. Тем не менее, я назвал GETUTCDATE() количество времени на запрос, и все они вернули одно и то же значение, поэтому мне кажется, что значение GETUTCDATE() остается таким же для каждого запроса.

Ответ 5

Основываясь на обширных экспериментах в SQL Server 2008, я считаю, что следующая характеристика правильная:

В одном запросе SELECT, INSERT или UPDATE каждое появление функции даты и времени возвращает одно и то же значение везде, где оно отображается во всех строках и столбцах, включая значения по умолчанию столбца.

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

Несколько запросов в одной партии могут возвращать разные значения.

SELECT GETUTCDATE(), GETUTCDATE() -- These will be the same

SELECT GETUTCDATE()  --  These may
SELECT GETUTCDATE()  --  be different

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