it-swarm.asia

كيفية إدراج بيانات (ملف) في عمود PostgreSQL bytea؟

هذا السؤال ليس عن Bytea v. oid v. blobs v. الأشياء الكبيرة ، إلخ.

لدي جدول يحتوي على حقل مفتاح أساسي integer وحقل bytea. أود إدخال البيانات في حقل bytea. يمكن القيام بذلك ، من المفترض ، بواسطة أحد PL/ اللغات ، وقد أبحث في القيام بذلك مع PL/Python فى المستقبل.

نظرًا لأنني ما زلت أختبر وأختبر ، أود ببساطة إدراج بيانات من ملف (على الخادم) باستخدام عبارات SQL "القياسية". إنني أدرك أن المسؤولين الذين لديهم إذن الكتابة على الخادم هم وحدهم القادرون على إدراج البيانات بالطريقة التي أريدها. لا أشعر بالقلق حيال ذلك في هذه المرحلة حيث لن يقوم المستخدمون بإدراج بيانات bytea في الوقت الحالي. لقد بحثت في مختلف مواقع StackExchange وأرشيفات PostgreSQL والإنترنت بشكل عام ، لكنني لم أتمكن من العثور على إجابة.

تحرير: هذا مناقشة عام 2008 تعني أن ما أريد القيام به غير ممكن. كيف يتم استخدام الحقول bytea بعد ذلك؟

تحرير: هذا سؤال مماثل من عام 2005 لا يزال دون إجابة.

محلولة: التفاصيل المقدمة هنا على موقع الويب psycopg قدم أساس الحل الذي كتبته في بيثون. قد يكون من الممكن أيضًا إدراج البيانات الثنائية في عمود bytea باستخدام PL/Python. لا أعرف ما إذا كان هذا ممكنًا باستخدام 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');
27
Jack says try topanswers.xyz

استخدم 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.

أولاً ، قم بتحويل الملف إلى شكل سداسي عشري ، مع مضاعفة حجم الملف. xxd -p يقرّبنا كثيرًا ، لكنه يلقي ببعض الخطوط الجديدة المزعجة التي يجب علينا الاهتمام بها:

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

بعد ذلك ، قم باستيراد البيانات في PostgreSQL كحقل text كبير جدًا. يحمل هذا النوع ما يصل إلى 1 غيغابايت لكل قيمة حقل ، لذلك يجب أن نكون بخير لمعظم الأغراض:

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

الآن بعد أن أصبحت بياناتنا عبارة عن سلسلة سداسية عريضة غير مبررة ، نستخدم PostgresQL's 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 نسخ مختصرة . هذا يعادل بشكل عام 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