Как сделать преобразование из varchar в детерминированный datetime?

В традициях этот вопрос и в свете документации, как можно сделать эту функцию детерминированной:

ALTER FUNCTION [udf_DateTimeFromDataDtID]
(
    @DATA_DT_ID int -- In form YYYYMMDD
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
    RETURN CONVERT(datetime, CONVERT(varchar, @DATA_DT_ID))
END

Или этот (из-за литералов строки / даты - и да, я также пробовал '1900-01-01'):

ALTER FUNCTION udf_CappedDate
(
    @DateTimeIn datetime
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
    IF @DateTimeIn < '1/1/1900'
        RETURN '1/1/1900'
    ELSE IF @DateTimeIn > '1/1/2100'
        RETURN '1/1/2100'

    RETURN @DateTimeIn
END

person Cade Roux    schedule 21.11.2008    source источник


Ответы (2)


BOL говорит, что CONVERT детерминирован с датой, если указан параметр style. Итак, если вы измените первый UDF на:

RETURN CONVERT(datetime, CONVERT(varchar, @DATA_DT_ID), 112)

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

Предположительно, тот же трюк можно было бы использовать во втором UDF:

IF @DateTimeIn < CONVERT(datetime, '1/1/1900', 101)
    RETURN CONVERT(datetime, '1/1/1900', 101)

Я действительно хотел бы, чтобы в T-SQL был способ указать литералы даты и времени.

ИЗМЕНИТЬ:

Как указал Арво в комментариях (спасибо, Арво), можно использовать формат литерала временной метки ODBC (даже при использовании OLE DB), поэтому вторую функцию выше можно было бы лучше записать как:

IF @DateTimeIn < {d '1900-01-01'}
    RETURN {d '1900-01-01'}
...etc.

и преобразование в datetime выполняется во время компиляции, а не во время выполнения. Обратите внимание, что формат даты должен быть очень конкретным (см. ссылку Арво на дату и время тип данных):

д гггг-мм-дд
т чч: мм: сс [.fff]
ц гггг-мм-дд чч: мм: сс [.fff]

person P Daddy    schedule 21.11.2008
comment
Я когда-либо использовал этот стиль только при преобразовании в varchar - документация неоднозначна, но я пробовал его, и он явно работает. - person Cade Roux; 21.11.2008
comment
@P Папа, аминь, литералы даты и времени. - person Amy B; 22.11.2008
comment
О литералах даты и времени - нельзя ли использовать формат метки времени ODBC, например {d '1990-10-02'}? Из msdn.microsoft.com/en-us/library/ms187819.aspx: приложения, использующие API на основе ADO, OLE DB и ODBC, могут использовать этот формат метки времени ODBC для представления даты и времени. - person Arvo; 26.11.2008

Из статей, на которые вы ссылались:

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

Вам необходимо использовать параметр стиля при преобразовании в datetime.

Например:

CONVERT(datetime, '2008-01-01', 121)

Только не используйте 121 ...

person Amy B    schedule 21.11.2008
comment
Значит, никаких буквальных дат в виде строк в UDF без ПРЕОБРАЗОВАНИЯ? - person Cade Roux; 21.11.2008
comment
Если строки неявно преобразуются в даты, то в этих преобразованиях отсутствуют константные стили, и функция будет недетерминированной. - person Amy B; 22.11.2008