2011-05-12 136 views
16

前一段时间,我问了一个关于SQL Server中层次结构/版本号排序的问题。 ( How Can I Sort A 'Version Number' Column Generically Using a SQL Server Query)。在这里使用varbinary比varchar有什么优势?

其中提交的答案是this link to a TSQL Coding challenge with much the same puzzle

在SQL2000解决方案中,作者演示了两个变体,一个使用并返回varchar和另一个varbinary。作者解释说他没有解释为什么会这样做。

所以,我的问题是真的,差异的主要差异/优势(如果有的话)?即为什么使用varbinary而不是varchar?

我没有发布代码,因为它在上面的文章中最优雅的总结。

+1

我相信预期varbinary数据通常会比原始字符串的每个部分的varchar one(10或11,我认为)消耗更少的字节(5),因此,对于非常大量的组件,或比较发生,它应该更有效率。但是我也猜测,对于大多数用户来说效率并没有太大的实际差异。 – 2011-05-12 14:20:53

+0

@Damien:为此欢呼。我很乐意接受并接受这个答案!如果你选择这样做,将会这样做。 – 2011-05-12 14:34:41

+1

我会假设这是因为结果将用于排序,二进制可能更有效,因为它不必担心排序问题。但不确定这是否是真的,一般情况下也是如此,即使真的如此,也不知道如何比较使用二进制“collat​​e”子句对字符串进行排序。 – 2011-05-12 15:31:31

回答

12

我相信期望是varbinary数据通常会比原始字符串的每个部分的varchar(10或11,我认为)消耗更少的字节(5),因此,对于非常大量的组件或比较发生时,应该更有效率。

但是我建议如果你正在寻找使用任何一种解决方案,你实现了两者(他们很短),并尝试对你的真实数据(和查询模式)进行分析,看看是否有实际的差异(我不这么认为)。

(Crafty Steal):正如Martin指出的那样,二进制比较将更有效率,因为它不涉及所有处理排序规则的代码。 :-)

0

如果我们使用varchar存储字符串并对不同的varchar列使用不同的排序规则,那么我们可能会在Sql查询中得到错误“排序规则混合无效”。 (例如,如果我们想要比较两个不兼容排序规则的字符串,或尝试将不同排序规则的数据选择到一个组合列中)。

但是,如果我们在查询中指定“COLLATE”,那么这可以被修复。例如:

WHERE 'A' COLLATE latin1_general_ci = 'A' COLLATE latin1_general_cs . 

但是,这会破坏您可能拥有的任何INDEX。

为了防止“归类错误混合”错误,我们可以使用varbinary。

如果varchar列使用多字节归类,则varbinary会比varchar使用更少的空间。 (二进制字符串没有字符集和归类,二进制字符串只是一个字节值序列)。但是,如果您选择单字节字符集(对于ex,latin1)而不是多字节字符集(对于ex,utf8或ucs2),则varbinary和varchar的空间要求是相同的。

如果没有有效性检查,则VARBINARY优于VARCHAR。 例如,如果默认字符集是UTF8,那么这是非法的:

CREATE TABLE t9 (s1 VARCHAR(5)); 
INSERT INTO t9 VALUES (0xF4808283); 

但是,由于字符集没有关系,这是合法的:

CREATE TABLE t10 (s1 VARBINARY(5)); 
INSERT INTO t10 VALUES (0xF4808283); 

所以,VARCHAR比较使用的字符“排序”和VARBINARY比较字节。大多数排序规则是“不区分大小写”,所以大写和小写被认为是相等的。因为,varbinary不使用任何排序规则,所以在varbinary的情况下,搜索操作总是区分大小写。