Как создать детерминированную функцию, возвращающую DATETIME2? - PullRequest
0 голосов
/ 16 апреля 2019

У меня есть таблица, которая бессмысленно имеет значения DateTime, хранящиеся в столбцах Год (INT), Месяц (INT), День (INT) и Время (FLOAT);к сожалению, мне не разрешено это менять, но есть требование разбить таблицу по годам и месяцам.Поэтому я пытаюсь создать постоянный вычисляемый столбец для хранения DateTime в формате DATETIME2.Однако моя CreateDateTime скалярная функция считается "недетерминированной", когда я пытаюсь добавить вычисляемый столбец на ее основе.

Это моя CreateDateTime функция.

CREATE FUNCTION dbo.CreateDateTime
(
    @year SMALLINT,
    @month TINYINT,
    @day TINYINT,
    @time FLOAT
)
RETURNS DATETIME2
WITH SCHEMABINDING
AS
BEGIN
    DECLARE @paddedYear VARCHAR(4) = FORMAT(@year, '0000')
    DECLARE @paddedMonth VARCHAR(2) = FORMAT(@month, '00')
    DECLARE @paddedDay VARCHAR(2) = FORMAT(@day, '00')
    DECLARE @formattedTime VARCHAR(8) = FORMAT(@time, '00:00:00')
    RETURN IIF
    (
        @year IS NULL
        OR @month IS NULL
        OR @day IS NULL,
        NULL,
        CAST
        (
            IIF
            (
                @time IS NULL OR TRY_CONVERT(TIME, @formattedTime) IS NULL,
                @paddedYear
                + @paddedMonth
                + @paddedDay,
                @paddedYear
                + @paddedMonth
                + @paddedDay
                + ' '
                + @formattedTime
            )
            AS DATETIME2
        )
    )
END

Но при использовании для попытки добавить вычисляемый столбец для DateTime (со следующим сценарием) это приводит к следующему сообщению об ошибке.

ALTER TABLE dbo.Logs
ADD [DateTime] AS (dbo.CreateDateTime(RY, RM, RD, RT)) PERSISTED

Вычисляемый столбец «DateTime»в таблице «Журналы» не могут быть сохранены, потому что столбец недетерминирован.

Я пытался изменить CreateDateTime до очень простой функции, которая возвращает фиксированный DateTime, используя следующее: CAST('20000101' AS DATETIME2), CONVERT(DATETIME2, '20000101') и '20000101', но все они выдают ту же ошибку, что и выше.Мне удалось добавить столбец, хотя, если я заставил функцию CreateDateTime возвращать VARCHAR(8), вместо этого, похоже, проблема с DATETIME2.

Как я могу создать эту функцию CreateDateTime, чтобы онасчитается детерминированным и все еще возвращает DATETIME2?

1 Ответ

2 голосов
/ 16 апреля 2019

Я смог создать постоянный вычисляемый столбец, минуя мою функцию CreateDateTime, и вместо этого использовал следующее:

ALTER TABLE dbo.Logs
ADD [DateTime] AS DATETIME2FROMPARTS
(
    RY,
    RM,
    RD,
    ROUND(RT / 10000, 0, 1),
    ROUND(RT / 100, 0, 1) - ROUND(RT / 10000, 0, 1) * 100,
    ROUND(RT, 0, 1) - ROUND(RT / 100, 0, 1) * 100,
    RT - ROUND(RT, 0, 1),
    3 --Precision to 3 decimal places (for milliseconds)
) PERSISTED

Хотя это не отвечает на мой вопрос о создании детерминированной функции, возвращающейDATETIME2;это решает конкретную проблему, с которой я столкнулся при создании DateTime2 сохраняемого вычисляемого столбца для отображения DateTime для каждого значения RY, RM, RD и RT.

Как подчеркнул Zohar, DATETIMEFROMPARTS не делаетвернуть DATETIME2;DATETIME2FROMPARTS также принимает дополнительный аргумент для десятичной точности - это сводит на нет ошибки округления, которые присутствовали в исходном решении DATETIMEFROMPARTS, которое я предоставил.

...