Пользовательская функция (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