如何将(文件)数据插入 PostgreSQL bytea 列?

Sab*_*lfy 49 postgresql plpgsql datafile blob

这个问题不是关于 bytea v. oid v. blob v. large objects 等。

我有一个包含主键integer字段和bytea字段的表。我想在该bytea字段中输入数据。据推测,这可以由其中一种PL/语言完成,我PL/Python将来可能会考虑这样做。

由于我仍在测试和试验,我只想使用“标准”SQL 语句从文件(在服务器上)插入数据。我知道只有在服务器上具有写入权限的管理员才能以我想要的方式插入数据。在这个阶段我并不担心,因为用户bytea目前不会插入数据。我已经搜索了各种 StackExchange 站点、PostgreSQL 档案和互联网,但一直没有找到答案。

编辑: 这个2008 年的讨论意味着我想做的事情是不可能的。那么如何使用bytea字段呢?

编辑: 2005 年的这个类似问题仍未得到解答。

解决:所提供的细节在这里上的psycopg网站,我用Python编写的解决方案提供了基础。也可以使用 将二进制数据插入到bytea列中PL/Python。我不知道这是否可以使用“纯”SQL。

Jac*_*las 30

作为超级用户:

create or replace function bytea_import(p_path text, p_result out bytea) 
                   language plpgsql as $$
declare
  l_oid oid;
begin
  select lo_import(p_path) into l_oid;
  select lo_get(l_oid) INTO p_result;
  perform lo_unlink(l_oid);
end;$$;
Run Code Online (Sandbox Code Playgroud)

lo_get 是在 9.4 中引入的,因此对于旧版本,您需要:

create or replace function bytea_import(p_path text, p_result out bytea) 
                   language plpgsql as $$
declare
  l_oid oid;
  r record;
begin
  p_result := '';
  select lo_import(p_path) into l_oid;
  for r in ( select data 
             from pg_largeobject 
             where loid = l_oid 
             order by pageno ) loop
    p_result = p_result || r.data;
  end loop;
  perform lo_unlink(l_oid);
end;$$;
Run Code Online (Sandbox Code Playgroud)

然后:

insert into my_table(bytea_data) select bytea_import('/my/file.name');
Run Code Online (Sandbox Code Playgroud)


sud*_*lai 29

使用pg_read_file('location_of file')::bytea.

例如,

create table test(id int, image bytea);
insert into test values (1, pg_read_file('/home/xyz')::bytea);
Run Code Online (Sandbox Code Playgroud)

手动的

  • 或者更简单一点,`pg_read_binary_file('/path/to/file')`。请参阅 https://www.postgresql.org/docs/current/static/functions-admin.html (10认同)

goo*_*ide 16

这个解决方案在运行时并不完全有效,但与为COPY BINARY. 此外,它不需要 bash 之外的任何库或脚本语言。

首先,将文件转换为十六进制转储,将文件的大小加倍。xxd -p让我们非常接近,但它会引入一些我们必须处理的烦人的换行符:

xxd -p /path/file.bin | tr -d '\n' > /path/file.hex
Run Code Online (Sandbox Code Playgroud)

接下来,将 PostgreSQL 中的数据作为一个非常大的text字段导入。这种类型每个字段值最多可容纳 1 GB,因此我们应该可以用于大多数用途:

CREATE TABLE hexdump (hex text); COPY hexdump FROM '/path/file.hex';
Run Code Online (Sandbox Code Playgroud)

现在我们的数据是一个非常大的十六进制字符串,我们使用 PostgresQLdecode将其转换为一个bytea类型:

CREATE TABLE bindump AS SELECT decode(hex, 'hex') FROM hexdump;
Run Code Online (Sandbox Code Playgroud)

  • SabreWolfy:不,没有。`tr -d '\n'` 对 xxd 的输出进行操作,它将输入的二进制内容编码为 ASCII 十六进制字符(0-9 和 af)。xxd 也碰巧定期输出换行符以使输出可读,但在这种情况下,我们希望将它们删除。*原始*数据中的换行将采用十六进制格式,并且不受影响。 (2认同)

小智 5

xxd答案很好,对于小文件,速度非常快。下面是我正在使用的示例脚本。

xxd  -p /home/user/myimage.png | tr -d '\n' > /tmp/image.hex
echo "
    -- CREATE TABLE hexdump (hex text);
    DELETE FROM hexdump;
    COPY hexdump FROM '/tmp/image.hex';

    -- CREATE TABLE bindump (binarydump bytea);
    DELETE FROM bindump;

    INSERT INTO bindump (binarydump)  
    (SELECT decode(hex, 'hex') FROM hexdump limit 1);

    UPDATE users 
    SET image= 
    (
        SELECT decode(hex, 'hex') 
        FROM hexdump LIMIT 1
    )  
    WHERE id=15489 ;
    " | psql mydatabase
Run Code Online (Sandbox Code Playgroud)