SQL Server计算列:如何将其设置为NOT NULL,而没有持久性

时间:2019-07-04 07:06:01

标签: sql sql-server sql-server-2012 calculated-columns

我要添加一个计算列,该列应为现有表上的NOT NULL 我的计算值的源列当然都是NOT NULL。我想使计算列不是持久性的,以节省空间,但是我没有这样做:

ALTER TABLE UnitHistory
ADD 
    [PrefixedUnitId] AS ((UnitHistory.UnitIdPrefix + cast(UnitHistory.UnitId     
    AS nvarchar(8)))) NOT NULL
GO

给予

  

在计算时只能创建UNIQUE或PRIMARY KEY约束   列,而CHECK,FOREIGN KEY和NOT NULL约束则需要   计算的列将保留。讯息15135,第16级,状态15   过程sp_addextendedproperty,第72行对象无效。扩展的   “ dbo.UnitHistory.PrefixedUnitId”上不允许使用属性,或者   该对象不存在。

现在,我明白了消息的含义,并且可以肯定的是,使用PERSISTED NOT NULL确实会产生该列。

但是,为了节省空间,我不想保留该列。

当基础列不是NULL时,是否有一种方法可以使计算列不是NULL,但不是持久性的?

注意:它应该可以在SQL Server 2012 SP2上运行

1 个答案:

答案 0 :(得分:1)

这似乎完全多余,但是您可以在check约束中重复该条件:

ALTER TABLE UnitHistory
    ADD PrefixedUnitId AS ( UnitHistory.UnitIdPrefix + cast(UnitHistory.UnitId AS nvarchar(8)) );

ALTER TABLE UnitHistory
    ADD CONSTRAINT CHECK ( UnitHistory.UnitIdPrefix + cast(UnitHistory.UnitId AS nvarchar(8)) IS NOT NULL );

但是,由于源列是NOT NULL,所以结果永远不会是NULL

非持久计算列的概念是,它们是根据 output 而不是 input 进行计算的。我认为这可以解释为什么check约束不合适。

例如,您可以拥有一个表,该表具有一个计算列,该列会生成错误并仍然充分使用该表:

create table t (
    id int identity primary key,
    x int,
    computed as (1 / 0)
);

-- works
insert into t (x) values (1);

-- works
select x
from t;

-- fails
select *
from t;

Here是db <>小提琴。

顺便说一句,总是会产生错误的计算列有一个很好的副作用-如果您要这样做,它将阻止用户使用select *