Пользовательская функция (TSQL) недетерминированный и вычисляемый постоянный столбец

У меня есть таблица, среди столбцов которой есть два типа INT и они называются:

ExpirationMonth

а также

ExpirationYear

Я хочу добавить в эту таблицу новый столбец, значение которого будет рассчитываться на основе значений ExpirationMonth а также ExpirationYear, Таким образом, этот столбец будет вычисляемым столбцом.

Для этой цели я создал пользовательскую скалярную функцию, которая вычисляет значение этого столбца на основе значений ExpirationMonth а также ExpirationYear, Определение функции следующее:

CREATE FUNCTION [dbo].[IsExpired]
(
    @ExpirationMonth INT,
    @ExpirationYear INT
)
RETURNS BIT
AS
BEGIN
    DECLARE @Today DATE = GETDATE()
    DECLARE @PreviousMonth INT = MONTH(@today)-1
    DECLARE @CurrentYear INT = YEAR(@today)

    DECLARE @IsExpired BIT = 0

    IF(@ExpirationYear<@CurrentYear OR
      (@ExpirationYear=@CurrentYear AND @ExpirationMonth<=@PreviousMonth))
        SET @IsExpired = 1

    RETURN @IsExpired

END

Первоначально я попытался добавить столбец, как показано ниже:

ALTER Table_Name
ADD IsExpired AS [dbo].[IsExpired]([ExpirationMonth], [ExpirationYear]) PERSISTED

И я получил следующую ошибку:

Вычисляемый столбец "IsExpired" в таблице "Table_Name" не может быть сохранен, поскольку столбец недетерминирован.

Я удалил PERSISTED из приведенного выше заявления, и я запустил его снова. Затем я заметил, что столбец был добавлен с ожидаемыми значениями.

У меня вопрос, как я могу сохранить этот столбец, если это вообще возможно?

Я понял, что причиной этой ошибки является использование GETDATE функция в IsExpired функция. поскольку GETDATE не является детерминированным, IsExpired не является детерминированным.

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

Не могли бы вы сказать мне, если это возможно, и если это так, как я могу это сделать.

2 ответа

Решение

Значение является недетерминированным, потому что оно зависит от текущей даты. Вы не можете сохранять вычисляемые столбцы, значения которых могут меняться со временем.

См. Эту статью на MSDN для получения дополнительной информации о детерминированных функциях.

Я бы предложил сделать это в представлении

SELECT * INTO yourTable
FROM (VALUES(2015,1),(2015,2),(2015,3),(2015,4),(2015,5),(2015,6)) AS A(ExpirationYear,ExpirationMonth);
GO

CREATE VIEW vw_Expiration
AS
SELECT  ExpirationYear,
        ExpirationMonth,
        CASE
            WHEN    ExpirationYear < YEAR(GETDATE()) OR
                    (ExpirationYear = YEAR(GETDATE()) AND ExpirationMonth <= MONTH(GETDATE()))
                THEN 1
            ELSE 0
        END AS IsExpired
FROM yourTable;
GO

SELECT *
FROM vw_Expiration

Результаты:

ExpirationYear ExpirationMonth IsExpired
-------------- --------------- -----------
2015           1               1
2015           2               1
2015           3               1
2015           4               1
2015           5               0
2015           6               0
Другие вопросы по тегам