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,smalldatetime或sql_variant.
CONVERT确定性除非存在以下条件之一:
...
源或目标类型是
datetime或smalldatetime,其他源或目标类型是字符串,并指定了非确定性样式.要确定性,样式参数必须是常量.此外,小于或等于100的样式是不确定的,但样式20和21除外.大于100的样式是确定性的,样式106,107,109和113除外.
好吧,你既不打电话,也不依赖于隐式转换,我期望这样做CAST.我不是依赖于此,而是转而使用CONVERT并给出确定的样式参数.
所以,我会这样做: CONVERT(datetime,CONVERT([varchar](4),@Year,(0))+'0101',112)取而代之.完成后,函数本身就变得具有确定性