将带有十六进制的文本字符串作为bytea插入到PostgreSQL中

时间:2010-06-23 15:50:07

标签: sql postgresql

我有一个文本文件,其中包含几个十六进制字符串:

013d7d16d7ad4fefb61bd95b765c8ceb
007687fc64b746569616414b78c81ef1

我想将它们作为 bytea 存储在数据库中,而不是 varchar 。也就是说,我希望数据库将01存储为单字节00000001,而不是字符'0'和& '1'。

我可以通过sed轻松运行这个文件,以任何方式格式化/转义它。

这就是我的尝试:

create table mytable (testcol BYTEA);

这有效:

insert into mytable (testcol) values (E'\x7f\x7f');

但是,只要我的字节高于\ x7f,我就会收到此错误:

insert into mytable (testcol) values (E'\x7f\x80');
ERROR:  invalid byte sequence for encoding "UTF8": 0x80

任何想法,或者我是否接近错误?

5 个答案:

答案 0 :(得分:70)

您可以使用decode函数将十六进制字符串转换为bytea(其中“encoding”表示将二进制值编码为某个文本值)。例如:

select decode('DEADBEEF', 'hex');
      decode      
------------------
 \336\255\276\357

使用9.0的默认输出更容易理解:

   decode   
------------
 \xdeadbeef

你不能只说E'\xDE\xAD\xBE\xEF'的原因是这是为了创建一个文本值而不是bytea,所以Postgresql会尝试将它从客户端编码转换为数据库编码。您可以像这样编写bytea转义格式,但需要加倍反斜杠:E'\\336\\255\\276\\357'::bytea。我想你可以看到为什么bytea格式被改变了....恕我直言decode()函数是一种写入输入的合理方式,即使涉及到一些开销。

答案 1 :(得分:27)

INSERT INTO
  mytable (testcol)
VALUES
  (decode('013d7d16d7ad4fefb61bd95b765c8ceb', 'hex'))

答案 2 :(得分:5)

Ruby Way

我最近需要从/向Postgres读取/写入二进制数据,但是通过Ruby。以下是我使用Pg library进行的操作。

虽然不是严格遵循Postgres,但我认为我会将这个以Ruby为中心的答案包含在内以供参考。

Postgres数据库设置

require 'pg'
DB = PG::Connection.new(host: 'localhost', dbname:'test')
DB.exec "CREATE TABLE mytable (testcol BYTEA)"
BINARY = 1

插入二进制数据

sql = "INSERT INTO mytable (testcol) VALUES ($1)"
param = {value: binary_data, format: BINARY}
DB.exec_params(sql, [param]) {|res| res.cmd_tuples == 1 }

选择二进制数据

sql = "SELECT testcol FROM mytable LIMIT 1"
DB.exec_params(sql, [], BINARY) {|res| res.getvalue(0,0) }

答案 3 :(得分:1)

简介

这是更新后的答案,其中包括如何插入以及如何查询。

可以使用decode函数将十六进制转换为bytea值。这应该同时用于查询和插入。

这既可以用于插入,也可以用于查询。

Example SQL Fiddle

查询现有数据

SELECT * FROM mytable WHERE testcol = (decode('013d7d16d7ad4fefb61bd95b765c8ceb', 'hex'));

编码与解码进行查询

用户询问了以下内容:

插入后如何按十六进制值搜索BYtea字段?

SELECT * FROM my_table WHERE myHexField =
(encode('013d7d16d7ad4fefb61bd95b765c8ceb', 'hex'));

不起作用。

在文档Binary String Functions and Operators中,它们同时描述了encodedecode

   +==================================+=============+=======================================================================================================+=======================================+============+
    |             Function             | Return Type |                                              Description                                              |                Example                |   Result   |
    +==================================+=============+=======================================================================================================+=======================================+============+
    | decode(string text, format text) | bytea       | Decode binary data from textual representation in string. Options for format are same as in encode.   | decode('123\000456', 'escape')        | 123\000456 |
    +----------------------------------+-------------+-------------------------------------------------------------------------------------------------------+---------------------------------------+------------+
    | encode(data bytea, format text)  | text        | Encode binary data into a textual representation. Supported formats are: base64, hex, escape. escape  | encode('123\000456'::bytea, 'escape') | 123\000456 |
    |                                  |             | converts zero bytes and high-bit-set bytes to octal sequences (\nnn) and doubles backslashes.         |                                       |            |
    +----------------------------------+-------------+-------------------------------------------------------------------------------------------------------+---------------------------------------+------------+

因此,您会注意到Encode用于encoding binary data into a textual string并返回文本。但是,由于我们存储的是bytea,因此插入和查询都必须使用decode

插入

create table mytable (testcol BYTEA);

INSERT INTO
  mytable (testcol)
VALUES
  (decode('013d7d16d7ad4fefb61bd95b765c8ceb', 'hex'));

发件人:请参见previous answer

答案 4 :(得分:0)

More和杂项options

-- insert 123[char of value zero]abc456
insert into mytable (testcol) values decode(E'123\\000abc456', 'escape');

-- insert abc456
insert into mytable (testcol) values decode('YWJjNDU2', 'base64');