SQL для чтения XML из файла в базу данных PostgreSQL

12

Как я могу написать SQL для чтения XML-файла в XMLзначение PostgreSQL ?

PostgreSQL имеет собственный тип данных XML с XMLPARSEфункцией синтаксического анализа текстовой строки для этого типа. Также есть способы чтения данных из файловой системы; COPYзаявление, среди других.

Но я не вижу способа написать собственные операторы PostgreSQL SQL для чтения содержимого из записи файловой системы и использования его для заполнения XMLзначения. Как я могу это сделать?

большой нос
источник

Ответы:

10

Подобно этому ответу на предыдущий вопрос, и если вы не хотите ограниченийpg_read_file() (короче: pg_read_fileне может читать файлы вне каталога базы данных и читает текст в кодировке символов текущего сеанса).

Эта функция работает для любого пути, но ее необходимо создать как суперпользователь:

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 был введен в 9.4, поэтому для более старых версий вам понадобится:

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

тогда:

select convert_from(stack.bytea_import('/tmp/test.xml'), 'utf8')::xml;
Джек говорит, попробуйте topanswers.xyz
источник
1
+1, спасибо за указание на то, что существуют ограничения для функций чтения файлов.
bignose
1
+1 хороший трюк, чтобы обойти pg_read_file(). Этого также можно добиться с помощью временной таблицы и COPY- заполнить только 1 столбец из 1 строки.
Эрвин Брандштеттер
4

pg_read_binary_fileФункция может сделать это.

Он имеет ограничения: новое в PostgreSQL 9.1 или выше; должен быть сеанс, принадлежащий суперпользователю базы данных; Необходимо прочитать файл в каталоге базы данных или ниже. Это приемлемо в моем случае использования.

Таким образом, следующее будет работать для создания собственного XMLзначения из файла:

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

В PostgreSQL 8.3–9.0 pg_read_fileможет использоваться функция с дополнительным ограничением, заключающимся в том, что вы не можете указать специфичную для файла кодировку (она читает файл как текст в кодировке текущей сессии).

-- PostgreSQL earlier than 9.1.
SELECT
    XMLPARSE(DOCUMENT pg_read_file('foo.xml'));
большой нос
источник
3

Я опубликовал полную реализацию того, что вы просите в недавнем ответе на SO .

Ключевыми функциями являются xpath()функция, pg_read_file()обработка массива, функции plpgsql, ..

Эрвин Брандштеттер
источник
Скорее другой (и более тяжелый), чем то, что мне нужно в этом случае. Но +1 за хорошее направление, спасибо.
bignose
Это не что тяжеловес, мой пример как раз очень в комплекте с резервными элементами, демонстрирующих варианты синтаксиса.
Эрвин Брандштеттер