在SQL中提取XML数据 - 太多交叉应用语句

时间:2012-09-26 18:16:23

标签: sql xml singleton cross-apply

我有一个xml文档,其中包含Statement:

的详细信息
<Statement>
<Id />

<Invoices>
    <Invoice>
        <Id />
        <Date />
        <AmountDue />
        etc.
    </Invoice>

    <Invoice>
        <Id />
        <Date />
        <AmountDue />
        etc.
    </Invoice>

    <Invoice>
        <Id />
        <Date />
        <AmountDue />
        etc.
    </Invoice>
</Invoices>

</Statement>

这适用于Statement特定细节:

SET @statementId = @xml.value('(Id)[1]', 'UNIQUEIDENTIFIER');

但它需要一个单例,并且只返回第一个值。我需要发票的所有值,而不仅仅是第一个,因此单例不起作用。

我可以使用这样的交叉申请语句来获取信息:

SELECT 
@statementId AS STATEMENT_ID
Id.value('.', 'uniqueidentifier') AS INVOICE_ID
Date.value('.', 'smalldatetime') AS INVOICE_DATE
Due.value('.', 'decimal') AS INVOICE_AMOUNT_DUE

FROM @xml.nodes('Statement') A(S)
cross apply S.nodes('Invoices/Invoice') B(InvoiceD)
cross apply InvoiceD.nodes('Id') C(Id)
cross apply InvoiceD.nodes('Date') D(Date)
cross apply InvoiceD.nodes('AmountDue') E(Due)

这将在声明中返回每个发票的ID,日期和金额 - 完美。

当我尝试提取所有发票详细信息时出现问题。我目前有七个交叉申请声明,我收到以下消息:

  

“查询处理器耗尽内部资源而无法使用   制定查询计划。这是一个罕见的事件,只有预期   非常复杂的查询或引用非常大的查询   表或分区的数量。请简化查询。如果你   相信您错误地收到了此消息,请联系客户   支持服务以获取更多信息。“

我想要做的是让一个交叉申请发票并缩小select语句中的确切字段,但除非我使用'。'我必须使语句返回单例,并且我没有获得所需的所有数据。

我已经做了一些关于在select语句中指定命名空间的研究,但是所有的例子都将命名空间设置为http地址而不是xml文档中的节点,我还没有得到任何回报方法

我正在寻找的结果是这样的,但有更多的发票明细:

STATEMENT_ID      INVOICE_ID      INVOICE_DATE      INVOICE_AMOUNT_DUE     ...
Statement-1-Id    Invoice-1-Id    Invoice-1-Date    Invoice-1-AmountDue    ...
Statement-1-Id    Invoice-2-Id    Invoice-2-Date    Invoice-2-AmountDue    ...
Statement-1-Id    Invoice-3-Id    Invoice-3-Date    Invoice-3-AmountDue    ...

我应该从哪里离开?

编辑:我删除了一些不必要的信息。获取所有特定于发票的详细信息是我的目标。

1 个答案:

答案 0 :(得分:4)

select @XML.value('(Statement/Id/text())[1]', 'uniqueidentifier') as StatementId, 
       T.N.value('(Id/text())[1]', 'uniqueidentifier') as InvoiceId,
       T.N.value('(Date/text())[1]', 'smalldatetime') as InvoiceDate,
       T.N.value('(AmountDue/text())[1]', 'decimal') as AmountDue
from @XML.nodes('/Statement/Invoices/Invoice') as T(N)

.nodes会将您的XML碎化为行,以便每行T.N指向自己的Invoice节点。在该节点上只有一个Id节点,因此获取指定单个Id[1]的值。

您可以使用Id[1](Id/text())[1],但后者会为您提供更有效的执行计划。