3

我有一个包含声明详细信息的 xml 文档:

<Statement>
<Id />

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

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

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

</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 语句中指定命名空间进行了一些研究,但是所有示例都将命名空间设置为 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    ...

我应该从这里去哪里?

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

4

1 回答 1

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]or(Id/text())[1]但后者会给你一个更有效的执行计划。

于 2012-09-26T20:15:09.703 回答