【问题标题】:I want to shred XML data to tabular format in sql server我想在 sql server 中将 XML 数据分解为表格格式
【发布时间】:2015-06-13 12:19:16
【问题描述】:
DECLARE @x AS XML;
SET @x = N'
<CustomersOrders>
    <Customer custid="1">
      <companyname>Customer NRZBB</companyname>
      <Order orderid="10692">
        <orderdate>2007-10-03T00:00:00</orderdate>
      </Order>
      <Order orderid="10702">
        <orderdate>2007-10-13T00:00:00</orderdate>
      </Order>
      <Order orderid="10952">
        <orderdate>2008-03-16T00:00:00</orderdate>
      </Order>
    </Customer>
    <Customer custid="2">
      <companyname>Customer MLTDN</companyname>
      <Order orderid="10308">
        <orderdate>2006-09-18T00:00:00</orderdate>
      </Order>
      <Order orderid="10926">
        <orderdate>2008-03-04T00:00:00</orderdate>
      </Order>
    </Customer>
</CustomersOrders>';

SELECT
    T.c.value('./@custid','INT') AS custid,
    T.c.value('./companyname','NVARCHAR(30)') AS companyname,
    T.C.value('../@orderid','INT') AS orderid
FROM  @x.nodes('//Customer') T(c)

我正在尝试将 xml 数据分解到表中,但出现错误:

XQuery [value()]: 'value()' 需要一个单例(或空序列),找到类型为 'xdt:untypedAtomic *' 的操作数

结果应该和这里的结果类似:

custid  companyname     orderid  orderdate
1       Customer NRZBB  10692    2007-10-03 00:00:00.000
1       Customer NRZBB  10702    2007-10-13 00:00:00.000
1       Customer NRZBB  10952    2008-03-16 00:00:00.000
2       Customer MLTDN  10308    2006-09-18 00:00:00.000
2       Customer MLTDN  10926    2008-03-04 00:00:00.000

【问题讨论】:

    标签: sql sql-server xml sql-server-2012 xquery


    【解决方案1】:

    您需要使用 两个 嵌套调用 .nodes() 来处理 1:n 客户,每个客户都有 1:n 订单:

    SELECT
        CustId = XC.value('@custid', 'INT') ,
        CompanyName = XC.value('(companyname)[1]', 'NVARCHAR(30)'),
        OrderID = XO.value('@orderid', 'INT'),
        OrderDate = XO.value('(orderdate)[1]', 'DATETIME2(3)')
    FROM  
        @x.nodes('/CustomersOrders/Customer') AS XT(XC)
    CROSS APPLY
        XC.nodes('Order') AS XT2(XO)
    

    【讨论】:

    • 是的,它有效.. 但你能回答(公司名称)[1] 和(公司名称)之间的区别吗? custid 属性和 CompanyName 元素的数量都大于 1。如果它与属性 custid 一起使用,为什么它不能与元素(公司名称)一起使用?
    • @www1986:我相信这是因为你永远不能在一个元素上拥有多个同名的属性 - 因此,不需要[1] - 但你可以轻松地拥有多个 i> 在给定父节点下具有相同名称 &lt;companyname&gt; 的节点 -> 因此您需要定义 (companyname)[1] 以获取这些(可能是多个)节点中的第一个
    【解决方案2】:

    您只需要返回 1 个元素,例如:

    SELECT
        T.c.value('../@custid[1]','INT') AS custid,
        T.c.value('../companyname[1]','NVARCHAR(30)') AS companyname,
        T.c.value('./@orderid[1]','INT') AS orderid,
        T.c.value('./orderdate[1]','datetime') AS orderdate
    FROM  @x.nodes('//Customer/Order') T(c)
    

    【讨论】:

    • 谢谢它有效.. 我想知道我是否写了 SELECT Tcvalue('../@custid','INT') AS custid FROM @x.nodes('//Customer/Order') T(c) 没有 [1] 它以正确的格式返回,但是如果我重写此查询 SELECT Tcvalue('../companyname','NVARCHAR(30)') AS companyname FROM @x.nodes('//Customer /Order') T(c) 再次返回错误,它们有什么区别?
    • 如果您查看您的 xml,您可以看到 custid 是客户元素的属性,而 companyname 是子元素。您可以返回所有属性,但要返回所有子元素,您需要遍历它们。
    猜你喜欢
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多