sql >> Base de Datos >  >> RDS >> PostgreSQL

Acceso a archivos XML externos como variables en un script PSQL (procedente de un script bash)

Bien, aquí está mi solución.

Publico una respuesta más detallada en mi blog Persagen.com.

Básicamente, decidí derogar el DO $$DECLARE ... (descrito en SO 49950384) a favor del enfoque simplificado, a continuación.

Entonces puedo acceder a la variable compartida BASH / PSQL, :bash_var , así:

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

Aquí hay una secuencia de comandos SQL de muestra que ilustra ese 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;

Notas del script SQL:

  • En las declaraciones xpath reformulé el ::text (por ejemplo:::text::varchar(15) ) según el esquema de la tabla de Postgres.

  • Más significativamente, si no refundir los tipos de datos en la declaración xpath y una entrada de campo (por ejemplo, name longitud) superó el SQL varchar(300) límite de longitud, esos datos generaron un error de PSQL y la tabla no se actualizó (es decir, los resultados de una tabla en blanco).

Cargué los archivos de datos XML utilizados en esta respuesta en este Gist

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

Enlaces directos:

  • hmdb_metabolitos_5000-01.xml

  • hmdb_metabolitos_5000-02.xml

  • hmdb_metabolitos_5000-03.xml

  • Fuente:HMDB.ca

    • Cita

ACTUALIZACIÓN (2019-05-15)

En el trabajo de seguimiento, detallado en mi publicación de blog de investigación Exportación de texto sin formato a PostgreSQL, cargo datos XML directamente en PostgreSQL, en lugar de usar tablas temporales.

TL/DR. En ese proyecto, observé las siguientes mejoras.

Parameter | Temp Tables  | Direct Import | Reduction
    Time: | 1048 min     | 1.75 min      | 599x
   Space: | 252,000 MB   | 18 MB         | 14,000x