[CATATAN:Jika Anda akan mengurangi jawaban ini, silakan tinggalkan komentar yang menjelaskan alasannya. Itu sudah diturunkan berkali-kali, dan akhirnya ypercube (terima kasih) menjelaskan setidaknya satu alasan mengapa. Saya tidak dapat menghapus jawabannya karena sudah diterima, jadi sebaiknya Anda membantu memperbaikinya.]
Menurut pertukaran ini di Microsoft, GETDATE()
beralih dari konstan dalam kueri ke non-deterministik di SQL Server 2005. Dalam retrospeksi, saya rasa itu tidak akurat. Saya pikir itu benar-benar non-deterministik sebelum SQL Server 2005 dan kemudian diretas menjadi sesuatu yang disebut "konstanta runtime non-deterministik" sejak SQL Server 2005". Ungkapan selanjutnya sepertinya benar-benar berarti "konstan dalam kueri".
(Dan GETDATE()
didefinisikan sebagai jelas dan bangga non-deterministik, tanpa kualifikasi.)
Sayangnya, di SQL Server, non-deterministik tidak berarti bahwa suatu fungsi dievaluasi untuk setiap baris. SQL Server benar-benar membuat hal ini menjadi rumit dan ambigu dengan sangat sedikit dokumentasi tentang masalah ini.
Dalam praktiknya, pemanggilan fungsi dievaluasi saat kueri berjalan, bukan sekali saat kueri dikompilasi dan nilainya berubah setiap kali dipanggil. Dalam praktiknya, GETDATE()
hanya dievaluasi sekali untuk setiap ekspresi yang digunakan -- pada waktu eksekusi daripada waktu kompilasi . Namun, Microsoft menempatkan rand()
dan getdate()
ke dalam kategori khusus, yang disebut fungsi konstanta runtime non-deterministik. Sebaliknya, Postgres tidak melompati rintangan seperti itu, ia hanya memanggil fungsi yang memiliki nilai konstan saat dijalankan sebagai "stabil".
Terlepas dari komentar Martin Smith, dokumentasi SQL Server sama sekali tidak eksplisit tentang masalah ini -- GETDATE()
digambarkan sebagai "nondeterministik" dan "konstanta runtime non-deterministik", tetapi istilah itu tidak benar-benar dijelaskan. Satu-satunya tempat saya menemukan istilah , misalnya, baris berikutnya dalam dokumentasi mengatakan untuk tidak menggunakan fungsi nondeterministik dalam subkueri. Itu akan menjadi saran konyol untuk "konstanta runtime nondeterministik".
Saya akan menyarankan menggunakan variabel dengan konstanta bahkan dalam kueri, sehingga Anda memiliki nilai yang konsisten. Ini juga membuat niatnya cukup jelas:Anda menginginkan satu nilai di dalam kueri. Dalam satu kueri, Anda dapat melakukan sesuatu seperti:
select . . .
from (select getdate() as now) params cross join
. . .
Sebenarnya, ini adalah saran yang harus mengevaluasi hanya sekali dalam kueri, tetapi mungkin ada pengecualian. Kebingungan muncul karena getdate()
mengembalikan nilai yang sama pada semua baris yang berbeda -- tetapi dapat mengembalikan nilai yang berbeda di kolom yang berbeda. Setiap ekspresi dengan getdate()
dievaluasi secara independen. Ini jelas jika Anda menjalankan:
select rand(), rand()
from (values (1), (2), (3)) v(x);
Dalam prosedur tersimpan, Anda ingin memiliki satu nilai dalam variabel. Apa yang terjadi jika prosedur tersimpan dijalankan saat tengah malam lewat, dan tanggal berubah? Apa dampaknya terhadap hasil?
Adapun kinerja, tebakan saya adalah bahwa pencarian tanggal/waktu minimal dan untuk kueri terjadi sekali per ekspresi saat kueri mulai berjalan. Ini seharusnya bukan masalah kinerja, tetapi lebih merupakan masalah konsistensi kode.