Можно ли сделать 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)