使用 XMLType 在 oracle 表中加载 XML 的过程

Posted

技术标签:

【中文标题】使用 XMLType 在 oracle 表中加载 XML 的过程【英文标题】:Procedure for loading XML in oracle table using XMLType 【发布时间】:2015-04-22 10:26:36 【问题描述】:

我的灵感来自一个 xml 类型的过程,用于在此处解析和插入表中的数据。在我的情况下,表已经存在,一旦外部应用程序生成 xml,我需要在表中加载数据,所以我创建了我的程序,当我编译一切正常但在执行时我有错误。 所以这是我里面的xml程序。

CREATE OR REPLACE PROCEDURE dta_proc AS 
l_xml xmltype;
l_val VARCHAR2(10000) := '<root>
  <record>
  <id_localisation>8PJ</id_localisation>
  <data>
   <id_client>50C</id_client>  
      <mail>1@mail.com</mail>
      <adress>10  </adress>
      <num_tel>001</num_tel>
      <key>C</key>
     <contact>
        <name>toto</name>
        <birth>01/30/009</birth>
        <city>London</city>
      </contact>
  </data> 
  <data>
  <id_client>25C</id_client> 
      <mail>2@gmaiil.com</mail>
      <adress>20</adress>
      <num_tel>02200</num_tel>
      <key>D1</key>
      <contact>
        <name>tata</name>
        <birth>02/08/2004</birth>
        <city>Spa</city>
      </contact>
  </data> 
</record>
  <record>
  <id_localisation>ESP31</id_localisation>
  <data>
   <id_client>70D</id_client>  
        <mail>3@gmail.com</mail>
        <adress>7Bcd</adress>
        <num_tel>5555</num_tel>
        <key>D2</key>
      <contact>
        <name>titi</name>
        <birth>05/07/2014</birth>
        <city>StMarine</city>
      </contact>
  </data>
  <data>
        <id_client>10D</id_client>
        <mail>4@gmail.com</mail>
        <adress>888</adress>
        <num_tel>881.0</num_tel>
        <key>D3</key>
      <contact>
        <name>awk</name>
        <birth>05/08/1999</birth>
        <city>Bahrein</city>
      </contact>
  </data>
 </record>
 </root>';
     statut number;
     id_client varchar2(13);
     date_ev date;
     id_diff  varchar2(13);
BEGIN
     l_xml        := xmltype(l_val);

     FOR x IN
     (SELECT VALUE(p) col_val
     FROM TABLE(XMLSEQUENCE(EXTRACT(l_xml, '/begin/entry'))) p
     )
     loop

IF x.col_val.existsnode('/root/record/id_localisation//text()') > 0 THEN
         localisation := x.col_val.extract('/root/record/id_localisation//text()').getstringval();
END IF;
if x.col_val.existsnode('/root/record/data/id_client/text()') > 0 then
     id_client := x.col_val.extract('/root/record/data/id_client/text()').getstringval();
end if;
if x.col_val.existsnode('/root/record/data/num_tel/text()') > 0 then
     num_tel := x.col_val.extract('/root/record/data/num_tel/text()').getstringval();
end if;
IF x.col_val.existsnode('/root/record/data/contact/city/text()') > 0 THEN
         city := x.col_val.extract('/root/record/data/contact/city/text()').getstringval();
end if;
INSERT INTO Customer
     (
          Loca,
          ID_CLT,
          TEL,
          Town
     )
     VALUES
     (
          localisation,
          id_client,
          num_tel,
          city
     );
     localisation := null;
     id_client := null;
     num_tel := null;
     city := null;
     end loop;
commit;
end  dta_proc;

执行时出错:

执行xml_procedure;

ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00245: extra data after end of document
Error at line 26
ORA-06512: at "SYS.XMLTYPE", line 310
ORA-06512: at "xml_procedure", line 58
ORA-06512: at line 1
31011. 00000 -  "XML parsing failed"
*Cause:    XML parser returned an error while trying to parse the document.
*Action:   Check if the document to be parsed is valid.

还有一个问题。生成后如何在我的过程中自动加载 xml?

【问题讨论】:

请编辑您的问题并描述运行代码时出现的问题。提供一些你认为应该发生的事情的例子,然后告诉我们真正发生的事情。谢谢。 您在执行过程中是否遇到任何错误,如果有,请发布它们 我把执行脚本后遇到的错误放在了 【参考方案1】:

我不会使用 xmlsequence 等来生成 xmltype,而是执行以下操作(在 11.2.0.3 上对我有用):

with sample_data as (select 
'<root>
  <record>
    <id_localisation>8PJ</id_localisation>
    <data>
      <id_client>50C</id_client>  
      <mail>1@mail.com</mail>
      <adress>10  </adress>
      <num_tel>001</num_tel>
      <key>C</key>
      <contact>
        <name>toto</name>
        <birth>01/30/009</birth>
        <city>London</city>
      </contact>
    </data> 
    <data>
      <id_client>25C</id_client> 
      <mail>2@gmaiil.com</mail>
      <adress>20</adress>
      <num_tel>02200</num_tel>
      <key>D1</key>
      <contact>
        <name>tata</name>
        <birth>02/08/2004</birth>
        <city>Spa</city>
      </contact>
    </data> 
  </record>
  <record>
    <id_localisation>ESP31</id_localisation>
    <data>
      <id_client>70D</id_client>  
      <mail>3@gmail.com</mail>
      <adress>7Bcd</adress>
      <num_tel>5555</num_tel>
      <key>D2</key>
      <contact>
        <name>titi</name>
        <birth>05/07/2014</birth>
        <city>StMarine</city>
      </contact>
    </data>
    <data>
      <id_client>10D</id_client>
      <mail>4@gmail.com</mail>
      <adress>888</adress>
      <num_tel>881.0</num_tel>
      <key>D3</key>
      <contact>
        <name>awk</name>
        <birth>05/08/1999</birth>
        <city>Bahrein</city>
      </contact>
    </data>
  </record>
</root>' str from dual)
-- end of mimicking your sample xml
 select x.localisation,
        y.id_client,
        y.num_tel,
        y.city
 from   sample_data sd,
        xmltable('/root/record'
                 passing xmltype(sd.str)
                 columns localisation varchar2(20) path 'id_localisation',
                         subxml xmltype path '.') x,
        xmltable('/record/data'
                 passing x.subxml
                 columns id_client varchar2(13) path 'id_client',
                         num_tel varchar2(10) path 'num_tel',
                         city varchar2(20) path 'contact/city') y;

LOCALISATION         ID_CLIENT     NUM_TEL    CITY                
-------------------- ------------- ---------- --------------------
8PJ                  50C           001        London              
8PJ                  25C           02200      Spa                 
ESP31                70D           5555       StMarine            
ESP31                10D           881.0      Bahrein             

然后您可以在插入中使用该 select 语句(显然,没有 WITH 子句,因为您会将 xml 数据存储在某处(例如,传入的表或参数)。

关于你关于自动加载生成的 xml 的问题......你没有给我们足够的信息来回答这个问题。我假设生成 xml 的外部应用程序想要调用您的过程来存储它,并将 xml 作为参数传递。

【讨论】:

对不起,我不明白你在这里做什么,程序的声明在哪里?插入部分在哪里? 我给了你一个选择语句,它接受你提供的“xml”并输出结果。然后您可以将其插入到插入语句中(您知道INSERT INTO.... SELECT ...,对吗?),然后您可以插入到过程中。你为什么不自己尝试做这件事——这样你会学到更多。如果您遇到困难,请务必编辑您的原始问题以添加您尝试过的内容,我们可以提供进一步的帮助。

以上是关于使用 XMLType 在 oracle 表中加载 XML 的过程的主要内容,如果未能解决你的问题,请参考以下文章

将 oracle xmltype 表字段选择到 xmltype 变量中会导致空对象

初识Oracle的XMLType

在数据仓库中加载数据的最佳方式

Oracle XMLTable / XMLTYPE(不知道)

Oracle-XMLTYPE:如何更新值

在不使用 Sqoop 的情况下在 HDFS 中加载 Oracle 数据