sql >> Base de Datos >  >> RDS >> Sqlserver

Cuando se usa GETDATE() en muchos lugares, ¿es mejor usar una variable?

[NOTA:si va a rechazar esta respuesta, deje un comentario explicando por qué. Ya ha sido votado negativamente muchas veces, y finalmente ypercube (gracias) explicó al menos una razón por la cual. No puedo eliminar la respuesta porque está aceptada, por lo que también podrías ayudar a mejorarla.]

Según este intercambio en Microsoft, GETDATE() pasó de ser constante dentro de una consulta a no determinista en SQL Server 2005. En retrospectiva, no creo que eso sea exacto. Creo que era completamente no determinista antes de SQL Server 2005 y luego pirateó algo llamado "constante de tiempo de ejecución no determinista" desde SQL Server 2005". La última frase realmente parece significar "constante dentro de una consulta".

(Y GETDATE() se define como inequívoca y orgullosamente no determinista, sin calificadores).

Por desgracia, en SQL Server, no determinista no significa que se evalúe una función para cada fila. SQL Server realmente hace que esto sea innecesariamente complicado y ambiguo con muy poca documentación sobre el tema.

En la práctica, la llamada a la función se evalúa cuando se ejecuta la consulta en lugar de una vez cuando se compila la consulta y su valor cambia cada vez que se llama. En la práctica, GETDATE() solo se evalúa una vez para cada expresión en la que se usa, en momento de ejecución en lugar de tiempo de compilación . Sin embargo, Microsoft pone rand() y getdate() en una categoría especial, denominada funciones constantes de tiempo de ejecución no deterministas. Por el contrario, Postgres no pasa por esos obstáculos, simplemente llama a funciones que tienen un valor constante cuando se ejecutan como "estables".

A pesar del comentario de Martin Smith, la documentación de SQL Server simplemente no es explícita en este asunto -- GETDATE() se describe como "no determinista" y "constante de tiempo de ejecución no determinista", pero ese término no se explica realmente. El único lugar donde encontré el término, por ejemplo, las siguientes líneas en la documentación dicen que no se usen funciones no deterministas en las subconsultas. Ese sería un consejo tonto para la "constante de tiempo de ejecución no determinista".

Sugeriría usar una variable con una constante incluso dentro de una consulta, para que tenga un valor consistente. Esto también deja bastante clara la intención:desea un valor único dentro de la consulta. Dentro de una sola consulta, puede hacer algo como:

select . . . 
from (select getdate() as now) params cross join
     . . . 

En realidad, esta es una sugerencia que debería evalúa solo una vez en la consulta, pero puede haber excepciones. La confusión surge porque getdate() devuelve el mismo valor en todas las filas diferentes, pero puede devolver valores diferentes en columnas diferentes. Cada expresión con getdate() se evalúa de forma independiente. Esto es obvio si ejecuta:

select rand(), rand()
from (values (1), (2), (3)) v(x);

Dentro de un procedimiento almacenado, le gustaría tener un solo valor en una variable. ¿Qué sucede si el procedimiento almacenado se ejecuta cuando pasa la medianoche y la fecha cambia? ¿Qué impacto tiene eso en los resultados?

En cuanto al rendimiento, supongo que la búsqueda de fecha/hora es mínima y que una consulta ocurre una vez por expresión cuando la consulta comienza a ejecutarse. Esto no debería ser realmente un problema de rendimiento, sino más bien un problema de consistencia del código.