Подтвердить что ты не робот

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

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

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))))

Но теперь я получаю сообщение о том, что формула для столбца недействительна. Даже если функция экономит штраф.

ИЗМЕНИТЬ 2:

Я точно показал, что я делаю (или, по крайней мере, я пробовал). На самом деле ничего лишнего нет. Как говорится в предыдущей функции (исходной), связанной с формулой ref [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 не обращал на него внимания. Но на самом деле есть не что иное, как то, что я только что сказал.

4b9b3361

Ответ 1

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) на своем месте. Сделав это, сама функция становится детерминированной.