NVarchar,Bin整理,Bin2整理有什么区别?

时间:2016-02-23 16:51:29

标签: sql-server unicode collation

所有3个选项都是大小写和重音敏感的,并且支持Unicode。 根据文件:

  1. NVarchar根据相关语言或字母表的"字典对数据进行排序和比较" (?)

  2. Bin根据"位模式排序和比较数据" (?)

  3. Bin2根据" Unicode数据的Unicode代码点对数据进行排序和比较" (?)

  4. 为了使复杂的事情变得简单,我可以说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;
    

    所有3个选项都支持各种字母表,无论是哪种排序规则。

    问题是 - 3个选项之间有什么实际区别?假设我想将私人名称存储在不同的字母表中,我可以使用哪个选项?我想我必须找到具体的名字(Select .. From .. Where ..),订单名称(Select .. From .. Order By ..)。

2 个答案:

答案 0 :(得分:3)

NVARCHAR是一种数据类型(如INTDATETIME等),而非选项。它以UCS-2 / UTF-16(Little Endian)编码存储Unicode字符。 UCS-2和UTF-16是U + 0000到U + FFFF(十进制值0 - 65535)范围的相同代码点。 UTF-16处理代码点U + 10000及以上(称为补充字符),所有代码点都定义为UCS-2范围内存在的代码点对(称为代理对)。由于字节序列在两者之间是相同的,唯一的区别在于数据的处理。意思是,当使用 not 结束_SC的排序规则时,内置函数不知道如何解释补充字符,而在使用排序规则时它们在完整的UTF-16范围内正常工作以_SC结尾。 SQL Server 2012中添加了_SC排序规则,但您仍可以在先前版本中存储和检索补充字符;只有内置函数在补充字符上运行时才能按预期运行。

Collat​​ions,虽然字面上是关于角色如何排序和相互比较,但在SQL Server中也暗示了Locale / LCID(它确定了覆盖这些比较的默认处理的文化规则)和用于{{的代码页。 1}}数据。

非二进制排序规则被认为是"字典"排序/比较,因为它们考虑了排序规则(特别是相关的LCID)指定的特定文化的规则。另一方面,二进制排序规则不处理任何特定于文化的规则,只根据每个2字节序列的数值进行排序和比较。出于这个原因,二进制排序规则要快得多,因为他们不需要应用大量规则,但他们也无法知道具有重音的VARCHAR单个双字节代码点与2个双字节序列不同,它们是u,并且在屏幕上呈现的单独重音与单个双字节代码点相同,并且在使用非二进制时将比较为相等排序规则。

u_BIN之间的差异是准确性,而不是表现。原始_BIN2排序规则进行了简单的逐字节排序和比较,而较新的(从SQL Server 2008开始可能?)_BIN排序规则比较每个代码点。对于U + 0000到U + FFFF范围(也是构成UCS-2字符集的前65536个值),这两种方法之间应该没有区别。但是,对于从U + 10000开始的代码点,由于它们由一对双字节序列组成,因此不一定与那对双字节序列自然排序的顺序相同。含义,Code Point U + 10001应该排在U + 10002之前。但是,如果您只查看构成这两个代码点的字节,那么您最终可能会首先对U + 10002进行排序。

此外,所有二进制排序规则在Unicode / NVARCHAR数据方面的排序和比较方式完全相同。代码点是数值,在比较时不需要考虑语言/文化差异。因此,唯一的目的是拥有不止一个全球性的“BINARY”#34;归类是需要仍然指定用于_BIN2数据的代码页。

  

假设我想将私人名称存储在不同的字母表中,我可以使用哪个选项?

如果您使用的是VARCHAR字段,那么特定于排序规则(无论是二进制还是非二进制)将确定哪些字符可用,因为这是8位扩展ASCII,通常具有256个不同字符的范围(除非使用双字节字符集,在这种情况下它可以处理更多,但那些仍然主要是单个文化/字母表)。如果使用VARCHAR来存储数据,因为它是Unicode,它有一个由所有语言的所有字符组成的单个字符集,以及许多其他东西。

因此,选择NVARCHAR可以解决能够保存来自各种语言的名称的正确字符的问题。但是,您仍然需要选择特定的文化字典规则,以便按照每种特定文化所期望的方式进行排序。这是一个问题,因为无法动态设置排序规则。所以选择最常用的那个。二进制排序规则对你没有帮助,事实上它会违背你想做的事情。但是,当你需要区分其他等同的字符时,它们非常方便,例如在这种情况下:SQL server filtering CJK punctuation characters(这里是S.O。)。

我使用NVARCHAR排序规则的另一个相关方案是检测网址中的大小写更改。 URL的某些部分不区分大小写,例如主机名/域名。但是,在QueryString中,传入的值可能是敏感的。如果您在不区分大小写的操作中比较URL值,则_BIN2将等同于http://domain.tld/page.ext?var1=val,并且不应假设这些值相同。使用区分大小写的排序规则也会通常工作,但我使用http://domain.tld/page.ext?var1=VAL因为它更快(没有语言规则)并且不会忽略Latin1_General_100_BIN2的更改到ü +组合分音符(渲染为u)。

我对Collat​​ions有更多解释,分布在以下答案中(因此大部分都包含几个例子,因此不会复制):

这些都在DBA.StackExchange上:

答案 1 :(得分:2)

nvarchar是一种数据类型,“BIN”或“BIN2”排序规则就是 - 整理顺序。它们是两回事。

使用nvarchar列存储unicode字符数据:

  

nchar和nvarchar(Transact-SQL)

     

字符串数据类型,它们是固定长度,nchar或可变长度,nvarchar,Unicode数据,并使用UNICODE UCS-2字符集。

https://msdn.microsoft.com/en-GB/library/ms186939(v=sql.105).aspx

nvarchar列将具有关联的归类序列,用于定义字符的排序和比较方式。这也可以为整个数据库设置。

  

COLLATE(Transact-SQL)

     

是一个可以应用于数据库定义或列定义以定义排序规则的子句,还是应用于字符串表达式以应用排序规则转换。

https://msdn.microsoft.com/en-us/library/ms184391(v=sql.105).aspx

因此,在SQL服务器中处理字符数据时,根据您的区分大小写,重音敏感等需求,始终使用字符数据类型(nvarchar,varchar,nchar或char)以及适当的排序规则。

例如,在我的工作中,我通常使用“Latin1_General_CI_AI”排序规则。这适用于拉丁字符集,并为查询提供不区分大小写和不区分重音的匹配。 这意味着以下字符串都被认为是相同的:

  • Höller,höller,Holler,holler

这对于可能包含带重音字符的单词的系统(如上所述)非常理想,但您无法确定用户在搜索内容时是否会输入重音符号。

如果您只想要不区分大小写,那么您将使用“CI_AS”(重音敏感)排序规则。

“_ BIN”排序规则用于二进制比较,将每个不同的字符视为不同,并且不会用于一般文本比较。

修改已更新的问题:

如果您总是使用nvarchar(而不是varchar)列,那么无论使用何种排序规则,您始终都支持所有unicode代码点。

您的示例查询没有实际差异,因为它只是一个简单的插入和选择。另外请记住,您的第一个“word1”列将使用数据库或服务器的默认排序规则 - 总是使用排序规则!

如果您对nvarchar列使用条件,或者按它们排序,则会出现差异。这是排序规则的用途 - 它们定义哪些字符应被视为等效的比较和排序。

我不能说西里尔语,但对于拉丁字符,使用“Latin1_General_CI_AI”排序规则,然后是A a á {{1}等字符等等都是等价的 - 案例和重音都被忽略了。

想象一下,如果您的“word1”列中存储了字符â,那么查询Aaáâ将返回您的行。

如果使用“_BIN”排序规则,则所有这些字符都被视为不同,并且上面的查询不会返回一行。在处理文本数据时,我想不出你想要使用“_BIN”排序规则的情况。 编辑2:实际上我可以 - 存储密码哈希值是使用二进制排序规则的好地方,因此比较是准确的。这就是全部。

我希望这更清楚。