Можно ли сделать SQL Server FORMAT детерминированным?

Я хочу сделать UDF, который возвращает целочисленную форму YYYYMM так что я могу легко разделить некоторые вещи на месяц. Я пытаюсь присвоить этой функции значение PERSISTED вычисляемый столбец.

В настоящее время у меня есть следующее, которое отлично работает:

CREATE FUNCTION dbo.GetYearMonth(@pDate DATETIME2)
RETURNS INT
WITH SCHEMABINDING
AS
BEGIN
    DECLARE @fYear VARCHAR(4) = RIGHT('0000' + CAST(YEAR(@pDate) AS VARCHAR),4)
    DECLARE @fMonth VARCHAR(2) = RIGHT('00' + CAST(MONTH(@pDate) AS VARCHAR),2)

    RETURN CAST(@fYear + @fMonth AS INT)
END

Но я думаю, что это чище, чтобы использовать FORMAT вместо. Я попробовал это:

CREATE FUNCTION dbo.GetYearMonth(@pDate DATETIME2)
RETURNS INT
WITH SCHEMABINDING
AS
BEGIN
    DECLARE @fYear VARCHAR(4) = FORMAT(@pDate,'yyyy', 'en-us')
    DECLARE @fMonth VARCHAR(2) = FORMAT(@pDate,'MM', 'en-us')

    RETURN CAST(@fYear + @fMonth AS INT)
END

Но эта функция недетерминирована. Есть ли способ сделать FORMAT детерминированный? Или есть лучший способ сделать это, сделав UDF детерминированным?

3 ответа

Решение

Интересный вопрос, поэтому я немного покопался и ничего не придумал:)

Начиная с детерминированных и недетерминированных функций

который явно не перечисляет FORMAT но говорится:

Все агрегатные и строковые встроенные функции являются детерминированными.

и ссылки на строковые функции

Опять же, на этой странице говорится

Все встроенные строковые функции являются детерминированными. Это означает, что они возвращают одно и то же значение каждый раз, когда их вызывают с определенным набором входных значений.

Тем не менее, страница на FORMAT молчит на эту тему.

FORMAT использует CLR, который не исключает его детерминированности, но doco ничего не говорит о фактической реализации FORMAT,

Наконец, подозревая, что это ошибка в документе (или коде), быстрый поиск соединения ничего не показывает.

Как насчет теста? (Комментарии приветствуются на действительность этого кода...)

CREATE FUNCTION WhatAmI(@Number INTEGER) 
RETURNS NVARCHAR
WITH SCHEMABINDING
AS 
BEGIN
RETURN FORMAT(@Number, 'd')
END
GO

SELECT OBJECTPROPERTY(OBJECT_ID('WhatAmI'),'IsDeterministic')

-----------
0

(1 row(s) affected)

Да, это недетерминировано.

Итак, интересное упражнение, но ничего убедительного.

Так что же мы узнали (согласно BOL)? Если встроенная функция недетерминирована, сделать это невозможно. Некоторые из них зависят от типов параметров, а некоторые должны быть, но это не так.

Мне интересно, почему вы используете функцию. Вы можете использовать простую формулу:

CONVERT(varchar(6), getdate(), 112) 

Microsoft не очень понимает, что функция форматирования может быть решающей. Я не смог найти никакой информации по этому вопросу в документации. Будучи функцией CLR, я предполагаю, что это невозможно.

Еще более простое решение для целочисленного форматирования будет таким:

YEAR(@pDate) * 100 + MONTH(@pDate)
Другие вопросы по тегам