在分解了一些严重的Xml之后,我几乎满足了我的需求-但是查看结果后,我发现在解析的一部分中,我无法轻松地解决这种遍历所有行细节的模式每个子标题- 因此,我没有为所有订单项写出总计3条记录,而是为每个子项目写出了三个订单项- 假设我有两个。我总共有6个!:-(我在下面的代码中将模式提炼为通用的标头/子标头/详细信息关系模型。
DECLARE @MetroXML xml SET @MetroXML = '<Header> <col1>Conoco</col1> <col2>ORD-1111</col2> <SubHeaders> <SubHeader> <col1>Dallas</col1> <col2>BOL-2213</col2> <Details> <Detail> <col1>Diesel</col1> <col2>7600.00</col2> </Detail> </Details> </SubHeader> </SubHeaders> <SubHeaders> <SubHeader> <col1>Fort Worth</col1> <col2>BOL-2216</col2> <Details> <Detail> <col1>Ethanol</col1> <col2>1852.00</col2> </Detail> <Detail> <col1>Unleaded</col1> <col2>900.00</col2> </Detail> </Details> </SubHeader> </SubHeaders> </Header>'; INSERT INTO [scratch].GenericHeader SELECT T.c.value('col1[1]','varchar(10)') AS 'col1', T.c.value('col2[1]','varchar(10)') AS 'col2' FROM @MetroXML.nodes('/Header') T(c); INSERT [scratch].GenericSubHeader (id,col1,col2) SELECT h.id, n.x.value('col1[1]','varchar(10)') AS 'col1', n.x.value('col2[1]','varchar(10)') AS 'col2' FROM [scratch].GenericHeader h CROSS APPLY @MetroXML.nodes('/Header/SubHeaders/SubHeader') n(x); INSERT [scratch].GenericDetail (id,subid,col1,col2) SELECT s.id, s.subid, n.x.value('col1[1]','varchar(10)') AS 'col1', n.x.value('col2[1]','varchar(10)') AS 'col2' FROM [scratch].GenericSubHeader s CROSS APPLY @MetroXML.nodes('/Header/SubHeaders/SubHeader/Details/Detail') as n(x); select * from [scratch].GenericHeader where id = 24; select * from [scratch].GenericSubHeader where id = 24; select * from [scratch].GenericDetail where id = 24;
注意:id,subid,detid被定义为INT IDENTITY(1,1)结果
我得到的是:
id|subid|detid|col1 |col2 -------------------------------- 24|44 |22 |Diesel |7600.00 24|44 |23 |Ethanol |1852.00 24|44 |24 |Unleaded |900.00 24|48 |25 |Diesel |7600.00 24|48 |26 |Ethanol |1852.00 24|48 |27 |Unleaded |900.00
我想要得到什么:
id|subid|detid|col1 |col2 -------------------------------- 24|44 |22 |Diesel |7600.00 24|48 |23 |Ethanol |1852.00 24|48 |24 |Unleaded |900.00
之所以会得到重复的行,是因为您正在对中的每一行的整个XML使用交叉应用GenericSubHeader。你必须想出一个办法来映射所产生ID的GenericHeader和所产生subid的GenericSubHeader对XML的相关部分。
GenericSubHeader
ID
GenericHeader
subid
如果您使用的是SQL Server 2008或更高版本,则可以与输出合并以创建一个表变量,该表变量包含生成的ID和所属的xml子节点。
declare @GH table ( id int, sub xml ); merge scratch.GenericHeader as T using ( select T.c.value('col1[1]','varchar(10)'), T.c.value('col2[1]','varchar(10)'), T.c.query('SubHeaders') from @MetroXML.nodes('/Header') T(c) ) as S(col1, col2, sub) on 0 = 1 when not matched then insert (col1, col2) values(S.col1, S.col2) output inserted.id, S.sub into @GH; declare @GSH table ( id int, subid int, det xml ); merge scratch.GenericSubHeader as T using ( select h.id, n.x.value('col1[1]','varchar(10)'), n.x.value('col2[1]','varchar(10)'), n.x.query('Details') from @GH as h cross apply h.sub.nodes('/SubHeaders/SubHeader') n(x) ) as S(id, col1, col2, det) on 0 = 1 when not matched then insert (id, col1, col2) values (S.id, S.col1, S.col2) output inserted.id, inserted.subid, S.det into @GSH; insert into scratch.GenericDetail(id, subid, col1, col2) select s.id, s.subid, n.x.value('col1[1]','varchar(10)') AS 'col1', n.x.value('col2[1]','varchar(10)') AS 'col2' from @GSH as s cross apply s.det.nodes('/Details/Detail') as n(x);