15

我有一个计算列的函数:

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

我添加了WITH schemabinding它,希望它可以使其具有确定性,以便我可以坚持下去。它应该作为两个输入[Week],并且[Year]总是会产生相同的结果。

确切的错误是:

无法保留表“Tmp_Bookings”中的计算列“AllocatedTimeStart”,因为该列是不确定的。

我在列中使用这个公式:

([dbo].[GetAllocatedStartTime]([Year],[Week]))

和列 defs :

[Week] [int] NOT NULL,
[Year] [int] NOT NULL,
[AllocatedTimeStart]  AS ([dbo].[GetAllocatedStartTime]([Year],[Week])),

有任何想法吗?

编辑:

将行更改为:

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

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

编辑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

然后我在计算域中尝试了与以前相同的公式(([dbo].[GetAllocatedStartTime]([Year],[Week])))......它拒绝了这个公式,说它无效......这很奇怪,因为公式是相同的,所以它必须对更改的内容进行某种检查功能并发现它无效,这也很奇怪,因为我做了一个简单的SELECT dbo.GetAllocatedStartTime(2012,13)并且它有效......

所以是的,我很困惑,我从来没有见过SqlFiddle没关系使用它。但真的没有什么比我刚才所说的更多了。

4

1 回答 1

22

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

从确定性函数的规则:

CAST

确定性,除非与datetimesmalldatetime或一起使用sql_variant

CONVERT

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

...

源或目标类型是datetimeor smalldatetime,另一个源或目标类型是字符串,并且指定了非确定性样式。为了具有确定性,样式参数必须是常数。此外,小于或等于 100 的样式是不确定的,除了样式 20 和 21。大于 100 的样式是确定的,除了样式 106、107、109 和 113。

好吧,您都没有调用,但是您依赖于隐式转换,我希望它的行为类似于CAST. 而不是依赖于此,我会切换到使用CONVERT并给出确定性样式参数。

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

于 2013-01-02T15:38:46.640 回答