由于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>
答案 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
链接。这可以通过将此值读入正常结果集列来完成,然后使用XQuery
在sql: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 |
+------------+--------------+--------+--------------+----------+------+