2016-07-27 18 views
3

Ich habe ein grundlegendes Verständnis für das Abfragen von XML in SQL Server 2008+. Basic. Aber ich kämpfe, um zu bekommen, was ich von diesem einfachen XML bekommen will, und ich habe SO und das Netz für eine ganze Weile nach diesem Tag gesucht und bin nicht auf die magischen Worte gekommen, um Hilfe zu finden.Abfragen von XML mit mehreren Untertiteln

Vor diesem XML:

declare @xml xml = 
'<?xml version="1.0" encoding="utf-8"?> 
<Customers> 
    <Customer id="12345" name="John Doe" addr1="123 Somewhere Ln" city="Riverside" state="CA"> 
    <Children>Jane</Children> 
    <Children>John Jr.</Children> 
    <Children>Susan</Children> 
    </Customer> 
</Customers> 
<Customers> 
    <Customer id="97531" name="Ben Franklin" addr1="456 Anywhere Dr" city="Albuquerque" state="NM"> 
    <Children>Andrew</Children> 
    <Children>Adam</Children> 
    </Customer> 
</Customers>' 

ich diese Abfrage ausführen kann und die IDs und Namen erhalten:

select cust.col.value('@id[1]','int') as id, 
     cust.col.value('@name[1]','varchar(30)') as name 
    from @xml.nodes('/Customers/Customer') as cust(col) 

id  name 
12345 John Doe 
97531 Ben Franklin 

jedoch, was ich will ist neben der ID und Name jedes Kind, und Ich konnte nicht herausfinden, was nötig ist, um das zu bekommen. IOW, ich will dies:

id  child 
12345 Jane 
12345 John Jr. 
12345 Susan 
97531 Andrew 
97531 Adam 

Beachten Sie, dass ich spaltenförmige Daten, nicht XML.

Also, was ist der SELECT, der mir diese Ergebnisse von diesem XML geben wird?

Danke!

Antwort

1

Aufbauend auf Ihrer Abfrage fügen Sie einfach CROSS APPLY auf Children Elemente hinzu. Jetzt können Sie wählen Daten aus Customer sowie Children Elemente:

select cust.col.value('@id','int') as id, 
     child.col.value('.','varchar(30)') as child 
from @xml.nodes('/Customers/Customer') as cust(col) 
    cross apply cust.col.nodes('Children') as child(col) 

Ausgang:

id   child 
----------- ------------------------------ 
12345  Jane 
12345  John Jr. 
12345  Susan 
97531  Andrew 
97531  Adam 

Beachten Sie, dass . verwendet aktuelle Element Kontext zu verweisen; und in XML dürfen nicht zwei Attribute desselben Namens im selben übergeordneten Element vorhanden sein, sodass der Indexer in @id[1] nicht benötigt wird.

+0

Perfect. Ich entdeckte das CROSS APPLY, nachdem ich etwas herumgestochert hatte, nachdem ich das gepostet hatte, aber ich versuchte alles, was ich mir vorstellen konnte, um die Namen der Kinder ohne Erfolg zu bekommen. Ich habe das '' nie gesehen. Vor. Ich komme mit diesem Zeug aus, aber ich grabe es immer noch nicht. Vielen Dank! – vr8ce

+0

Zusätzlich zu dem, was ich in dieser Antwort geschrieben habe, verweist '.' In diesem Fall auf 'Children' Element, weil es auf' child.col' – har07

+0

verwendet wird ... und vergiss nicht, diese Antwort zu akzeptieren ([mehr lesen] (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work)). Danke – har07

1

Sie können nur:

select cust.col.value('../@id','int') as id, 
     cust.col.value('../@name','varchar(30)') as name, 
     cust.col.value('.','varchar(30)') as child 
    from @xml.nodes('/Customers/Customer/Children') as cust(col) 

zu erhalten:

id  name   child 
12345 John Doe  Jane 
12345 John Doe  John Jr. 
12345 John Doe  Susan 
97531 Ben Franklin Andrew 
97531 Ben Franklin Adam 
Verwandte Themen