[注:この回答に反対票を投じる場合は、その理由を説明するコメントを残してください。それはすでに何度も反対票を投じられており、最後にypercube(ありがとう)は少なくとも1つの理由を説明しました。受け入れられたため、回答を削除できません。改善にご協力いただければ幸いです。]
Microsoftでのこの交換によると、GETDATE()
SQL Server 2005では、クエリ内で一定から非決定論に切り替わりました。振り返ってみると、それは正確ではないと思います。 SQL Server 2005以前は完全に非決定論的でしたが、SQL Server 2005以降は「非決定論的ランタイム定数」と呼ばれるものにハッキングされたと思います。後のフレーズは、実際には「クエリ内で一定」を意味しているようです。
(そしてGETDATE()
は、明確かつ誇らしげに非決定論的であり、修飾子はありません。)
残念ながら、SQL Serverでは、非決定論的とは、関数がすべての行に対して評価されることを意味するわけではありません。 SQL Serverは、これを不必要に複雑で曖昧にし、この主題に関するドキュメントはほとんどありません。
実際には、関数呼び出しは、クエリがコンパイルされたときに1回ではなく、クエリが実行されているときに評価され、その値は呼び出されるたびに変化します。実際には、GETDATE()
使用される式ごとに1回だけ評価されます-実行時 コンパイル時ではなく 。ただし、Microsoftはrand()
を配置します およびgetdate()
非決定論的ランタイム定数関数と呼ばれる特別なカテゴリに分類されます。対照的に、Postgresはそのようなフープを飛び越えず、「安定」として実行されたときに一定の値を持つ関数を呼び出すだけです。
Martin Smithのコメントにもかかわらず、SQLServerのドキュメントはこの問題について明確ではありません-GETDATE()
は「非決定論的」と「非決定論的実行時定数」の両方として説明されていますが、その用語は実際には説明されていません。たとえば、私がこの用語を見つけた1つの場所は、ドキュメントの次の行で、サブクエリで非決定論的関数を使用しないように言っています。これは、「非決定論的なランタイム定数」に対するばかげたアドバイスになります。
クエリ内でも定数を持つ変数を使用することをお勧めします。そうすれば、一貫した値が得られます。これにより、意図が非常に明確になります。クエリ内に単一の値が必要です。 1つのクエリ内で、次のようなことができます。
select . . .
from (select getdate() as now) params cross join
. . .
実際、これはすべき提案です。 クエリで1回だけ評価しますが、例外がある場合があります。 getdate()
が原因で、混乱が生じます。 すべての異なる行で同じ値を返しますが、異なる列で異なる値を返す可能性があります。 getdate()
を含む各式 は独立して評価されます。これは、次のコマンドを実行すると明らかです。
select rand(), rand()
from (values (1), (2), (3)) v(x);
ストアドプロシージャ内では、変数に単一の値を含める必要があります。深夜が過ぎたときにストアドプロシージャが実行され、日付が変更された場合はどうなりますか?結果にどのような影響がありますか?
パフォーマンスに関しては、日付/時刻のルックアップは最小限であり、クエリの実行が開始されると、式ごとに1回クエリが実行されると思います。これは実際にはパフォーマンスの問題ではなく、コードの一貫性の問題です。