ALTER DATABASE 兼容级别 (Transact-SQL)

将某些数据库行为设置为与指定的 SQL Server 版本兼容。以下 ALTER DATABASE 语法是 SQL Server 2008 中新增的语法,它取代了用于设置数据库兼容级别的 sp_dbcmptlevel 过程。有关其他 ALTER DATABASE 选项,请参阅 ALTER DATABASE (Transact-SQL)

主题链接图标Transact-SQL 语法约定

语法

ALTER DATABASE database_name 
SET COMPATIBILITY_LEVEL = { 80 | 90 | 100 }

参数

  • database_name
    要修改的数据库的名称。

  • COMPATIBILITY_LEVEL { 80 | 90 | 100 }
    要使数据库与之兼容的 SQL Server 版本。该值必须为下列值之一:

    80 = SQL Server 2000

    90 = SQL Server 2005

    100 = SQL Server 2008

注释

对于所有 SQL Server 2008 安装,默认的兼容级别都为 100。除非 model 数据库有更低的兼容级别,否则 SQL Server 2008 中创建的数据库会设置为该级别。在将数据库从 SQL Server 的任何早期版本升级到 SQL Server 2008 时,如果数据库的兼容级别不在 80 以下,则该数据库将保留其现有的兼容级别。升级兼容级别低于 80 的数据库会将数据库的兼容级别设置为 80。这既适用于系统数据库也适用于用户数据库。使用 ALTER DATABASE 可更改数据库的兼容级别。若要查看数据库的当前兼容级别,请查询 sys.databases 目录视图中的 compatibility_level 列。

利用兼容级别获得向后兼容

兼容级别只影响指定数据库的行为,而不影响整个服务器的行为。兼容级别只实现与 SQL Server 的早期版本保持部分向后兼容。通过将兼容级别用作临时性的迁移辅助工具,可解决相关兼容级别设置控制的行为之间存在的版本差异问题。如果现有 SQL Server 应用程序受到 SQL Server 2008 中行为差异的影响,请对该应用程序进行转换,使之能正常运行。然后使用 ALTER DATABASE 将兼容级别更改为 100。数据库的新兼容性设置将在该数据库下次成为当前数据库(无论是在登录时作为默认数据库还是在 USE 语句中指定)时生效。

最佳实践

如果在用户连接到数据库时更改兼容级别,可能会使活动查询产生不正确的结果集。例如,如果在编写查询计划时兼容级别发生更改,则编写后的计划可能同时基于旧的和新的兼容级别,从而造成计划不正确,并可能导致结果不准确。此外,如果将计划放在计划缓存中供后续的查询重用,则问题可能更加复杂。为了避免查询结果不准确,建议您使用以下过程来更改数据库的兼容级别:

  1. 通过使用 ALTER DATABASE SET SINGLE_USER,将数据库设置为单用户访问模式。

  2. 更改数据库的兼容级别。

  3. 通过使用 ALTER DATABASE SET MULTI_USER,将数据库设为多用户访问模式。

  4. 有关设置数据库访问模式的详细信息,请参阅 ALTER DATABASE (Transact-SQL)

SET 选项

新功能可以在旧的兼容级别下正常运行,但是可能需要调整 SET 选项。例如,在兼容级别 80 下使用 xml 数据类型需要相应的 ANSI SET 选项。此外,当数据库兼容级别设置为 90 或更高时,如果将 ANSI_WARNINGS 设置为 ON,则会隐式地将 ARITHABORT 设置为 ON。如果将数据库兼容级别设置为 80,则必须将 ARITHABORT 选项显式设置为 ON。有关详细信息,请参阅影响结果的 SET 选项

兼容级别和存储过程

执行某一存储过程时,该存储过程将使用定义它的数据库的当前兼容级别。在更改某一数据库的兼容性设置时,该数据库的所有存储过程都将随之自动重新编写。

兼容级别 80 和兼容级别 90 之间的差异

本节介绍随兼容级别 90 引入的新行为。

使用兼容级别 90 时,行为将发生下列变化。

兼容级别设置为 80

兼容级别设置为 90

影响的可能性

对于 FROM 子句中的锁提示,WITH 关键字始终是可选的。

但在一些例外情况中,仅当用 WITH 关键字指定表提示时,FROM 子句中才支持这些提示。有关详细信息,请参阅 FROM (Transact-SQL)

支持在警告消息中使用外部联接运算符 *= 和 =*。

不支持使用这两个运算符;应使用 OUTER JOIN 关键字。

在将 ORDER BY 列表中的列引用绑定到在 SELECT 列表中定义的列时,将忽略列的多义性,有时还会忽略列前缀。这可以导致以意外顺序返回结果集。

例如,可以接受具有一个两部分列 (<table_alias>.<column>) 的 ORDER BY 子句,而且该列被用作对 SELECT 列表中的列的引用,但忽略表别名。请考虑下面的查询。

SELECT c1 = -c1 FROM t_table AS x ORDER BY x.c1

执行时,将忽略 ORDER BY 中的列前缀。排序操作对指定的源列 (x.c1) 不按预期方式执行,而是对在查询中定义的派生 c1 列执行。此查询的执行计划将显示:首先计算派生列的值,然后对计算得到的值进行排序。

如果存在列的多义性,则将引发错误。在绑定到 SELECT 列表中所定义的列时,不忽略在 ORDER BY 中指定的列前缀(如果有)。

请考虑下面的查询。

SELECT c1 = -c1 FROM t_table AS x ORDER BY x.c1

执行时,不忽略 ORDER BY 子句中的列前缀。排序操作对指定的源列 (x.c1) 按预期方式执行。此查询的执行计划将显示排序运算符对从 t_table 返回的行排序,然后再对在 SELECT 列表中定义的派生列 c1 的值排序。

在 INSERT SELECT 中,如果 UNION 属于不同的数据类型,则每个 UNION 分支都直接转换为 INSERT 目标列的类型。即使本身所使用的联合可能会因不兼容的类型转换而失败,INSERT SELECT 也会使 UNION 成功执行,因为 UNION 的结果类型的分支从不进行转换。

UNION 的结果类型是独立于 INSERT SELECT 而派生的。UNION 的每一分支都转换为 UNION 的结果类型,然后转换为 INSERT 的目标列类型。如果 UNION 中有不兼容类型,则第一个转换可能会导致错误。若要以兼容级别 90 运行,则必须修复在 INSERT SELECT 中使用的所有不兼容类型的联合。

当视图或被引用视图使用 TOP 子句时,指定了 WITH CHECK OPTION 子句的视图中无法正确支持通过视图进行插入和更新操作。

当视图或被引用视图使用 TOP 子句时,使用 WITH CHECK OPTION 的视图中不支持通过视图进行插入和更新操作。

可变长度列和固定长度列的 UNION 将生成一个固定长度列。

可变长度列和固定长度列的 UNION 将生成一个可变长度列。

忽略在触发器中使用 SET XACT_ABORT OFF。该选项始终设置为 ON。

可以在触发器中将 SET XACT_ABORT 设置为 OFF。

允许在视图中使用(并忽略)FOR BROWSE 子句。

不允许在视图中使用 FOR BROWSE 子句。

ANSI_WARNINGS 不控制域错误。如果 ANSI_WARNINGS 设置为 OFF 并且 ARITHABORT 没有更改,则遵守 ARITHABORT 设置。

域错误由 ANSI_WARNINGS 控制,并且是严重级别为 16 的错误。如果 ANSI_WARNINGS 或 ARITHABORT 为 ON,则将引发错误,而不是返回 NULL 值。此更改可能会破坏依赖于设置为 OFF 的 ARITHABORT 的用户脚本。

如果对远程数据源(OPENROWSET 或 OPENQUERY)所执行的直接传递查询生成名称重复的列,则除非在该查询中显式命名了这些列,否则将忽略重复的列名。

如果对远程数据源(OPENROWSET 或 OPENQUERY)所执行的直接传递查询生成列名重复的列,将引发错误。

大小大于 8000 的字符串常量和 varbinary 常量被视为 text、ntext 或 image。

大小大于 8000 的字符串常量和 varbinary 常量被视为 varchar(max) 类型(或分别被视为 nvarchar(max) 和 varbinary(max))。如果 SELECT 列表包含此类表达式,则这样可以更改使用 SELECT … INTO 创建的表的数据类型。

通过将类型层次结构中优先级较低的比较数转换为优先级较高的类型,从而在各数值类型(smallint、tinyint、int、bigint、numeric、decimal、smallmoney、money)之间进行比较。

数值类型值不经转换便进行比较。这有助于提高性能。但这可能会导致行为发生某些更改,尤其是在转换导致溢出异常的情况下。

使用字符串参数的内置元数据函数在其输入长度大于 4000 个字符的情况下,将截断该输入。

如果截断导致丢失非空格字符,则内置元数据函数会引发错误。

未加引号的标识符中被禁用的字符集保持不变。

Transact-SQL 分析器支持 Unicode 3.2 标准,该标准更改了目前禁止在未分隔标识符中使用的一些国际字符的字符分类。

在出现浮点域错误(即 log() 函数的参数为负)时,SET ANSI_WARNINGS ON 不覆盖 SET ARITHABORT OFF 的设置。如果 ANSI_WARNINGS 为 ON 但 ARITHABORT 为 OFF,则浮点域错误不会导致查询终止。

SET ANSI_WARNINGS ON 完全覆盖 ARITHABORT OFF 设置。在这种情况下,浮点域错误将导致查询终止。

允许在 ORDER BY 子句中使用(并忽略)非整数常量。

不允许在 ORDER BY 子句使用非整数常量。

允许使用空的 SET 语句(未指定 SET 选项)。

不允许使用空的 SET 子句。

没有为派生表所生成的列正确派生 IDENTITY 属性。

为派生表所生成的列正确派生了 IDENTITY 属性。

对浮点数据类型执行运算的算术运算符的可为 Null 性属性始终可以为 Null。

在输入不可为 Null 并且 ANSI_WARNINGS 为 ON 的情况下,对浮点数据类型执行运算的算术运算符的可为 Null 性属性将更改为不可为 Null。

在使用 UNION 组合的 INSERT ..SELECT 语句中,由各个结果集生成的类型都将转换为目标结果类型。

在使用 UNION 组合的 INSERT ..SELECT 语句中,确定各分支的主要类型,并在将结果转换为目标表类型之前将其转换为该类型。

在 SELECT ..FOR XML 语句中,始终实体化 hex(27)(' 字符)和 hex(22)(" 字符),即使在不需要的情况下也是如此。

FOR XML 只在需要时才实体化 hex(27) 和 hex(22)。在下列情况下不实体化这些字符:

  • 在属性内容中,如果属性值以 " 分隔,则不实体化 hex(27)(' 字符);如果属性值以 ' 分隔,则不实体化 hex(22)(" 字符)。

  • 在元素内容中,从不实体化 hex(27) 和 hex(22)。

在 FOR XML 中,时间戳值映射为整数。

在 FOR XML 中,时间戳值映射为二进制值。

有关详细信息,请参阅timestamp 数据类型的 FOR XML 支持

如果使用 timestamp 列,则为高;否则为低

在 FOR XML 和 OPENXML 中,名称中大范围 Unicode 字符(3 字节)使用 8 位表示。

例如,FOR XML 用 8 位表示 Unicode 码位 U+10000 的方式如下:

<a_x00010000_ c1="1" />

在 FOR XML 和 OPENXML 中,名称中大范围 Unicode 字符(3 字节)使用 6 位表示。

例如,FOR XML 用 6 位表示 Unicode 码位 U+10000 的方式如下:

<a_x010000_ c1="1" />

在 FOR XML 中,使用 AUTO 模式的派生表映射被视为是透明的。

例如:

USE AdventureWorks
CREATE TABLE Test(id int);
INSERT INTO Test VALUES(1);
INSERT INTO Test VALUES(2);
SELECT * FROM (SELECT a.id AS a, 
b.id AS b FROM Test a 
JOIN Test b ON a.id=b.id) 
Test FOR XML AUTO;

如果 AdventureWorks 的兼容级别设置为 80,则以上示例将生成:

<a a="1"><b b="1"/></a>

<a a="2"><b b="2"/></a>

在 FOR XML 中,使用 AUTO 模式的派生表映射被视为是不透明的。

如果 AdventureWorks 的兼容级别设置为 90,则以上示例将生成:

<Test a="1" b="1"/>

<Test a="2" b="2"/>

如果对视图应用 FOR XML AUTO 模式,则为高;否则为低

仅在日语和朝鲜语中,字符串到 money 的转换才支持使用反斜杠字符 (\) 作为货币符号。

在所有语言中,所有字符串到 money 的转换中都接受反斜杠字符 (\)。当 \ 用作货币符号时,ISNUMERIC 将返回 True。

对于 SQL Server 2005 之前的 SQL Server 版本上的数据库,这一新行为会拆分依赖于包含 \ 的 ISNUMERIC 返回值并且所使用的语言既不是日语也不是朝鲜语的索引和计算列。

即使操作数不可为 Null 并且 ANSI_WARNINGS 或 ARITHABORT 设置为 ON,算术运算符的结果也始终可为 Null。

在 ANSI_WARNINGS 或 ARITHABORT 设置为 ON 时,如果两个操作数都不可为 Null,则浮点算术运算符的结果也不可为 Null。

在以下情况中,这种为空性的更改可能导致错误:使用 bcp 从包含计算列(该计算列使用浮点算术运算符)的 SQL Server 2000 表中大容量导出二进制格式的数据,然后使用 bcp 或 BULK INSERT 将这些数据大容量导入包含同一定义的 SQL Server 2005 表。

注意注意
当两个选项均为 OFF 时,数据库引擎 将把结果标记为可以为 Null。这与 SQL Server 2000 中相同。

对于以 nvarchar 作为参数的内置函数,如果所提供的值为 varchar,则该值将转换为 nvarchar(4000)。在 SQL Server 2000 中,如果传递较大值,则该值将自行截断。

对于以 nvarchar 作为参数的内置函数,即使所提供的值为 varchar,该值仍将转换为 nvarchar(4000)。但如果传递较大值,SQL Server 2008 将生成错误。

若要以兼容级别 90 运行,必须修复依赖于截断行为的所有自定义代码。

固定长度(char、binary 或 nchar)字符串与可变长度(varchar、varbinary、nvarchar)字符串的联合返回固定长度的结果。

可变大小字符串和固定大小字符串的联合返回可变大小字符串。

若要以兼容级别 90 运行,那么对于任何地方(索引、查询和计算列),只要它依赖与将可变大小类型和固定大小类型求并集得到的类型,就必须修复。

包含字符 0xFFFF 的对象名是有效标识符。

包含字符 0xFFFF 的对象名是无效标识符,不能访问。

若要以兼容级别 90 运行,必须重命名包含此字符的对象。

在 SELECT ISNUMERIC('<string>') 中,<string> 内嵌入的逗号非常重要。

例如,下面的 SELECT ISNUMERIC('121212,12') 查询返回 0。这指示字符串 121212,12 不是数值。

在 SELECT ISNUMERIC('<string>') 中,<string> 内嵌入的逗号可以忽略。

例如,下面的 SELECT ISNUMERIC('121212,12') 查询返回 1。这指示字符串 121212,12 是数值。

忽略了 Transact-SQL 语句中保留关键字后面的冒号 (:)。

Transact-SQL 语句中保留关键字后面的冒号 (:) 将导致语句失败。

引用外部查询中的列的子查询中的 GROUP BY 子句成功。

按照 SQL 标准,引用外部查询中的列的子查询中的 GROUP BY 子句返回错误。

较低兼容级别和级别 100 之间的差异

本节介绍随兼容级别 100 引入的新行为。

兼容级别设置为 90 或更低

兼容级别设置为 100

影响的可能性

对于多语句表值函数,在创建它们时,无论会话级别设置如何,QUOTED_IDENTIFER 设置始终为 ON。

在创建多语句表值函数时,会遵循 QUOTED IDENTIFIER 会话设置。

在创建或更改分区函数时,会评估函数中的 datetime 和 smalldatetime 文字,并假定语言设置为 US_English。

使用当前语言设置来评估该分区函数中的 datetime 和 smalldatetime 文字。

INSERT 和 SELECT INTO 语句中允许使用(但会忽略)FOR BROWSE 子句。

INSERT 和 SELECT INTO 语句中不允许使用 FOR BROWSE 子句。

OUTPUT 子句中允许使用全文谓词。

OUTPUT 子句中不允许使用全文谓词。

不支持 CREATE FULLTEXT STOPLIST、ALTER FULLTEXT STOPLIST 和 DROP FULLTEXT STOPLIST。系统非索引字表自动与新的全文索引相关联。

支持 CREATE FULLTEXT STOPLIST、ALTER FULLTEXT STOPLIST 和 DROP FULLTEXT STOPLIST。

MERGE 不作为保留关键字强制应用。

MERGE 是完全保留的关键字。在 100 和 90 兼容级别下,都支持 MERGE 语句。

使用 INSERT 语句的 <dml_table_source> 参数会引发语法错误。

您可以捕获嵌套的 INSERT、UPDATE、DELETE 或 MERGE 语句中 OUTPUT 子句的结果,然后将这些结果插入目标表或视图。这通过使用 INSERT 语句的 <dml_table_source> 参数来实现。

除非指定 NOINDEX,否则 DBCC CHECKDB 或 DBCC CHECKTABLE 将对单个表或索引视图及其所有非聚集索引和 XML 索引同时执行物理和逻辑一致性检查。不支持空间索引。

除非指定 NOINDEX,否则 DBCC CHECKDB 或 DBCC CHECKTABLE 将对单个表及其所有非聚集索引同时执行物理和逻辑一致性检查。但是,在默认情况下,仅对 XML 索引、空间索引和索引视图执行物理一致性检查。

如果指定了 WITH EXTENDED_LOGICAL_CHECKS,则将对索引视图、XML 索引和空间索引(如果存在)执行逻辑检查。默认情况下,先执行物理一致性检查,然后执行逻辑一致性检查。如果还指定了 NOINDEX,则仅执行逻辑检查。

如果将 OUTPUT 子句和数据操作语言 (DML) 语句一起使用,并且在语句执行过程中发生运行时错误,则会终止并回滚整个事务。

如果将 OUTPUT 子句和数据操作语言 (DML) 语句一起使用,并且在语句执行过程中发生运行时错误,则行为取决于 SET XACT_ABORT 设置。如果 SET XACT_ABORT 设置为 OFF,则由使用 OUTPUT 子句的 DML 语句所生成的语句中止错误将终止该语句,但批处理的执行仍会继续,并且不会回滚事务。如果 SET XACT_ABORT 设置为 ON,则由使用 OUTPUT 子句的 DML 语句所生成的全部运行时错误都将终止批处理,并回滚事务。

CUBE 和 ROLLUP 不作为保留关键字强制应用。

CUBE 和 ROLLUP 是 GROUP BY 子句中的保留关键字。

对 XML anyType 类型的元素应用严格验证。

对 XML anyType 类型的元素应用宽松验证。有关详细信息,请参阅通配符组成部分和内容验证

数据操作语言语句不能查询或修改特殊属性 xsi:nilxsi:type

这意味着 /e/@xsi:nil 失败,同时 /e/@* 忽略 xsi:nil 和 xsi:type 属性。但是,/e 返回 xsi:nil 和 xsi:type 属性,以保持与 SELECT xmlCol 的一致性,即使 xsi:nil = "false" 也是如此。

特殊属性 xsi:nilxsi:type 作为常规属性存储,不能查询和修改。

例如,执行查询 SELECT x.query('a/b/@*') 会返回包括 xsi: nilxsi: type 在内的所有属性。若要在查询中排除这些类型,请用 @*[namespace-uri(.) != "insert xsi namespace uri" 替换 @*,而不是用 (local-name(.) = "type" 或 local-name(.) ="nil" 来替换。

用于将 XML 常量字符串值转换为 SQL Server datetime 类型的用户定义函数被标记为确定的。

用于将 XML 常量字符串值转换为 SQL Server datetime 类型的用户定义函数被标记为不确定的。

不完全支持 XML 联合和列表类型。

完全支持联合和列表类型,包括以下功能:

  • 列表的联合

  • 联合的联合

  • 原子类型的列表

  • 联合的列表

当视图或内联表值函数中包含 xQuery 方法时,不对该方法所需的 SET 选项进行验证。

当视图或内联表值函数中包含 xQuery 方法时,对该方法所需的 SET 选项进行验证。如果该方法的 SET 选项设置不正确,将引发一个错误。

有关所需选项设置的详细信息,请参阅设置选项(XML 数据类型)

包含行尾字符(回车符和换行符)的 XML 属性值不根据 XML 标准进行规范化。即返回回车符和换行符,而不是单个换行符。

包含行尾字符(回车符和换行符)的 XML 属性值会根据 XML 标准进行规范化。也就是说,外部已分析实体(包括文档实体)中的所有换行符都会在输入时进行规范化,方法是将两字符序列 #xD #xA 和后面没有跟 #xA 的所有 #xD 都转换为单个 #xA 字符。

使用属性来传输包含行尾字符的字符串值的应用程序接收到的这些字符将和提交时有所不同。若要避免规范化过程,请使用 XML 数字字符实体对所有行尾字符进行编码。

ROWGUIDCOL 和 IDENTITY 列属性可能错误地命名为约束。例如,CREATE TABLE T (C1 int CONSTRAINT MyConstraint IDENTITY) 语句可以执行,但约束名不会保留,也无法让用户访问。

ROWGUIDCOL 和 IDENTITY 列属性不能命名为约束。返回错误 156。

使用双向赋值(如 UPDATE T1 SET @v = column_name = <expression>)来更新列会产生意外后果,因为在语句执行过程中,可以在其他子句(如 WHERE 和 ON 子句)中使用变量的实时值,而不是使用语句起始值。这会导致谓词的含义无法预测地逐行变化。

只有在兼容级别设置为 90 时,此行为才适用。

使用双向赋值来更新列会产生预期的结果,因为在语句执行过程中,只会访问列的语句起始值。

在包含顶级 UNION 运算符的语句中,允许使用变量赋值,但会返回意外的结果。例如,在以下语句中,将来自两个表的联合的 EmployeeID 列的值赋给局部变量 @v。按照定义,如果 SELECT 语句返回多个值,则将返回的最后一个值赋给变量。在这种情况下,会正确地将最后一个值赋给变量,但还会返回 SELECT UNION 语句的结果集。

ALTER DATABASE AdventureWorks
SET compatibility_level = 90;
GO
USE AdventureWorks;
GO
DECLARE @v int;
SELECT @v = EmployeeID FROM HumanResources.Employee
UNION ALL
SELECT @v = EmployeeID FROM HumanResources.EmployeeAddress;
SELECT @v;

在包含顶级 UNION 运算符的语句中不允许变量赋值。返回错误 10734。

若要纠正该错误,请重写查询,如下例所示。

DECLARE @v int;
SELECT @v = EmployeeID FROM 
    (SELECT EmployeeID FROM HumanResources.Employee
     UNION ALL
     SELECT EmployeeID FROM HumanResources.EmployeeAddress) AS Test
SELECT @v;

ODBC 函数 {fn CONVERT()} 使用语言的默认日期格式。对于有些语言,默认格式为 YDM,这会导致在将 CONVERT() 与要求使用 YMD 格式的其他函数(如 {fn CURDATE()})结合使用时出现转换错误。

在转换为 ODBC 数据类型 SQL_TIMESTAMP、SQL_DATE、SQL_TIME、SQLDATE、SQL_TYPE_TIME 和 SQL_TYPE_TIMESTAMP 时,ODBC 函数 {fn CONVERT()} 使用样式 121(一种独立于语言的 YMD 格式)。

ODBC 函数 {fn CURDATE()} 仅返回“YYYY-MM-DD”格式的日期。

ODBC 函数 {fn CURDATE()} 同时返回日期和时间,例如“YYYY-MM-DD hh:mm:ss”。

日期时间内部函数(如 DATEPART)不需要字符串输入值,即可成为有效的日期时间文字。例如,SELECT DATEPART (year, '2007/05-30') 可以成功编译。

日期时间内部函数(如 DATEPART)需要字符串输入值,才能成为有效的日期时间文字。在使用无效的日期时间文字时,会返回错误 241。

保留关键字

兼容性设置还确定了数据库引擎所保留的关键字。下表显示了每个兼容级别所引入的保留关键字。

兼容级别设置

保留关键字

100

CUBE、MERGE、ROLLUP

90

EXTERNAL、PIVOT、UNPIVOT、REVERT、TABLESAMPLE

80

COLLATE、FUNCTION、OPENXML

在给定兼容级别,保留关键字包括在该级别或较低级别引入的所有关键字。例如,对于兼容级别为 100 的应用程序,将保留上表列出的所有关键字。在较低的兼容级别中,级别 100 的关键字仍保留有效的对象名,但与这些关键字相对应的级别 100 的语言功能将不可用。

一旦引入,关键字便会保持为保留关键字。例如,在兼容级别 80 中引入的保留关键字 OPENXML 在级别 90 和 100 中也被保留。

如果某一应用程序使用对其保留级别而言是关键字的标识符,则该应用程序将失败。若要解决这一问题,请用方括号 ([]) 或引号 ("") 括起该标识符;例如,若要将使用标识符 EXTERNAL 的应用程序升级为兼容级别 90,可以将该标识符更改为 [EXTERNAL]"EXTERNAL"

有关详细信息,请参阅保留关键字 (Transact-SQL)

权限

需要对数据库具有 ALTER 权限。

示例

A. 更改兼容级别

以下示例将 AdventureWorks 数据库的兼容级别更改为 90,SQL Server 2005。

ALTER DATABASE AdventureWorks
SET COMPATIBILITY_LEVEL = 90;
GO

B. 兼容级别对 ORDER BY 的影响(第 1 种情况)

以下示例阐述了当兼容级别分别为 80 和 100 时 ORDER BY 绑定所存在的差异。此示例在 tempdb 数据库中创建了一个示例表 SampleTable。

USE tempdb;
CREATE TABLE SampleTable(c1 int, c2 int);
GO

当采用 90 或更高兼容级别(默认级别)时,以下 SELECT... ORDER BY 语句将产生错误,因为 AS 子句中的列别名 c1 不明确。

SELECT c1, c2 AS c1
FROM SampleTable
ORDER BY c1;
GO

在将该数据库的兼容级别重置为 80 之后,这一 SELECT... ORDER BY 语句将成功执行。

ALTER DATABASE tempdb
SET COMPATIBILITY_LEVEL = 80;
GO
SELECT c1, c2 AS c1
FROM SampleTable
ORDER BY c1;
GO

以下 SELECT... ORDER BY 语句在两个兼容级别下都可以运行,因为不明确的别名在 AS 子句中指定。

ALTER DATABASE tempdb
SET COMPATIBILITY_LEVEL = 100;
GO
SELECT c1, c2 AS c3
FROM SampleTable
ORDER BY c1;
GO

ALTER DATABASE tempdb
SET COMPATIBILITY_LEVEL = 80;
GO
SELECT c1, c2 AS c3
FROM SampleTable
ORDER BY c1;
GO

C. 兼容级别对 ORDER BY 的影响(第 2 种情况)

当采用 90 或更高兼容级别(默认级别)时,以下 SELECT...ORDER BY 语句会产生错误,因为在 ORDER BY 子句中指定的列别名包含一个表前缀。

SELECT c1 AS x
FROM SampleTable
ORDER BY SampleTable.x;
GO

在将该数据库的兼容级别重置为 80 之后,这一 SELECT...ORDER BY 语句将成功执行。

ALTER DATABASE tempdb
SET COMPATIBILITY_LEVEL = 80;
GO
SELECT c1 AS x
FROM SampleTable
ORDER BY SampleTable.x;
GO

以下 SELECT...ORDER BY 语句在两个兼容级别下都可以运行,因为表前缀已从 ORDER BY 子句中指定的列别名中删除。

ALTER DATABASE tempdb
SET COMPATIBILITY_LEVEL = 100;
GO
SELECT c1 AS x
FROM SampleTable
ORDER BY x;
GO
ALTER DATABASE tempdb
SET COMPATIBILITY_LEVEL = 80;
GO
SELECT c1 AS x
FROM SampleTable
ORDER BY x;
GO

更改历史记录

更新的内容

更正了在触发器内指定时 XACT_ABORT 语句的行为。在触发器内将 XACT_ABORT 设置为 OFF 在 80 兼容性级别中将被忽略,但在 90 和更高的兼容性级别中则允许。以前的文档与此信息正好相反。