Can I make SQL Server FORMAT deterministic?

六眼飞鱼酱① 提交于 2019-12-22 09:47:51

问题


I want to make a UDF which returns an integer form of YYYYMM so that I can easily partition some things on month. I am trying to assign this function to the value of a PERSISTED computed column.

I currently have the following, which works fine:

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

But I think it's cleaner to use FORMAT instead. I tried this:

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

But this function is nondeterministic. Is there a way to make FORMAT deterministic? Or is there a better way to do this, making the UDF deterministic?


回答1:


Interesting question so I did some digging and came up with nothing conclusive :)

Starting with Deterministic and Nondeterministic Functions

which doesn't explicitly list FORMAT but states:

All of the aggregate and string built-in functions are deterministic.

and links to String Functions

Again, this page states

All built-in string functions are deterministic. This means they return the same value any time they are called with a specific set of input values.

However, the page on FORMAT is silent on the subject.

FORMAT uses the CLR which doesn't preclude it from being deterministic but the doco is silent as to the actual implementation of FORMAT.

Finally, suspecting this is a bug in the doco (or the code) a quick search of connect reveals nothing.

How about a test case? (Comments welcome on the validity of this code…)

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, that's nondeterministic.

So, an interesting exercise but nothing conclusive.

So what did we learn (according to BOL)? If a built-in function is nondeterministic, there's no way of making it so. Some are both depending on the parameter types, and some are supposed to be but aren't.




回答2:


I'm wondering why you are using a function. You can use a simple formula:

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



回答3:


Microsoft isn't very clear about the format function being able to be determinstic. I couldn't find any info on the subject in its documentation. Being a CLR function i guess the awnser is it is not possible.

An even more simple solution to get an integer formatted the way you want would be:

YEAR(@pDate) * 100 + MONTH(@pDate)


来源:https://stackoverflow.com/questions/37621457/can-i-make-sql-server-format-deterministic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!