Как работает этот синтаксис? {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()компонентом Database Engine:

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

Понятно, что использование {fn Now()}гораздо тупее, чем GetDate(). Я, например, избегу такого синтаксиса, как чума, поскольку он недокументирован.

Макс Вернон
источник

Ответы:

25

Это escape-синтаксис 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 лет.

Аарон Бертран
источник
Этот escape-синтаксис также поддерживается JDBC.
a_horse_with_no_name