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

Importando um esquema xml no postgres para criar automaticamente uma tabela e preenchê-la com um arquivo xml?


Provavelmente existem mil maneiras de importar arquivos XML para o PostgreSQL, mas aqui está uma alternativa que acho bastante fácil de implementar e já foi testada com documentos xml grandes (120 GB+)

Dependendo do tamanho do seu arquivo XML, considere dividi-lo. Uma excelente ferramenta para fazer isso é xml_split . Este comando divide file.xml em arquivos menores com no máximo 100 MB:
xml_split -n 5 -l 1 -s 100MB file.xml

Depois de dividir seus arquivos em um tamanho razoável, você pode começar a importá-los sem correr o risco de ficar sem memória.

Vamos considerar a seguinte estrutura de arquivo XML...
<?xml version="1.0"?>
<t>
    <foo>
        <id j="a">1</id>
        <val>bar1</val>
    </foo>
    <foo>
        <id j="b">8</id>
        <val>bar1</val>
    </foo>
    <foo>
        <id j="c">5</id>
        <val>bar1</val>
    </foo>
    <foo>
        <id j="b">2</id>
    </foo>
</t>

... e a seguinte tabela de destino, onde inseriremos os registros XML.
CREATE TABLE t (id TEXT, entry XML);

O código abaixo importa arquivos XML para um desconectado table e unnest colocá-los na tabela t usando um CTE (aka cláusula WITH) pelo nó <foo> . O comando perl -pe 's/\n/\\n/g' substitui caracteres de nova linha por \\n para que você não obtenha um Premature end of data exceção:
#!/bin/bash

psql testdb -c "CREATE UNLOGGED TABLE tmp (entry xml);"

for f in /path/to/your/files/;do

    cat $f | perl -pe 's/\n/\\n/g' |psql testdb -c "COPY tmp FROM STDIN;"
    psql testdb -c "
    WITH j AS (
      SELECT UNNEST(XPATH('//t/foo',entry)) AS entry FROM tmp
    )
      INSERT INTO t 
      SELECT XPATH('//foo/id/text()',j.entry),j.entry FROM j;

      TRUNCATE TABLE tmp;"

done

psql testdb -c "DROP TABLE tmp;"

E aqui estão seus dados:
testdb=# SELECT * FROM t;
 id  |          entry           
-----+--------------------------
 {1} | <foo>                   +
     |         <id j="a">1</id>+
     |         <val>bar1</val> +
     |     </foo>
 {8} | <foo>                   +
     |         <id j="b">8</id>+
     |         <val>bar1</val> +
     |     </foo>
 {5} | <foo>                   +
     |         <id j="c">5</id>+
     |         <val>bar1</val> +
     |     </foo>
 {2} | <foo>                   +
     |         <id j="b">2</id>+
     |     </foo>
(4 Zeilen)