sql >> Databáze >  >> RDS >> Sqlserver

Při použití GETDATE() na mnoha místech, je lepší použít proměnnou?

[POZNÁMKA:Pokud se chystáte hlasovat proti této odpovědi, zanechte prosím komentář s vysvětlením proč. Už to bylo mnohokrát odmítnuto a konečně ypercube (děkuji) vysvětlil alespoň jeden důvod. Odpověď nemohu odstranit, protože je přijata, takže byste ji také mohli pomoci vylepšit.]

Podle této výměny na Microsoftu GETDATE() přešel z konstantní v dotazu na nedeterministický v SQL Server 2005. Zpětně si nemyslím, že je to přesné. Myslím, že před SQL Serverem 2005 to bylo zcela nedeterministické a poté se od SQL Serveru 2005 nabouralo do něčeho, co se nazývá „nedeterministická běhová konstanta“. Zdá se, že pozdější fráze skutečně znamená „konstanta v rámci dotazu“.

(A GETDATE() je definován jako jednoznačně a hrdě nedeterministický, bez kvalifikátorů.)

Bohužel, v SQL Server nedeterministický neznamená, že funkce je vyhodnocena pro každý řádek. SQL Server to opravdu dělá zbytečně komplikovaným a nejednoznačným s velmi malou dokumentací na toto téma.

V praxi se volání funkce vyhodnocuje, když je dotaz spuštěn, spíše než jednou při kompilaci dotazu a jeho hodnota se mění při každém volání. V praxi GETDATE() je vyhodnocen pouze jednou pro každý výraz, kde je použit -- v době provedení spíše než čas kompilace . Microsoft však uvádí rand() a getdate() do speciální kategorie, nazývané nedeterministické konstantní funkce za běhu. Naproti tomu Postgres přes takové obruče neskáče, pouze volá funkce, které mají konstantní hodnotu, když jsou spuštěny jako "stabilní".

Navzdory komentáři Martina Smithe dokumentace k SQL Serveru v této záležitosti jednoduše není explicitní -- GETDATE() je popsána jako "nedeterministická" i "nedeterministická runtime konstanta", ale tento termín není ve skutečnosti vysvětlen. Na jednom místě jsem například našel termín , hned na následujících řádcích v dokumentaci je uvedeno, že se v dílčích dotazech nemají používat nedeterministické funkce. To by byla hloupá rada pro "nedeterministickou běhovou konstantu".

Navrhoval bych použít proměnnou s konstantou i v rámci dotazu, abyste měli konzistentní hodnotu. Tím je také zcela jasný záměr:v dotazu chcete jedinou hodnotu. V rámci jednoho dotazu můžete udělat něco jako:

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

Ve skutečnosti se jedná o návrh, který by měl vyhodnotit pouze jednou v dotazu, ale mohou existovat výjimky. Vzniká zmatek, protože getdate() vrátí stejnou hodnotu na všech různých řádcích - ale může vrátit různé hodnoty v různých sloupcích. Každý výraz s getdate() se vyhodnocuje nezávisle. To je zřejmé, pokud spustíte:

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

V rámci uložené procedury byste chtěli mít v proměnné jednu hodnotu. Co se stane, když je uložená procedura spuštěna kolem půlnoci a změní se datum? Jaký dopad to má na výsledky?

Pokud jde o výkon, odhaduji, že vyhledávání data/času je minimální a pro dotaz se vyskytuje jednou na výraz, když se dotaz začne spouštět. Ve skutečnosti by to neměl být problém s výkonem, ale spíše problém s konzistencí kódu.



  1. Postgresql:Skriptování provádění psql s heslem

  2. SQL Server Textový typ vs. datový typ varchar

  3. Úvod do Python SQL knihoven

  4. Jak používat indexy ke zlepšení výkonu dotazů MySQL