2

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がすでにタグを閉じているため、連結できません。

この時点で考えられる唯一の解決策は、必要なさまざまなXMLElementピースをさまざまなVARCHARSに選択し、文字列操作関数を使用して、さまざまなピースを挿入する適切な場所を見つけることです。大文字で醜い-U。

別の解決策はありますか?XMELEMENTがタグを閉じないようにして、複雑なループロジックを使用できるようにする方法はありますか?または、単一のselectステートメントを使用せずにこのXMLを構築するという目標を達成できる別のOracle構造ですか?

私の最後の手段は、JavaやPerlなどの別の言語からXMLを生成することです。この言語では、データをフェッチして、そこで複雑な処理とXML生成を行うことができます。ただし、正しいXMLを文字列として返すSQL関数があればいいので、PL / SQLで実行できるのであれば、それが私の好みのルートです。

4

2 に答える 2

3

これはクエリとして実行できると思います。組み合わせてxmlagg xmlelementxmlforest

次に例を示します。

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

そしてここにフィドルがあります

于 2012-10-30T08:33:18.330 に答える
2

代わりにXMLDOM(別の組み込みパッケージ)を使用してXMLを作成するのはどうですか?

おそらくもっとコードを書く必要があるでしょうが、ロジックが十分に複雑な場合は、とにかくこれを行う必要があります。


これは、使用できるいくつかのオプション(XMLDOMを含む)の簡単な要約です。例を示します。

http://www.akadia.com/services/ora_gen_xml.html

于 2012-10-30T07:17:29.790 に答える