我在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。
有人能引导我朝正确的方向前进吗?
答案 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