排序规则优先级

适用于: SQL Server Azure SQL 数据库 Azure SQL 托管实例 Azure Synapse Analytics 分析平台系统 (PDW) Microsoft Fabric 中的 SQL 分析端点 Microsoft Fabric 中的仓库

排序规则优先级(也称为排序规则)确定以下两个结果:

  • 计算结果为字符串的表达式的最终结果排序规则。

  • 区分排序规则的运算符所使用的排序规则,这些运算符使用字符串输入但不返回字符串,如 LIKE 和 IN。

排序规则的优先顺序规则只应用于下列字符串数据类型:char、varchar、text、nchar、nvarchar 和 ntext。 具有其他数据类型的对象不参与排序规则计算。

排序规则标签

下表列出并说明了四个用于标识所有对象的排序规则的类别。 每个类别的名称叫做排序规则标签。

排序规则标签 对象类型
Coercible-default 任何 Transact-SQL 字符串变量、参数、文字、目录内置函数的输出或不使用字符串输入但生成字符串输出的内置函数。

如果在用户定义函数、存储过程或触发器中声明对象,则为该对象分配创建函数、存储过程或触发器所采用的数据库默认排序规则。 如果在批处理中声明对象,则为该对象分配用于连接的当前数据库的默认排序规则。
Implicit X 列引用。 从为表或视图中的列定义的排序规则得到表达式 (X) 的排序规则。

即使使用COLLATECREATE VIEW语句中的CREATE TABLE子句显式为列分配排序规则,列引用也分类为隐式引用。
Explicit X 使用表达式中的 COLLATE 子句显式转换为特定排序规则 (X) 的表达式。
No-collation 指示表达式的值是两个字符串之间的运算结果,而这两个字符串具有隐式排序规则标签的冲突排序规则。 表达式的结果被定义为不具有排序规则。

排序规则

只引用一个字符串对象的简单表达式的排序规则标签是被引用对象的排序规则标签。

如果复杂表达式被引用两个操作数表达式的排序规则标签相同,则该复杂表达式的排序规则标签为操作数表达式的排序规则标签。

如果复杂表达式被引用两个操作数表达式的排序规则不同,则该复杂表达式最终结果的排序规则标签基于下列规则:

  • 显式优先于隐式。 隐式优先于强制默认:

    显式 > 隐式 > 强制默认

  • 组合两个已被分配有不同排序规则的显式表达式将生成错误:

    显式 X + 显式 Y = 错误

  • 组合两个具有不同排序规则的隐式表达式将生成无排序规则的结果:

    隐式 X + 隐式 Y = 无排序规则

  • 将无排序规则的表达式与除显式排序规则(参阅下一个规则)之外任何标签表达式组合都将生成无排序规则标签的结果:

    无排序规则 + 任何内容 = 无排序规则

  • 将无排序规则的表达式与具有显式排序规则的表达式组合将生成具有显式标签的表达式:

    无排序规则 + 显式 X = 显式

下表概述了这些规则。

操作数强制标签 显式 X 隐式 X 强制默认 无排序规则
Explicit Y 生成错误 结果为显式 Y 结果为显式 Y 结果为显式 Y
Implicit Y 结果为显式 X 结果为无排序规则 结果为隐式 Y 结果为无排序规则
Coercible-default 结果为显式 X 结果为隐式 X 结果为强制默认 结果为无排序规则
No-collation 结果为显式 X 结果为无排序规则 结果为无排序规则 结果为无排序规则

下列附加规则也适用于排序规则优先顺序:

  • 在已经是显式表达式的表达式上不能有多个 COLLATE 子句。 例如,下面的 WHERE 子句无效,因为已经为显式表达式指定了 COLLATE 子句:

    WHERE ColumnA = ( 'abc' COLLATE French_CI_AS) COLLATE French_CS_AS

  • 不允许进行 text 数据类型的代码页转换。 如果排序规则的代码页不同,则不能将 text 表达式从一种排序规则转换为另一种排序规则。 如果右边文本操作数的排序规则代码页与左边文本操作数的排序规则代码页不同,则不能为赋值运算符赋值。

在数据类型转换之后确定排序规则优先顺序。 生成结果排序规则的操作数可以与提供最终结果数据类型的操作数不同。 例如,请看下面的批处理:

CREATE TABLE TestTab  
   (PrimaryKey int PRIMARY KEY,  
    CharCol char(10) COLLATE French_CI_AS  
   )  
  
SELECT *  
FROM TestTab  
WHERE CharCol LIKE N'abc'  

注意

Fabric Warehouse 不支持 nvarchar 数据类型,但本文中的大多数示例都适用于使用 UTF-8 和 nvarchar 的 varchar,因此,除非另有说明,否则仍适用于 Fabric Warehouse。

简单表达式 N'abc' 的 Unicode 数据类型有更高的数据类型优先级。 因此,所生成的表达式将 Unicode 数据类型分配给 N'abc'。 但是,表达式 CharCol 具有隐式排序规则标签,而 N'abc' 具有级别更低的强制标签,即强制默认。 因此,所使用的排序规则是 French_CI_ASCharCol 排序规则。

排序规则示例

以下示例显示排序规则如何工作。 若要运行该示例,请创建以下测试表。

USE tempdb;  
GO  
  
CREATE TABLE TestTab (  
   id int,   
   GreekCol nvarchar(10) collate greek_ci_as,   
   LatinCol nvarchar(10) collate latin1_general_cs_as  
   )  
INSERT TestTab VALUES (1, N'A', N'a');  
GO  

排序规则冲突和错误

下面查询中的谓词具有排序规则冲突,因此会产生错误。

SELECT *   
FROM TestTab   
WHERE GreekCol = LatinCol;  

结果集如下。

Msg 448, Level 16, State 9, Line 2  
Cannot resolve collation conflict between 'Latin1_General_CS_AS' and 'Greek_CI_AS' in equal to operation.  

显式标签与隐式标签

由于右表达式有显式标签,因此采用排序规则 greek_ci_as 计算以下查询中的谓词。 它的优先级高于左表达式的隐式标签。

SELECT *   
FROM TestTab   
WHERE GreekCol = LatinCol COLLATE greek_ci_as;  

结果集如下。

id          GreekCol             LatinCol  
----------- -------------------- --------------------  
          1 A                    a  
  
(1 row affected)  

无排序规则标签

注意

由于 UTF-8 排序规则中 nvarchar 和 varchar 的行为之间的差异,此示例不适用于 Fabric Warehouse。

下列查询中的 CASE 表达式具有无排序规则标签,所以它们不能出现在选择列表中,也不能由区分排序规则的运算符进行运算。 不过,这些表达式可由不区分排序规则的运算符进行运算。

SELECT (CASE WHEN id > 10 THEN GreekCol ELSE LatinCol END)   
FROM TestTab;  

结果集如下。

Msg 451, Level 16, State 1, Line 1  
Cannot resolve collation conflict for column 1 in SELECT statement.  
SELECT PATINDEX((CASE WHEN id > 10 THEN GreekCol ELSE LatinCol END), 'a')  
FROM TestTab;  

结果集如下。

Msg 446, Level 16, State 9, Server LEIH2, Line 1  
Cannot resolve collation conflict for patindex operation.  
SELECT (CASE WHEN id > 10 THEN GreekCol ELSE LatinCol END) COLLATE Latin1_General_CI_AS   
FROM TestTab;  

结果集如下。

--------------------  
a  
  
(1 row affected)  

排序规则敏感和排序规则不区分

运算符和函数可以区分排序规则,也可以不区分排序规则。

  • 区分排序规则:这意味着指定无排序规则操作数是编译时错误。 表达式结果不能无排序规则。
  • 排序规则不区分:这意味着操作数和结果可以是无排序规则。

运算符和排序规则

比较运算符以及排序规则敏感,以及 MAXMINBETWEENLIKEIN 运算符。 运算符所使用的字符串被赋以具有较高优先顺序的操作数的排序规则标签。 该 UNION 语句也区分排序规则,并且所有字符串操作数和最终结果都分配有最高优先级的操作数的排序规则。 操作数和结果的 UNION 排序规则优先级按列计算。

赋值运算符不区分排序规则,右边的表达式转换到左边的排序规则上。

字符串串联运算符区分排序规则,两个字符串操作数和结果被赋以排序规则优先级最高的操作数的排序规则标签。 UNION ALLCASE语句不区分排序规则,所有字符串操作数和最终结果都分配具有最高优先级的操作数的排序规则标签。 操作数和结果的 UNION ALL 排序规则优先级按列计算。

函数和排序规则

COLLATE CONVERTCAST函数对 charvarchar文本数据类型区分排序规则。 如果输入和函数的CASTCONVERT输入和输出是字符串,则输出字符串具有输入字符串的排序规则标签。 如果输入不是字符串,则输出字符串为 Coercible-default,并为连接分配当前数据库的排序规则,或包含用户定义函数、存储过程或触发器 CAST 的数据库(在其中引用或 CONVERT 引用该数据库)。

对于返回字符串但不采用字符串输入的内置函数,结果字符串为 Coercible-default。 为结果字符串分配当前数据库的排序规则或包含用户定义函数、存储过程或在其中引用函数的触发器的数据库的排序规则。

下列函数区分排序规则,并且它们的输出字符串具有输入字符串的排序规则标签:

CHARINDEX

REPLACE

DIFFERENCE

REVERSE

ISNUMERIC

RIGHT

LEFT

SOUNDEX

LEN

STUFF

LOWER

SUBSTRING

PATINDEX

UPPER