J'ai une database SQL Server 2008 à partir de laquelle j'extrais plusieurs valeurs de diverses tables à mettre dans une seule table. Parmi ces valeurs, il y a des données tirées de XML qui jusqu'à récemment étaient stockées sur un seul niveau comme ceci:
<XMLData> <Item> <Name>Name1</Name> <Value>Value1</Value> </Item> <Item> <Name>Name2</Name> <Value>Value2</Value> </Item> <Item> <Name>Name3</Name> <Value>Value3</Value> </Item> <Item> <Name>Name4</Name> <Value>Value4</Value> </Item> </XMLData>
Je voudrais extraire les informations nécessaires avec la méthode suivante:
SELECT Name = IXML.value('(./Name)[1]', 'varchar(20)'), Value = IXML.value('(./Value)[1]', 'varchar(20)') INTO dbo.newTable FROM dbo.oldTable CROSS APPLY oldTable.InfoXML.nodes('/XMLData/item') Book(IXML)
Ce qui reviendrait:
Name Value -------------- Name1 Value1 Name2 Value2 Name3 Value3 Name4 Value4
Cependant, maintenant la list XML a été modifiée et est générée dans une autre list comme ceci:
<XMLData> <LongDirectory> <Category> <Item> <CategoryName>Cat1</CategoryName> <SubCategory> <Item> <Name>Name1</Name> <Value>Value1</Value> </Item> <Item> <Name>Name2</Name> <Value>Value2</Value> </Item> <Item> <Name>Name3</Name> <Value>Value3</Value> </Item> </SubCategory> </Item> <Item> <CategoryName>Cat2</CategoryName> <SubCategory> <Item> <Name>Name4</Name> <Value>Value4</Value> </Item> <Item> <Name>Name5</Name> <Value>Value5</Value> </Item> </SubCategory> </Item> <Item> <CategoryName>Cat3</CategoryName> <SubCategory> <Item> <Name>Name6</Name> <Value>Value6</Value> </Item> <Item> <Name>Name7</Name> <Value>Value7</Value> </Item> </SubCategory> </Item> </Category> </LongDirectory> </XMLData>
Et j'ai besoin de générer l'information pour ressembler à ceci:
Name Value Category ------------------------- Name1 Value1 Cat1 Name2 Value2 Cat1 Name3 Value3 Cat1 Name4 Value4 Cat2 Name5 Value5 Cat2 Name6 Value6 Cat3 Name7 Value7 Cat3
Comment pourrais-je modifier ma requête pour accommoder le changement de structure? Toute aide est appréciée.
Vous pouvez le faire avec des methods node () nestedes:
select ICvalue('(Name)[1]', 'varchar(20)') as Name, ICvalue('(Value)[1]', 'varchar(20)') as Value, CCvalue('(CatName)[1]', 'varchar(20)') as Category -- into dbo.newTable from dbo.oldTable as T cross apply T.InfoXML.nodes('XMLData/Category') as C(C) cross apply CCnodes('Item') as I(C)
Ou utilisez l'axe parent ( ..
):
select ICvalue('(Name)[1]', 'varchar(20)') as Name, ICvalue('(Value)[1]', 'varchar(20)') as Value, ICvalue('(../CatName)[1]', 'varchar(20)') as Category -- into dbo.newTable from dbo.oldTable as T cross apply T.InfoXML.nodes('XMLData/Category/Item') as I(C)
sql fiddle exemple
mettre à jour :
select ICvalue('(Name)[1]', 'varchar(20)') as Name, ICvalue('(Value)[1]', 'varchar(20)') as Value, CCvalue('(CategoryName)[1]', 'varchar(20)') as Category from dbo.oldTable as T outer apply T.InfoXML.nodes('XMLData/LongDirectory/Category/Item') as C(C) outer apply CCnodes('SubCategory/Item') as I(C)
sql fiddle exemple