Почему это преобразование типа отклоняется как недетерминированный для вычисляемого столбца PERSISTED в таблицах возврата пользовательских функций (UDF) в SQL Server?
CREATE FUNCTION MyTimeIntervalFunction(@Param1 INT)
RETURNS @MyTimeInterval TABLE
(
StartUtc DATETIME NOT NULL PRIMARY KEY
,EndUtc DATETIME NOT NULL
,DateUtc AS CONVERT(DATE, StartUtc) PERSISTED
)
AS BEGIN
--do stuff
RETURN
END
Обратите внимание, что это не преобразование к или от в строковое представление, поэтому я не знаю, почему это не работает, потому что глобализация / регион не должны иметь значения.
Это работает за пределами UDF (включая хранимые процедуры):
DECLARE @MyTimeInterval TABLE
(
StartUtc DATETIME NOT NULL PRIMARY KEY
,EndUtc DATETIME NOT NULL
,DateUtc AS CONVERT(DATE, StartUtc) PERSISTED
)
INSERT INTO @MyTimeInterval(StartUtc, EndUtc)
VALUES ('2018-01-01', '2018-01-02')
SELECT * FROM @MyTimeInterval
Кажется, что добавление WITH SCHEMABINDING к определению UDF закрывает его, но я не понимаю почему, потому что похоже, что это только отмечает функцию вывод как детерминированную на основе параметров Вход. И я должен использовать другие недетерминированные вещи в своей функции, поэтому это не вариант обходного пути.
Вонки манипуляции со строками также может быть обходным путем, но это не является предпочтительным. Стиль 126 для ISO-8601 на CONVERT все еще недетерминирован согласно SQL Server. Кажется, единственный вариант - отказаться от использования постоянных вычисляемых столбцов?
Потому что я хочу быть ленивым и иметь временные метки, усеченные до DATE в различных столбцах, поскольку для каждого столбца требуется меньше строк, которые я могу опустить в операторах INSERT.
Извините, я имею в виду, почему это должен быть PERSISTED ... Я понимаю использование вычисляемого столбца, но я не понимаю, что на самом деле здесь делает PERSISTED ... Это кажется бесполезным в UDF.
В этом нет необходимости, я просто хочу его использовать, и мне любопытно, почему я не могу, поскольку это Только отклонено из UDF. Ему больше всего нравится ошибка.
Не думаю, что это ошибка. Проблема в том, что без WITH SCHEMABINDING SQL просто ничего не предполагает о функции, поэтому он не знает, является ли вычисляемый столбец детерминированным или нет, он просто предполагает, что это не так. Использование WITH SCHEMABINDING заставляет SQL проверять, есть это или нет. Примечание. Это не означает, что функция должна быть детерминированной, это просто означает, что SQL выполнит проверки, в противном случае этого не произошло бы. Но кроме всего прочего, PERSISTED здесь не делает ничего полезного. Ваш UDF вызывается каждый раз, когда вы его используете, поэтому на самом деле ничто не будет сохраняться с одного раза, когда вы его вызовете в другой, в отличие от таблицы ...
На самом деле это несерьезно, и я не могу думать о преимуществах PERSISTED в этом случае, но я до сих пор не понимаю, почему проверка детерминизма проходит только за пределами UDF. Это моя главная мысль. Или вы говорите, что в UDF без указания WITH SCHEMABINDING он не предполагает ничего детерминированного, а не пытается его установить, поэтому он просто автоматически не проходит проверку на PERSISTED?
да. Без WITH SCHEMABINDING он вообще ничего не предполагает о функции. Поскольку вычисляемые столбцы с PERSISTED должны быть детерминированными, а SQL ничего не проверяет о функции, он просто предполагает, что это невозможно. Это отличается от детерминированности самой функции, но WITH SCHEMABINDING, очевидно, также проверит, так ли это. Но технически вы можете иметь недетерминированную функцию с постоянным вычисляемым столбцом на выходе, если вы используете WITH SCHEMABINDING, я полагаю, хотя я думаю, что это бессмысленно ...
Тогда это похоже на ответ. Вы хотите превратить это в единое целое, и я приму это? Спасибо.





Как упоминалось в начале этот несколько связанный ответ, отсутствие указания WITH SCHEMABINDING означает, что SQL Server пропускает проверки таких вещей, как детерминизм и доступ к данным.
Поскольку PERSISTED в компьютерном столбце требует, чтобы «выражение вычисляемого столбца» было детерминированным, а SQL Server пропускает любые проверки того, действительно ли оно детерминировано, это не будет разрешено. Та же ошибка возникла бы, даже если бы у вас было что-то столь же простое, как i AS 1 PERSISTED.
(Это не связано с тем, является ли все в самой функции детерминированным.)
Все это говорит о том, что, насколько мне известно, использование PERSISTED в TVF на самом деле ничего не добавляет к функции.
Я не понимаю, почему вам нужно указывать
PERSISTEDв столбцах вывода функции. Кроме того,WITH SCHEMABINDINGне делает UDF детерминированным (по крайней мере, не по умолчанию) - он просто делает SQL чек тем, что происходит в функции. Если вы хотите немного больше понять, что он делает, этот ответ может быть вам полезен.