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

Don*_*ner 45 sql postgresql

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

013d7d16d7ad4fefb61bd95b765c8ceb
007687fc64b746569616414b78c81ef1
Run Code Online (Sandbox Code Playgroud)

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

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

这是我尝试过的:

create table mytable (testcol BYTEA);
Run Code Online (Sandbox Code Playgroud)

这有效:

insert into mytable (testcol) values (E'\x7f\x7f');
Run Code Online (Sandbox Code Playgroud)

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

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

任何想法,还是我接近错误?

ara*_*nid 73

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

select decode('DEADBEEF', 'hex');
      decode      
------------------
 \336\255\276\357
Run Code Online (Sandbox Code Playgroud)

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

   decode   
------------
 \xdeadbeef
Run Code Online (Sandbox Code Playgroud)

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


Jul*_*eau 28

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


Men*_*los 6

介绍

\n

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

\n

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

\n

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

\n

SQL 小提琴示例

\n

查询已有数据

\n
SELECT * FROM mytable WHERE testcol = (decode(\'013d7d16d7ad4fefb61bd95b765c8ceb\', \'hex\'));\n
Run Code Online (Sandbox Code Playgroud)\n

查询时的编码与解码

\n

一位用户提出了以下问题:

\n
\n

插入后如何通过十六进制值搜索bytea字段?

\n
SELECT * FROM my_table WHERE myHexField =\n(encode(\'013d7d16d7ad4fefb61bd95b765c8ceb\', \'hex\'));\n
Run Code Online (Sandbox Code Playgroud)\n

不起作用。

\n
\n

在文档Binary String Functions and Operatorsencode中,有和的描述decode

\n
   +==================================+=============+=======================================================================================================+=======================================+============+\n    |             Function             | Return Type |                                              Description                                              |                Example                |   Result   |\n    +==================================+=============+=======================================================================================================+=======================================+============+\n    | decode(string\xc2\xa0text,\xc2\xa0format\xc2\xa0text) | bytea       | Decode binary data from textual representation in\xc2\xa0string. Options for\xc2\xa0format\xc2\xa0are same as in\xc2\xa0encode.   | decode(\'123\\000456\', \'escape\')        | 123\\000456 |\n    +----------------------------------+-------------+-------------------------------------------------------------------------------------------------------+---------------------------------------+------------+\n    | encode(data\xc2\xa0bytea,\xc2\xa0format\xc2\xa0text)  | text        | Encode binary data into a textual representation. Supported formats are:\xc2\xa0base64,\xc2\xa0hex,\xc2\xa0escape.\xc2\xa0escape\xc2\xa0 | encode(\'123\\000456\'::bytea, \'escape\') | 123\\000456 |\n    |                                  |             |\xc2\xa0converts zero bytes and high-bit-set bytes to octal sequences (\\nnn) and doubles backslashes.         |                                       |            |\n    +----------------------------------+-------------+-------------------------------------------------------------------------------------------------------+---------------------------------------+------------+\n
Run Code Online (Sandbox Code Playgroud)\n

所以你会注意到它Encode是用于encoding binary data into a textual string并返回文本。但是,由于我们要存储,因此bytea必须decode同时用于插入和查询。

\n

插入

\n
create table mytable (testcol BYTEA);\n\nINSERT INTO\n  mytable (testcol)\nVALUES\n  (decode(\'013d7d16d7ad4fefb61bd95b765c8ceb\', \'hex\'));\n
Run Code Online (Sandbox Code Playgroud)\n

出自:见之前的回答

\n


Cli*_*chl 5

Ruby方式

我最近需要从/向Postgres读取/写入二进制数据,但是通过Ruby.这是我使用Pg库的方式.

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

Postgres数据库设置

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

插入二进制数据

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

选择二进制数据

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