PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Importieren Sie ein XML-Schema in Postgres, um automatisch eine Tabelle zu erstellen und diese dann mit einer XML-Datei zu füllen?

Es gibt wahrscheinlich tausend Möglichkeiten, XML-Dateien in PostgreSQL zu importieren, aber hier ist eine Alternative, die ich recht einfach zu implementieren finde und die bereits mit großen XML-Dokumenten (120 GB+) getestet wurde.

Ziehen Sie je nach Größe Ihrer XML-Datei in Erwägung, sie aufzuteilen. Ein tolles Tool dafür ist xml_split . Dieser Befehl teilt file.xml in kleineren Dateien mit maximal 100 MB:

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

Sobald Sie Ihre Dateien auf eine angemessene Größe aufgeteilt haben, können Sie mit dem Import beginnen, ohne Gefahr zu laufen, dass Ihnen der Speicherplatz ausgeht.

Betrachten wir die folgende XML-Dateistruktur ...

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

... und die folgende Zieltabelle, in die wir die XML-Einträge einfügen werden.

CREATE TABLE t (id TEXT, entry XML);

Der folgende Code importiert XML-Dateien in einen temporären abgemeldet Tabelle und entschachteln sie in die Tabelle t mit einem CTE (auch bekannt als WITH-Klausel) durch den Knoten <foo> . Der Befehl perl -pe 's/\n/\\n/g' ersetzt Zeilenumbrüche durch \\n damit Sie kein Premature end of data bekommen Ausnahme:

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

Und hier sind Ihre Daten:

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)