计算列上的索引

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Microsoft Fabric 中的 SQL 数据库

只要满足下列要求就可以为计算列定义索引:

  • 所有权要求
  • 确定性要求
  • 精度要求
  • 数据类型要求
  • SET 选项要求

注意

在创建或更改计算列的索引或索引视图时,SET QUOTED_IDENTIFIER 必须为 ON。 有关详细信息,请参阅SET QUOTED_IDENTIFIER(Transact-SQL)。

所有权要求

计算列中的所有函数引用必须与表具有相同的所有者。

确定性要求

如果对于一组指定的输入表达式始终返回相同的结果,则说明表达式具有确定性。 IsDeterministic 函数的 属性报告 computed_column_expression 是否为确定性的。

Computed_column_expression 必须具有确定性。 当以下所有条件均为真时,computed_column_expression 是确定的:

  • 表达式引用的所有函数都具有确定性,并且是精确的。 这些函数包括用户定义函数和内置函数。 有关详细信息,请参阅 Deterministic and Nondeterministic Functions。 如果计算列是 PERSISTED,则函数可能不精确。 有关详细信息,请参阅本主题后面的对持久化计算列创建索引。

  • 表达式引用的所有列都来自包含计算列的表。

  • 任何列引用都不会从多行中提取数据。 例如,聚合函数(如 SUM 或 AVG)依靠来自多行的数据,这使 computed_column_expression 具有不确定性。

  • computed_column_expression 不会访问系统数据或用户数据。

任何包含公共语言运行时 (CLR) 表达式的计算列都必须具有确定性并标记为 PERSISTED,这样才能为该列创建索引。 允许在计算列定义中使用 CLR 用户定义类型的表达式。 类型为 CLR 用户定义类型的计算列,只要该类型可比较,即可建立索引。 有关详细信息,请参阅 CLR 用户定义类型。

CAST 和 CONVERT

如果你在 SQL Server 内的索引计算列中引用日期数据类型的字符串文字,则建议使用确定性日期格式样式将该文字显式转换为所需的日期类型。 有关确定性日期格式样式的列表,请参阅 CAST and CONVERT。

有关详细信息,请参阅文字日期字符串转换为日期值的不确定性转换。

兼容性级别

非 Unicode 字符数据在排序规则间的隐式转换被视为具有不确定性,除非兼容性级别设置为 80 或更低。

当数据库兼容级别设置为 90 时,不能对包含这些表达式的计算列创建索引。 但在已升级的数据库中,包含这些表达式的现有计算列是可以维护的。 如果使用包含字符串到日期的隐式转换的索引计算列,则为了避免损坏索引,请确保数据库和应用程序中的 LANGUAGE 和 DATEFORMAT 设置一致。

兼容性级别 90 对应于 SQL Server 2005 (9.x)。

精度要求

computed_column_expression 必须精确。 如果下列一项或多项为真,则 computed_column_expression 是精确的:

  • 表达式的数据类型不是 float 或 real。

  • 表达式定义中没有使用 float 或 real 数据类型。 例如,在下列语句中,列 y 为 int 且具有确定性,但不精确。

    CREATE TABLE t2 (a int, b int, c int, x float,
        y AS CASE x
              WHEN 0 THEN a
              WHEN 1 THEN b
              ELSE c
          END);
    

注意

任何 float 或 real 表达式都被认为是不精确的,不能作为索引键; float 或 real 表达式可以在索引视图中使用,但不能作为键使用。 对于计算列同样如此。 如果任何函数、表达式或用户定义函数包含任何 float 或 real 表达式,则被认为是不精确的。 这也包括逻辑运算(比较运算)。

IsPrecise 函数的 COLUMNPROPERTY 属性报告 computed_column_expression 是否精确。

数据类型要求

  • 为计算列定义的 computed_column_expression 不能对 text、ntext 或 image 数据类型求值。
  • 只要计算列的数据类型可用作索引键列,则从image、ntext、text、varchar(max)、nvarchar(max)、varbinary(max)和xml数据类型派生的计算列即可建立索引。
  • 只要计算列的数据类型允许用作非键索引列,由 image、ntext 和 text 数据类型派生的计算列就可以作为非聚集索引中的非键(包含)列。

SET 选项要求

  • 执行定义计算列的 ANSI_NULLS 或 ON 语句时,必须将 CREATE TABLE 连接级选项设置为 ALTER TABLE。 OBJECTPROPERTY 函数通过 IsAnsiNullsOn 属性报告此选项是否设置为 ON。

  • 对于在其中创建索引的连接和所有尝试执行 INSERT、UPDATE 或 DELETE 语句(将更改索引中的值)的连接,必须将六个 SET 选项设置为 ON,将一个选项设置为 OFF。 对于由未使用这些相同的选项设置的连接执行的任何 SELECT 语句,优化器都会忽略计算列上的索引。

    NUMERIC_ROUNDABORT 选项必须设置为 OFF,且下列选项必须设置为 ON:

    • ANSI_NULLS
    • ANSI_PADDING
    • ANSI_WARNINGS
    • ARITHABORT
    • CONCAT_NULL_YIELDS_NULL
    • QUOTED_IDENTIFIER

注意

当数据库兼容级别设置为 ANSI_WARNINGS 或更高时,如果将 ON 设置为 ARITHABORT,则将使 ON 隐式设置为 90。

对持久化计算列创建索引

有时可以创建一个计算列,并使用一个确定性但不精确的表达式进行定义。 当该列在 PERSISTED 或 CREATE TABLE 语句中被标记为 ALTER TABLE 时,可以执行此操作。

这意味着 数据库引擎 在表中存储计算值,并且在计算列所依赖的任何其他列发生更新时更新这些值。 如果 数据库引擎 对列创建了索引并且该索引由某查询引用,则会使用这些持久值。

当数据库引擎不能准确证明返回计算列表达式的函数(特别是在 .NET Framework 中创建的 CLR 函数)是否既具有确定性又精确时,使用此选项可以对计算列创建索引。

注意

不能对计算列创建筛选索引。