二进制数据类型 =================== .. container:: toc `bytea\ 的十六进制格式 `__ `bytea\ 的转义格式 `__ ``bytea``\ 数据类型允许存储二进制串,参见\ `表 `__\ 。 .. container:: table :name: DATATYPE-BINARY-TABLE **表 二进制数据类型** .. container:: table-contents ========= ========================== ============ 名字 存储尺寸 描述 ========= ========================== ============ ``bytea`` 1或4字节外加真正的二进制串 变长二进制串 ========= ========================== ============ 二进制串是一个八位位组(或字节)的序列。 二进制串和字符串的区别有两个: 首先,二进制串明确允许存储零值的字节以及其它“不可打印的”字节(通常是位于十进制范围32到126之外的字节)。 字符串不允许零字节,并且也不允许那些对于数据库的选定字符集编码是非法的任何其它字节值或者字节值序列。 第二,对二进制串的操作会处理实际上的字节,而字符串的处理和取决于区域设置。 简单说,二进制字串适用于存储那些程序员认为是“裸字节”的数据,而字符串适合存储文本。 ``bytea``\ 类型支持两种用于输入和输出的格式:“十六进制”格式和PostgreSQL的历史的“转义”格式。在输入时这两种格式总是会被接受。输出格式则取决于配置参数\ `bytea_output `__\ ,其默认值为十六进制(注意十六进制格式是在PostgreSQL 0中被引入的,早期的版本和某些工具无法理解它)。 SQL标准定义了一种不同的二进制串类型, 叫做\ ``BLOB``\ 或者\ ``BINARY LARGE OBJECT``\ 。其输入格式和\ ``bytea``\ 不同,但是提供的函数和操作符大多一样。  ``bytea``\ 的十六进制格式 ------------------------------------------ “十六进制”格式将二进制数据编码为每个字节2个十六进制位,最高有效位在前。整个串以序列\ ``\x``\ 开头(用以和转义格式区分)。在某些情景中,开头的反斜线可能需要通过双写来转义,详见( `节 `__)。 作为输入,十六进制位可以是大写也可以是小写,在位对之间可以有空白(但是在位对内部以及开头的\ ``\x``\ 序列中不能有空白)。十六进制格式和很多外部应用及协议相兼容,并且其转换速度要比转义格式更快,因此人们更愿意用它。 例子: .. code:: programlisting SELECT '\xDEADBEEF';  ``bytea``\ 的转义格式 ------------------------------------------ “转义”格式是\ ``bytea``\ 类型的传统PostgreSQL格式。它采用将二进制串表示成ASCII字符序列的方法,而将那些无法用ASCII字符表示的字节转换成特殊的转义语句。从应用的角度来看,如果将字节表示为字符有意义,那么这种表示将很方便。但是在实际中,这常常是令人困扰的,因为它使二进制串和字符串之间的区别变得模糊,并且这种特别的转义机制也有点难于处理。因此这种格式可能会在大部分新应用中避免使用。 在转义模式下输入\ ``bytea``\ 值时,某些值的字节\ *必须*\ 被转义,而所有的字节值都\ *可以*\ 被转义。通常,要转义一个字节,需要把它转换成与它的三位八进制值, 并且前导一个反斜线。反斜线本身(十进制字节值92)也可以用双写的反斜线表示。\ `表 `__\ 显示了必须被转义的字符,并给出了可以使用的替代转义序列。 .. container:: table :name: DATATYPE-BINARY-SQLESC **表 bytea 文字转义字节** .. container:: table-contents +-------------+-------------+-------------+-------------+-------------+ | 十 | 描述 | 转 | 例子 | 十 | | 进制字节值 | | 义输入表示 | | 六进制表示 | +=============+=============+=============+=============+=============+ | 0 | 0字节 | \ '\000'\ | \ S | \ \x00\ | | | | | ELECT '\000 | | | | | | '::bytea;\ | | +-------------+-------------+-------------+-------------+-------------+ | 39 | 单引号 | \ | | \ \x27\ | | | | ''''\ \ 或\ | SELECT ''' | | | | | \ '\047'\ | '::bytea;\ | | +-------------+-------------+-------------+-------------+-------------+ | 92 | 反斜线 | \ | | \ \x5c\ | | | | '\\'\ \ 或\ | SELECT '\\ | | | | | \ '\134'\ | '::bytea;\ | | +-------------+-------------+-------------+-------------+-------------+ | 0到3 | “不可 | \ ' | \ S | \ \x01\ | | 1和127到255 | 打印的”字节 | \xxx'\ \ ( | ELECT '\001 | | | | | 八进制值) | '::bytea;\ | | +-------------+-------------+-------------+-------------+-------------+ 转义“不可打印的”字节的要求取决于区域设置。在某些实例中,你可以不理睬它们,让它们保持未转义的状态。 如\ `表 `__\ 中所示,要求单引号必须写两次的原因对任何SQL命令中的字符串常量都是一样的。 文字解析器消耗最外层的单引号,并缩减成对的单引号为一个普通数据字符。 ``bytea``\ 输入函数看到的只是一个单引号,它将其视为普通数据字符。 但是,\ ``bytea``\ 输入函数将反斜杠视为特殊字符,\ `表 `__\ 中显示的其他行为由该函数实现。 在某些情况下,反斜杠必须加倍,如上所示,因为通用的字符串文字解析器也会 将一对反斜杠减少为一个数据字符;请参阅\ `节 `__\ 。 ``Bytea``\ 字节默认被输出为\ ``hex``\ 格式。如果你把\ `bytea_output `__\ 改为\ ``escape``\ ,“不可打印的”字节会被转换成与之等效的三位八进制值并且前置一个反斜线。大部分“可打印的”字节被输出为它们在客户端字符集中的标准表示形式,例如: .. code:: programlisting SET bytea_output = 'escape'; SELECT 'abc \153\154\155 \052\251\124'::bytea; bytea ---------------- abc klm *\251T 十进制值为92(反斜线)的字节在输出时被双写。详情请见\ `表 `__\ 。 .. container:: table :name: DATATYPE-BINARY-RESESC **表 bytea 输出转义字节** .. container:: table-contents +-------------+-------------+-------------+-------------+----------+ | 十 | 描述 | 转义 | 例子 | 输出结果 | | 进制字节值 | | 的输出表示 | | | +=============+=============+=============+=============+==========+ | 92 | 反斜线 | ``\\`` | ``S | ``\\`` | | | | | ELECT '\134 | | | | | | '::bytea;`` | | +-------------+-------------+-------------+-------------+----------+ | 0到3 | “不可 | ` | ``S | ``\001`` | | 1和127到255 | 打印的”字节 | `\xxx``\ ( | ELECT '\001 | | | | | 八进制值) | '::bytea;`` | | +-------------+-------------+-------------+-------------+----------+ | 32到126 | “可 | 客户端 | ``S | ``~`` | | | 打印的”字节 | 字符集表示 | ELECT '\176 | | | | | | '::bytea;`` | | +-------------+-------------+-------------+-------------+----------+ 根据你使用的PostgreSQL前端,你在转义和未转义\ ``bytea``\ 串方面可能需要做额外的工作。例如,如果你的接口自动翻译换行和回车,你可能也不得不转义它们。