この構文はどのように機能しますか?{fn CurDate()}または{fn Now()}など


19

最近、SQL Server 2005用に作成されたかなり古いストアドプロシージャを調べてきましたが、理解できないことがわかりました。何らかのタイプの関数呼び出しのようです。

サンプル:

SELECT o.name, o.type_desc, o.create_date
FROM sys.objects o
WHERE o.create_date < {fn Now()} -1;

これは、すべての行が表示されますsys.objects持ってcreate_date前から24時間前。

このクエリの実行プランを表示する{fn Now()}getdate()、データベースエンジンに置き換えられていることがわかります。

SELECT [o].[name],[o].[type_desc],[o].[create_date] 
FROM [sys].[objects] [o] 
WHERE [o].[create_date]<(getdate()-@1)

明らかに、を使用すること{fn Now()}は、よりもはるかに鈍いですGetDate()。文書化されていないので、私はペストのようなこの構文を避けます。

回答:


25

これはODBCエスケープ構文であり、実行計画で見たように、エンジンは独自の実装が何であるかを認識し、交換します。次のような他のものもあります。

SELECT {fn curdate()},
       {ts '2016-05-24 15:19:36'}, -- not vulnerable to SET LANGUAGE!
       {guid 'D08891B4-BC25-4C7C-BAEF-3B756055AC6E'};

ここここここ、そして最も重要なことはここのドキュメントを参照してください。ただし、この構文については調査および学習しないでください。私見では、ほとんどの部分でネイティブ構文を使用し、このようなことを聞​​いたことがないふりをする必要があります。

またgetdate()-1、特に古いコードに戻って更新する場合は、速記にも反対することを強くお勧めします。DATEADD暗黙の速記は新しい型では機能しないため、明示的に使用します。たとえば、試してみてください:

DECLARE @d DATE = GETDATE();
SELECT @d - 1;

結果:

メッセージ206、レベル16、状態2、行2
オペランドタイプの衝突:日付はintと互換性がありません

10年後のコードを本当に保護したい場合は、そこにいる間にセミコロンを追加することもできます。


このエスケープ構文は、JDBCでもサポートされています。
a_horse_with_no_name
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.