Reputation: 8239
I'm trying to insert XML to a Table with XQuery. Some nodes are multiple, but there's only one column in the Table, so I need to concatenate same nodes.
How can I iterate in a "INSERT ... SELECT ... FROM @xmlDoc.nodes ..."
kind of query.
Here's a sample of my xml file
<Persons>
<Person>
<FirstName>aaa</FirstName>
<LastName>bbb</LastName>
<DocumentNumber>AA 1234</DocumentNumber>
<DocumentNumber>BB 1234</DocumentNumber>
<WorkPlace>AAA Ltd</WorkPlace>
<WorkPlace>BBB Ltd</WorkPlace>
</Person>
<Person>
<FirstName>ccc</FirstName>
<LastName>ddd</LastName>
<DocumentNumber>CCC 1234</DocumentNumber>
<DocumentNumber>DDD 1234</DocumentNumber>
<DocumentNumber>EEE 1234</DocumentNumber>
<WorkPlace>CCC Ltd</WorkPlace>
<WorkPlace>DDD Ltd</WorkPlace>
</Person>
</Persons>
Thanks.
Upvotes: 0
Views: 3587
Reputation: 138960
Here is a version using a cte to isolate DocumentNumber and WorkPlace in xml columns first and then using for xml path('') to concatenate the values.
declare @xml xml
set @xml =
'
<Persons>
<Person>
<FirstName>aaa</FirstName>
<LastName>bbb</LastName>
<DocumentNumber>AA 1234</DocumentNumber>
<DocumentNumber>BB 1234</DocumentNumber>
<WorkPlace>AAA Ltd</WorkPlace>
<WorkPlace>BBB Ltd</WorkPlace>
</Person>
<Person>
<FirstName>ccc</FirstName>
<LastName>ddd</LastName>
<DocumentNumber>CCC 1234</DocumentNumber>
<DocumentNumber>DDD 1234</DocumentNumber>
<DocumentNumber>EEE 1234</DocumentNumber>
<WorkPlace>CCC Ltd</WorkPlace>
<WorkPlace>DDD Ltd</WorkPlace>
</Person>
</Persons>
'
;with cte as
(
select
p.value('FirstName[1]', 'varchar(50)') as FirstName,
p.value('LastName[1]', 'varchar(50)') as LastName,
p.query('DocumentNumber') as docXML,
p.query('WorkPlace') as workXML
from
@xml.nodes('Persons/Person') p(p)
)
select
FirstName,
LastName,
(select d.value('.', 'varchar(100)')+' '
from cte.docXML.nodes('DocumentNumber') d(d)
for xml path('')) as DocumentNumber,
(select w.value('.', 'varchar(100)')+' '
from cte.workXML.nodes('WorkPlace') w(w)
for xml path('')) as WorkPlace
from cte
Upvotes: 2
Reputation: 754258
Your XML is very poorly organized..... the trouble is the multiple entries of <DocumentNumber>
and <WorkPlace>
entities directly inside <Person>
and not within their own "container" node.
This makes is extremely hard to get this parsed properly.....
If you want to grab only the names, you could use this:
DECLARE @input XML = '<Persons>
<Person>
<FirstName>aaa</FirstName>
<LastName>bbb</LastName>
<DocumentNumber>AA 1234</DocumentNumber>
<DocumentNumber>BB 1234</DocumentNumber>
<WorkPlace>AAA Ltd</WorkPlace>
<WorkPlace>BBB Ltd</WorkPlace>
</Person>
<Person>
<FirstName>ccc</FirstName>
<LastName>ddd</LastName>
<DocumentNumber>CCC 1234</DocumentNumber>
<DocumentNumber>DDD 1234</DocumentNumber>
<DocumentNumber>EEE 1234</DocumentNumber>
<WorkPlace>CCC Ltd</WorkPlace>
<WorkPlace>DDD Ltd</WorkPlace>
</Person>
</Persons>'
SELECT
Person.value('(FirstName)[1]', 'varchar(50)') 'First Name',
Person.value('(LastName)[1]', 'varchar(50)') 'Last Name'
FROM
@input.nodes('/Persons/Person') AS Persons(Person)
and of course, you could also do an INSERT INTO dbo.YourTable(FirstName, LastName)
before that select to store the information.
But again: trying to get those <DocumentNumber>
and <WorkPlace>
nodes into a proper format is really really hard..... you either end up duplicating data, or you have to do a second and third parsing pass to get this stuff properly stored.
Upvotes: 1