(ファイル)データをPostgreSQL bytea列に挿入する方法は?


38

この質問はbytea v。oid v。blob v。大きなオブジェクトなどに関するものではありません。

主キーintegerフィールドとフィールドを含むテーブルがありbyteaます。byteaフィールドにデータを入力したいのですが。これはおそらく、いずれかのPL/言語で行うことができPL/Python、将来的にはこれを行うことを検討するかもしれません。

私はまだテストと実験を行っているので、「標準」のSQLステートメントを使用して(サーバー上の)ファイルからデータを挿入するだけです。サーバーに対する書き込み権限を持つ管理者のみが、希望する方法でデータを挿入できることを認識しています。ユーザーはbytea現在データを挿入しないので、この段階では心配していません。さまざまなStackExchangeサイト、PostgreSQLアーカイブ、およびインターネットを一般的に検索しましたが、答えが見つかりませんでした。

編集: 2008年からのこの議論は、私がやりたいことは不可能であることを意味します。byteaフィールドはどのように使用されますか?

編集: 2005年のこの類似の質問は未回答のままです。

解決済み: Webサイトのここで提供される詳細はpsycopg、Pythonで作成したソリューションの基礎を提供しました。byteaを使用して、バイナリデータを列に挿入することもできますPL/Python。「純粋な」SQLを使用してこれが可能かどうかはわかりません。


1
psycopgドキュメントへのリンクが壊れており、編集が拒否されたようです(!?)。 これが現在の場所です。
アリエレイブタウログ

@AryehLeibTaurog:ありがとう。あなたの変更されたテキストがハイパーリンクであることは私には明らかではなかったため、編集を拒否しました。もう一度編集したい場合は、承認します。
-SabreWolfy

@Andriy_Mなぜ「この編集は投稿の元の意図から逸脱している」と思いますか。(informatik01によって行われた編集?)
miracle173

@ miracle173:提案されたタグのいくつかは無関係であるという印象を受けたので(実際、1つだけblobです)。それが間違いだった場合、私は心から謝罪します。
アンドリーM

回答:


27

スーパーユーザーとして:

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;$$;

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;$$;

その後:

insert into my_table(bytea_data) select bytea_import('/my/file.name');

逆のプロセスのために、私は試していないこれを、それが動作するかどうか、lo_exportはあなたが必要なすべてのだろう
ジャック・ダグラス


15

このソリューションは、実行時間の点では正確には効率的ではありませんが、の独自のヘッダーを作成するのに比べて簡単ですCOPY BINARY。さらに、bash以外のライブラリやスクリプト言語は必要ありません。

まず、ファイルを16進ダンプに変換し、ファイルのサイズを2倍にします。xxd -p私たちをかなり近づけますが、それは私たちが注意しなければならないいくつかの迷惑な改行を投げます:

xxd -p /path/file.bin | tr -d '\n' > /path/file.hex

次に、PostgreSQLのデータを非常に大きなtextフィールドとしてインポートします。このタイプは、フィールド値ごとに最大1 GBを保持するため、ほとんどの目的で問題ありません。

CREATE TABLE hexdump (hex text); COPY hexdump FROM '/path/file.hex';

データが無意味に大きな16進文字列になったので、PostgresQLを使用decodeしてbytea型に変換します。

CREATE TABLE bindump AS SELECT decode(hex, 'hex') FROM hexdump;

ただし、この解決策により、ファイルから\ n文字が削除されます。
-SabreWolfy

2
SabreWolfy:いいえ、ありません。tr -d '\n'ASCII 16進数の文字(0-9およびAF)などの入力のバイナリコンテンツをコードする、XXDの出力で動作しています。xxdは、出力を人間が読めるようにするために定期的に出力ラインフィードにも発生しますが、この場合は削除する必要があります。でラインフィードの元データは、六角形態であろうと、影響を受けません。
-goodside

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

1

Postgres COPY BINARY関数を使用します。これは、Oracleの外部テーブルとほぼ同等です。


ありがとう。指定したリンクは、データがASCIIまたはPostgreSQLのバイナリテーブル形式である必要があることを示しています。ページのさらに下で、COPY TOコマンドを使用してバイナリテーブル形式が最初に作成されることに言及しています。これらのアプローチのいずれかで、バイナリファイル(PDF、ドキュメント、スプレッドシート)をbytea列に挿入できますか?
-SabreWolfy

COPY BINARYのPostgreSQLドキュメント(postgresql.org/docs/8.4/interactive/sql-copy.html)は、バイナリデータを挿入するときに特別なファイルヘッダーが必要であることを示しています。このヘッダーを作成してバイナリデータに追加する必要がありますか?バイナリデータの文字列を単純に格納する場合、これはやや複雑に思えます。
SabreWolfy

うーん、今あなたがそれについて言及したので、私は確信していません、私はちょうどコマンドを覚えていて、それがそうするだろうと思いました。おそらくPL / whateverがそれを行う唯一の方法です。
ガイウス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.