1、所有权要求
2、确定性要求
3、精度要求
4、数据类型要求
5、SET 选项要求
计算列中的所有函数引用必须与表具有相同的所有者。
测试环境(MSSQL 2012):
--自定义所有者为guest的标量函数GetMonth
CREATE FUNCTION guest.GetMonth(@1 datetime)
returns nvarchar(10)
as
begin
DECLARE @return nvarchar(10)
SET @return=month(@1)
RETURN(@return)
END
--添加计算列AddMonth,使用函数GetMonth
ALTER TABLE T1 ADD AddMonth AS (guest.GetMonth(AddTime))
--为计算列AddMonth创建索引
CREATE INDEX xAddMonth_iID ON T1(AddMonth)INCLUDE(ID)
报错:
消息 1980,级别 16,状态 1,第 1 行
无法对表 ‘T1‘ 的计算列 ‘AddMonth‘ 创建索引,因为基础对象 ‘GetMonth‘ 的所有者不同。
如果下列一项或多项为真,则具有确定性:
1. 表达式引用的所有函数都具有确定性,并且是精确的。 这些函数包括用户定义函数和内置函数。 有关详细信息,请参阅确定性函数和不确定性函数。 如果计算列是 PERSISTED,则函数可能不精确。
2. 表达式引用的所有列都来自包含计算列的表。
3. 没有列引用从多行中请求数据。 例如,聚合函数(如 SUM 或 AVG)依靠来自多行的数据,这使列具有不确定性。
4. 没有系统数据访问或用户数据访问。
如果下列一项或多项为假,则是不精确的:
a. 表达式的数据类型不是 float 或 real。
b. 表达式定义中没有使用 float 或 real 数据类型。
注意:任何 float 或 real 表达式都被认为是不精确的,不能作为索引键;float 或 real 表达式可以在索引视图中使用,但不能作为键使用。 对于计算列同样如此。 如果任何函数、表达式或用户定义函数包含任何 float 或 real 表达式,则被认为是不精确的。 这也包括逻辑表达式(比较)。
测试环境(MSSQL 2012):
CREATE TABLE T2(ID BIGINT,Score FLOAT,Val REAL)
CREATE INDEX x_Score ON T2(Score)
命令已成功完成。
CREATE INDEX x_Val ON T2(Val)
命令已成功完成。
ALTER TABLE T2 ADD Score1 AS (ID*Score)
ALTER TABLE T2 ADD Val1 AS (ID*Val)
CREATE INDEX x_Score1 ON T2(Score1)
消息 2799,级别 16,状态 1,第 1 行
无法对表 ‘T2‘ 创建索引或统计信息 ‘x_Score1‘,因为计算列 ‘Score1‘ 不精确而且未持久化。请考虑从索引或统计信息键中删除列,或者将计算列标记为持久化。
CREATE INDEX x_Val1 ON T2(Val1)
消息 2799,级别 16,状态 1,第 1 行
无法对表 ‘T2‘ 创建索引或统计信息 ‘x_Val1‘,因为计算列 ‘Val1‘ 不精确而且未持久化。请考虑从索引或统计信息键中删除列,或者将计算列标记为持久化。
ALTER TABLE T2 ADD Val2 AS (CONVERT(BIGINT,ID*Val))
CREATE INDEX x_Val2 ON T2(Val2)
消息 2799,级别 16,状态 1,第 1 行
无法对表 ‘T2‘ 创建索引或统计信息 ‘x_Val2‘,因为计算列 ‘Val2‘ 不精确而且未持久化。请考虑从索引或统计信息键中删除列,或者将计算列标记为持久化。
ALTER TABLE T2 ADD ID1 AS (CONVERT(FLOAT,ID*ID))
CREATE INDEX x_ID1 ON T2(ID1)
消息 2799,级别 16,状态 1,第 1 行
无法对表 ‘T2‘ 创建索引或统计信息 ‘x_ID1‘,因为计算列 ‘ID1‘ 不精确而且未持久化。请考虑从索引或统计信息键中删除列,或者将计算列标记为持久化。
测试结论:可以直接在float 或 real列上建立索引,不能在含有float 或 real表达式或者含有float 或 real数据类型的计算列上建索引
1. 为计算列定义的的值不能为 text、ntext 或 image 数据类型。
2. 只要计算列的数据类型可以作为索引键列,从 image、ntext、text、varchar(max)、nvarchar(max)、varbinary(max) 和 xml 数据类型派生的计算列上就可以创建索引。
3. 只要计算列的数据类型可以作为非键索引列,从 image、ntext 和 text 数据类型派生的计算列就可以作为非聚集索引中的非键(包含性)列。
a. 执行定义计算列的 CREATE TABLE 或 ALTER TABLE 语句时,必须将 ANSI_NULLS 连接级选项设置为 ON。 OBJECTPROPERTY 函数通过 IsAnsiNullsOn 属性报告此选项是否设置为 ON。
b. 对于在其中创建索引的连接和所有尝试执行 INSERT、UPDATE 或 DELETE 语句(将更改索引中的值)的连接,必须将六个 SET 选项设置为 ON,将一个选项设置为 OFF。 如果不具有上述选项设置的连接执行了任何 SELECT 语句,优化器将忽略计算列的索引。
NUMERIC_ROUNDABORT选项必须设置为OFF,
且下列选项必须设置为 ON:
1. ANSI_NULLS
2. ANSI_PADDING
3. ANSI_WARNINGS
4. ARITHABORT
5. CONCAT_NULL_YIELDS_NULL
6. QUOTED_IDENTIFIER
当数据库兼容级别设置为 90 或更高时,如果将 ANSI_WARNINGS 设置为 ON,则将使 ARITHABORT 隐式设置为 ON。
如果计算列使用确定性但不精确的表达式定义,但在 CREATE TABLE 或 ALTER TABLE 语句中标记为 PERSISTED,则可以在该列上创建索引。 这意味着数据库引擎在表中存储计算值,并且在计算列所依赖的任何其他列发生更新时更新这些值。 如果数据库引擎对列创建了索引并且该索引由某查询引用,则会使用这些持久值。 当数据库引擎不能准确证明返回计算列表达式的函数(特别是在 .NET Framework 中创建的 CLR 函数)是否既具有确定性又精确时,使用此选项可以对计算列创建索引。
测试环境(MSSQL 2012):
ALTER TABLE T2 ADD ID2 AS (CONVERT(FLOAT,ID*ID))PERSISTED
CREATE INDEX x_ID2 ON T2(ID2)
命令已成功完成。
① https://msdn.microsoft.com/zh-cn/library/ms189292.aspx
原文地址:http://sukunwu.blog.51cto.com/10453116/1672871