oracle数据库中,用SQL Select直接讀取openoffice ods數據

来至http://blog.chinaunix.net/uid-173640-id-4187684.html

之前有用java封裝一個讀取excel 2000的 oracle package
這個是用來讀取 openoffice ods格式的 package
原理是:
1. 用as_zip解壓得到xml
2. 用oracle xmltype讀取每一行數據, pipelined方式返回.

測試代碼如下

点击(此处)折叠或打开

  1. select b.*
  2. from table( ods_utl_pkg.get_ods_table(
  3.      utl_lob.url2blob('ftp://172.17.2.43/pub/test/work.ods'))) b

oracle package: ods_utl_pkg封裝如下.

点击(此处)折叠或打开

  1. create or replace package ods_utl_pkg
  2. as
  3. /* ********************************************************************
  4.    Ver Date Author Description
  5.    --------- ---------- --------------- ------------------------------------
  6.    1.0 2014-3-29 gangjh 1. 用sql select 讀取open office ods數據
  7.    
  8. ********************************************************************/
  9. subtype celltype is varchar2(4000 byte) ; -- limit for oracle 10g
  10.   type xls_row is record (
  11.     sheet int ,
  12.     row_idx int ,
  13.     col0 celltype,
  14.     col1 celltype,
  15.     col2 celltype,
  16.     col3 celltype,
  17.     col4 celltype,
  18.     col5 celltype,
  19.     col6 celltype,
  20.     col7 celltype,
  21.     col8 celltype,
  22.     col9 celltype,
  23.     col10 celltype,
  24.     col11 celltype,
  25.     col12 celltype,
  26.     col13 celltype,
  27.     col14 celltype,
  28.     col15 celltype,
  29.     col16 celltype,
  30.     col17 celltype,
  31.     col18 celltype,
  32.     col19 celltype
  33.   );
  34.   
  35. type xls_table is table of xls_row ;


  36.                                      
  37. function get_xml (p_blob in blob, p_file_name in varchar2) return xmltype ;

  38. function get_ods_table(p_data in blob) return xls_table pipelined ;
  39. function get_ods_table2(p_data in blob) return xls_table pipelined ;

  40. end ods_utl_pkg;
  41. /
  42. create or replace package body ods_utl_pkg
  43. as

  44. subtype ods_table is xmltype;

  45.   ns_ods constant varchar2(32767) := '
  46. xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
  47. xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
  48. xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
  49. xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
  50. ';



  51. -- for openoffice ods
  52. /*
  53. select ods_utl_pkg.get_xml(utl_lob.url2blob('ftp://172.17.2.43/pub/test/work.ods'),'content.xml') aa
  54. from dual;
  55. */

  56. function get_xml(p_blob in blob, p_file_name varchar2) return xmltype is
  57.   l_clob clob;
  58.   l_blob blob ;
  59.   dest_offset integer := 1;
  60.   src_offset integer := 1;
  61.   lang_context integer := 0;
  62.   warning integer :=0;
  63. begin
  64.   
  65.   l_blob := as_zip.get_file (p_blob, p_file_name);
  66.   dbms_lob.createtemporary(l_clob, true, dbms_lob.call) ;
  67.   dbms_lob.convertToclob( l_clob
  68.                           , l_blob
  69.                           , dbms_lob.lobmaxsize
  70.                           , dest_offset
  71.                           , src_offset
  72.                           , nls_charset_id( 'AL32UTF8' )
  73.                           , lang_context
  74.                           , warning
  75.                           );
  76.   
  77.   return xmltype (l_clob);
  78. end get_xml;

  79. function get_table(p_ods xmltype , idx pls_integer) return xmltype is
  80. xpath_tab constant varchar2(200) :=
  81.     '/office:document-content/office:body/office:spreadsheet/table:table['|| idx ||']' ;
  82. begin
  83.   if p_ods.existsNode(xpath_tab, ns_ods) > 0 then
  84.     return p_ods.extract(xpath_tab, ns_ods);
  85.   else
  86.     return null;
  87.   end if;
  88. end ;



  89. function getStringval(p_node xmltype, p_xpath varchar2, p_ns varchar2 default ns_ods ) return varchar2 is
  90.   t xmltype;
  91. begin
  92.   t := p_node.extract(p_xpath, p_ns) ;
  93.   return case when t is null then null else t.getStringval() end ;
  94. end ;

  95. function getNumberval(p_node xmltype, p_xpath varchar2, p_ns varchar2 default ns_ods ) return Number is
  96.   t xmltype;
  97. begin
  98.   t := p_node.extract(p_xpath, p_ns) ;
  99.   return case when t is null then null else t.getNumberval() end ;
  100. end ;

  101. function get_Cellvalue(p_cell xmltype) return varchar2 is
  102.   vdata_type varchar2(20) ;
  103.   vdata celltype ;
  104. begin
  105.   vdata_type := getStringval(p_cell, '//@office:value-type') ;
  106.   
  107.   if vdata_type = 'string' then
  108.      vdata := getStringval(p_cell, '//text:p/node()');
  109.      if vdata like '<text:s xmlns:text%' then
  110.          vdata := getStringval(xmltype(vdata), '/text:s/text()') ;
  111.      end if;
  112.   elsif vdata_type = 'float' then
  113.      vdata := getStringval(p_cell, '//text:p/node()');
  114.   else
  115.      vdata := null;
  116.   end if;
  117.   
  118.   return vdata ;
  119. end ;


  120.  procedure fill_cell(p_row in out xls_row, v_cellval celltype, c pls_integer) is
  121.  begin
  122.     case
  123.       when c=0 then p_row.col0 := v_cellval ;
  124.       when c=1 then p_row.col1 := v_cellval ;
  125.       when c=2 then p_row.col2 := v_cellval ;
  126.       when c=3 then p_row.col3 := v_cellval ;
  127.       when c=4 then p_row.col4 := v_cellval ;
  128.       when c=5 then p_row.col5 := v_cellval ;
  129.       when c=6 then p_row.col6 := v_cellval ;
  130.       when c=7 then p_row.col7 := v_cellval ;
  131.       when c=8 then p_row.col8 := v_cellval ;
  132.       when c=9 then p_row.col9 := v_cellval ;
  133.       when c=10 then p_row.col10 := v_cellval ;
  134.       when c=11 then p_row.col11 := v_cellval ;
  135.       when c=12 then p_row.col12 := v_cellval ;
  136.       when c=13 then p_row.col13 := v_cellval ;
  137.       when c=14 then p_row.col14 := v_cellval ;
  138.       when c=15 then p_row.col15 := v_cellval ;
  139.       when c=16 then p_row.col16 := v_cellval ;
  140.       when c=17 then p_row.col17 := v_cellval ;
  141.       when c=18 then p_row.col18 := v_cellval ;
  142.       when c=19 then p_row.col19 := v_cellval ;
  143.     end case;
  144.  end;



  145. function get_ods_row_value(p_xmlrow xmltype) return xls_row is
  146.   c_cell_path constant varchar2(200) :='/table:table-row/table:covered-table-cell |
  147.                          /table:table-row/table:table-cell';
  148.   cursor cur_cell is
  149.    select rownum,value(p) data
  150.    from table(xmlsequence( extract(p_xmlrow, c_cell_path, ns_ods))) p;

  151.   v_row xls_row ;

  152.   vrepeated pls_integer ;
  153.   v_current_col pls_integer := 1 ;

  154. begin
  155.     for r in cur_cell loop
  156.       vrepeated := getNumberval(r.data, '//@table:number-columns-repeated') ;
  157.       
  158.       fill_cell(v_row, get_Cellvalue(r.data), v_current_col -1) ;
  159.           
  160.       v_current_col := v_current_col + nvl(vrepeated,1) ;
  161.           
  162.       exit when v_current_col > 20 ; --limit for 20 column
  163.     end loop;
  164.     return v_row;
  165. end get_ods_row_value;
  166.     


  167. function get_ods_table(p_data in blob) return xls_table pipelined is
  168.   xpath_row varchar2(2000) := '/table:table/table:table-row' ;
  169.  
  170.   v_row xls_row ;

  171.   cursor c_2(p_table xmltype)
  172.   is
  173.   select value(p) row_data
  174.   from table(xmlsequence(extract(p_table, xpath_row, ns_ods))) p;
  175.   
  176.   vx_tab ods_table := null;
  177.   vx_ods xmltype;
  178.   v_rows_repeated pls_integer ;
  179.   v_current_row pls_integer ;
  180. begin
  181.     vx_ods := get_xml(p_data, 'content.xml') ;
  182.    
  183.     for i in 1..100 loop
  184.        vx_tab := get_table(vx_ods, i) ;
  185.        exit when vx_tab is null;
  186.        v_current_row :=1;
  187.        for r2 in c_2(vx_tab) loop
  188.             v_rows_repeated := getNumberval(r2.row_data, '/table:table-row/@table:number-rows-repeated');
  189.          
  190.             v_row := get_ods_row_value(r2.row_data) ;
  191.             v_row.sheet := i;
  192.             v_row.row_idx := v_current_row ;
  193.             v_current_row := v_current_row + nvl(v_rows_repeated, 1);
  194.             pipe row( v_row) ;
  195.        end loop;
  196.     end loop;
  197.     return ;
  198. end get_ods_table;


  199. end ods_utl_pkg;
  200. /

ods_utl_pkg需要as_zip 包來解壓blob數據.
as_zip可由網上取得http://technology.amis.nl/wp-content/uploads/images/as_zip.txt

讀取基本的數據是沒有問題的.
如使用中遇到bug, 可站內告知我,十分感謝.

                         阿飛
               2014/03/29

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值