SQL XML 列 - 交叉应用以根据 XML 1 到多生成多行
SQL XML Column - Cross Apply to Produce Multiple Rows based on XML 1 to many
我一直在研究这个post, but I'm still not understanding the "cross apply" with XML data. Also this post。
我有一个 Xml 列,其中包含一名乘客,以及他机票上的多个航班和航段。
这就是我经过多次摆弄后的工作:
Select xmlDoc.value('(//Passenger[1]/text())[1]', 'varchar(100)') as Passenger,
XmlData2.xmlDoc2.query('//FlightLeg') as xmlDoc2b
FROM xmlData as t
CROSS APPLY
t.xmlDoc.nodes('//FlightLeg') AS XmlData2(xmlDoc2)
where xmlSchema = 'Reservation'
这是目前的结果。好消息是有三行对应于 FlightLegs 的数量。
每个结果中的数据相同:
<FlightLeg seq="1">
<FlightNumber>1849</FlightNumber>
<DepartureAirport>MDW</DepartureAirport>
<ArrivalAirport>STL</ArrivalAirport>
<DepartureDateTime>2019-11-02T19:20:00</DepartureDateTime>
<ArrivalDateTime>2019-11-02T20:25:00</ArrivalDateTime>
</FlightLeg>
<FlightLeg seq="2">
<FlightNumber>2105</FlightNumber>
<DepartureAirport>STL</DepartureAirport>
<ArrivalAirport>OKC</ArrivalAirport>
<DepartureDateTime>2019-11-02T21:25:00</DepartureDateTime>
<ArrivalDateTime>2019-11-02T22:50:00</ArrivalDateTime>
</FlightLeg>
<FlightLeg seq="1">
<FlightNumber>4565</FlightNumber>
<DepartureAirport>OKC</DepartureAirport>
<ArrivalAirport>MDW</ArrivalAirport>
<DepartureDateTime>2019-11-04T11:10:00</DepartureDateTime>
<ArrivalDateTime>2019-11-04T13:05:00</ArrivalDateTime>
</FlightLeg>
我的目标是第 1 行的每一个都有第一个 FlightLeg,第 2 行有第二个,等等......然后我将把特定的 XML 元素拉出到列中。
更容易重现样本:
DECLARE @xml XML='<Reservation><Name>Neal</Name><Flight>12</Flight><Flight>34</Flight><Flight>56</Flight></Reservation>';
DECLARE @xmlTable TABLE (
xmlDoc Xml
);
Insert into @xmltable values (@xml)
Select xmlDoc from @XmlTable
Select xmlDoc.value('(//Name[1]/text())[1]', 'varchar(100)') as Passenger,
XmlData2.xmlDoc2.query('//Flight') as xmlDoc2b
FROM @xmlTable as t
CROSS APPLY
t.xmlDoc.nodes('//Flight') AS XmlData2(xmlDoc2)
我可以看到这里使用了一些下标:
XmlData2.xmlDoc2.query('//Flight[@xxxx]') as xmlDoc2b
但不能使用 RowNumber,必须在 table 的每一行上重新设置。
现在我正在尝试让我的 SQL 看起来像我找到的示例 here:
DECLARE @xml XML='<Reservation><Name>Neal</Name><Flight>12</Flight><Flight>34</Flight><Flight>56</Flight></Reservation>';
DECLARE @xmlTable TABLE (
xmlDoc Xml
);
Insert into @xmltable values (@xml)
--Select xmlDoc from @XmlTable
-- This was running, but same data on all three rows
Select xmlDoc.value('(//Name[1]/text())[1]', 'varchar(100)') as Passenger,
XmlData2.xmlDoc2.query('//Flight') as xmlDoc2b
FROM @xmlTable as t
CROSS APPLY
t.xmlDoc.nodes('//Flight') AS XmlData2(xmlDoc2)
-- Trying to make above look like blog sample below
Select xmlDoc.value('(//Name[1]/text())[1]', 'varchar(100)') as Passenger,
My_XML.FlightTest.query('//Flight') as FlightLegTest
FROM (SELECT xmlDoc
FROM @xmlTable as T(My_XML))
CROSS APPLY My_XML.nodes('//Flight') AS My_XML (FlightTest)
/* Sample from https://www.mssqltips.com/sqlservertip/5707/simple-way-to-import-xml-data-into-sql-server-with-tsql/ */
SELECT
MY_XML.Customer.query('Name').value('.', 'VARCHAR(50)')
FROM (SELECT CAST(MY_XML AS xml)
FROM OPENROWSET(BULK 'c:\XMLClass\IntroSamples\BulkLoadCustomers1.xml', SINGLE_BLOB) AS T(MY_XML)) AS T(MY_XML)
CROSS APPLY MY_XML.nodes('Customers/Customer') AS MY_XML (Customer);
我收到错误:“(”附近的语法不正确
其中 line# 指向这一行:
FROM @xmlTable as T(My_XML))
到目前为止,我不明白为什么我们把 "as x(y)",换句话说,括号中的第二个值;我还在研究那个。
Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) 2019 年 9 月 24 日 13:48:23 版权所有 (C) 2019 Microsoft Corporation Developer Edition(64 位)在 Windows 服务器 2019 标准版 10.0(内部版本 17763:)
CROSS APPLY
t.xmlDoc.nodes('//Flight') AS XmlData2(xmlDoc2)
生成三行,其中上下文节点已依次设置为三个航班。您只需要使用 .
即可访问它。
例如XmlData2.xmlDoc2.query('.')
或XmlData2.xmlDoc2.value('.', 'int')
as in this db <> fiddle example
我一直在研究这个post, but I'm still not understanding the "cross apply" with XML data. Also this post。
我有一个 Xml 列,其中包含一名乘客,以及他机票上的多个航班和航段。
这就是我经过多次摆弄后的工作:
Select xmlDoc.value('(//Passenger[1]/text())[1]', 'varchar(100)') as Passenger,
XmlData2.xmlDoc2.query('//FlightLeg') as xmlDoc2b
FROM xmlData as t
CROSS APPLY
t.xmlDoc.nodes('//FlightLeg') AS XmlData2(xmlDoc2)
where xmlSchema = 'Reservation'
这是目前的结果。好消息是有三行对应于 FlightLegs 的数量。
每个结果中的数据相同:
<FlightLeg seq="1">
<FlightNumber>1849</FlightNumber>
<DepartureAirport>MDW</DepartureAirport>
<ArrivalAirport>STL</ArrivalAirport>
<DepartureDateTime>2019-11-02T19:20:00</DepartureDateTime>
<ArrivalDateTime>2019-11-02T20:25:00</ArrivalDateTime>
</FlightLeg>
<FlightLeg seq="2">
<FlightNumber>2105</FlightNumber>
<DepartureAirport>STL</DepartureAirport>
<ArrivalAirport>OKC</ArrivalAirport>
<DepartureDateTime>2019-11-02T21:25:00</DepartureDateTime>
<ArrivalDateTime>2019-11-02T22:50:00</ArrivalDateTime>
</FlightLeg>
<FlightLeg seq="1">
<FlightNumber>4565</FlightNumber>
<DepartureAirport>OKC</DepartureAirport>
<ArrivalAirport>MDW</ArrivalAirport>
<DepartureDateTime>2019-11-04T11:10:00</DepartureDateTime>
<ArrivalDateTime>2019-11-04T13:05:00</ArrivalDateTime>
</FlightLeg>
我的目标是第 1 行的每一个都有第一个 FlightLeg,第 2 行有第二个,等等......然后我将把特定的 XML 元素拉出到列中。
更容易重现样本:
DECLARE @xml XML='<Reservation><Name>Neal</Name><Flight>12</Flight><Flight>34</Flight><Flight>56</Flight></Reservation>';
DECLARE @xmlTable TABLE (
xmlDoc Xml
);
Insert into @xmltable values (@xml)
Select xmlDoc from @XmlTable
Select xmlDoc.value('(//Name[1]/text())[1]', 'varchar(100)') as Passenger,
XmlData2.xmlDoc2.query('//Flight') as xmlDoc2b
FROM @xmlTable as t
CROSS APPLY
t.xmlDoc.nodes('//Flight') AS XmlData2(xmlDoc2)
我可以看到这里使用了一些下标:
XmlData2.xmlDoc2.query('//Flight[@xxxx]') as xmlDoc2b
但不能使用 RowNumber,必须在 table 的每一行上重新设置。
现在我正在尝试让我的 SQL 看起来像我找到的示例 here:
DECLARE @xml XML='<Reservation><Name>Neal</Name><Flight>12</Flight><Flight>34</Flight><Flight>56</Flight></Reservation>';
DECLARE @xmlTable TABLE (
xmlDoc Xml
);
Insert into @xmltable values (@xml)
--Select xmlDoc from @XmlTable
-- This was running, but same data on all three rows
Select xmlDoc.value('(//Name[1]/text())[1]', 'varchar(100)') as Passenger,
XmlData2.xmlDoc2.query('//Flight') as xmlDoc2b
FROM @xmlTable as t
CROSS APPLY
t.xmlDoc.nodes('//Flight') AS XmlData2(xmlDoc2)
-- Trying to make above look like blog sample below
Select xmlDoc.value('(//Name[1]/text())[1]', 'varchar(100)') as Passenger,
My_XML.FlightTest.query('//Flight') as FlightLegTest
FROM (SELECT xmlDoc
FROM @xmlTable as T(My_XML))
CROSS APPLY My_XML.nodes('//Flight') AS My_XML (FlightTest)
/* Sample from https://www.mssqltips.com/sqlservertip/5707/simple-way-to-import-xml-data-into-sql-server-with-tsql/ */
SELECT
MY_XML.Customer.query('Name').value('.', 'VARCHAR(50)')
FROM (SELECT CAST(MY_XML AS xml)
FROM OPENROWSET(BULK 'c:\XMLClass\IntroSamples\BulkLoadCustomers1.xml', SINGLE_BLOB) AS T(MY_XML)) AS T(MY_XML)
CROSS APPLY MY_XML.nodes('Customers/Customer') AS MY_XML (Customer);
我收到错误:“(”附近的语法不正确 其中 line# 指向这一行: FROM @xmlTable as T(My_XML))
到目前为止,我不明白为什么我们把 "as x(y)",换句话说,括号中的第二个值;我还在研究那个。
Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) 2019 年 9 月 24 日 13:48:23 版权所有 (C) 2019 Microsoft Corporation Developer Edition(64 位)在 Windows 服务器 2019 标准版 10.0(内部版本 17763:)
CROSS APPLY
t.xmlDoc.nodes('//Flight') AS XmlData2(xmlDoc2)
生成三行,其中上下文节点已依次设置为三个航班。您只需要使用 .
即可访问它。
例如XmlData2.xmlDoc2.query('.')
或XmlData2.xmlDoc2.value('.', 'int')
as in this db <> fiddle example