Tsql 如何将CTE与FOR XML子句组合?
我正在尝试生成一些具有不同嵌套级别的XML,并且冒着过度简化的风险,输出XML的格式将松散:Tsql 如何将CTE与FOR XML子句组合?,tsql,sql-server-2008,common-table-expression,for-xml,Tsql,Sql Server 2008,Common Table Expression,For Xml,我正在尝试生成一些具有不同嵌套级别的XML,并且冒着过度简化的风险,输出XML的格式将松散: <invoice number="1"> <charge code="foo" rate="123.00"> <surcharge amount="10%" /> </charge> <charge code="bar" /> </invoice> 现在,这是难以置信的接近,给出(注意嵌套的): 但我需要找到一种方法
<invoice number="1">
<charge code="foo" rate="123.00">
<surcharge amount="10%" />
</charge>
<charge code="bar" />
</invoice>
现在,这是难以置信的接近,给出(注意嵌套的
):
但我需要找到一种方法,使结束查询包含XML列的值,该列将被视为元素的内容,而不是新元素。这是可能的,还是我需要采取一种新的方法?我认为可以通过省略“for xml path('overload')”语句中的根节点类型来做到这一点。也就是说,使用“for xml path(“”)”。您有一个列查询,它返回多行(@charge、@rate和一个xml类型)。我希望您发布的查询会给出错误:
只能指定一个表达式 在选择列表中,当子查询 不与EXISTS一起引入 但是,通过将查询移动到
外部应用
,可以很容易地解决这个问题。要删除doublesupployee
元素,可以将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>
第一个元素来自联合体的顶部,其中
assemployment=null
似乎将(假)列命名为“*”将使用该列的内容作为元素的内容,因此按以下方式更改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
这就产生了一个错误:“行标记省略(空行标记名称)不能与以属性为中心的XML序列化一起使用。”+1附加费是由位于联合体顶部的
NULL作为附加费隐式添加的,因此路径('surgcharge')看起来是重复的。我对该错误感到困惑。如果按照我建议的方式在联合体中使用“for xml”子句单独运行第二个select,会发生什么情况?如果子查询没有引入EXISTS,则select列表中只能指定一个表达式。@user3752281该解决方案对我有效,因此我不理解您的评论?
<invoice number="1">
<charge code="1" rate="1" />
</invoice>
<invoice number="1">
<charge code="1" rate="1">
<surcharge amount="1" />
</charge>
</invoice>
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