Невозможно сохранить вычисляемый столбец-не детерминированный

у меня есть эта функция для вычисляемого столбца:

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] всегда будет давать одни и те же результаты.

код ошибки :

вычисляемый столбец "AllocatedTimeStart" в таблице "Tmp_Bookings" не может быть сохранен, так как столбец недетерминированный.

я использую эту формулу в столбец :

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

и столбец defs:

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

какие идеи?

EDIT:

изменить строки :

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

но теперь я получаю ошибку, говоря, что формула для столбца недействительна. Хотя функция сохраняет отлично.

EDIT 2:

я показал, что именно я делать (или, по крайней мере, я пробовал). На самом деле нет ничего лишнего. Как говорится в предыдущей функции (исходной) в сочетании с формулой ref [dbo].AllocatedStartDate(...) чтобы он в колонке работал, но не настаивал, он сказал, что он не детерминирован. Поэтому в соответствии с предложением я изменил функцию, заменив часть преобразования новым кодом, поэтому функция теперь выглядит так:

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]))) ... и он отвергает формула говорит, что она недействительна... что странно, поскольку формула одинакова, поэтому она должна выполнять какую-то проверку измененной функции и находить ее недействительной, что также странно, потому что я сделал plain SELECT dbo.GetAllocatedStartTime(2012,13) и это сработало...

так что да, я запутался, и я никогда не видел SqlFiddle неважно, используйте его. Но на самом деле нет ничего более, что я только что сказал.

1 ответов


CONVERT([varchar](4),@Year,(0))+'-01-01' передается DATEDIFF вызова, в позиции, где ожидается дата, заставляя неявное преобразование происходит.

из правил для детерминированные функции:

CAST

детерминированным, если не используется с datetime, smalldatetime или sql_variant.

CONVERT

детерминированный, если только одно из этих условий не существует:

...

тип источника или цели datetime или smalldatetime, другим исходным или целевым типом является символьная строка и указывается недетерминированный стиль. Чтобы быть детерминированным, параметр style должен быть константой. Кроме того, стили, меньшие или равные 100, являются недетерминированными, за исключением стилей 20 и 21. Стили более 100 являются детерминированными, за исключением стилей 106, 107, 109 и 113.

Ну, вы не звоните ни тому, ни другому, но вы полагаетесь на неявное преобразование, которое я ожидал бы действовать как CAST. Вместо того, чтобы полагаться на это, я бы переключился на использование CONVERT и дайте детерминированный параметр стиля.

Итак, я делаю: CONVERT(datetime,CONVERT([varchar](4),@Year,(0))+'0101',112) в своем месте. После этого сама функция становится детерминированной