在我的“现实”生活中,我将第一次使用二进制数据类型。 我们需要存储某种条形码。
我的高级团队成员告诉我应该使用
varbinary
,因为这是文档中的建议(我们使用Vertica)。
我说好吧,但我的好奇心告诉我“为什么?”
我认为
varbinary
或 binary
类型会在选择后以不可读的文本打印在屏幕上。但这并没有发生。
所以我在 Vertica 和 SQLite 中进行了测试,他们给了我正确的答案。
我创建一个表并插入数据。
create table TEST_VARBINARY_2
(
id int,
va_r binary(5)
);
insert into TEST_VARBINARY_2 (id, va_r)
values (1, '11111')
这就是答案。
显然数据库可以在
varbinary
中存储字符串。
所以我的问题是:为什么我们使用 char/varchar
而不是 varbinary/binary
?
Varbinary/binary
类型可以比 varchar/char
更有效地存储数据 - 那么为什么我们需要 varchar/char
?
在讨论这个问题时,您能给我示例或文档链接吗?
UDP 我相信在评论部分我找到了答案。
基本上,因为字节与字符不同。
BINARY
/VARBINARY
存储字节字符串。但这些字节可能对应于可打印的 ASCII 字符
https://docs.vertica.com/24.1.x/en/sql-reference/data-types/binary-data-types-binary-and-varbinary/ 说:
与输入格式一样,输出格式是八进制代码和可打印 ASCII 字符的混合。可打印 ASCII 字符范围(范围
)中的字节由相应的 ASCII 字符表示,但反斜杠 ([0x20, 0x7e]
) 除外,它被转义为'\'
。所有其他字节值均由其相应的八进制值表示。例如,字节'\\'
,在 ASCII 中为{97,92,98,99}
,转换为文本为{a,\,b,c}
。'a\\bc'
这就是你的字符串
'1111'
正常打印的原因。这些是可打印的 ASCII 字符。它们实际上是字节值 49,但当输出到文本显示器时,它们是可打印字符。
这些二进制字符串类型仅存储字节。如果您想要存储使用除 ASCII 之外的其他编码的字符,或者使用排序规则来指导排序和字符比较,则必须使用
CHAR
/VARCHAR
以及可能的区域设置。
您说过您正在使用 Vertica。 https://docs.vertica.com/24.1.x/en/admin/about-locale/locale-and-utf-8-support/ 说:
Vertica 数据库服务器期望接收 UTF-8 格式的所有数据,并且 Vertica 输出 UTF-8 格式的所有数据。
以下字符串函数将
参数视为 UTF-8 字符串(当未指定VARCHAR
时),无论区域设置如何。USING OCTETS
(后面是字符串函数列表)
由于 UTF-8 字符的长度是可变的,因此字符串的字符长度可能与字节长度不同。
LENGTH()
字符串函数在给定 CHARACTER_LENGTH()
/CHAR
参数时报告 VARCHAR
,但在给定 OCTET_LENGTH()
/BINARY
参数时报告 VARBINARY
。
排序是字符串的另一个重要属性。对二进制数据进行排序时,使用字节值进行排序。同样,如果使用二进制排序规则对字符数据进行排序。但是,如果您想要对特定区域设置进行准确排序,则字节顺序不一定是给定区域设置的正确顺序。
阅读 https://docs.vertica.com/24.1.x/en/admin/about-locale/ 了解有关 Vertica 中区域设置的更多信息。