我可以使 SQL Server FORMAT 具有确定性吗?
Posted
技术标签:
【中文标题】我可以使 SQL Server FORMAT 具有确定性吗?【英文标题】:Can I make SQL Server FORMAT deterministic? 【发布时间】:2016-06-03 18:46:25 【问题描述】:我想制作一个返回整数形式的 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 具有确定性?
【问题讨论】:
你要为计算列使用函数吗? @FLICKER 是的,我是。一个持久的。 请看我的回答。我也不知道你为什么使用 SCEHMEBINDING @FLICKERschemabinding
必须有任何机会被认为是确定性的。
嗯,我不知道,反正我认为使用 convert 也是确定性的
【参考方案1】:
有趣的问题,所以我做了一些挖掘,但没有得出任何结论:)
以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)?如果内置函数是不确定的,那么就没有办法做到这一点。有些都取决于参数类型,有些应该是但不是。
【讨论】:
请vote on fixing this bug。【参考方案2】:我想知道你为什么要使用函数。 您可以使用一个简单的公式:
CONVERT(varchar(6), getdate(), 112)
【讨论】:
因为我不知道我能做到这一点 这条评论给了我想要的东西,但没有具体回答这个问题,所以我投了赞成票,但没有接受。 +1。具体来说,样式 112 (ISO) 是确定性的。根据docs,有些样式是确定性的,有些则不是。【参考方案3】:Microsoft 对格式函数能否具有确定性并不是很清楚。我在其文档中找不到有关该主题的任何信息。作为一个 CLR 函数,我猜 awnser 是不可能的。
按照您想要的方式格式化整数的更简单的解决方案是:
YEAR(@pDate) * 100 + MONTH(@pDate)
【讨论】:
这条评论给了我想要的东西,但没有具体回答这个问题,所以我投了赞成票,但没有接受。以上是关于我可以使 SQL Server FORMAT 具有确定性吗?的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server 2005 事务日志条目:LOP_Format_Page
SQL Server:如何将float格式化为字符串,不使用逗号?