Не удается сохранить вычисленный столбец - не детерминированный
У меня есть эта функция для вычисленного столбца:
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
не обращал на него внимания. Но на самом деле есть не что иное, как то, что я только что сказал.
Ответы
Ответ 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)
на своем месте. Сделав это, сама функция становится детерминированной.