web-dev-qa-db-ja.com

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

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

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

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

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

編集:This 2005年の同様の質問は未回答のままです。

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

40
SabreWolfy

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

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');

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

手動

19
User2397

このソリューションは、ランタイムの点で正確には効率的ではありませんが、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;
15
goodside

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
5
user1555

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

1
Gaius

スーパーユーザー権限なしで(Herokuなどで)実行する方法を次に示します。

\lo_import '/cygdrive/c/Users/Chloe/Downloads/Contract.pdf'
update contracts set contract = lo_get(:LASTOID) where id = 77;

\lo_listを使用してラージオブジェクトを表示し、\lo_unlinkを使用してそれらを削除できます。この例のcontractフィールドはbyteaです。

     Column      |            Type             |
contract         | bytea                       |
0
Chloe