所有 3 个选项均区分大小写和重音,并支持 Unicode。
NVARCHAR
是一种数据类型(例如INT
, DATETIME
等)而不是一个选项。它以 UCS-2 / UTF-16(Little Endian)编码存储 Unicode 字符。 UCS-2 和 UTF-16 在 U+0000 到 U+FFFF(十进制值 0 - 65535)范围内是相同的代码点。 UTF-16 处理 U+10000 及以上代码点(称为补充字符),所有这些代码点都定义为 UCS-2 范围中存在的代码点对(称为代理对)。由于两者之间的字节序列相同,唯一的区别在于数据的处理。意思是,内置函数在使用排序规则时不知道如何解释补充字符not end in _SC
,而当使用以结尾的排序规则时,它们确实可以在整个 UTF-16 范围内正常工作_SC
. The _SC
SQL Server 2012 中添加了排序规则,但您仍然可以在以前的版本中存储和检索补充字符;只有内置函数在操作增补字符时无法按预期运行。
更直接:
-
NVARCHAR
作为一种数据类型,本质上不区分大小写或重音(或任何其他敏感性)敏感或不敏感。确切的行为取决于为列设置的排序规则、数据库的默认排序规则或COLLATE
子句,取决于表达式的上下文。
- 虽然这是一个极其常见的误解,但二进制排序规则既不区分大小写也不区分重音。它只是appears简单地看,它们就是这样的。 “敏感”意味着能够检测特定敏感度(大小写、重音、宽度、假名类型以及从 SQL Server 2017 开始:变体选择器)的差异,同时仍然允许其他敏感度和/或底层字节表示形式的差异。更多详细信息和示例请参见:不,二进制排序规则不区分大小写.
排序规则,虽然字面上是关于字符如何排序和相互比较,但在 SQL Server 中还意味着区域设置/LCID(它确定覆盖这些比较的默认处理的文化规则)以及用于VARCHAR
data.
非二进制排序规则被视为“字典”排序/比较,因为它们考虑了排序规则指定的特定区域性的规则(特别是关联的 LCID)。另一方面,二进制排序规则不处理任何特定于区域性的规则,仅根据每个 2 字节序列的数值进行排序和比较。因此,二进制排序规则要快得多,因为它们不需要应用大量规则,但它们也无法知道单个两字节代码点是一个u
带重音符号与 2 个两字节序列不同,它们是u
以及一个单独的重音符号,它将在屏幕上呈现为与单个两字节代码点相同,并且在使用非二进制排序规则时将比较为相等。
和...之间的不同_BIN
and _BIN2
is 分拣精度,而不是性能。年龄较大的_BIN
排序规则进行简单的逐字节排序和比较(在第一个字符之后,它被视为代码点而不是两个字节,因此it排序正确)而较新的_BIN2
排序规则(从 SQL Server 2005 开始)比较每个代码“单元”(补充字符由两个代码单元组成,并且_BIN2
排序规则单独查看每个代码单元,而不是将它们的组合视为代码点)。这两种方法之间的排序顺序存在差异,主要是由于 SQL Server 是存储字节的“Little Endian”(对于单个实体:UTF-16 代码单元,INT
value, BIGINT
值等)以相反的顺序。因此,代码点 U+0206 实际上会排序afterU+0402 使用时_BIN
整理:
SELECT *, CONVERT(VARBINARY(20), tmp.[Thing]) AS [ThingBytes]
FROM (VALUES (1, N'a' + NCHAR(0x0206)), (2, N'a' + NCHAR(0x0402))) tmp ([ID], [Thing])
ORDER BY tmp.[Thing] COLLATE Latin1_General_100_BIN;
/*
ID Thing ThingBytes
2 aЂ 0x61000204
1 aȆ 0x61000602 <-- U+0206, stored as 0x06 then 0x02, should sort first
*/
SELECT *, CONVERT(VARBINARY(20), tmp.[Thing]) AS [ThingBytes]
FROM (VALUES (1, N'a' + NCHAR(0x0206)), (2, N'a' + NCHAR(0x0402))) tmp ([ID], [Thing])
ORDER BY tmp.[Thing] COLLATE Latin1_General_100_BIN2;
/*
ID Thing ThingBytes
1 aȆ 0x61000602
2 aЂ 0x61000204
*/
有关此区别的更多详细信息和示例,请参阅:各种二进制排序规则之间的差异(文化、版本以及 BIN 与 BIN2).
此外,当涉及 Unicode / 时,所有二进制排序规则都以完全相同的方式进行排序和比较。NVARCHAR
数据。代码点是数值,在比较它们时无需考虑语言/文化差异。因此,拥有多个全局“BINARY”排序规则的唯一目的是仍然需要指定要使用的代码页VARCHAR
data.
假设我想用不同的字母存储私有名称,我可以使用哪个选项?
如果您正在使用VARCHAR
字段,那么特定于排序规则(无论二进制或非二进制)将确定哪些字符可用,因为它是 8 位扩展 ASCII,通常具有 256 个不同字符的范围(除非使用双字节字符集,其中它可以处理更多的情况,但这些仍然大部分属于单一文化/字母表)。如果使用NVARCHAR
为了存储数据,因为它是 Unicode,所以它有一个由所有语言的所有字符以及许多其他内容组成的字符集。
所以选择NVARCHAR
解决了能够保存来自不同语言的名称的正确字符的问题。但是,您仍然需要选择特定文化的字典规则,以便以每种特定文化期望的方式进行排序。这是一个问题,因为无法动态设置排序规则。所以选择最常用的一个。二进制排序规则在这里对你没有帮助,事实上会违背你想要做的事情。然而,当您需要区分原本相等的字符时,它们非常方便,例如在本例中:SQL Server过滤CJK标点字符(这里是S.O.)。
我使用过的另一个相关场景_BIN2
排序规则正在检测 URL 中的大小写更改。 URL 的某些部分不区分大小写,例如主机名/域名。但是,在 QueryString 中,传入的值可能是敏感的。如果您在不区分大小写的操作中比较 URL 值,则http://domain.tld/page.ext?var1=val
相当于http://domain.tld/page.ext?var1=VAL
,并且这些值不应被假定为相同。使用区分大小写的排序规则也会通常工作,但我用Latin1_General_100_BIN2
因为它更快(没有语言规则)并且不会忽略ü
to u
+ 结合分音符(呈现为ü
).
我对以下答案有更多关于排序规则的解释(因此不会在此处重复,因为其中大多数都包含几个示例):
- UCS-2 和 SQL Server
- SQL Server默认字符编码
- nvarchar (Unicode) 列的 COLLATIONS 有何意义?
- Unicode 到非 unicode 的转换
- NVARCHAR 存储 SQL Server 上 UCS-2 编码不支持的字符
这些都在 DBA.StackExchange 上:
- 如何去除希伯来语重音符号
- 更改数据库默认排序规则时 Latin1_General_BIN 性能影响
- 在表中存储日语字符
有关使用排序规则、编码、Unicode 等的更多信息,请访问:校对信息