如何将CTE与for XML子句组合?
-
09-10-2019 - |
题
我正在尝试生成一些具有各种嵌套级别的XML,并且冒着过度简化的危险,输出XML将宽松地与格式:
<invoice number="1">
<charge code="foo" rate="123.00">
<surcharge amount="10%" />
</charge>
<charge code="bar" />
</invoice>
我为此继承的数据库模式恰好存储在不同表中的费用,这意味着附加费的存储方式不同,基于表格的表格。
鉴于你 不能用 UNION
与 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列的值视为元素的内容,而不是将其视为新元素。这是可能的,还是我需要采取新方法?
解决方案 2
看来将(假)列命名为“*”将使用该列的内容作为元素的内容,因此更改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
其他提示
您有一个列查询,该查询返回mulitple行(@Charge,@rate和XML类型。)我希望您发布的查询会出现错误:
当不存在子查询时,在选择列表中只能指定一个表达式。
但是,通过将查询移至 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
.
我认为您可以通过省略“ for xml路径('附加费')”语句中的根节点类型来做到这一点。也就是说,使用“用于XML路径('')”。
不隶属于 StackOverflow