我想创建一个返回整数形式YYYYMM
的UDF,以便我可以在一个月内轻松地对某些内容进行分区。我试图将此函数分配给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确定性吗?
答案 0 :(得分:6)
有趣的问题所以我做了一些挖掘并且没有得出任何结论:)
从Deterministic and Nondeterministic Functions
开始并未明确列出FORMAT
,但声明:
所有聚合和字符串内置函数都是确定性的。
以及指向String Functions
的链接同样,此页面说明了
所有内置字符串函数都是确定性的。这意味着只要使用一组特定的输入值调用它们,它们就会返回相同的值。
但是,the page on FORMAT
对此问题保持沉默。
FORMAT
使用doesn't preclude it from being deterministic的CLR,但doco对FORMAT
的实际实施保持沉默。
最后,怀疑这是doco(或代码)中的一个错误,quick search of connect没有透露任何内容。
测试用例怎么样? (欢迎评论此代码的有效性......)
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)
Nup,那是不确定的。
所以,这是一项有趣的练习,但没有定论。
那么我们学到了什么(根据BOL)?如果内置函数是不确定的,那么就无法做到这一点。有些都取决于参数类型,有些应该是但不是。
答案 1 :(得分:3)
我想知道你为什么要使用一个功能。 您可以使用简单的公式:
CONVERT(varchar(6), getdate(), 112)
答案 2 :(得分:1)
微软并不清楚格式功能是否具有决定性。我在其文档中找不到关于该主题的任何信息。作为一个CLR功能,我猜这是不可能的。
一个更简单的解决方案,可以按照你想要的方式获得一个整数:
YEAR(@pDate) * 100 + MONTH(@pDate)