O GETUTCDATE () retornará o mesmo valor se usado duas vezes na mesma instrução?

Eu tenho um gatilho que define automaticamente o CreationDate e ModifiedDate da input dada para a hora UTC atual sempre que um valor é inserido. (CreationDate permanecerá o mesmo depois disso, enquanto ModifiedDate será atualizado em cada atualização através de outro trigger).

Eu quero ter certeza de que os itens inseridos e nunca atualizados terão exatamente o mesmo valor para CreationDate e ModifiedDate, então usei uma variável como esta:

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

Na minha mentalidade de programação imperativa, GETUTCDATE() que isso evite que GETUTCDATE() seja chamado duas vezes e, potencialmente, produza resultados ligeiramente diferentes. Isso é realmente necessário? Se não, isso seria mais caro, menos caro, ou exatamente o mesmo que o código a seguir?

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

 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.*/ 

E só para provar isso acontece quando na lista SELECT também.

 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: SE, por algum motivo, você quiser avaliar GETUTCDATE() por linha, poderá agrupá-lo em uma UDF escalar.

 CREATE FUNCTION dbo.GETUTCDATE() RETURNS DATETIME WITH SCHEMABINDING AS BEGIN RETURN GETUTCDATE() END GO SELECT GETUTCDATE(),dbo.GETUTCDATE() FROM master..spt_values 

Graças aos links fornecidos pelo gbn, acredito que isso responde à minha pergunta :

Em comum com rand () é avaliado uma vez por coluna, mas uma vez avaliado permanece o mesmo para todas as linhas. … observe as propriedades do operador ComputeScalar no plano de execução real e você verá que GetDate () é avaliado duas vezes.

Eu verifiquei, e parece que isso ainda acontece da mesma maneira no SQL Server 2008: GetUtcDate() é avaliado duas vezes no plano de execução. Ele não produzirá resultados diferentes por linha, mas é possível que ele produza um resultado diferente por coluna se o tempo acabar bem.

Editar

Eu posso realmente provar esse comportamento! Tente isto:

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

Na minha experiência, terminei com 2011-05-17 20:47:34.247 na primeira coluna e 2011-05-17 20:47:34.250 na coluna final, mostrando uma diferença de três milissegundos como resultado da avaliação de todos os RAND() s entre a primeira e segunda chamadas para GETUTCDATE ().

Será o mesmo valor.

GETDATE e GETUTCDATE são algumas das funções avaliadas uma vez por consulta: não por linha ou coluna nessa consulta. O otimizador garantirá que eles sejam os mesmos, porque atualiza os valores ao mesmo tempo

Outra opção é definir as restrições DEFAULT para que você possa fazer isso e se preocupar menos com isso.

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

Eu tenho tabelas com colunas semelhantes com restrições padrão e nunca tive um problema. Isso também significa que nunca preciso pensar em qual function eu uso no código.

Editar:

Eu posso estar errado: SQL Server: intrigado com GETDATE ()

Ou eu poderia estar certo: Selecionando a function GETDATE () duas vezes em uma lista de seleção – mesmo valor para ambos?

Artigo: Conor Cunnigham menciona o comportamento

Edit2: Eu sou demonstrativamente errado: veja a auto resposta de StriplingWarrior. É avaliado por coluna (não por linha e não por consulta)

Manter o GETUTCDATE () em uma variável é uma opção melhor, pois garante que CreationDate e ModifiedDate permaneçam iguais. No entanto, eu chamei GETUTCDATE() número de tempo por consulta e todos eles retornaram o mesmo valor, então para mim parece que o valor GETUTCDATE () permanece igual por consulta.

Com base em extensos experimentos no SQL Server 2008, acredito que a seguinte caracterização está correta:

Em uma única consulta SELECT, INSERT ou UPDATE, cada aparência de uma function de data e hora retornará o mesmo valor em todos os lugares em todas as linhas e colunas, incluindo os valores padrão da coluna.

Duas funções diferentes de data e hora (por exemplo, GETUTCDATE () e GETDATE ()) podem retornar diferentes tempos umas das outras (mesmo após o ajuste para fusos horários ou qualquer outro).

Várias consultas em um único lote podem retornar valores diferentes.

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

Esse comportamento não é documentado em nenhum lugar, e o uso de uma variável torna a intenção clara, então eu provavelmente não confiaria nesse comportamento, a menos que evitar essa dependência seja um grande fardo.