¿GETUTCDATE () devolverá el mismo valor si se usa dos veces en la misma statement?

Tengo un activador que establece automáticamente el Fecha de Creación y el Fecha Modificado de la entrada dada en la hora UTC actual cada vez que se ingresa un valor. (CreationDate seguirá siendo el mismo a partir de entonces, mientras que ModifiedDate se actualizará en cada actualización mediante otro desencadenador).

Quiero asegurarme de que los elementos insertados y nunca actualizados tengan exactamente el mismo valor para CreationDate y ModifiedDate, así que he usado una variable como esta:

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

En mi mentalidad de progtwigción imperativa, estoy asumiendo que esto evita que se GETUTCDATE() dos veces, y que potencialmente produzca resultados ligeramente diferentes. ¿Es esto realmente necesario? De lo contrario, ¿sería más caro, menos costoso o exactamente el mismo código?

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

Y solo para demostrar que esto sucede cuando también está en la lista 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 

Por cierto: si por alguna razón quieres evaluar GETUTCDATE() por fila, puedes envolverlo en un UDF escalar.

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

Gracias a los enlaces proporcionados por gbn, creo que esto responde mi pregunta :

En común con rand () Se evalúa una vez por columna pero una vez evaluado permanece igual para todas las filas. … observe las propiedades del operador ComputeScalar en el plan de ejecución real verá que GetDate () se evalúa dos veces.

Lo comprobé, y parece que esto todavía ocurre de la misma manera en SQL Server 2008: GetUtcDate() se evalúa dos veces en el plan de ejecución. No va a producir resultados diferentes por fila, pero es posible que pueda producir un resultado diferente por columna si el momento fue el correcto.

Editar

¡De hecho puedo probar este comportamiento! Prueba esto:

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

En mi experimento, terminé con 2011-05-17 20:47:34.247 en la primera columna y 2011-05-17 20:47:34.250 en la columna final, mostrando una diferencia de tres milisegundos como resultado de la evaluación de todos los RAND() entre la primera y la segunda llamada a GETUTCDATE ().

Será el mismo valor.

GETDATE y GETUTCDATE son algunas de las funciones que se evalúan una vez por consulta: no por fila o columna en esa consulta. El optimizador se asegurará de que sean iguales porque actualiza los valores al mismo tiempo

Otra opción es definir una restricción DEFAULT para que pueda hacer esto y preocuparse menos por ello.

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

Tengo tablas con columnas similares con restricciones DEFAULT y nunca tuve un problema. Esto también significa que nunca tengo que pensar en qué función uso en el código.

Editar:

Podría estar equivocado: SQL Server: intrigado por GETDATE ()

O podría estar en lo cierto: seleccionar la función GETDATE () dos veces en una lista de selección– ¿el mismo valor para ambos?

Artículo: Conor Cunnigham lo menciona como el comportamiento

Edit2: Estoy demostrablemente equivocado: ver la auto respuesta de StriplingWarrior. Se evalúa por columna (no por fila y no por consulta)

Mantener el GETUTCDATE () en una variable es una mejor opción, ya que asegura que CreationDate y ModifiedDate permanezcan iguales. Sin embargo, llamé a GETUTCDATE() número de veces por consulta y todas devolvieron el mismo valor, por lo que a mí me parece que el valor GETUTCDATE () sigue siendo el mismo por consulta.

Basado en extensos experimentos en SQL Server 2008, creo que la siguiente caracterización es correcta:

En una sola consulta SELECCIONAR, INSERTAR o ACTUALIZAR, cada aspecto de una función de fecha y hora devolverá el mismo valor donde aparezca en todas las filas y columnas, incluidos los valores predeterminados de columna.

Dos funciones diferentes de fecha y hora (p. Ej., GETUTCDATE () y GETDATE ()) pueden devolver tiempos diferentes el uno del otro (incluso después de ajustar por zonas horarias o lo que sea).

Múltiples consultas en un solo lote pueden devolver diferentes valores.

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

Este comportamiento no está documentado en ninguna parte, y el uso de una variable aclara la intención, por lo que probablemente no confíe en este comportamiento a menos que evitar esta dependencia sea una carga importante.