2016-04-22 14 views
0

私は450 MBのxmlファイルを持っています。これをOracleテーブルのBlobカラムに挿入します。私は文字列としてファイルの内容を挿入しようとしましたが、それは "文字列リテラルが長すぎる"と言います。誰もテーブルに挿入するエレガントな方法をお勧めします。 提供:データベースサーバーにディレクトリアクセス権がありません。ローカルシステムにxmlファイルがあります大きなxmlファイルをblobとしてoracleテーブルに挿入します。

+0

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

答えて

1

適切に細工された匿名のplsqlブロックを実行するsqlスクリプトにxmlファイルを変換することができます。このスクリプトをdbにロードすると、BLOBが読み込まれます。

基本的な考え方は、xmlファイルを2000文字のチャンクに分割することです。最初のチャンクは、ターゲットテーブルのBLOBカラムに直接挿入することができます。お互いは、dbms_lob.fragment_insertパッケージ手順を利用して更新ステートメントによって追加されます。 !!!警告:これはお勧めできません!。あなたのためにそれをロードするためにdbaを入手してください!

  • 仮定:

    • 対象テーブルが2列、PKおよびブロブを有しています。
    • このpkは42である。
    • 2000は、適切であると考えられるサンプルチャンクサイズである。技術的には、dbms_lob.fragment_insertが最大32767を処理しますが、他のツール(例:sqlplus)では行の長さがより厳しくなる場合があります。
  • コード:

    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 
    

準備作業

  1. あなたは何の単一引用符は、XMLファイル内で発生していないことを確認する必要があります。 そうしないと、生成されたplsqlコードに構文エラーが含まれます。

    アトリビュート値の区切り文字として一重引用符を使用しない場合は、数値エンティティ&x#28;に置き換えます。

  2. 定期的にファイルにデータを挿入するための

方法はthis SO questionに提示されている、最も柔軟なアプローチがin this answerを概説している匿名のPLSQLの大部分を作成します。改行の代わりに、次の文字列を挿入します。

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

残りの匿名のplsqlは、手作業でコピー/書き込みできます。

警告

は通りであり、スクリプトのサイズは、元のXMLと同じ大きさになり、PLSQLブロックが200K +の行を含むことになります。あなたは、関係するツールのいくつかの制限にぶち込まれます。次のようにしかし、このスクリプトは、チャンクの任意の数に分割することができます。

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 

そして再び:!!!警告:これはお勧めできません!。あなたのためにそれをロードするためにdbaを入手してください!

1

ファイルを読み込んでテーブルに挿入クエリを作成することができます。

+0

これは最も簡単に聞こえます。このプログラムは、Oracleデータベース上で直接PLSQLを使用して実行できます。しかし、これは仕事を必要とするかもしれません。 –

+0

私は他の言語 - Java、Python ...を意味しました... それ以上の時間を費やすべきではありません –

2

少し探して、search resultを見つけたとしましょう:PL/SQLコードのあるページがあります。 (あなたが<path_on_db_server>でサーバー上のtest.xmlファイルを入れて、oracleユーザーがファイルへのアクセス権を持っていることを確実にした後)

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; 

は、その後、あなたはそれを試してみてください。

関連する問題