二进制数据类型

bytea数据类型允许存储二进制字符串。参阅下表。

表.二进制数据类型

名字 存储空间 描述
bytea 4字节加上实际的二进制字符串 变长的二进制字符串

二进制字符串是一个字节序列。二进制字符串和普通字符字符串的区别有两个: 首先,二进制字符串完全可以存储字节零值以及其它”不可打印的” 字节(定义在 32 到 126 范围之外的字节)。字符串不允许字节零值, 并且也不允许那些不符合选定的字符集编码的非法字节值或者字节序列。 第二,对二进制字符串的处理实际上就是处理字节,而对字符串的处理则取决于区域设置。 简单说,二进制字符串适用于存储那些程序员认为是”原始字节”的数据, 而字符串适合存储文本。

当录入bytea值时,你 必须 转义某些字节值,当作为SQL声明中字符串数值时, 可以 转义所有字节值。通常,要转义一个字节值, 必须将它转换成与十进制八位字节值等价的三位八进制值的形式,前缀为两个反斜杠。下表给出了必须转义的字符串,和替代的转义序列。

表.bytea文本转义八进制

十进制数值 描述 输入转义形式 例子 输出形式
0 八进制的零 E’\ \000’ SELECT E’\ \000’::bytea; \000
39 单引号 ‘ ‘ ‘ ‘ 或 E’\ \047’ SELECT E’ '’::bytea;
92 反斜杠 E’\ \ \ \ ' 或 E’\ \134’ SELECT E’\ \ \ \ '::bytea; \ \
0 to 31 and 127 to 255 “不可打印”八进制字符 E’\ \xxx’ (八进制值) SELECT E’\ \001’::bytea \001

转义 不可打印 字节的要求因区域设置而异。在某些场合下, 你可以不转义它们。请注意上表里的每个例子都是刚好一个字节长,虽然输出形式比一个字符要长。

你必须写这么多反斜杠的原因,如上表所示, 是因为一个写成字符串文本的输入字符串必须通过OushuDB 服务器里的两个分析阶段。每一对反斜杠中的第一个会被字符串文本分析器理解成一个转义字符而消耗掉, 于是第二个反斜杠会被留下。(可以使用美元符引用字符串避免此类转义。)剩下的第二个反斜杠被bytea输入函数当作一个三位八进制值或者是转义另外一个反斜杠的开始。比如,一个传递给服务器的字符串文本E’\001’在通过字符串分析器之后会当作001 发送给bytea输入函数,在这里它被转换成一个十进制值为 1 的单个字节。请注意, 单引号字符(‘)不会被bytea特殊对待,它遵循字符串文本的普通规则。又见 字符串常量

Bytea字节也在输出中转义。通常,每个”不可打印” 的字节值都转化成对应的前导反斜杠的三位八进制数值。大多数”可打印的” 字节值是以客户端字符集的标准表现形式出现的。十进制值为 92(反斜杠)的字节在输出中双写。 细节在下表里描述。

表.bytea输出转义序列

字节的十进制值 描述 转义的输出形式 例子 输出结果
92 反斜杠 \ \ SELECT E’\ \134’::bytea; \ \
0 to 31 and 127 to 255 “不可打印”八进制字符 \xxx (八进制值) SELECT E’\ \001’::bytea; \001
32 to 126 “可打印”八进制字符 客户端字符集表现形式 SELECT E’\ \176’::bytea; ~

根据你使用的前端不同,在是否转义bytea字符串的问题上你可能有一些额外的工作要做。 比如,如果你的接口自动转换换行和回车,那你可能还要转义它们。

SQL标准化定义了一个不同的二进制字符串类型,叫做BLOB或BINARY LARGE OBJECT。其输入模式与bytea不同,但是提供的函数和操作符几乎相同。