【问题标题】:Insert large xml file as as blob in oracle table在 oracle 表中将大型 xml 文件作为 blob 插入
【发布时间】:2016-08-15 17:14:04
【问题描述】:

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

【问题讨论】:

标签: xml database oracle plsql blob


【解决方案1】:

假设您搜索了一下并偶然发现了 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 文件放在服务器上&lt;path_on_db_server&gt; 并确保oracle 用户可以访问该文件之后)。

【讨论】:

    【解决方案2】:

    您可以将 xml 文件转换为执行适当制作的匿名 plsql 块的 sql 脚本。将此脚本加载到数据库中将填充 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代码会包含语法错误。

      如果不使用单引号作为属性值分隔符,只需将它们替换为数字实体&amp;x#28;

    2. 创建大量匿名 plsql

    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 为您加载它!

    【讨论】:

      【解决方案3】:

      如何编写任何语言的小程序,它能够读取文件并将查询插入到您的表中。

      【讨论】:

      • 这听起来最简单。该程序可以直接在 Oracle 数据库上使用 PLSQL 完成。但这可能需要工作。
      • 我的意思是其他语言 - java、python ...它不应该花费超过一个小时
      猜你喜欢
      • 2022-07-11
      • 2014-11-26
      • 2015-02-20
      • 2011-02-01
      • 2019-11-22
      • 2013-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多