[OPMERKING:als je dit antwoord gaat downvoten, laat dan een reactie achter waarin je uitlegt waarom. Het is al vele malen naar beneden gestemd, en uiteindelijk legde ypercube (dank je) ten minste één reden uit waarom. Ik kan het antwoord niet verwijderen omdat het is geaccepteerd, dus je kunt net zo goed helpen het te verbeteren.]
Volgens deze uitwisseling op Microsoft, GETDATE()
veranderd van constant zijn binnen een query naar niet-deterministisch in SQL Server 2005. Achteraf denk ik niet dat dat juist is. Ik denk dat het vóór SQL Server 2005 volledig niet-deterministisch was en vervolgens gehackt is in iets dat "niet-deterministische runtime-constante" wordt genoemd sinds SQL Server 2005". De latere uitdrukking lijkt echt "constant binnen een query" te betekenen.
(En GETDATE()
wordt gedefinieerd als ondubbelzinnig en trots niet-deterministisch, zonder kwalificaties.)
Helaas betekent niet-deterministisch in SQL Server niet dat een functie voor elke rij wordt geëvalueerd. SQL Server maakt dit echt nodeloos ingewikkeld en dubbelzinnig met heel weinig documentatie over het onderwerp.
In de praktijk wordt de functie-aanroep geëvalueerd wanneer de query wordt uitgevoerd in plaats van één keer wanneer de query wordt gecompileerd en de waarde verandert elke keer dat deze wordt aangeroepen. In de praktijk, GETDATE()
wordt slechts één keer geëvalueerd voor elke uitdrukking waar deze wordt gebruikt -- op uitvoeringstijd in plaats van compileertijd . Microsoft plaatst echter rand()
en getdate()
in een speciale categorie, genaamd niet-deterministische runtime-constante-functies. Postgres daarentegen springt niet door dergelijke hoepels, het roept alleen functies aan die een constante waarde hebben wanneer ze worden uitgevoerd als "stabiel".
Ondanks de opmerking van Martin Smith is de SQL Server-documentatie eenvoudigweg niet expliciet over deze kwestie -- GETDATE()
wordt beschreven als zowel "niet-deterministische" als "niet-deterministische runtime-constante", maar die term wordt niet echt uitgelegd. De enige plaats waar ik de term heb gevonden, bijvoorbeeld, de volgende regels in de documentatie zeggen dat ik geen niet-deterministische functies in subquery's mag gebruiken. Dat zou een dwaas advies zijn voor "niet-deterministische runtime-constante".
Ik zou willen voorstellen om een variabele met een constante te gebruiken, zelfs binnen een query, zodat je een consistente waarde hebt. Dit maakt ook de bedoeling heel duidelijk:je wilt een enkele waarde in de query. Binnen een enkele zoekopdracht kunt u zoiets doen als:
select . . .
from (select getdate() as now) params cross join
. . .
Eigenlijk is dit een suggestie die moet evalueer slechts één keer in de query, maar er kunnen uitzonderingen zijn. Er ontstaat verwarring omdat getdate()
geeft dezelfde waarde terug op alle verschillende rijen -- maar het kan verschillende waarden in verschillende kolommen retourneren. Elke uitdrukking met getdate()
wordt onafhankelijk geëvalueerd. Dit is duidelijk als u het volgende uitvoert:
select rand(), rand()
from (values (1), (2), (3)) v(x);
Binnen een opgeslagen procedure zou u een enkele waarde in een variabele willen hebben. Wat gebeurt er als de opgeslagen procedure wordt uitgevoerd als middernacht verstrijkt en de datum verandert? Welke impact heeft dat op de resultaten?
Wat de prestaties betreft, vermoed ik dat de datum/tijd-lookup minimaal is en dat een query eenmaal per expressie plaatsvindt wanneer de query begint te lopen. Dit zou niet echt een prestatieprobleem moeten zijn, maar meer een probleem met de consistentie van de code.