Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Ao usar GETDATE() em muitos lugares, é melhor usar uma variável?


[OBSERVAÇÃO:Se você for rejeitar esta resposta, por favor, deixe um comentário explicando o porquê. Já foi rejeitado muitas vezes e, finalmente, ypercube (obrigado) explicou pelo menos um motivo. Não posso remover a resposta porque ela é aceita, então você também pode ajudar a melhorá-la.]

De acordo com esta troca na Microsoft, GETDATE() passou de constante em uma consulta para não determinístico no SQL Server 2005. Em retrospecto, não acho que isso seja preciso. Eu acho que era completamente não determinístico antes do SQL Server 2005 e, em seguida, hackeado em algo chamado "constante de tempo de execução não determinístico" desde o SQL Server 2005. A frase posterior realmente parece significar "constante dentro de uma consulta".

(E GETDATE() é definido como inequívoca e orgulhosamente não determinista, sem qualificadores.)

Infelizmente, no SQL Server, não determinístico não significa que uma função seja avaliada para cada linha. O SQL Server realmente torna isso desnecessariamente complicado e ambíguo com muito pouca documentação sobre o assunto.

Na prática, a chamada de função é avaliada quando a consulta está em execução e não uma vez quando a consulta é compilada e seu valor muda cada vez que é chamada. Na prática, GETDATE() é avaliado apenas uma vez para cada expressão em que é usado -- no tempo de execução em vez de tempo de compilação . No entanto, a Microsoft coloca rand() e getdate() em uma categoria especial, chamada funções de constantes de tempo de execução não determinísticas. Por outro lado, o Postgres não passa por esses obstáculos, ele apenas chama funções que têm um valor constante quando executadas como "estáveis".

Apesar do comentário de Martin Smith, a documentação do SQL Server simplesmente não é explícita sobre este assunto -- GETDATE() é descrito como "não determinístico" e "constante de tempo de execução não determinístico", mas esse termo não é realmente explicado. O único lugar em que encontrei o termo , por exemplo, as próximas linhas na documentação dizem para não usar funções não determinísticas em subconsultas. Isso seria um conselho tolo para "constante de tempo de execução não determinística".

Eu sugeriria usar uma variável com uma constante mesmo dentro de uma consulta, para que você tenha um valor consistente. Isso também deixa a intenção bem clara:você quer um único valor dentro da consulta. Dentro de uma única consulta, você pode fazer algo como:
select . . . 
from (select getdate() as now) params cross join
     . . . 

Na verdade, esta é uma sugestão que deve avaliar apenas uma vez na consulta, mas pode haver exceções. A confusão surge porque getdate() retorna o mesmo valor em todas as linhas diferentes -- mas pode retornar valores diferentes em colunas diferentes. Cada expressão com getdate() é avaliado independentemente. Isso é óbvio se você executar:
select rand(), rand()
from (values (1), (2), (3)) v(x);

Dentro de um procedimento armazenado, você deseja ter um único valor em uma variável. O que acontece se o procedimento armazenado for executado quando a meia-noite passar e a data for alterada? Qual o impacto disso nos resultados?

Quanto ao desempenho, meu palpite é que a pesquisa de data/hora é mínima e, para uma consulta, ocorre uma vez por expressão à medida que a consulta começa a ser executada. Isso não deve realmente ser um problema de desempenho, mas mais um problema de consistência de código.