sql server shred xml在一个查询中有多个节点

时间:2018-04-06 08:23:40

标签: sql-server xml tsql xpath xquery

由于xml中节点的级别不同,我在sql server中粉碎这个xml时遇到了麻烦。我怎么能用1个查询来解决这个问题。下面的xml示例。

<Report>
<P>
    <Data>
             <Cust custID = "A" custName = "B" ></Cust>
 </Data>
</P>
<H>
    <Data1>
        <Seats>
            <Seat id = "abc" value = "123" ></Seat>
            <Date depart = "abc1" arrive = "1231" ></Date>
            <Records>
                <Record  recID = "C" col2 = "D" ></Record>
            </Records>
        </Seats>
        <Seats>
            <Seat id = "xyz" value = "756" ></Seat>
            <Date depart = "asd" arrive = "6781" ></Date>
            <Records>
                <Record  recID = "1" col2 = "6" ></Record>
                <Record  recID = "2" col2 = "7" ></Record>
            </Records>
        </Seats>
     </Data1>
    <Data2>
        <S id = "1" value = "eco" ></S>
        <S id = "2" value = "bus" ></S>
    </Data2>
    <Data3>
        <Guest id = "100" value = "aaa" recID="C"></Guest>
        <Guest id = "101" value = "bbb" recID="1"></Guest>
        <Guest id = "102" value = "ccc" recID="2"></Guest>
    </Data3>
 </H>
 </Report>

1 个答案:

答案 0 :(得分:1)

以下代码提供了一些模板,用于将任何位置的值读取到平面表中。自己添加缺失的列。这应该很容易。

DECLARE @xml XML=
N'<Report>
 <P>
    <Data>
      <Cust custID="A" custName="B" />
    </Data>
  </P>
  <H>
    <Data1>
      <Seats>
        <Seat id="abc" value="123" />
        <Date depart="abc1" arrive="1231" />
        <Records>
          <Record recID="C" col2="D" />
        </Records>
      </Seats>
      <Seats>
        <Seat id="xyz" value="756" />
        <Date depart="asd" arrive="6781" />
        <Records>
          <Record recID="1" col2="6" />
          <Record recID="2" col2="7" />
        </Records>
      </Seats>
    </Data1>
    <Data2>
      <S id="1" value="eco" />
      <S id="2" value="bus" />
    </Data2>
    <Data3>
      <Guest id="100" value="aaa" recID="C" />
      <Guest id="101" value="bbb" recID="1" />
      <Guest id="102" value="ccc" recID="2" />
    </Data3>
  </H>
</Report>';

- 查询通过@xml

从派生表中直接读取.nodes()元数据中的元数据和嵌套数据
 select @xml.value('(/Report/P/Data/Cust/@custID)[1]','nvarchar(max)') AS CustomerID
       ,@xml.value('(/Report/P/Data/Cust/@custName)[1]','nvarchar(max)') AS CustomerName
       ,B.Seat.value('(Seat/@id)[1]','nvarchar(max)') AS SeatId
       ,B1.Record.value('@recID','nvarchar(max)') AS SeatRecordId
       ,C.S.value('@id','int') AS S_Id
       ,D.Guest.value('@id','int') AS Guest_Id
 INTO #FlatTable
 FROM @xml.nodes('/Report/H') AS A(DataNode)
 OUTER APPLY A.DataNode.nodes('Data1/Seats') AS B(Seat)
 OUTER APPLY B.Seat.nodes('Records/Record') AS B1(Record) 
 OUTER APPLY A.DataNode.nodes('Data2/S') AS C(S) 
 OUTER APPLY A.DataNode.nodes('Data3/Guest') AS D(Guest);

 SELECT * FROM #FlatTable;

获得此平面表中的数据后,您可以使用任何类型的SELECT...GROUP BY来准备插入到特定详细信息表中。

如果这对您没有帮助,您必须提供有关目标结构的更多信息。

更新

根据您的评论,您希望将座位放在座位旁边,通过@recID链接。这可以通过将此值读入正常结果集列来完成,然后使用XQuerysql:column()谓词中使用此值:

 select @xml.value('(/Report/P/Data/Cust/@custID)[1]','nvarchar(max)') AS CustomerID
       ,@xml.value('(/Report/P/Data/Cust/@custName)[1]','nvarchar(max)') AS CustomerName
       ,B.Seat.value('(Seat/@id)[1]','nvarchar(max)') AS SeatId
       ,B2.RecordId AS SeatRecordId
       ,B3.Guest.value('@id','int') AS Guest_Id
       ,C.S.value('@id','int') AS S_Id
 INTO #FlatTable
 FROM @xml.nodes('/Report/H') AS A(DataNode)
 OUTER APPLY A.DataNode.nodes('Data1/Seats') AS B(Seat)
 OUTER APPLY B.Seat.nodes('Records/Record') AS B1(Record) 
 OUTER APPLY (SELECT B1.Record.value('@recID','nvarchar(max)')) AS B2(RecordId)
 OUTER APPLY A.DataNode.nodes('Data3/Guest[@recID=sql:column("B2.RecordId")]') AS B3(Guest)
 OUTER APPLY A.DataNode.nodes('Data2/S') AS C(S);

此结果(不知道您希望如何处理<S>值)

+------------+--------------+--------+--------------+----------+------+
| CustomerID | CustomerName | SeatId | SeatRecordId | Guest_Id | S_Id |
+------------+--------------+--------+--------------+----------+------+
| A          | B            | abc    | C            | 100      | 1    |
+------------+--------------+--------+--------------+----------+------+
| A          | B            | abc    | C            | 100      | 2    |
+------------+--------------+--------+--------------+----------+------+
| A          | B            | xyz    | 1            | 101      | 1    |
+------------+--------------+--------+--------------+----------+------+
| A          | B            | xyz    | 1            | 101      | 2    |
+------------+--------------+--------+--------------+----------+------+
| A          | B            | xyz    | 2            | 102      | 1    |
+------------+--------------+--------+--------------+----------+------+
| A          | B            | xyz    | 2            | 102      | 2    |
+------------+--------------+--------+--------------+----------+------+