PL/SQL处理XML的问题

Namana 2010-08-02 10:55:25
现在碰到一个问题,有一个存储过程用于解析XML数据。
在表A中有字段CLOB存储XML文本
TABLE A
( id integer,
text CLOB
)


PROCEDURE proc_import_xml_info
(
p_seqno IN VARCHAR2,
p_o_retmsg OUT VARCHAR2
) IS
v_tmp_msg VARCHAR2(4000);
xml_parser xmlparser.parser;
vs_xml dat_aas_xml_text.text%TYPE;
vd_doc xmldom.domdocument;
vn_docnode xmldom.domnode;
vs_sql VARCHAR2(8000);
vs_vsql VARCHAR2(8000);
vi_depest_fno INTEGER;
BEGIN
--获取需要处理的数据
BEGIN
SELECT t.text
INTO vs_xml
FROM A t
WHERE t.id=p_seqno ;
EXCEPTION
WHEN OTHERS THEN
v_tmp_msg := '获取XML文本出错';
ROLLBACK;
END;
--解析XML
xml_parser := xmlparser.newparser;
xmlparser.setvalidationmode(xml_parser, FALSE);
xmlparser.parseclob(xml_parser, vs_xml);
vd_doc := xmlparser.getdocument(xml_parser);
xmlparser.freeparser(xml_parser);
vn_docnode := xmldom.makenode(xmldom.getdocumentelement(vd_doc));
--解析完成,按XML内字段处理
IF NOT xmldom.isnull(vd_doc) THEN
SELECT MAX(t.forest_no)
INTO vi_depest_fno
FROM par_aas_xml_model t
WHERE t.fcode = p_fcode;
BEGIN
r_split_xml(p_fcode, '', vn_docnode, vd_doc, vi_depest_fno, vs_sql, vs_vsql);
EXCEPTION
WHEN OTHERS THEN
p_o_retmsg := 'xml解析异常' || SQLERRM;
RETURN;
END;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;

r_split_xml是解析XML的存储过程。解析的方式使用配好到表的各个XML的TAG进行解析

PROCEDURE r_split_xml
(
is_fcode IN VARCHAR2, --文件类型
ii_pforest_no IN INTEGER, --当前结点层次序号
in_node IN xmldom.domnode, --当前结点
id_doc IN xmldom.domdocument, --XML文档对象
ii_depest_fno IN INTEGER, --最末层次序号
vs_sql IN OUT VARCHAR2, --缓存SQL语句1
vs_value_sql IN OUT VARCHAR2 --缓存SQL语句2
) AS
vn_node xmldom.domnode;
len INTEGER := 0;
vn_nlist xmldom.domnodelist;
vs_node_name VARCHAR2(200);
vi_count INTEGER;
vs_column_name config_table_sub.table_column%TYPE;
vs_this_sql VARCHAR2(8000) := vs_sql;
vs_this_vsql VARCHAR2(8000) := vs_value_sql;
BEGIN
FOR vr_splits IN (SELECT *
FROM config_table
WHERE fcode = is_fcode
AND (parent_forest = ii_pforest_no OR (parent_forest IS NULL AND ii_pforest_no IS NULL)))
LOOP
IF ii_pforest_no IS NULL THEN
vs_this_sql := 'INSERT INTO ' || vr_splits.recieve_table_name || '(';
vs_this_vsql := ' VALUES(';
vs_sql := vs_this_sql;
vs_value_sql := vs_this_vsql;
END IF;
--获取当前层次的子节点集合
vn_nlist := xmldom.getchildnodes(in_node);
len := xmldom.getlength(vn_nlist);
--如果存在该层子结点的数据,则按config_table_sub中该层的NODE_NAME解析
IF len > 0 THEN
FOR i IN 0 .. len - 1
LOOP
vn_node := xmldom.item(vn_nlist, i);
vs_node_name := xmldom.getnodename(vn_node);
SELECT COUNT(1)
INTO vi_count
FROM config_table t
WHERE t.parent_forest = vr_splits.forest_no
AND t.node_name = vs_node_name;
IF vi_count >= 1 THEN
--如果子节点名,以该节点循环处理该节点下的子结点
r_split_xml(is_fcode, nvl(ii_pforest_no, 0) + 1, vn_node, id_doc, ii_depest_fno, vs_sql, vs_value_sql);
ELSE
--如果是普通结点,判断是否需要插入表中。
vs_column_name := '';
BEGIN
SELECT t.table_column
INTO vs_column_name
FROM config_table_sub t
WHERE t.f_code = is_fcode
AND t.forest_no = vr_splits.forest_no
AND t.node_name = vs_node_name;
EXCEPTION
WHEN no_data_found THEN
NULL;
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;
IF vs_column_name IS NOT NULL THEN
vs_this_sql := vs_this_sql || vs_column_name || ',';
vs_this_vsql := vs_this_vsql || '''' || xmldom.getnodevalue(xmldom.getfirstchild(vn_node)) || ''',';
END IF;
IF vr_splits.forest_no < ii_depest_fno THEN
--如果还没到最末节点,缓存
vs_sql := vs_this_sql;
vs_value_sql := vs_this_vsql;
END IF;
END IF;
END LOOP;
END IF;
IF vr_splits.forest_no = ii_depest_fno THEN
--如果到达最末节点,则拼接完成SQL语句,执行操作。
--接收表都定义了以下字段,所以需要处理
vs_this_sql := vs_this_sql || 'DATA_DATE,DATA_WAY,DATA_TIME,IS_DEALED )';
vs_this_vsql := vs_this_vsql || 'to_char(sysdate,''YYYYMMDD''),''1'',sysdate,''1'')';
dbms_output.put_line('insert_sql :' || vs_this_sql || vs_this_vsql);
BEGIN
EXECUTE IMMEDIATE vs_this_sql || vs_this_vsql;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END r_split_xml;

其中config_tab保存的是每个有子节点的XML TAG。config_tab保存的是每层的子节点
例如对于下面的XML,在config_tab里会配置两条
forest_no parent_forest node_name
1 OUT
2 1 DETAIL
在config_tab_sub里会配置OUT和DETAIL下的TAG
forest_no node_name
2 TAG1
2 TAG2
3 DT1
3 DT2

<OUT>
<TAG1></TAG1>
<TAG2></TAG2>
<DETAIL>
<DT1></DT1>
<DT2></DT2>
</DETAIL>
<DETAIL>
<DT1></DT1>
<DT2></DT2>
</DETAIL>
<DETAIL>
<DT1></DT1>
<DT2></DT2>
</DETAIL>
<DETAIL>
<DT1></DT1>
<DT2></DT2>
</DETAIL>
</OUT>

那么情况是如果这么XML很大,有几百K,并且主要集中是会有近千条的DETAIL。
问题1: 在解析一个XML的过程中,CLOB这个字段什么时候释放;如果以XML为400K为例,占用的内存大小至少是多少;
2: 解析一个上面情况的XML需要花的时候会不会很久;
3: 因为在解析的时候用了递归,是不是在处理是会消耗更多的内存;
4: 直接结束之后是否需要对LOB进行手工FREE。我试了一下FREE的时候会报错。这种情况使用的LOB变量是不是不用FREE了?
5: 是否有更优的解析方法。
望各位达人不吝赐教啊。
...全文
297 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
rockywu 2010-12-02
  • 打赏
  • 举报
回复
xml
雕虫大计 2010-08-04
  • 打赏
  • 举报
回复
数据库也能解析xml,学习了。
Namana 2010-08-04
  • 打赏
  • 举报
回复
这个是释放表里这个字段的空间吧?释放变量的呢?我给赋值成empty_clob算吗
iqlife 2010-08-03
  • 打赏
  • 举报
回复
http://blog.mchz.com.cn/?p=955
看看
Namana 2010-08-03
  • 打赏
  • 举报
回复
那为什么程序里的那个LOB我用dbms_lob.freetemporary的时候报invalid loc locator的错误呢~~~
iqlife 2010-08-02
  • 打赏
  • 举报
回复
临时LOB对象
LOB对象包括BLOB、CLOB、NCLOB、和BFILE。在PLSQL程序块中,如果定义了LOB变量,则这些LOB变量就是临时LOB对象。临时LOB对象被创建在临时表空间上,直到LOB数据被释放,或者会话结束。
Oracle官方11g 最新版jdbc驱动。 新特性:   1、支持JDK6,支持JDBC 4.0,新的java.sql.SQLXML类型没有被支持,是使用ojdbc6.jar来支持。J2SE 5.0 和 JDBC 3.0 全面支持使用ojdbc5.jar。   2.不再支持oracle.jdbc.driver。从9.0.1开始的每个release都推荐使用oracle.jdbc。这一天终于到来,在11g中,引用oracle.jdbc.driver不再通过编译。   3.j2se 1.2,1.3,1.4不再支持。11R1不再包括这些版本的jar和zip,如果仍然使用这些版本,可以继续使用10gR2的jdbc。   4.11gR1 Thin driver支持AES加密算法,SHA1 hash算法,RADIUS, KERBEROS,SSL认证机制.   5.支持ANYDATE和ANYTYPE类型。这两种类型自9i引入,11R1前,程序员只能通过PL/SQL操作。   6.高级队列支持。11R1提供了访问AQ的高性能接口。   7.支持数据库变更通知。   8.Thin和OCI的数据库启动和关闭。11R1提供了这样的方法来启动和关闭数据库。   9.新的工厂方法。Oracle JDBC 11R1 oracle.jdbc.OracleConnection提供了创建Oracle对象的工厂方法。   包括ARRAY, BFILE, DATE, INTERVALDS, NUMBER, STRUCT, TIME,TIMESTAMP,TIMESTAMP等。   ojdbc5.jar: 适用于jdk5   ojdbc6.jar: 适用于jdk6   ***_g.jar 只是用javac -g编译,生成所有调试信息,其它全一样   ---------------------------------------------------   总体讲新版本的JDBC驱动 性能强、很多bug被发现并已解决。   我遇到的,之前使用ojdbc14.jar(不记得哪个版本了)批量插入10万条,实际只插入了3万多条,其它的丢失了,换ojdbc6.jar后,一次commit批量插入100万条也OK了。   尽量使用和数据库版本一致的驱动,有bug时,换高版本的JDBC驱动试试 。

3,490

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 高级技术相关讨论专区
社区管理员
  • 高级技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧