SQL XML列 - 交叉应用以产生基于XML的多行1到多行。

问题描述 投票:1回答:1

我一直在研究这个 岗位但我还是不明白XML数据的 "交叉应用"。另外,这个 岗位.

我有一个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的数量。enter image description here

每个结果中的数据都是一样的。

<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>

我的目标是第一行有第一个FlightLeg,第二行有第二个,等等... ... 然后在这之后,我会把具体的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,必须在每一行都重新设置。

现在,我试图让我的SQL看起来像我找到的样本一样 此处:

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);

我收到错误信息。'('附近的语法不正确,行#指向这一行。 FROM @xmlTable as T(My_XML))

到目前为止,我还不明白为什么我们要把 "作为x(y)",换句话说就是在括号里加上第二个值,我还在研究这个问题。

Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) 2019年9月24日 13:48:23 Copyright (C) 2019 Microsoft Corporation Developer Edition (64-bit) on Windows Server 2019 Standard 10.0 (Build 17763: )

sql-server sqlxml
1个回答
1
投票
CROSS APPLY 
    t.xmlDoc.nodes('//Flight') AS XmlData2(xmlDoc2)

生成三行,其中上下文节点已经依次设置为三个航班。你只需要使用 . 来访问它。

例如 XmlData2.xmlDoc2.query('.')XmlData2.xmlDoc2.value('.', 'int') 如本例中的db<>提琴例子。

© www.soinside.com 2019 - 2024. All rights reserved.