Ger*_*hef 5 sql-server unicode collation
所有 3 个选项都区分大小写和重音,并支持 Unicode。根据文档:
NVarchar 根据“相关语言或字母表的字典”对数据进行排序和比较 (?)
Bin 根据“位模式”(?)对数据进行排序和比较
Bin2根据“Unicode数据的Unicode代码点”对数据进行排序和比较(?)
把复杂的事情简单化,我能不能说Bin是NVarchar的改进,Bin2是Bin的改进;除非我仅限于向后兼容,否则总是建议使用 Bin2 或至少使用 Bin 以享受更好的性能?
================================================== ======================== 我会再次尝试解释我自己。
看一看:
If Object_ID('words2','U') Is Not Null Drop Table words2;
Create Table words2(word1 NVarchar(20),
word2 NVarchar(20) Collate Cyrillic_General_BIN,
word3 NVarchar(20) Collate Cyrillic_General_BIN2);
Insert
Into words2
Values (N'???????',N'???????',N'???????'),
(N'?????????',N'?????????',N'?????????'),
(N'?????',N'?????',N'?????'),
(N'???',N'???',N'???');
Select * From words2;
Run Code Online (Sandbox Code Playgroud)
所有 3 个选项都支持各种字母表,无论是什么排序规则。
问题是 - 3 个选项之间的实际区别是什么?假设我想以不同的字母存储私人姓名,我可以使用哪个选项?我想我将不得不找到特定的名称(选择...从...在哪里...),订单名称(选择...从...订购...)。
所有 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 范围内的代码点对(称为代理对)。由于两者之间的字节序列相同,唯一的区别在于数据的处理。意思是,内置函数在使用不以 .结尾的排序规则时不知道如何解释补充字符_SC,而在使用以_SC. 这_SCSQL Server 2012 中添加了排序规则,但您仍然可以在以前的版本中存储和检索补充字符;只有内置函数在对补充字符进行操作时不会按预期运行。
更直接:
NVARCHAR,作为一种数据类型,本质上不是大小写或重音(或任何其他敏感性)敏感或不敏感的。确切的行为取决于列的排序规则集、数据库的默认排序规则或COLLATE子句,具体取决于表达式的上下文。排序规则虽然字面上是关于字符如何排序和相互比较,但在 SQL Server 中也暗示了区域设置/LCID(它决定了覆盖这些比较的默认处理的文化规则)和用于VARCHAR数据的代码页。
非二进制排序规则被视为“字典”排序/比较,因为它们考虑了排序规则指定的特定区域性的规则(特别是关联的 LCID)。另一方面,二进制排序规则不处理任何特定于文化的规则,仅根据每个 2 字节序列的数值进行排序和比较。出于这个原因,二进制排序要快得多,因为它们不需要应用大量规则,但它们也无法知道u带有重音符号的单个两字节代码点与 2 和 2 不同-byte 序列是一个u和一个单独的重音,将在屏幕上呈现与单个两字节代码点相同,并且在使用非二进制排序规则时将比较为相等。
_BIN和之间的区别_BIN2是排序精度,而不是性能。年长的_BIN排序规则做一个简单的逐字节的排序和比较(第一个字符,这被看作是一个代码点,而不是两个字节之后,因此它正确排序),而较新的_BIN2排序规则(2005年在SQL Server开始)比较每代码“单元”(补充字符由两个代码单元组成,_BIN2排序规则单独查看每个代码单元,而不是将它们的组合视为代码点)。这两种方法之间的排序顺序存在差异,主要是因为 SQL Server 是存储字节的“Little Endian”(对于单个实体:UTF-16 代码单元、INT值、BIGINT值等)以相反的顺序。因此,当使用排序规则时,代码点 U+0206 实际上会在U+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
*/
Run Code Online (Sandbox Code Playgroud)
有关此区别的更多详细信息和示例,请参阅:各种二进制排序规则之间的差异(文化、版本和 BIN 与 BIN2)。
此外,当涉及到 Unicode /NVARCHAR数据时,所有二进制排序规则都以完全相同的方式进行排序和比较。代码点是数值,在比较它们时没有需要考虑的语言/文化差异。因此,拥有多个全局“BINARY”排序规则的唯一目的是仍然需要指定用于VARCHAR数据的代码页。
假设我想以不同的字母存储私人姓名,我可以使用哪个选项?
如果您使用的是VARCHAR字段,那么特定于排序规则(无论是二进制还是非二进制)将确定哪些字符可用,因为它是 8 位扩展 ASCII,通常具有 256 个不同字符的范围(除非使用双字节字符)设置,在这种情况下它可以处理更多,但那些仍然主要是单一文化/字母表)。如果NVARCHAR用于存储数据,由于那是 Unicode,它有一个单一的字符集,包含来自所有语言的所有字符,以及许多其他内容。
因此,选择NVARCHAR可以解决能够保存来自各种语言的名称的正确字符的问题。但是,您仍然需要选择特定的文化字典规则,以便以每种特定文化期望的方式进行排序。这是一个问题,因为无法动态设置排序规则。所以选择使用最多的那个。二进制排序在这里对您没有帮助,实际上会与您尝试做的事情背道而驰。但是,当您需要区分原本等同的字符时,它们非常方便,例如在这种情况下:SQL 服务器过滤 CJK 标点字符(这里是 SO)。
我使用_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+ 组合分音符(呈现为u?)的变化。
我在以下答案中有更多关于排序规则的解释(因此不会在此处重复,因为它们中的大多数包含几个示例):
这些在 DBA.StackExchange 上:
有关使用排序规则、编码、Unicode 等的更多信息,请访问:排序规则信息
nvarchar是一种数据类型,“BIN”或“BIN2”排序规则就是排序规则序列。他们是两个不同的东西。
您使用nvarchar列来存储 unicode 字符数据:
\n\nnchar 和 nvarchar (Transact-SQL)
\n字符串数据类型,可以是固定长度、nchar 或可变长度、nvarchar、Unicode 数据,并使用 UNICODE UCS-2 字符集。
\n
https://msdn.microsoft.com/en-GB/library/ms186939(v=sql.105).aspx
\n列nvarchar将具有关联的排序规则序列,用于定义字符如何排序和比较。也可以针对整个数据库进行设置。
\n\n整理 (Transact-SQL)
\n是一个子句,可应用于数据库定义或列定义以定义排序规则,或应用于字符串表达式以应用排序规则转换。
\n
https://msdn.microsoft.com/en-us/library/ms184391(v=sql.105).aspx
\n因此,在 SQL Server 中处理字符数据时,您始终根据大小写敏感、重音敏感等需求使用字符数据类型(nvarchar、varchar、nchar 或 char)以及适当的排序规则。
\n例如,在我的工作中,我通常使用“Latin1_General_CI_AI”排序规则。这适用于拉丁字符集,并为查询提供不区分大小写和不区分重音的匹配。\n这意味着以下字符串都被认为是相等的:
\n这对于可能存在包含重音字符的单词(如上所述)的系统来说是理想的选择,但您无法确定用户在搜索某些内容时会输入重音符号。
\n如果您只想不区分大小写,那么您可以使用“CI_AS”(区分重音)排序规则。
\n“_BIN”排序规则用于二进制比较,将每个不同的字符视为不同的,并且不会用于一般文本比较。
\n编辑更新的问题:
\n如果您始终使用nvarchar(而不是varchar)列,那么您始终支持所有 unicode 代码点,无论使用什么排序规则。
您的示例查询没有实际差异,因为它只是简单的插入和选择。另请记住,您的第一个“word1”列将使用数据库或服务器的默认排序规则 - 始终有一个正在使用的排序规则!
\n如果您对 nvarchar 列使用条件或按它们排序,则会出现差异。这就是排序规则的用途 - 它们定义哪些字符应被视为等效字符以进行比较和排序。
\n我不能说任何关于西里尔字母的事情,但对于拉丁字符,使用“Latin1_General_CI_AI”排序规则,然后是诸如A a \xc3\xa1 \xc3\xa2等的字符都是等效的 - 大小写和重音被忽略。
想象一下,如果您将字符串Aa\xc3\xa1\xc3\xa2存储在“word1”列中,那么查询SELECT * FROM words2 WHERE word1 = \'aaaa\'将返回您的行。
如果您使用“_BIN”排序规则,则所有这些字符都被视为不同的,并且上面的查询不会返回行。我想不出在处理文本数据时您会想要使用“_BIN”排序规则的情况。编辑2:其实我可以-存储密码散列将是使用二进制排序规则的好地方,以便比较准确。这就是全部了。
\n我希望这能让事情变得更清楚。
\n| 归档时间: |
|
| 查看次数: |
3939 次 |
| 最近记录: |