SQL Server - преобразование DATE из DATETIME не является детерминированным, но только в пользовательской функции

Почему это преобразование типа отклоняется как недетерминированный для вычисляемого столбца 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

SQL Server - преобразование DATE из DATETIME не является детерминированным, но только в пользовательской функции

Обратите внимание, что это не преобразование к или от в строковое представление, поэтому я не знаю, почему это не работает, потому что глобализация / регион не должны иметь значения.

Это работает за пределами 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

SQL Server - преобразование DATE из DATETIME не является детерминированным, но только в пользовательской функции

Кажется, что добавление WITH SCHEMABINDING к определению UDF закрывает его, но я не понимаю почему, потому что похоже, что это только отмечает функцию вывод как детерминированную на основе параметров Вход. И я должен использовать другие недетерминированные вещи в своей функции, поэтому это не вариант обходного пути.

Вонки манипуляции со строками также может быть обходным путем, но это не является предпочтительным. Стиль 126 для ISO-8601 на CONVERT все еще недетерминирован согласно SQL Server. Кажется, единственный вариант - отказаться от использования постоянных вычисляемых столбцов?

Я не понимаю, почему вам нужно указывать PERSISTED в столбцах вывода функции. Кроме того, WITH SCHEMABINDING не делает UDF детерминированным (по крайней мере, не по умолчанию) - он просто делает SQL чек тем, что происходит в функции. Если вы хотите немного больше понять, что он делает, этот ответ может быть вам полезен.

ZLK 14.12.2018 00:20

Потому что я хочу быть ленивым и иметь временные метки, усеченные до DATE в различных столбцах, поскольку для каждого столбца требуется меньше строк, которые я могу опустить в операторах INSERT.

Elaskanator 14.12.2018 15:16

Извините, я имею в виду, почему это должен быть PERSISTED ... Я понимаю использование вычисляемого столбца, но я не понимаю, что на самом деле здесь делает PERSISTED ... Это кажется бесполезным в UDF.

ZLK 16.12.2018 22:07

В этом нет необходимости, я просто хочу его использовать, и мне любопытно, почему я не могу, поскольку это Только отклонено из UDF. Ему больше всего нравится ошибка.

Elaskanator 17.12.2018 17:29

Не думаю, что это ошибка. Проблема в том, что без WITH SCHEMABINDING SQL просто ничего не предполагает о функции, поэтому он не знает, является ли вычисляемый столбец детерминированным или нет, он просто предполагает, что это не так. Использование WITH SCHEMABINDING заставляет SQL проверять, есть это или нет. Примечание. Это не означает, что функция должна быть детерминированной, это просто означает, что SQL выполнит проверки, в противном случае этого не произошло бы. Но кроме всего прочего, PERSISTED здесь не делает ничего полезного. Ваш UDF вызывается каждый раз, когда вы его используете, поэтому на самом деле ничто не будет сохраняться с одного раза, когда вы его вызовете в другой, в отличие от таблицы ...

ZLK 17.12.2018 22:05

На самом деле это несерьезно, и я не могу думать о преимуществах PERSISTED в этом случае, но я до сих пор не понимаю, почему проверка детерминизма проходит только за пределами UDF. Это моя главная мысль. Или вы говорите, что в UDF без указания WITH SCHEMABINDING он не предполагает ничего детерминированного, а не пытается его установить, поэтому он просто автоматически не проходит проверку на PERSISTED?

Elaskanator 17.12.2018 22:24

да. Без WITH SCHEMABINDING он вообще ничего не предполагает о функции. Поскольку вычисляемые столбцы с PERSISTED должны быть детерминированными, а SQL ничего не проверяет о функции, он просто предполагает, что это невозможно. Это отличается от детерминированности самой функции, но WITH SCHEMABINDING, очевидно, также проверит, так ли это. Но технически вы можете иметь недетерминированную функцию с постоянным вычисляемым столбцом на выходе, если вы используете WITH SCHEMABINDING, я полагаю, хотя я думаю, что это бессмысленно ...

ZLK 17.12.2018 22:26

Тогда это похоже на ответ. Вы хотите превратить это в единое целое, и я приму это? Спасибо.

Elaskanator 17.12.2018 23:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
353
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как упоминалось в начале этот несколько связанный ответ, отсутствие указания WITH SCHEMABINDING означает, что SQL Server пропускает проверки таких вещей, как детерминизм и доступ к данным.

Поскольку PERSISTED в компьютерном столбце требует, чтобы «выражение вычисляемого столбца» было детерминированным, а SQL Server пропускает любые проверки того, действительно ли оно детерминировано, это не будет разрешено. Та же ошибка возникла бы, даже если бы у вас было что-то столь же простое, как i AS 1 PERSISTED.

(Это не связано с тем, является ли все в самой функции детерминированным.)

Все это говорит о том, что, насколько мне известно, использование PERSISTED в TVF на самом деле ничего не добавляет к функции.

Другие вопросы по теме