it-swarm.com.de

SQL zum Lesen von XML aus einer Datei in die PostgreSQL-Datenbank

Wie kann ich SQL schreiben, um eine XML-Datei in einen PostgreSQL XML -Wert zu lesen?

PostgreSQL hat ein natives XML-Datentyp mit der Funktion XMLPARSE, um eine Textzeichenfolge für diesen Typ zu analysieren. Es gibt auch Möglichkeiten, Daten aus dem Dateisystem zu lesen. unter anderem die Anweisung COPY.

Ich sehe jedoch keine Möglichkeit, native PostgreSQL-SQL-Anweisungen zu schreiben, um den Inhalt aus einem Dateisystemeintrag zu lesen und damit einen XML -Wert zu füllen. Wie kann ich das machen?

12
bignose

Die pg_read_binary_file Funktion kann dies tun.

Es gibt Einschränkungen: neu in PostgreSQL 9.1 oder höher; muss eine Sitzung sein, die dem Datenbank-Superuser gehört; muss eine Datei im Datenbankverzeichnis oder darunter lesen. Diese sind in meinem Anwendungsfall akzeptabel.

Das Folgende funktioniert also, um einen nativen XML -Wert aus einer Datei zu erstellen:

-- PostgreSQL 9.1 or later.
SELECT
    XMLPARSE(DOCUMENT convert_from(
        pg_read_binary_file('foo.xml'), 'UTF8'));

In PostgreSQL 8.3 - 9.0 wird das pg_read_file kann verwendet werden, mit der zusätzlichen Einschränkung, dass Sie keine dateispezifische Codierung angeben können (sie liest die Datei als Text in der Codierung der aktuellen Sitzung).

-- PostgreSQL earlier than 9.1.
SELECT
    XMLPARSE(DOCUMENT pg_read_file('foo.xml'));
4
bignose

Ähnlich wie this Antwort auf eine vorherige Frage, und wenn Sie nicht möchten die Einschränkungen von pg_read_file() (kurz: pg_read_file kann keine Dateien außerhalb des Datenbankverzeichnisses lesen und liest Text in der Zeichenkodierung der aktuellen Sitzung.

Diese Funktion funktioniert für jeden Pfad, muss jedoch als Superuser erstellt werden:

create or replace function stack.bytea_import(p_path text, p_result out bytea) 
                   language plpgsql as $$
declare
  l_oid oid;
begin
  select lo_import(p_path) into l_oid;
  select lo_get(l_oid) INTO p_result;
  perform lo_unlink(l_oid);
end;$$;

lo_get wurde in 9.4 eingeführt, sodass Sie für ältere Versionen Folgendes benötigen würden:

create or replace function stack.bytea_import(p_path text, p_result out bytea) 
                   language plpgsql as $$
declare
  l_oid oid;
  r record;
begin
  p_result := '';
  select lo_import(p_path) into l_oid;
  for r in ( select data 
             from pg_largeobject 
             where loid = l_oid 
             order by pageno ) loop
    p_result = p_result || r.data;
  end loop;
  perform lo_unlink(l_oid);
end;$$;

dann:

select convert_from(stack.bytea_import('/tmp/test.xml'), 'utf8')::xml;

Ich habe eine vollständige Implementierung dessen, was Sie verlangen, in einem aktuelle Antwort auf SO veröffentlicht.

Die Hauptmerkmale sind die Funktion xpath(), pg_read_file(), Array-Handhabung, plpgsql-Funktionen, ..

3