2

postgresql 8.4 で COPY コマンドを使用してバイトタイプのデータをエクスポートすると、単一のレコードに対してはうまく機能します。

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 など) を使用して、結果の 16 進ファイルにそれに応じた名前を付けます。

4

1 に答える 1

3

これには、PostgreSQL を直接サポートするスクリプト言語を使用します。

これは、列(​​整数) と(バイト) でregress呼び出されるテーブルを含むという名前のデータベースを考えると、非常にうまく機能します。のようなパターンに従って名前が付けられたファイルで、変数で指定されたディレクトリ内のファイルにデータを書き込みます。filesfileidfiledataoutdir{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、シェル変数に入れる必要があります。シェル変数をループし、ID ごとに、ID の文字列補間で作成されたファイル名SELECT filedata FROM filesへのxxdパイプにループします。

IMO: 手間をかける価値はありません。PostgreSQL に直接アクセスできるスクリプト言語を使用してください。

トランザクションセーフが必要ない場合は、少し簡単です。1 回の呼び出しで ID を取得しpsql、その後の呼び出しでファイル データを取得するだけです。遅くなり、トランザクションセーフではなくなりますが、簡単になります。

于 2012-11-11T23:45:45.283 に答える