排序规则的优先顺序
排序规则的优先顺序(也称为排序规则类型强制规则)是赋予一组规则的术语,而这组规则决定:
- 取值为字符串的表达式的最终结果的排序规则。
- 区分排序规则的运算符所使用的排序规则,这些运算符使用字符串输入但不返回字符串,如 like 和 in。
排序规则的优先顺序规则只适用于字符串数据类型:char、varchar、text、nchar、nvarchar 和 ntext。具有其它数据类型的对象不参加排序规则的评估。
所有对象的排序规则可归为四类中的一种。每类的名称叫做排序规则标志。
| 排序规则标志 | 对象类型 |
| 强制默认 | 任何 transact-sql 字符串变量、参数、字面值、目录内置函数的输出、或不使用字符串输入但产生字符串输出的内置函数。
如果在用户定义函数、存储过程或触发器中声明某个对象,则将该对象指派为在其中创建函数、存储过程或触发器的数据库的默认排序规则。如果在批处理中声明该对象,则将其指派为连接所使用的当前数据库的默认排序规则。 |
| 隐性 x | 列引用。从为表或视图中的列定义的排序规则得到表达式(由 x 表示)的排序规则。
即使 create table 或 create view 语句中的 collate 子句给列显式指派了排序规则,该列引用仍归为隐性。 |
| 显式 x | 使用表达式中的 collate 子句显式投影到特定排序规则(由 x 表示)的表达式。 |
| 无排序规则 | 表示表达式的值是两个字符串之间操作的结果,而这两个字符串具有隐性排序规则标志的冲突排序规则。表达式的结果被定义为不具有排序规则。 |
只引用一个字符串对象的简单表达式的排序规则标志是被引用对象的排序规则标志。
如果复杂表达式所引用的两个操作数表达式的排序规则标志相同,则该复杂表达式的排序规则标志为数表达式的排序规则标志。
如果复杂表达式所引用的两个操作数表达式的排序规则不同,则该复杂表达式最终结果的排序规则标志基于下列规则:
- 显式优先于隐性。隐性优先于强制默认。换言之,
显式 > 隐性 > 强制默认
- 组合两个已指派给不同排序规则的显式表达式将生成错误。
显式 x + 显式 y = 错误
- 组合两个具有不同排序规则的隐性表达式将产生无排序规则。
隐性 x + 隐性 y = 无排序规则
- 将无排序规则的表达式与任何标志的表达式组合,除了显式排序规则外(参见下一项),都产生无排序规则标志的结果。
无排序规则 + 任何标志 = 无排序规则
- 将无排序规则的表达式与显式排序规则的表达式组合将产生具有显式标志的表达式。
无排序规则 + 显式 x = 显式
下面的示例说明上述规则。
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 446, level 16, state 9, server ctsserv, line 1
cannot resolve collation conflict for 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)
下面查询中的 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)
下表汇总了上述规则。
| 操作数强制标志 | 显式 x |
隐性 x |
强制默认 | 无排序规则 |
| 显式 y | 生成错误 | 结果为显式 y | 结果为显式 y | 结果为显式 y |
| 隐性 y | 结果为显式 x | 结果为无排序规则 | 结果为隐性 y | 结果为无排序规则 |
| 强制默认 | 结果为显式 x | 结果为隐性 x | 结果为强制默认 | 结果为无排序规则 |
| 无排序规则 | 结果为显式 x | 结果为无排序规则 | 结果为无排序规则 | 结果为无排序规则 |