PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Importer un schéma xml dans postgres pour créer automatiquement une table puis la remplir avec un fichier xml ?

Il y a probablement mille façons d'importer des fichiers XML dans PostgreSQL, mais voici une alternative que je trouve assez facile à mettre en œuvre et qui est déjà testée avec de gros documents xml (120 Go+)

En fonction de la taille de votre fichier XML, envisagez de le diviser. Un outil formidable pour le faire est xml_split . Cette commande divise file.xml dans des fichiers plus petits avec un maximum de 100 Mo :

xml_split -n 5 -l 1 -s 100MB file.xml

Une fois vos fichiers fractionnés dans une taille raisonnable, vous pouvez commencer à les importer sans risquer de manquer de mémoire.

Considérons la structure de fichier XML suivante ...

<?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>

... et la table cible suivante, où nous allons insérer les enregistrements XML.

CREATE TABLE t (id TEXT, entry XML);

Le code ci-dessous importe des fichiers XML dans un non connecté table et unnest les dans la table t en utilisant un CTE (alias clause WITH) par le nœud <foo> . La commande perl -pe 's/\n/\\n/g' remplace les caractères de saut de ligne par \\n afin que vous n'obteniez pas une Premature end of data exception :

#!/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;"

Et voici vos données :

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)