2011-06-14 25 views
3

私は、COPYを使用して、テーブルからファイルにフィールドをコピーしています。このフィールドは圧縮されたテキストファイルなので、バイナリコピーを使用します。 ファイルが作成されましたが、唯一の問題はCOPYがヘッダーとトレーラー(?)をファイルに追加することです。これは不要です。これは変更できますか? COPYにデータベース内のフィールドとまったく同じフィールドを入れる原因となるパラメータはありますか?postgresコピーコマンド、バイナリファイル

不要なヘッダーを手動で削除すると、zcatまたはgunzipでファイルを抽出できます。

psql -d some_database -c \ 
"copy (select some_column from a_table where id=900) to stdout with BINARY;" > /tmp/tmp.gz 

をそして私は

gunzip /tmp/tmp.gz 

任意のアイデアをしたい:

私はこのように気にいらないのでしょうか?

答えて

1

ジップテキストをバイナリ形式でデータベースに保存するにはどうすればよいですか?

長い文字列が自動的に システムにより圧縮されているので、ディスク上の物理的な 要件は以下のようになります。documentation長いテキストによると、暗黙的/自動的に圧縮されます。 のバックグラウンドテーブルにも非常に長い値が格納されているため、短い 列値への迅速なアクセスを妨げません( )。いずれにしても、 が格納できる最大の文字列は で約1GBです。

+0

私はそれが:-)最善の方法ではありませんが、私は、私はちょうどに持って、それを行うことを決めたものではありませんよ同意それをそこから取り出してください:-) – user797710

1

私は単純な方法はわかりません... COPYには、可変長のヘッダーを持つバイナリ形式があり、「トリミング」するのはそれほど簡単ではありません。それ以外のところでは、PGはむしろテキスト中心であり、BYTEAフィールドのSELECTから「生の」(バイナリ)出力を強制する方法はありません。

テキストの16進数の出力を得て、小さなプログラム(C、perlなど)を書いて、\x000102414243からバイナリに変換することができます。

psql -t -q -c "select binaryfield from.. where ..." mydb | myhextobin > tmp.gz 

難しいことではありませんが、単純ではない(とHEXフォーマットは、PostgreSQL 9.0である)ところで、グジェゴシの答えは非常に適切です。

を追加しました:非常にきれいな、でも誰にでもできるではない、何かが重宝だけならば...

/* expects a pg hexadecimal string, in "\x....." format, and converts to binary*/ 
/* warning: no checks! it just ignores chars outside [0-9a-f] */ 
#include<stdio.h> 
int main() { 
    int x, pos, v; 
    char hex[3]={0,0,0}; 
    pos = 0; 
    while((x = getchar()) >= 0) { 
     if((x >='0' && x <= '9') || (x >= 'a' && x <= 'f')) { 
      hex[pos++] = (char)x; 
      if(pos == 2) { 
       sscanf(hex, "%x", &v); 
       putchar((char)v); 
       pos = 0; 
      } 
     } 
    } 
    return pos==0 ? 0 : 1; 
} 
0

PostgreSQLのバイナリフォーマットをデコードしようとすることが提案されていません。あなたが使用しているテストファイルがすべてが機能するとは限りません。たとえば、特定の文字シーケンス(テストファイルには表示されない)がエスケープされる可能性があります。あなたがそれを好きではないかもしれないが動作します

+0

私はそれを手に入れません。 'b 'が(私が仮定した)' bytea'フィールドであれば、生のバイナリの内容ではなく16進文字列を出力します。 (私はdownvoteしなかった) – leonbloy

+0

@leonbloy:はい、データの種類が指定されていません。実際の出力フォーマットはbytea_output()に依存しますが、デフォルトのフォーマットはすべてエンコードされたフォーマットです。 PostgreSQLはBLOB型のインラインをサポートしておらず、ラージオブジェクトへの参照のみです。 –

3

一つの可能​​性、:

psql -At -c "select encode(content, 'base64') from t where ..." | base64 -d 

すなわちBASE64などのコンテンツを印刷し、それをデコードします。現実には、psqlは可読な出力を生成することを意図しており、生のバイナリデータを解読することを意図的に困難にするよう説得しています。

私は十分にしたい場合は、データベースに接続し、生の出力を直接印刷するためのツール(Perl/pythonスクリプト)を書くことができます。

COPYの「WITH BINARY」オプションは単純なバイナリ出力を行うだけではなく、おそらく疑わしいエンコードを実行します。

+0

それは動作し、私はそれが好きです!ありがとう!! – user797710

0

クライアントドライバを持つ言語を使用して、PHP、Python、Ruby、Perl、JavaScript、Javaなどのバイトタイプを読み取ることができます。おそらくすでにその言語で存在するgzipライブラリを作成し、そのファイルを書き出します。

また、データベース内でプロシージャ言語を使用してストアドプロシージャを作成することもできます。要求されたファイル名をストアドプロシージャに渡します。

+0

また、base64型で 'encode()'を使うことについてのAraqnidの答えが好きです。 – justis

0

copyコマンドはジョブを実行します。あなたに伝える必要があるのは--no-align--tuples-onlyです。

圧縮のために、psqlの間gzipを使用して、ファイル

psqlの--tuples-only --no-align -d some_database -c \ "copy (select some_column from a_table where id=900) to stdout with BINARY;" | gzip > /tmp/tmp.gz

関連する問題