it-swarm.asia

SQL untuk membaca XML dari file ke dalam database PostgreSQL

Bagaimana saya bisa menulis SQL untuk membaca file XML ke dalam nilai PostgreSQL XML?

PostgreSQL memiliki asli tipe data XML dengan fungsi XMLPARSE untuk mengurai string teks ke tipe itu. Ini juga memiliki cara untuk membaca data dari sistem file; pernyataan COPY, antara lain.

Tapi saya tidak melihat cara untuk menulis pernyataan SQL PostgreSQL asli untuk membaca konten dari entri sistem file dan menggunakannya untuk mengisi nilai XML. Bagaimana saya bisa melakukan ini?

12
bignose

The pg_read_binary_file fungsi dapat melakukan ini.

Ini memiliki keterbatasan: baru di PostgreSQL 9.1 atau lebih tinggi; harus sesi yang dimiliki oleh pengguna super basis data; harus membaca file di dalam direktori database atau di bawah ini. Itu dapat diterima dalam kasus penggunaan saya.

Jadi yang berikut ini akan berfungsi untuk membuat nilai asli XML dari file:

-- PostgreSQL 9.1 or later.
SELECT
    XMLPARSE(DOCUMENT convert_from(
        pg_read_binary_file('foo.xml'), 'UTF8'));

Dalam PostgreSQL 8.3 - 9.0, the pg_read_file fungsi dapat digunakan, dengan batasan tambahan bahwa Anda tidak dapat menentukan pengkodean file khusus (itu membaca file sebagai teks dalam pengkodean sesi saat ini).

-- PostgreSQL earlier than 9.1.
SELECT
    XMLPARSE(DOCUMENT pg_read_file('foo.xml'));
4
bignose

Mirip dengan ini menjawab pertanyaan sebelumnya, dan jika Anda tidak ingin pembatasan pg_read_file() (singkatnya: pg_read_file tidak dapat membaca file di luar direktori basis data, dan membaca teks dalam pengkodean karakter sesi saat ini).

Fungsi ini berfungsi untuk semua jalur, tetapi harus dibuat sebagai superuser:

create or replace function stack.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 diperkenalkan pada 9,4 sehingga untuk versi yang lebih lama Anda perlu:

create or replace function stack.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;$$;

kemudian:

select convert_from(stack.bytea_import('/tmp/test.xml'), 'utf8')::xml;

Saya telah memposting implementasi lengkap dari apa yang Anda minta dalam jawaban terakhir pada SO .

Fitur utama adalah xpath() fungsi, pg_read_file(), penanganan array, fungsi plpgsql, ..

3