使用Oracle 10gR2,我需要从存储在标准关系表中的数据中生成类似下面的伪示例。
<product>
<productName>p1</productName>
<productNumber>100</productNumber>
<productObsoletes>
<obsoletedProduct label=1>50</obsoletedProduct>
<obsoletedProduct label=2>55</obsoletedProduct>
</productObsoletes>
</product>
问题是,我需要使用包含数据的行做决策。我的数据库(我继承了)设计很差,决定行包含所需的逻辑很复杂。不幸的是,重新设计数据库不是一种选择。我在这里大大简化了逻辑,所以不是可以使用简单连接或where子句的情况。数据的层次结构和数据格式定义都很复杂。
在伪代码中,过度简化的决策看起来像是:
BEGIN
--select our basic attributes
select XMLEMENT("product",XMLELEMENT("productName",name),XMLELEMENT("productNumber",product_number))
into xml_output from products where product_number = 100;
--now process our obsolete rows
select XMLELEMENT("productObsoletes") into xml_output from dual;
FOR c_row in (select * from product_obsoletes where id=100)
LOOP
IF c_row.display = 'YES' THEN
select XMLELEMENT("obsoletedProduct", XMLATTRIBUTES(c_row.label as "label"), c_row.obsoleted_product_id) into xml_output from dual;
ELSE
CONTINUE;
END IF;
END LOOP;
END;
显然,这不起作用。首先,XMLElement总是打开一个结束标记,所以除非你可以制定一个包含所有元素的select语句,否则它不起作用。其次,在这个例子中,我将覆盖以前的XMLELEMENT输出。我无法连接,因为XMLELEMENT已经关闭了标签。
此时我能想到的唯一解决方案是在不同的VARCHARS中选择我需要的各种XMLElement部分,然后使用字符串操作函数找到插入各个部分的正确位置。丑陋的资本-U。
还有其他解决方案吗?是否有一种方法可以阻止XMELEMENT关闭标记,以便您可以使用复杂的循环逻辑?还是另一个Oracle构造,它允许我实现构建这个XML的目标,而不必使用单个select语句?
我的最后一种方法是使用其他语言(如Java或Perl)进行XML生成,在那里我可以简单地获取数据,然后在那里进行复杂的处理和XML生成。但是,我更喜欢只有一个SQL函数,它会将正确的XML作为字符串返回,所以如果可以在PL / SQL中执行它,那么这将是我的首选路径。
答案 0 :(得分:3)
我认为这可以作为查询完成,您必须合并xmlagg
xmlelement
和xmlforest
以下是一个例子:
select XMLELEMENT("product",(XMLForest( p.product_name as "productName",
p.product_number as "productNumber",
xmlagg(
XMLELEMENT("obsoletedProduct",
XMLATTRIBUTES(po.label as "label"),
po.obsoleted_product_id)) as "productObsoletes")))
from products p
join product_obsoletes po on p.product_number=po.id
group by p.product_name, p.product_number
和here是小提琴
答案 1 :(得分:2)
如何使用XMLDOM(一个不同的内置包)来创建XML呢?
您可能需要编写更多代码,但如果您的逻辑非常复杂,那么无论如何您都必须这样做。
这是您可以使用的一些选项(包括XMLDOM)的快速摘要,并附带示例: