Importieren von XML-Dateien, die zu PostgreSQL
Ich habe eine Menge von XML-Dateien, die ich importieren möchten, die in der Tabelle xml_data
:
create table xml_data(result xml);
Dazu habe ich ein einfaches bash-Skript mit Schleife:
#!/bin/sh
FILES=/folder/with/xml/files/*.xml
for f in $FILES
do
psql psql -d mydb -h myhost -U usr -c \'\copy xml_data from $f \'
done
Allerdings wird dies versuchen zu importieren, die jede Zeile in jeder Datei als separate Zeile. Dies führt zu Fehler:
ERROR: invalid XML content
CONTEXT: COPY address_results, line 1, column result: "<?xml version="1.0" encoding="UTF-8"?>"
Verstehe ich, warum es ausfällt, aber kann nicht herausfinden, wie zu machen \copy
zu importieren, ohne die ganze Datei auf einmal in eine einzige Zeile.
- Nicht this thread auf der dba-Website SO helfen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde versuchen einen anderen Ansatz: Lesen Sie die XML-Datei direkt in variable innerhalb einer plpgsql-Funktion und gehen von dort aus. Sollte viel schneller und viel robuster.
Müssen Sie superuser Privilegien, und die Datei muss lokal auf dem DB-server, in einem leicht zugänglichen Verzeichnis.
Komplettes code-Beispiel mit mehr Erklärung und links:
pg_read_file
liest auf dem server.Necromancing:
Für diejenigen, die brauchen ein funktionierendes Beispiel:
Oder mit weniger Lärm
Mit diesem Beispiel-XML-Datei (MyData.xml):
Beachten:
MyData.xml muss in der PG_Data Verzeichnis (Eltern-Verzeichnis des pg_stat-Verzeichnis).
z.B.
/var/lib/postgresql/9.3/main/MyData.xml
Dies erfordert PostGreSQL 9.1+
Insgesamt haben, können Sie erreichen es fileless, wie diese:
Beachten Sie, dass im Gegensatz zu MS-SQL, xpath text() gibt NULL zurück, auf einen NULL-Wert, und nicht einen leeren string.
Wenn aus irgendeinem Grund Sie brauchen, um explizit zu überprüfen, für die Existenz der NULL, die Sie verwenden können
[not(@xsi:nil="true")]
, die Sie brauchen, um übergeben Sie ein array der namespaces, weil Sie andernfalls eine Fehlermeldung erhalten (Sie können jedoch alle namespaces weglassen, aber xsi).Können Sie auch überprüfen, ob ein Feld enthalten ist, in einem XML-text, indem Sie
zum Beispiel, wenn Sie übergeben Sie ein XML-Wert einer gespeicherten Prozedur/Funktion für CRUD.
(siehe oben)
Beachten Sie auch, dass die richtige Art und Weise übergeben Sie einen null-Wert in der XML ist
<elementName xsi:nil="true" />
und nicht<elementName />
oder nichts. Es gibt keine richtige Art und Weise übergeben Sie den Wert NULL in Attributen (Sie können nur das Attribut weglassen, aber dann wird es schwierig/langsam zu schließen, die Anzahl der Spalten und deren Namen in ein großes dataset).z.B.
(ist kompakter, aber sehr schlecht, wenn Sie brauchen, um es zu importieren, vor allem, wenn von XML-Dateien mit mehreren GB Daten - sehen Sie ein wunderbares Beispiel dafür, dass in der stackoverflow-Daten-dump)
Ausweitung @stefan-steiger ausgezeichnete Antwort, hier ist ein Beispiel, extrahiert die XML-Elemente von der child-Knoten, die enthalten mehrere Geschwister (z.B. mehrere
<synonym>
Elemente, die für einen bestimmten<synomyms>
übergeordneten Knoten).Dass ich auf diese Frage mit meinen Daten gesucht und schon einiges für eine Lösung; seine Antwort war die hilfreichste, zu mir.
Beispiel-Datendatei,
hmdb_metabolites_test.xml
:Beiseite: der original-XML-Datei hatte eine URL in das Dokument-Element
verhindert, dass
xpath
aus der Analyse der Daten. Es wird ausgeführt (ohne Fehlermeldungen), aber die relation/Tabelle ist leer:Da die source-Datei ist 3,4 GB, habe ich beschlossen, zu Bearbeiten, die Zeile mit
sed
:[Hinzufügen der
2
(weistsed
Bearbeiten "Zeile 2") auch-zufällig-in diesem Beispiel-die Verdoppelung dersed
Befehl die Ausführungsgeschwindigkeit.]Mein postgres Ordner "data" (PSQL:
SHOW data_directory;
) istso, als
sudo
musste ich kopieren meine XML-Daten-Datei es undchown
es für den Einsatz in PostgreSQL:Skript (
hmdb_test.sql
):Ausführung, Ausgang (in
PSQL
):Ich habe
tr
ersetzt alle Zeilenumbrüche durch Leerzeichen. So erstellen Sie XML-Datei mit nur einer Zeile. Eine solche Datei kann ich importieren, einfach in eine Zeile mit\copy
.Offensichtlich ist dies nicht eine gute Idee, im Fall, wo Sie multi-line-Werte in XML. Zum Glück ist das nicht mein Fall.
Importieren alle XML-Dateien in den Ordner, den Sie verwenden können, dieses bash-Skript: