4

さまざまなレベルのネストを使用して XML を生成しようとしていますが、単純化しすぎるリスクがあるため、出力 XML は大まかに次の形式になります。

<invoice number="1">
 <charge code="foo" rate="123.00">
  <surcharge amount="10%" />
 </charge>
 <charge code="bar" />
</invoice>

このために継承したデータベース スキーマでは、たまたま異なるテーブルに料金が格納されています。つまり、追加料金は、料金の発生元のテーブルに基づいて異なる方法で格納されます。

s をで使用できないことUNIONFOR XMLを考えると、CTE でいくつかのUNIONing を行ったので、次のようにします。

WITH Charges ( [@code], [@rate], surcharge, InvoiceId ) AS (
    SELECT code AS [@Code], amount AS [@rate], NULL as surcharge, InvoiceId
    FROM item.charges
UNION ALL
    SELECT 
        code AS [@Code], 
        amount AS [@rate],
        (
             SELECT amount AS [@amount]
             FROM order.surcharges os
             WHERE oc.ChargeId = os.ChargeId
             FOR XML PATH('surcharge'), TYPE
        ), 
        InvoiceId
    FROM order.charges oc
)
SELECT
    Number AS [@number],
    (
         SELECT
             [@code],
             [@rate],
             surcharge
         FROM Charges
         WHERE Charges.InvoiceId = i.InvoiceId
    )
FROM Invoices i
FOR XML PATH( 'invoice' ), TYPE

今、それは信じられないほど近いです(ネストされた に注意してください<surcharge>):

<invoice number="1">
 <charge code="foo" rate="123.00">
  <surcharge>
   <surcharge amount="10%" />
  </surcharge>
 </charge>
 <charge code="bar" />
</invoice>

しかし、新しい要素としてではなく、要素のコンテンツとして扱われる XML 列の値をエンド クエリに含める方法を見つける必要があります。これは可能ですか、それとも新しいアプローチを取る必要がありますか?

4

3 に答える 3

1

複数の行(@ Charge、@ rate、およびXMLタイプ)を返す列クエリがあります。投稿したクエリでエラーが発生することが予想されます。

EXISTSでサブクエリが導入されていない場合、選択リストで指定できる式は1つだけです。

ただし、クエリをに移動することで簡単に修正できますouter apply。doublesurcharge要素を削除するには、次のようにXML列名をできるだけ下に移動します。

;WITH Charges (code, rate, surcharge, InvoiceId) AS 
    (
    SELECT  code, amount, NULL, InvoiceId
    FROM    @charges
    UNION ALL
    SELECT  code
    ,       amount
    ,       (
            SELECT  amount AS [@amount]
            FROM    @surcharges os
            WHERE   oc.ChargeId = os.ChargeId
            FOR XML PATH('surcharge'), TYPE
            )
    ,       InvoiceId
    FROM    @charges oc
)
SELECT  Number AS [@number]
,       c.code as [charge/@code]
,       c.rate as [charge/@rate]
,       c.surcharge as [charge]
FROM    @Invoices i
outer apply
        (
        SELECT  code
        ,       rate
        ,       surcharge
        FROM    Charges
        WHERE   Charges.InvoiceId = i.InvoiceId
        ) c
WHERE   i.InvoiceID = 1
FOR XML PATH( 'invoice' ), TYPE

これは、たとえば次のように出力されます。

<invoice number="1">
  <charge code="1" rate="1" />
</invoice>
<invoice number="1">
  <charge code="1" rate="1">
    <surcharge amount="1" />
  </charge>
</invoice>

最初の要素は、ユニオンの上部から取得されます。ここで、surcharge = null

于 2011-01-10T18:06:57.573 に答える
1

(偽の)列に「*」という名前を付けると、その列の内容が要素の内容として使用されるように見えるため、SQLを次のように変更すると機能します。

WITH Charges ( [@code], [@rate], surcharge, InvoiceId ) AS (
    SELECT code AS [@Code], amount AS [@rate], NULL as surcharge, InvoiceId
    FROM item.charges
UNION ALL
    SELECT 
        code AS [@Code], 
        amount AS [@rate],
        (
             SELECT amount AS [@amount]
             FROM order.surcharges os
             WHERE oc.ChargeId = os.ChargeId
             FOR XML PATH('surcharge'), TYPE
        ), 
        InvoiceId
    FROM order.charges oc
)
SELECT
    Number AS [@number],
    (
         SELECT
             [@code],
             [@rate],
             surcharge AS [*] -- Thsi will embed the contents of the previously generated XML in here.
         FROM Charges
         WHERE Charges.InvoiceId = i.InvoiceId
    )
FROM Invoices i
FOR XML PATH( 'invoice' ), TYPE
于 2011-01-10T18:40:28.350 に答える
0

「for xml path('surcharge')」ステートメントでルート ノード タイプを省略することで、これを行うことができると思います。つまり、代わりに「for xml path('')」を使用します。

于 2011-01-10T17:03:17.083 に答える