PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Acessando arquivos XML externos como variáveis ​​em um script PSQL (originado de um script bash)


OK, aqui está a minha solução.

Eu posto uma resposta mais detalhada no meu blog Persagen.com.

Basicamente, decidi revogar o DO $$DECLARE ... abordagem (descrita no SO 49950384) em favor da abordagem simplificada, abaixo.

Posso então acessar a variável compartilhada BASH/PSQL, :bash_var , assim:
xpath('//metabolite', XMLPARSE(DOCUMENT convert_from(pg_read_binary_file(:'bash_var'))))

Aqui está um exemplo de script SQL, ilustrando esse uso:

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;

Observações do script SQL:

  • Nas instruções xpath eu reformulo o ::text (por exemplo:::text::varchar(15) ) de acordo com o esquema da tabela Postgres.

  • Mais significativamente, se eu não reformule os tipos de dados na instrução xpath e uma entrada de campo (por exemplo, name length) excedeu o SQL varchar(300) limite de comprimento, esses dados geraram um erro de PSQL e a tabela não foi atualizada (ou seja, resultados de uma tabela em branco).

Eu carreguei os arquivos de dados XML usados ​​nesta resposta neste Gist

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

Links diretos:

  • hmdb_metabolites_5000-01.xml

  • hmdb_metabolites_5000-02.xml

  • hmdb_metabolites_5000-03.xml

  • Fonte:HMDB.ca
    • Citação

ATUALIZAÇÃO (2019-05-15)

No trabalho de acompanhamento, detalhado em minha postagem no blog de pesquisa Exportando texto simples para PostgreSQL, carrego dados XML diretamente no PostgreSQL, em vez de usar tabelas temporárias.

TL/DR. Nesse projeto, observei as seguintes melhorias.
Parameter | Temp Tables  | Direct Import | Reduction
    Time: | 1048 min     | 1.75 min      | 599x
   Space: | 252,000 MB   | 18 MB         | 14,000x