2

使用 postgresql 8.4 中的 COPY 命令导出 bytea 类型的数据,这对于单个记录可以正常工作:

copy (SELECT encode(test_column, 'hex') FROM test_table LIMIT 1) TO '/home/user/file.hex'

之后,我使用xxd命令来获取适当的文件类型。如果这是一个非常菜鸟的问题,请提前抱歉,但是是否可以将所有记录导出到 file-1、file-2...file-n 中?什么是正确的语法或脚本?我似乎无法在 postgresql 副本的人中找到它。
例如,这是一个单行的 bash 脚本:

#!/bin/bash

psql \  
    -P t \  
    -P format=unaligned \  
    -X \  
    -U myuser \  
    -h myhost \  
    -c "select my_bytea_col from my_table where id=1" \  
    mydb \  
| xxd -r -p > dump.txt  

但是,我需要在所有 id 上执行它,并将它们保存在不同的文件下,例如 file1.txt、file2.txt、file3.txt.. 等。
也可能非常有趣的是能够使用另一列的数据(例如 id)以相应地命名生成的 hex 文件。

4

1 回答 1

3

我会使用直接支持 PostgreSQL 的脚本语言。

regress给定一个名为的数据库,该数据库包含一个名为filesfileid(一个整数)和filedata(一个字节)的表,这可以很好地完成这项工作。它将数据写入由outdir变量指定的目录中的文件中,这些文件的命名方式类似于{filenameprefix}{fileid}{filenamesuffix}.

#!/usr/bin/env python3
import os
import sys
import psycopg2

outdir = "files"
filenameprefix = "f"
filenamesuffix = ""

def main():
        os.makedirs(outdir, exist_ok=True)
        conn = psycopg2.connect("dbname=regress")
        curs = conn.cursor();
        curs.execute("SELECT fileid, filedata FROM files;")
        for (fileid, filedata) in curs:
            fn = filenameprefix+str(fileid)+filenamesuffix
            f = open(os.path.join(outdir, fn), "wb")
            f.write(filedata)
            f.close()
        conn.close();

if __name__ == '__main__':
        main()

我使用这段代码来创建上面脚本中提到的测试环境:

#!/usr/bin/env python3
import psycopg2
conn = psycopg2.connect("dbname=regress")
curs = conn.cursor()
curs.execute('CREATE TABLE files(fileid serial primary key, filedata bytea);')
for i in range(1,10)
    curs.execute('INSERT INTO  files(filedata) VALUES (%s);', (psycopg2.Binary(open('/dev/urandom','rb').read(1024)),))

编辑:为了使其与您在问题中使用的命名相同,我只是假设它是通用匿名名称,请更改:

  • regress-> 无论您的数据库名称是什么
  • files->my_table
  • fileid->id
  • filedata->my_bytea_col

相当于这个脚本可以在bash中完成,只是比较麻烦。您需要使用协同流程以事务安全的方式执行此操作。您需要创建一个psql协同进程并在其中打开一个SERIALIZABLE事务,然后SELECT fileid FROM files进入一个 shell 变量。遍历 shell 变量并为每个 ID 循环SELECT filedata FROM filesxxd管道中,以指向使用 ID 上的字符串插值创建的文件名。

IMO:不值得麻烦,使用可以让您直接访问 PostgreSQL 的脚本语言。

如果您不需要它,交易安全会更容易一些;只需在一次调用中获取 ID psql,然后在后续调用中获取文件数据。它会更慢并且不会是交易安全的,但它会更容易。

于 2012-11-11T23:45:45.283 回答