Доступ к внешним XML-файлам как переменным в сценарии PSQL (получен из сценария bash) - PullRequest
0 голосов
/ 27 апреля 2018

После этого примера у меня возникли проблемы с использованием переменных PostgreSQL в сценарии * .sql:

  • Я хочу перебрать несколько файлов данных XML, используя скрипт BASH

  • скрипт BASH назначает имена файлов XML переменной, которая передается в скрипт SQL

  • SQL-скрипт, вызываемый этим BASH-скриптом, загружает эти данные в PostgreSQL

Если я получу файлы XML напрямую, проблем не будет; Однако я не могу получить доступ к этой переменной в моем сценарии SQL:

В моем скрипте SQL (hmdb.sql) я могу получить доступ к переменной PSQL :bash_var (передается из скрипта BASH):

\echo '\nEXTERNAL VARIABLE (= "datafile", HERE):' :bash_var '\n'

и / или непосредственно ссылаться на файл XML,

datafile text := 'hmdb/hmdb.xml';

но не как переменная:

datafile text := 'bash_var';

hmdb.sh

#!/bin/bash

DATA_DIR=data/

for file in $DATA_DIR/*.xml
  do
    bash_var=$(echo ${file##*/})
    echo $bash_var
    psql -d hmdb -v bash_var=$bash_var -f hmdb.sql
done

1 Ответ

0 голосов
/ 28 апреля 2018

ОК, вот мое решение.

Более подробный ответ я публикую в своем блоге Persagen.com .

По сути, я решил отказаться от подхода DO $$DECLARE ... (описанного в SO 49950384 ) в пользу упрощенного подхода ниже.

Затем я могу получить доступ к общей переменной BASH / PSQL, :bash_var, таким образом:

xpath('//metabolite', XMLPARSE(DOCUMENT convert_from(pg_read_binary_file(:'bash_var'))))

Вот пример сценария SQL, иллюстрирующий это использование:

hmdb.sql

\c hmdb

CREATE TABLE hmdb_identifiers (
  id SERIAL,
  accession VARCHAR(15) NOT NULL,
  name VARCHAR(300) NOT NULL,
  cas_number VARCHAR(12),
  pubchem_cid INT,
  PRIMARY KEY (id),
  UNIQUE (accession)
);

\echo '\n[hmdb.sql] bash_var:' :bash_var '\n'

-- UPDATE (2019-05-15): SEE MY COMMENTS BELOW RE: TEMP TABLE!
CREATE TEMP TABLE tmp_table AS 
SELECT 
  (xpath('//accession/text()', x))[1]::text::varchar(15) AS accession
  ,(xpath('//name/text()', x))[1]::text::varchar(300) AS name 
  ,(xpath('//cas_registry_number/text()', x))[1]::text::varchar(12) AS cas_number 
  ,(xpath('//pubchem_compound_id/text()', x))[1]::text::int AS pubchem_cid 
-- FROM unnest(xpath('//metabolite', XMLPARSE(DOCUMENT convert_from(pg_read_binary_file('hmdb/hmdb.xml'), 'UTF8')))) x
FROM unnest(xpath('//metabolite', XMLPARSE(DOCUMENT convert_from(pg_read_binary_file(:'bash_var'), 'UTF8')))) x
;

INSERT INTO hmdb_identifiers (accession, name, cas_number, pubchem_cid)
  SELECT lower(accession), lower(name), lower(cas_number), pubchem_cid FROM tmp_table;

DROP TABLE tmp_table;

Примечания сценария SQL:

  • В инструкциях xpath я переделываю ::text (например: ::text::varchar(15)) для схемы таблицы Postgres.

  • Что еще важнее, если бы я не преобразовал типы данных в операторе xpath, и запись в поле (например, name length) превысила ограничение длины SQL varchar(300), эти данные бросили бы Ошибка PSQL и таблица не обновлялась (т.е. результаты пустой таблицы).

Я загрузил файлы данных XML, использованные в этом ответе, в этот список

https://gist.github.com/victoriastuart/d1b1959bd31e4de5ed951ff4fe3c3184

Прямые ссылки:


ОБНОВЛЕНИЕ (2019-05-15)

В последующих работах, подробно описанных в моем посте в исследовательском блоге Экспорт простого текста в PostgreSQL , я напрямую загружаю данные XML в PostgreSQL, а не использую временные таблицы.

TL / DR. В этом проекте я заметил следующие улучшения.

Parameter | Temp Tables  | Direct Import | Reduction
    Time: | 1048 min     | 1.75 min      | 599x
   Space: | 252,000 MB   | 18 MB         | 14,000x
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...