用户定义函数 (TSQL) 非确定性和计算持久列

user defined function (TSQL) non deterministic and computed persisted column

我有一个 table,在它的列中有两列 INT 类型,它们被称为:

ExpirationMonth

ExpirationYear

我想向这个 table 添加一个新列,其值将根据 ExpirationMonthExpirationYear 的值计算。因此,此列将是一个计算列。

为此,我创建了一个用户定义的标量函数,它根据 ExpirationMonthExpirationYear 的值计算此列的值。函数的定义如下:

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

我收到以下错误:

Computed column 'IsExpired' in table 'Table_Name' cannot be persisted because the column is non-deterministic.

我从上面的语句中删除了 PERSISTED 并再次 运行 。然后我注意到该列已添加了预期值。

我的问题是,如果可能的话,我怎样才能让这个专栏持久化?

我意识到这个错误的原因是在IsExpired函数中使用了GETDATE函数。由于 GETDATE 不是确定性的,因此 IsExpired 也不是确定性的。

但是,我不明白我们如何才能使这个函数 IsExpired 具有确定性,并因此将计算列定义为持久化列(如果可能的话)。

你能告诉我这是否可行吗?如果可行,我该怎么做。

该值是不确定的,因为它取决于当前日期。您不能保留其值会随时间变化的计算列。

有关确定性函数的详细信息,请参阅 MSDN 上的 this article

我建议在视图中进行

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