2

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

ExpirationMonth

ExpirationYear

我想在此表中添加一个新列,其值将根据 和 的值ExpirationMonth计算 ExpirationYear。所以这个列将是一个计算列。

为此,我创建了一个用户定义的标量函数,它根据 和 的值计算该列的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

我收到以下错误:

无法保留表“Table_Name”中的计算列“IsExpired”,因为该列是不确定的。

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

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

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

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

你能告诉我这是否可能,如果是的话,我该怎么做。

4

2 回答 2

2

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

有关确定性函数的更多信息,请参阅MSDN 上的这篇文章

于 2015-04-21T15:35:16.440 回答
0

我建议在视图中这样做

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
于 2015-04-21T16:08:51.210 回答