[ЗАБЕЛЕЖКА:Ако ще откажете този отговор, моля, оставете коментар, обясняващ защо. Вече е бил отрицателен много пъти и накрая ypercube (благодаря) обясни поне една причина защо. Не мога да премахна отговора, защото е приет, така че можете да помогнете за подобряването му.]
Според този обмен на Microsoft, GETDATE()
премина от постоянен в рамките на заявка към недетерминистичен в SQL Server 2005. В ретроспекция, не мисля, че това е точно. Мисля, че беше напълно недетерминиран преди SQL Server 2005 и след това беше хакнат в нещо, наречено „недетерминирана константа по време на изпълнение“ от SQL Server 2005. По-късната фраза изглежда наистина означава „константа в рамките на заявка“.
(И GETDATE()
се определя като недвусмислено и гордо недетерминистично, без квалификации.)
Уви, в SQL Server недетерминистичното не означава, че функцията се оценява за всеки ред. SQL Server наистина прави това ненужно сложно и двусмислено с много малко документация по темата.
На практика извикването на функцията се оценява, когато заявката се изпълнява, а не веднъж, когато заявката се компилира и стойността й се променя всеки път, когато е извикана. На практика GETDATE()
се оценява само веднъж за всеки израз, където се използва -- в време на изпълнение вместо време за компилиране . Въпреки това, Microsoft поставя rand()
и getdate()
в специална категория, наречена недетерминирани константни функции по време на изпълнение. За разлика от това, Postgres не скача през такива обръчи, той просто извиква функции, които имат постоянна стойност, когато се изпълняват като "стабилни".
Въпреки коментара на Мартин Смит, документацията на SQL Server просто не е изрична по този въпрос - GETDATE()
се описва едновременно като "недетерминистична" и "недетерминирана константа по време на изпълнение", но този термин всъщност не е обяснен. Единственото място, където намерих термина, например, следващите редове в документацията казват да не се използват недетерминистични функции в подзаявки. Това би бил глупав съвет за "недетерминирана константа на изпълнение".
Бих предложил да използвате променлива с константа дори в рамките на заявка, така че да имате последователна стойност. Това също прави намерението съвсем ясно:Искате една стойност вътре в заявката. В рамките на една заявка можете да направите нещо като:
select . . .
from (select getdate() as now) params cross join
. . .
Всъщност това е предложение, което трябва оценява само веднъж в заявката, но може да има изключения. Объркване възниква, защото getdate()
връща една и съща стойност на всички различни редове - но може да връща различни стойности в различни колони. Всеки израз с getdate()
се оценява независимо. Това е очевидно, ако изпълните:
select rand(), rand()
from (values (1), (2), (3)) v(x);
В рамките на съхранена процедура бихте искали да имате една стойност в променлива. Какво се случва, ако съхранената процедура се изпълнява, докато полунощ минава и датата се промени? Какво влияние оказва това върху резултатите?
Що се отнася до производителността, предполагам, че търсенето на дата/час е минимално и за заявка се появява веднъж на израз, когато заявката започне да се изпълнява. Това всъщност не би трябвало да е проблем с производителността, а по-скоро проблем с последователността на кода.