从SQL中创建的表中获取XML

时间:2016-04-05 15:41:56

标签: sql xml oracle xpath

我在Oracle SQL Developer

中创建了这个表
CREATE TABLE Test_T (
  COL_1 VARCHAR(30),
  COL_2 XMLTYPE
);

已将此插入其中

INSERT INTO Test_T VALUES ('two', ('<?xml version="1.0" encoding="UTF-8"?>
<CATALOG>
 <PLANT>
  <COMMON>Bloodroot</COMMON>
  <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
  <ZONE>4</ZONE>
  <LIGHT>Mostly Shady</LIGHT>
  <PRICE>$2.44</PRICE>
  <AVAILABILITY>031599</AVAILABILITY>
 </PLANT>
 <PLANT>
  <COMMON>Columbine</COMMON>
  <BOTANICAL>Aquilegia canadensis</BOTANICAL>
  <ZONE>3</ZONE>
  <LIGHT>Mostly Shady</LIGHT>
  <PRICE>$9.37</PRICE>
  <AVAILABILITY>030699</AVAILABILITY>
 </PLANT></CATALOG>'));

我的目标是返回&lt; COMMON&gt;名称&lt; / COMMON&gt;只有区域是3或更少。所以这应该返回Columbine

我考虑过使用XMLExists我不太熟悉XML,所以这就是我到目前为止所做的。

SELECT COL_2 FROM Test_T WHERE XMLExists('//ZONE[COL_2 <= 3]' PASSING BY REF COL_2);

我不确定我是否正确访问ZONE。

有人能引导我朝正确的方向前进吗?

2 个答案:

答案 0 :(得分:1)

尝试以下选择查询:

 SELECT COMMON_NAME FROM Test_T WHERE XMLExists( 'CATALOG/PLANT[ZONE<=3]/COMMON[text()]' PASSING COMMON_NAME )

答案 1 :(得分:0)

问题在于您的路径('//ZONE[COL_2 <= 3]')。 COL_2不是有效的XML节点,它只是列的名称。

正确的路径是//ZONE[text() <= 3]

text()是一个特殊的节点引用,它告诉oracle抓取ZONE节点<ZONE>THIS TEXT</ZONE>内的文本。您只能在实际XML架构中定位节点。

另外,请注意该路径对XML中的内容具有CASE SENSITIVE。记住这会节省你的时间。

此外,另一种编写选择的方法就是这样。在此示例中,Oracle执行隐式连接并为/ ZONE / text()&lt; = 3返回每个// PLANT的行。XMLSEQUENCE中的路径在此非常重要,因为它确定了oracle如何拆分每个行,意味着你不能只定位// ZONE,因为每个ZONE只能得到一行,而不是每个PLANT都有一行。

在select子句中,如果您有多个PLANT,则可以为每个PLANT提取单个节点值。

SELECT VALUE(P) --THE FULL XML FOR EACH PLANT
    VALUE(P).EXTRACT('//COMMON/text()').getstringval() AS COMMON, --INDIVIDUAL NODE VALUE
    VALUE(P).EXTRACT('//BOTANICAL/text()').getstringval() AS BOTANICAL --INDIVIDUAL NODE VALUE
FROM Test_T, TABLE(XMLSEQUENCE(EXTRACT(COL_2, '//PLANT[ZONE<= 3]'))) p