2016-04-22 3 views
0

Ich habe eine 450 MB xml-Datei, und ich möchte es in Blob Spalte in Oracle-Tabelle einfügen. Ich habe versucht, den Inhalt der Datei als Zeichenfolge einzufügen, aber es sagt "Zeichenfolge literal zu lang" .Kann jemand bitte einen eleganten Weg vorschlagen, in die Tabelle einzufügen. Bereitgestellt: Ich habe keinen Verzeichniszugriff im Datenbankserver, ich habe die XML-Datei in meinem lokalen SystemFügen Sie große XML-Datei als Blob in Oracle-Tabelle

+0

Verwenden Sie http://blogs.perficient.com/delivery/blog/2012/05/29/insert-a-long-xml-string-to-db-table-with-plsql/ –

Antwort

1

Sie können die XML-Datei in ein SQL-Skript konvertieren, das einen entsprechend gestalteten anonymen PLSQL-Block ausführt. Das Laden dieses Skripts in die Datenbank füllt den Blob.

Die Grundidee besteht darin, die XML-Datei in Stücke von 2000 Zeichen aufzuteilen. Der erste Chunk kann direkt in die Blob-Spalte der Zieltabelle eingefügt werden. Die anderen werden durch eine Update-Anweisung hinzugefügt, die den Vorteil der Paketprozedur dbms_lob.fragment_insert nutzt. !!! WARNUNG: Dies ist keine empfohlene Übung!. Holen Sie sich besser eine dba, um es für Sie zu laden!

Beispiel:

  • Annahmen:

    • Die Zieltabelle hat 2 Spalten, die pk und den Blob.
    • der PC ist 42.
    • 2000 ist ein Beispiel Chunk Größe als geeignet erachtet. Technisch gesehen behandelt dbms_lob.fragment_insert bis zu 32767, jedoch können andere beteiligte Werkzeuge (z. B. sqlplus) engere Grenzen für die Zeilenlänge haben.
  • Code:

    declare 
        l_b BLOB; 
    begin 
        insert 
         into 
        t_target (c_pk, c_blob) 
        values (42, utl_raw.cast_to_raw('<This literal contains the first 2000 (chunksize) characters of the xml file>')) 
    returning c_blob 
        into l_b 
         ; 
    
    dbms_lob.fragment_insert (l_b, 2000, 1+dbms_lob.getlength(l_b), utl_raw.cast_to_raw('<This literal contains 2000 characters starting at [0-based] offset 2000>')); 
    dbms_lob.fragment_insert (l_b, 2000, 1+dbms_lob.getlength(l_b), utl_raw.cast_to_raw('<This literal contains 2000 characters starting at [0-based] offset 4000>')); 
    dbms_lob.fragment_insert (l_b, 2000, 1+dbms_lob.getlength(l_b), utl_raw.cast_to_raw('<This literal contains 2000 characters starting at [0-based] offset 6000>')); 
    ... 
    dbms_lob.fragment_insert (l_b, 2000, 1+dbms_lob.getlength(l_b), utl_raw.cast_to_raw('<This literal contains the last chunk>')); 
    
    commit; 
    end; 
    /
    show err 
    

Vorbereitende Arbeiten

  1. Sie müssen sicherstellen, dass kein Apostroph in Ihrem XML-Datei auftritt. Andernfalls enthält der generierte Plsql-Code Syntaxfehler.

    Wenn einfache Anführungszeichen nicht als Attributwertbegrenzer verwendet werden, ersetzen Sie sie einfach durch die numerische Entität &x#28;.

  2. den Großteil des anonymen plsql erstellen

Methoden für die Daten in eine Datei in regelmäßigen Abständen präsentiert in this SO question, die flexibelste Ansatz in this answer Einfügen skizziert werden. Statt neue Zeilen, legen Sie die folgende Zeichenfolge eingefügt:

"'));\n  dbms_lob.fragment_insert (l_b, 2000, 1+dbms_lob.getlength(l_b), utl_raw.cast_to_raw('" 

Der Rest des anonymen plsql kann von Hand kopiert/geschrieben werden.

Caveat

Wie ist, wird das Skript Größe wie das Original xml in der gleichen Größenordnung sein und der plsql Block 200k + Zeilen enthalten. Sehr wahrscheinlich stoßen Sie auf einige Einschränkungen der beteiligten Tools. Allerdings kann das Skript in eine beliebige Anzahl von Stücken wie folgt aufgeteilt werden:

declare 
    l_b BLOB; 
begin 
    select c_blob 
     into l_b 
     from t_target 
    where c_pk = 42 
     ; 

dbms_lob.fragment_insert (l_b, 2000, 1+dbms_lob.getlength(l_b), utl_raw.cast_to_raw('<This literal contains 2000 characters starting at [0-based] offset <k>*2000>')); 
dbms_lob.fragment_insert (l_b, 2000, 1+dbms_lob.getlength(l_b), utl_raw.cast_to_raw('<This literal contains 2000 characters starting at [0-based] offset (<k>+1)*2000>')); 
dbms_lob.fragment_insert (l_b, 2000, 1+dbms_lob.getlength(l_b), utl_raw.cast_to_raw('<This literal contains 2000 characters starting at [0-based] offset (<k>+2)*2000>')); 
... 
dbms_lob.fragment_insert (l_b, 2000, 1+dbms_lob.getlength(l_b), utl_raw.cast_to_raw('<This literal contains 2000 characters starting at [0-based] offset (<k>+<n_k>)*2000>')); 
end; 
/
show err 

Und noch einmal: !!! WARNUNG: Dies ist keine empfohlene Übung!. Holen Sie sich besser eine dba, um es für Sie zu laden!

1

Wie wäre es mit kleinen Programm auf allen Sprachen, die in der Lage ist, eine Datei zu lesen und einfügen Abfrage in Ihre Tabelle.

+0

Das klingt am einfachsten. Das Programm könnte mit PLSQL direkt in der Oracle-Datenbank durchgeführt werden. Aber das könnte Arbeit erfordern. –

+0

Ich meinte andere Sprachen - Java, Python ... Es sollte nicht mehr als Stunde ausgeben –

2

Nehmen wir an, Sie suchen ein wenig und stoßen auf eine search result: Sie finden eine Seite mit PL/SQL-Code.

CREATE OR REPLACE DIRECTORY test_dir AS '<path_on_db_server>'; 

DECLARE 
    l_bfile BFILE; 
    l_blob BLOB; 
BEGIN 
    -- this depends on your table definition, col1 being the BLOB column 
    INSERT INTO tab1 (col1, col2) VALUES (empty_blob(), 'test1') 
    RETURN col1 INTO l_blob; 

    l_bfile := BFILENAME('test_dir', 'my.xml'); 
    DBMS_LOB.fileopen(l_bfile, Dbms_Lob.File_Readonly); 
    DBMS_LOB.loadfromfile(l_blob, l_bfile, DBMS_LOB.getlength(l_bfile)); 
    DBMS_LOB.fileclose(l_bfile); 

    COMMIT; 
END; 

Dann versuchen Sie es (nachdem Sie Ihre test.xml Datei auf dem Server in <path_on_db_server> setzen und dafür gesorgt, dass oracle Benutzer Zugriff auf die Datei hat).

Verwandte Themen