22

前段时间,我问了一个关于 SQL Server 中层次结构/版本号排序的问题。( 我如何一般使用 SQL Server 查询对“版本号”列进行排序)。

在提交的答案中,有一个 TSQL 编码挑战的链接,其中有很多相同的谜题

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

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

我已经省略了发布代码,因为它在上面的文章中得到了最优雅的总结。

4

2 回答 2

18

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

但我建议,如果您正在寻找使用任一解决方案,您都实现(它们很短),并尝试对您的真实数据(和查询模式)进行一些分析,看看是否存在实际差异(我没想到会这样)。

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

于 2011-05-12T15:58:02.683 回答
5

如果我们对不同的 varchar 列使用不同的排序规则来存储字符串,并在 sql 查询中使用多个这样的列,那么 sql 查询可能会抛出错误“Invalid mix of collat​​ions”。(例如,如果我们想比较两个排序规则不兼容的字符串,或者尝试将不同排序规则的数据选择到一个组合列中)。

但是,如果我们在查询中指定“COLLATE”,就可以解决这个问题。例如:

 WHERE 'A' COLLATE latin1_general_ci = 'A' COLLATE latin1_general_ci 

但是,这会击败您可能拥有的任何 INDEX。

为了防止“无效的排序规则组合”错误,我们可以使用 varbinary。

如果多字节排序规则用于 varchar 列,则 varbinary 使用的空间比 varchar 少。(二进制字符串没有字符集和排序规则。二进制字符串只是一个字节值序列)。

*** 顺便说一句,字符集是一组符号和编码。排序规则是一组用于比较字符集中字符的规则https://dev.mysql.com/doc/refman/5.7/en/charset-general.html

但是,如果您选择单字节字符集(例如,latin1)而不是多字节字符集(例如,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 的情况下搜索操作始终区分大小写。

于 2018-01-27T14:12:19.593 回答