SQL Server 2012中的XML解析器;当子元素不存在时不返回任何行

时间:2014-12-03 20:29:34

标签: sql sql-server xml

我有以下XML消息,需要将数据插入到表中。

当我在msg中的所有元素如下所示时,XML解析器起作用:

DECLARE @XmlVal XML=
'
<Customers>
<CustomerID> C001 </CustomerID>
<CustomerName> Carlos </CustomerName>
    <Orders>
        <Order>
            <OrderID>100</OrderID> 
            <OrderDetail>
                <ProductID>10</ProductID>
                <Quantity>5 </Quantity>
            </OrderDetail >
        </Order>
        <Order>
            <OrderID>101</OrderID> 
            <OrderDetail>
                <ProductID>10</ProductID>
                <Quantity>5 </Quantity>
            </OrderDetail >
        </Order>
    </Orders>
<Address> Address line 1, 2, 3</Address>    
</Customers>
'

这很好用,并在以下查询的帮助下返回2行。

  SELECT 
    Cust.value('CustomerID[1]','varchar(100)') AS CustomerID,
    Cust.value('CustomerName[1]','varchar(100)') AS CustomerName,
    Cust.value('Address[1]','varchar(100)') AS Address,
    Orders.value('../OrderID[1]','varchar(10)') AS OrderID,
    Orders.value('ProductID[1]','varchar(80)') AS ProductID,
    Orders.value('Quantity[1]','varchar(3)') AS Quantity
 FROM @XmlVal.nodes('//Customers') AS i(Cust)
    CROSS APPLY @XmlVal.nodes('//Customers/Orders/Order/OrderDetail') AS j(Orders)

但是当我使用下面的xml消息时,我只得到一行。我还需要第二行,CustomerID,CustomerName,Address,OrderID,ProductID和Quantity为空。

<Customers>
<CustomerID> C001 </CustomerID>
<CustomerName> Carlos </CustomerName>
    <Orders>
        <Order>
            <OrderID>100</OrderID> 
            <OrderDetail>
                <ProductID>10</ProductID>
                <Quantity>5 </Quantity>
            </OrderDetail >
        </Order>
        <Order>
            <OrderID>101</OrderID>              
        </Order>
    </Orders>
<Address> Address line 1, 2, 3</Address>    
</Customers>

有可能吗?我的方法有误吗?

我无法更改xml格式。有什么办法可以改变SQL查询来获得第二行吗?

请帮助!!!

提前致谢!!

1 个答案:

答案 0 :(得分:0)

您需要稍微更改一下您的查询:

  • 将对.nodes()的调用分为三部分 - 第一部分为<Customers>节点(现在为您),第二部分为<Order>子节点(基于在客户节点上)和第三个用于<OrderDetail>(如果存在)

  • 由于第三级节点是可选的,因此您需要使用OUTER APPLY代替CROSS APPLY

  • 我还建议您在查询中使用更合适的数据类型 - 所有那些数字的元素都应该这样转换为{{ 1}}左右 - 不要在懒惰的地方使用INT

所以试试这句话:

varchar