4

我正在尝试生成一些具有各种嵌套级别的 XML,并且冒着过度简化的风险,输出 XML 的格式将松散:

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

我为此继承的数据库架构恰好将费用存储在不同的表中,这意味着附加费的存储方式根据费用来源的表而不同。

鉴于您不能将UNIONs 与 一起使用FOR XML,我UNION在 CTE 中进行了一些操作,因此类似于:

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 引入子查询时,选择列表中只能指定一个表达式。

但是,通过将查询移动到outer apply. 要删除双surcharge元素,您可以将 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 回答