5.4. 二进制字串

bytea 数据类型允许存储二进制字串. 参阅Table 5-6

Table 5-6. 二进制字串类型

类型名存储描述
bytea4 字节加上实际的二进制字串变长(没有明确长度限制)的二进制字串

二进制字串是一个八进制(或者字节)数值的序列。 二进制字串和字符字串的区别有两个:首先,二进制字串完全可以允许 存储八进制零值以及其它"不可打印的"字符。 第二,对二进制串的处理就是实际上的字节,而字符串的处理和编码 取决于区域设置。

在输入 bytea 数值的时候, 在一个 SQL 语句的文本串里面, 你必须逃逸某些八进制数值(但 可以逃逸所有八进制数值) 通常,要逃逸一个八进制数,需要把它的数值转换成对应的三位八进制数字, 并且前导两个反斜扛.有些八进制数值有可选的逃逸序列, 在 Table 5-7 中显示.

Table 5-7. bytea 文本逃逸八进制

十进制数值描述输入逃逸表现形式例子打印结果
0 零的八进制 '\\000' select '\\000'::bytea; \000
39 单引号 '\'' 或者 '\\047' select '\''::bytea; '
92 反斜扛 '\\\\' 或者 '\\134' select '\\\\'::bytea; \\

请注意Table 5-7里的每个例子都是刚好一个八进制位长,虽然零的八进制和反斜扛 的八进制的输出形式比一个字符要长.Bytea 输出的八进制 也是经过逃逸的.通常,每个"不可打印"的八进制数字值 都转化成对应的前导反斜扛的三位八进制数值.大多数"可打印的" 八进制是以客户端字符集的标准表现形式出现的.十进制值为 92 (反斜扛) 的八进制数有一个特殊的可选输出形式.细节在 Table 5-8 里描述.

Table 5-8. bytea 输出逃逸序列

十进制数值描述输出逃逸形式例子打印结果
92 反斜扛 \\ select '\\134'::bytea; \\
0 到 31 和 127 到 255 "不可打印"八进制字符 \### (octal value) select '\\001'::bytea; \001
32 到 126 "可打印"八进制字符 ASCII 表现形式 select '\\176'::bytea; ~

要使用 bytea 逃逸八进制表示法, 字串文本(输入字串)必须由两个反斜扛前缀, 因为它们必须通过PostgreSQL后端里的两个分析器.第一个反斜扛 被字串文本分析器解释成逃逸字符,于是被消耗掉,留下后面跟着的八进制. 剩下的反斜扛被 bytea 输入函数识别,它把它当做一个 三位的八进制数值前缀看待.比如,一个字串文本以 '\\001' 的形式传递给后端,在通过字串文本分析器之后就变成了 '\001'.然后 '\001' 被发送给 bytea 输入函数,被该函数转换成一个八进制数值为 1.

由于类似的原因,一个反斜扛必须以 '\\\\' 形式 输入(或者是 '\\134').第一个和第三个反斜扛被 字串文本分析器当做逃逸字符解释并消耗掉,字串里剩下两个反斜扛传递 给 bytea 输入函数,然后该函数把它转换成表示一个反斜扛. 比如,一个以 '\\\\' 形式传递给后端的字串文本 在通过字串文本分析器后变成 '\\'. 然后 '\\' 被发送给 bytea 输入函数,在那里它被转换成十进制数值为 92 的单个字符.

单引号略有不同,因为它必须以 '\''(或者 '\\047')形式输入,而不是'\\'' 形式.这是因为虽然文本分析器把单引号 解释成一个特殊的字符,并且将消耗掉一个反斜扛,但是 bytea 输入函数并认为单引号 是一个特殊的八进制.因此,一个传递给后端的 '\'' 在通过字串文本分析器之后变成 '''. 然后 ''' 被发送给 bytea 输入函数, 输入函数仍然把它转换成单个十进制值为 39 的字符.

根据你使用的前端的不同,在逃不逃逸 bytea 字串的问题上 你可能有一些额外的工作要做.比如,如果你的接口自动转换进行和回车, 那你可能还要逃逸它们.而如果你选的语言或者工具的分析器也把反斜扛 当逃逸字符看,那么你可能还要成倍地用它.

SQL 标准定义了一种不同的二进制字串类型, 叫做 BLOB 或者 BINARY LARGE OBJECT。 期输入格式和 bytea 不同,但是提供的函数和操作符 大多一样。