[OBS:Om du ska rösta ned det här svaret, vänligen lämna en kommentar som förklarar varför. Den har redan blivit nedröstad många gånger, och äntligen förklarade ypercube (tack) åtminstone en anledning till varför. Jag kan inte ta bort svaret eftersom det är accepterat, så du kan lika gärna hjälpa till att förbättra det.]
Enligt denna börs på Microsoft, GETDATE()
bytte från att vara konstant i en fråga till icke-deterministisk i SQL Server 2005. I efterhand tror jag inte att det stämmer. Jag tror att det var helt icke-deterministiskt före SQL Server 2005 och sedan hackade in något som kallas "icke-deterministisk körtidskonstant" sedan SQL Server 2005". Den senare frasen verkar verkligen betyda "konstant i en fråga".
(Och GETDATE()
definieras som otvetydigt och stolt icke-deterministiskt, utan kvalificeringar.)
Tyvärr, i SQL Server betyder icke-deterministiskt inte att en funktion utvärderas för varje rad. SQL Server gör verkligen detta onödigt komplicerat och tvetydigt med väldigt lite dokumentation om ämnet.
I praktiken utvärderas funktionsanropet när frågan körs snarare än en gång när frågan kompileras och dess värde ändras varje gång den anropas. I praktiken GETDATE()
utvärderas endast en gång för varje uttryck där det används -- vid körningstid snarare än kompileringstid . Däremot lägger Microsoft rand()
och getdate()
till en speciell kategori, som kallas icke-deterministiska körtidskonstantfunktioner. Däremot hoppar Postgres inte genom sådana ramar, det anropar bara funktioner som har ett konstant värde när de körs som "stabila".
Trots Martin Smiths kommentar är SQL Server-dokumentationen helt enkelt inte explicit i denna fråga -- GETDATE()
beskrivs som både "icke-deterministisk" och "icke-deterministisk körtidskonstant", men den termen förklaras inte riktigt. Det enda stället jag har hittat termen , till exempel, på de följande raderna i dokumentationen står det att inte använda icke-deterministiska funktioner i underfrågor. Det skulle vara ett dumt råd för "icke-deterministisk körtidskonstant".
Jag skulle föreslå att du använder en variabel med en konstant även inom en fråga, så att du har ett konsekvent värde. Detta gör också avsikten ganska tydlig:Du vill ha ett enda värde inuti frågan. Inom en enda fråga kan du göra något som:
select . . .
from (select getdate() as now) params cross join
. . .
Egentligen är detta ett förslag som bör utvärdera endast en gång i frågan, men det kan finnas undantag. Förvirring uppstår eftersom getdate()
returnerar samma värde på alla olika rader -- men det kan returnera olika värden i olika kolumner. Varje uttryck med getdate()
utvärderas oberoende.Detta är uppenbart om du kör:
select rand(), rand()
from (values (1), (2), (3)) v(x);
Inom en lagrad procedur skulle du vilja ha ett enda värde i en variabel. Vad händer om den lagrade proceduren körs när midnatt passerar och datumet ändras? Vilken inverkan har det på resultaten?
När det gäller prestanda är min gissning att datum/tid-sökningen är minimal och att en fråga förekommer en gång per uttryck när frågan börjar köras. Detta borde egentligen inte vara ett prestandaproblem, utan snarare ett problem med kodkonsistens.