无法持久计算列 - 不确定

spr*_*t12 12 database sql-server calculated-columns sql-server-2008-r2

我有一个计算列的函数:

CREATE FUNCTION [dbo].[GetAllocatedStartTime](@Year INT, @Week INT)
RETURNS DATETIME

WITH schemabinding
AS BEGIN
    RETURN dateadd(week,@Week-(1),dateadd(day,(-1),dateadd(week,datediff(week,(0),CONVERT([varchar](4),@Year,(0))+'-01-01'),(1))))
END

GO
Run Code Online (Sandbox Code Playgroud)

我添加了WITH schemabinding希望它会使它确定性,所以我可以坚持下去.它应该作为两个输入[Week]并且[Year]将始终产生相同的结果.

确切的错误是:

表'Tmp_Bookings'中的计算列'AllocatedTimeStart'无法保留,因为该列是非确定性的.

我在列中使用此公式:

([dbo].[GetAllocatedStartTime]([Year],[Week]))
Run Code Online (Sandbox Code Playgroud)

列定义:

[Week] [int] NOT NULL,
[Year] [int] NOT NULL,
[AllocatedTimeStart]  AS ([dbo].[GetAllocatedStartTime]([Year],[Week])),
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

编辑:

将行改为:

RETURN dateadd(week,@Week-(1),dateadd(day,(-1),dateadd(week,datediff(week,(0),CONVERT(datetime,CONVERT([varchar](4),@Year,(0))+'0101',112)),(1))))
Run Code Online (Sandbox Code Playgroud)

但现在我得到一个错误,说该列的公式无效.即使功能保存良好.

编辑2:

我已经准确地展示了我在做什么(或至少我已经尝试过).真的没什么.正如它所说的那样,前一个函数(原始函数)加上[dbo].AllocatedStartDate(...)列中的公式参考,但是没有坚持,它说这是不确定的.所以根据建议我更改了FUNCTION,用新代码替换了转换部分,所以现在看起来像:

FUNCTION [dbo].[GetSTime](@Year INT, @Week INT)

RETURNS DATETIME
WITH schemabinding
AS BEGIN
    RETURN dateadd(week,@Week-(1),dateadd(day,(-1),dateadd(week,datediff(week,(0),CONVERT(datetime,CONVERT([varchar](4),@Year,(0))+'0101',112)),(1))))
END
Run Code Online (Sandbox Code Playgroud)

然后我在计算字段中尝试了与之前相同的公式(([dbo].[GetAllocatedStartTime]([Year],[Week])))......并且它拒绝公式,说它无效......这很奇怪,因为公式是相同的,所以它必须对变化进行某种检查功能和发现是无效的,这也很奇怪,因为我做了一个平原SELECT dbo.GetAllocatedStartTime(2012,13),它的工作......

所以是的,我很困惑,我从来没有见过,SqlFiddle从不介意使用它.但实际上只有我刚才所说的.

Dam*_*ver 19

CONVERT([varchar](4),@Year,(0))+'-01-01'被传递给一个DATEDIFF调用,在一个预期日期的位置,强制进行隐式转换.

根据确定性函数的规则:

CAST

确定性除非使用datetime,smalldatetimesql_variant.

CONVERT

确定性除非存在以下条件之一:

...

源或目标类型是datetimesmalldatetime,其他源或目标类型是字符串,并指定了非确定性样式.要确定性,样式参数必须是常量.此外,小于或等于100的样式是不确定的,但样式20和21除外.大于100的样式是确定性的,样式106,107,109和113除外.

好吧,你既不打电话,也不依赖于隐式转换,我期望这样做CAST.我不是依赖于此,而是转而使用CONVERT并给出确定的样式参数.

所以,我会这样做: CONVERT(datetime,CONVERT([varchar](4),@Year,(0))+'0101',112)取而代之.完成后,函数本身就变得具有确定性