一、计算列
1、概念
计算列由可以使用同一表中的其他列的表达式计算得来。表达式可以是非计算列的列名、常量、函数,也可以是用一个或多个运算符连接的上述元素的任意组合。表达式不能为子查询。
一般在写SQL的时候应该避免在条件中使用函数,因为这样就不能有效的使用索引,从而无法生成高效的执行计划。SQL Server提供了计算列可以帮助我们解决这个问题。
例如,某查询对大小写敏感,希望查询某列全部转为小写,如果程序设计时没有考虑到,那么需要在查询的时候就必须要强制转化。 select * from table1 where lower(column1) = 'abc'
计算列可用于选择列表、WHERE 子句、ORDER BY 子句或任何可使用正则表达式的其他位置,但下列情况除外:
(1)用作 CHECK、FOREIGN KEY 或 NOT NULL 约束的计算列必须标记为 PERSISTED。如果计算列的值由具有确定性的表达式定义,并且索引列中允许使用计算结果的数据类型,则可将该列用作索引中的键列,或者用作 PRIMARY KEY 或 UNIQUE 约束的一部分。
(2)计算列不能作为 INSERT 或 UPDATE 语句的目标。
数据库引擎基于使用的表达式自动确定计算列的为 Null 性。即使只有非空列,大多数表达式的结果也“认为”可为空值,因为下溢或溢出生成的结果也可能为空。通过指定 ISNULL (check_expression,constant) 可以将可为空值的表达式转换为不可为空值的表达式,其中, constant 是可替换所有空结果的非空值.
2、创建计算列
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) |
3、创建持久化计算列
如果不使用PERSISTED 关键字,计算列是未实际存储在表中的虚拟列。每当在查询中引用计算列时,都将重新计算它们的值。
使用PERSISTED 关键字计算列实际存储在表中。如果在计算列的计算更改时涉及任何列,将更新计算列的值。
二、为计算列创建索引的限制条件
1. 所有权
计算列中的所有函数引用必须与表具有相同的所有者。
2. 确定性
如果对于一组指定的输入表达式始终返回相同的结果,则说明表达式具有确定性。
computed_column_expression 必须具有确定性。如果下列一项或多项为真,则 computed_column_expression 具有确定性:
(1)表达式引用的所有函数都具有确定性,并且是精确的。这些函数包括用户定义函数和内置函数。如果计算列是 PERSISTED,则函数可能不精确。
(2)表达式引用的所有列都来自包含计算列的表。
(3)没有列引用从多行中请求数据。例如,聚合函数(如 SUM 或 AVG)依靠来自多行的数据,这使 computed_column_expression 具有不确定性。
(4)没有系统数据访问或用户数据访问。
任何包含公共语言运行时 (CLR) 表达式的计算列都必须具有确定性并标记为 PERSISTED,这样才能为该列创建索引。允许在计算列定义中使用 CLR 用户定义类型的表达式。类型为 CLR 用户定义类型的计算列只要其类型是可比较的,就可以在该列上创建索引。
3. 精度
computed_column_expression 必须精确。如果下列一项或多项为真,则 computed_column_expression 是精确的:
(1)表达式的数据类型不是 float 或 real。
(2)表达式定义中没有使用 float 或 real 数据类型。
任何 float 或 real 表达式都被认为是不精确的,不能作为索引键;float 或 real 表达式可以在索引视图中使用,但不能作为键使用。对于计算列同样如此。如果任何函数、表达式或用户定义函数包含任何 float 或 real 表达式,则被认为是不精确的。这也包括逻辑表达式(比较)。
如果计算列使用确定性但不精确的表达式定义,但在 CREATE TABLE 或 ALTER TABLE 语句中标记为 PERSISTED,则可以在该列上创建索引。这意味着数据库引擎在表中存储计算值,并且在计算列所依赖的任何其他列发生更新时更新这些值。如果数据库引擎对列创建了索引并且该索引由某查询引用,则会使用这些持久值。当数据库引擎不能准确证明返回计算列表达式的函数(特别是在 .NET Framework 中创建的 CLR 函数)是否既具有确定性又精确时,使用此选项可以对计算列创建索引。
4. 数据类型
数据类型要求如下:
(1)为计算列定义的 computed_column_expression 的值不能为 text、ntext 或 image 数据类型。
(2)只要计算列的数据类型可以作为索引键列,从 image、ntext、text、varchar(max)、nvarchar(max)、varbinary(max) 和 xml 数据类型派生的计算列上就可以创建索引。
(3)只要计算列的数据类型可以作为非键索引列,从 image、ntext 和 text 数据类型派生的计算列就可以作为非聚集索引中的非键(包含性)列。
5. SET选项
SET 选项要求如下:
(1)执行定义计算列的 CREATE TABLE 或 ALTER TABLE 语句时,必须将 ANSI_NULLS 连接级选项设置为 ON。
(2)对于在其中创建索引的连接和所有尝试执行 INSERT、UPDATE 或 DELETE 语句(将更改索引中的值)的连接,必须将六个 SET 选项(ANSI_NULLS、ANSI_PADDING、ANSI_WARNINGS、ARITHABORT、CONCAT_NULL_YIELDS_NULL、QUOTED_IDENTIFIER)设置为 ON,将一个选项(NUMERIC_ROUNDABORT)设置为 OFF。如果不具有上述选项设置的连接执行了任何 SELECT 语句,优化器将忽略计算列的索引。
(3)当数据库兼容级别设置为 90 时,如果 ANSI_WARNINGS 设置为 ON,则会将 ARITHABORT 隐式设置为 ON。如果数据库兼容级别设置为 80 或更低,则必须将 ARITHABORT 选项显式设置为 ON。
本文结语:
需要频繁访问的计算列可以考虑持久化。当计算列为确定性且精确,或确定性、不精确、持久化时,可以创建索引。
本文出自 “我们一起追过的MSSQL” 博客,转载请与作者联系!