PostgreSQL bayt sütununa veri (dosya) nasıl eklenir?


37

Bu soru bytea v. Oid v. Blobs v. Büyük nesneler vb. İle ilgili değildir.

Birincil anahtar integeralan ve bir byteaalan içeren bir tablo var . byteaAlana veri girmek istiyorum . Bu, muhtemelen, PL/dillerden biri tarafından yapılabilir PL/Pythonve gelecekte bunu birlikte yapabilirim .

Hala test edip, deniyorum, sadece "standart" SQL ifadelerini kullanarak bir dosyadan (sunucudaki) veri eklemek istiyorum. Yalnızca sunucuda yazma iznine sahip olan yöneticilerin istediğim gibi veri ekleyebileceğini biliyorum. Bu aşamada kullanıcılar byteaşu anda veri eklemek istemeyeceğinden endişelenmiyorum . Genelde çeşitli StackExchange sitelerini, PostgreSQL Arşivlerini ve Internet'i aradım ancak bir cevap bulamadım.

Düzenleme: 2008'deki bu tartışma yapmak istediğim şeyin mümkün olmadığını gösteriyor. byteaO zaman alanlar nasıl kullanılır?

Düzenleme: 2005 yılından bu benzer soru cevapsız kalır.

Çözüldü: sağlanan ayrıntılar burada üzerinde psycopgweb Python içinde yazdım çözüm için temel oluşturdu. İkili veriyi byteakullanarak bir sütuna eklemek de mümkün olabilir PL/Python. Bunun "saf" SQL kullanarak mümkün olup olmadığını bilmiyorum.


1
Psikopos dökümanlarına bağlantı koptu ve düzenlemem reddedildi (!?). İşte geçerli konum .
Aryeh Leib Taurog 27:13

@AryehLeibTaurog: Teşekkürler. Düzenlemeyi reddettim, çünkü değiştirilen metninizin köprü olduğu açık değildi. Düzenlemeyi tekrar yapmak isterseniz, onaylayacağım.
SabreWolfy 27:13

@Andriy_M Neden "Bu düzenleme yazının asıl amacından sapmış" diyorsunuz. (Düzenleme informatik01 tarafından yapıldı?)
miracle173

@ miracle173: Çünkü önerilen etiketlerden bazılarının alakasız olduğu izlenimini edindim (aslında, sadece bir tanesi blob). Bu bir hata olsaydı, içtenlikle özür dilerim.
Andriy M

Yanıtlar:


26

süper kullanıcı olarak:

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'te tanıtıldı, böylece daha eski sürümler için ihtiyacınız olacak:

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

sonra:

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

Ters süreç için, ben denemedim bu , ama eğer çalışırsa, lo_export Tek ihtiyacınız olacak
Jack Douglas,


15

Bu çözüm çalışma zamanı açısından tam olarak verimli değildir, ancak kendi başlıklarınızı oluşturmaya kıyasla oldukça kolaydır COPY BINARY. Ayrıca, bash dışında herhangi bir kütüphane veya kodlama dili gerektirmez.

İlk önce dosyayı bir hexdump'a dönüştürün, dosyanın boyutunu ikiye katlayın. xxd -pbizi oldukça yakınlaştırıyor, ancak dikkat etmesi gereken bazı sinir bozucu yeni hatlara fırlatıyor:

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

Ardından, verileri PostgreSQL'de çok geniş bir textalan olarak içe aktarın . Bu tür alan değeri başına bir GB’a kadar çıkar, bu nedenle çoğu amaç için uygun olmalıyız:

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

Şimdi verilerimiz gereksiz yere büyük altıgen dizesi olduğunu, biz PostgreSQL'in kullanmak decodebir içine almak byteatürü:

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

Bu çözüm \ n karakterlerinin dosyadan silinmesine neden olur.
SabreWolfy,

2
SabreWolfy: Hayır, değil. Bu tr -d '\n', girişin ikili içeriğini ASCII onaltılık karakterleri (0-9 ve af) olarak kodlayan xxd çıkışında çalışıyor. xxd ayrıca çıktı satırının, beslemeyi insan tarafından okunabilir hale getirmek için düzenli aralıklarla gerçekleşir, ancak bu durumda bunların kaldırılmasını istiyoruz. Orijinal verilerdeki satır beslemeleri onaltılık biçimde olacak ve etkilenmeden kalacaktır.
Ağustos'ta

5

XXd ile cevap çok hızlı, küçük dosyalar için, güzel ve. Aşağıda kullanıyorum örnek bir komut dosyasıdır.

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 işlevini kullanın . Bu, genel olarak Oracle'ın dış tablolarına eşdeğerdir .


Teşekkürler. Verdiğiniz bağlantı, verilerin ASCII veya PostgreSQL'in ikili tablo biçiminde olması gerektiğini gösterir. Sayfadan aşağıya, ikili tablo formatının ilk önce COPY TO komutuyla oluşturulduğundan söz edilir. Bu yaklaşımlardan herhangi biri bir byteasütuna ikili dosya (PDF, belge, elektronik tablo) eklememe izin verir mi?
SabreWolfy

COPY BINARY ( postgresql.org/docs/8.4/interactive/sql-copy.html ) ile ilgili PostgreSQL belgeleri, ikili veri eklerken özel bir dosya başlığının gerekli olduğunu belirtir. Bu başlığı oluşturup ikili veriye eklemem gerekiyor mu? Bu sadece bir dizi ikili veriyi depolamak için biraz karmaşık görünüyor.
SabreWolfy

Hmm, şimdi bahsettiğinizden emin değilim, sadece komutu hatırladım ve bunun olacağını tahmin ettim. Belki de PL / bunu yapmanın tek yolu budur.
Gaius
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.