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