这个语法是如何工作的?{fn CurDate()} 或 {fn Now()} 等

Han*_*non 21 sql-server functions

最近我浏览了一些为 SQL Server 2005 编写的相当老的存储过程,我注意到一些我不明白的东西。它似乎是某种类型的函数调用。

一个样品:

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

这将显示所有行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)
Run Code Online (Sandbox Code Playgroud)

显然, using{fn Now()}GetDate(). 我会像瘟疫一样避免这种语法,因为它没有记录。

Aar*_*and 27

它是 ODBC 转义语法,引擎知道它自己的实现是什么,并将其换出,正如您在执行计划中看到的那样。还有其他一些东西,比如:

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

请参阅此处此处此处以及最重要的此处的文档。但是请不要调查和学习这种语法;恕我直言,您应该在大多数情况下使用本机语法,并假装您从未听说过这些东西。

我也强烈建议不要使用getdate()-1简写,特别是如果您要返回并更新旧代码。明确并使用DATEADD,因为隐式速记不适用于新类型。例如,尝试:

DECLARE @d DATE = GETDATE();
SELECT @d - 1;
Run Code Online (Sandbox Code Playgroud)

结果:

消息 206,级别 16,状态 2,第 2 行
操作数类型冲突:日期与 int 不兼容

当您在那里时,如果您真的想在未来 10 年保护您的代码,也可以添加分号。