我有一个450 MB的xml文件,我想将它插入Oracle表的Blob列中。我尝试将文件内容插入为字符串,但它说“字符串文字太长”。任何人都可以建议一种优雅的方式插入表格。 提供:我在数据库服务器中没有目录访问权限,我在本地系统中有xml文件
答案 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为你加载它!
<强> 实施例 强>:
假设:
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
准备工作
您需要确保xml文件中没有单引号。 否则生成的plsql代码将包含语法错误。
如果单引号未用作属性值分隔符,只需将其替换为数字实体&x#28;
。
创建大量匿名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为你加载它!