在oracle表中插入大型xml文件和blob一样

时间:2016-04-22 07:29:22

标签: xml database oracle plsql blob

我有一个450 MB的xml文件,我想将它插入Oracle表的Blob列中。我尝试将文件内容插入为字符串,但它说“字符串文字太长”。任何人都可以建议一种优雅的方式插入表格。 提供:我在数据库服务器中没有目录访问权限,我在本地系统中有xml文件

3 个答案:

答案 0 :(得分:2)

假设您搜索了一下{偶然发现search result:您找到了一个包含PL / SQL代码的页面。

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;

然后你尝试一下(将test.xml文件放在<path_on_db_server>的服务器上,并确保oracle用户有权访问该文件。

答案 1 :(得分:1)

如何在任何语言上编写小程序,能够读取文件并在表中进行插入查询。

答案 2 :(得分:1)

您可以将xml文件转换为执行适当制作的匿名plsql块的sql脚本。将此脚本加载到db中将填充blob。

基本思想是将xml文件拆分为2000个字符的块。第一个块可以直接插入目标表的blob列。彼此将通过利用dbms_lob.fragment_insert包过程的更新语句添加。的 !!!警告:建议不要这样做!。最好让dba为你加载它!

<强> 实施例

  • 假设:

    • 目标表有2列,pk和blob。
    • 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. 创建大量匿名plsql

  3. this SO question中提供了定期将数据插入文件的方法,这是最灵活的方法in this answer。插入以下字符串而不是换行符:

    "'));\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为你加载它!