2011-02-15 56 views
0

我试图用XQuery将XML插入表中。有些节点是多个节点,但表中只有一列,所以我需要连接相同的节点。如何使用XQuery连接相同的节点值

如何迭代"INSERT ... SELECT ... FROM @xmlDoc.nodes ..."类型的查询。

这里是我的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> 

感谢。

+2

标准抱怨的XQuery引擎已经实现[`串联接()`](http://www.w3.org/TR/xpath-functions/#func-string-join)的XPath 2.0功能。但是SQL-Server ... – 2011-02-15 23:20:12

回答

2

这是一个使用cte的版本,首先在xml列中分离DocumentNumber和WorkPlace,然后使用xml路径('')连接值。

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

它似乎工作:)谢谢。我会在我的查询中尝试。 – hgulyan 2011-02-15 09:58:40

1

你的XML组织很差.....麻烦是<DocumentNumber><WorkPlace>实体里面直接<Person>,而不是在他们自己的“容器”节点的多个条目。

这使得极难得到这个正确解析.....

如果你想抓住唯一的名称,你可以这样做:

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) 

,当然,你可以在选择存储信息之前,还要执行INSERT INTO dbo.YourTable(FirstName, LastName)

但再次:试图让那些<DocumentNumber><WorkPlace>节点成合适的格式是真的真的很难.....你要么最终会复制数据,或者你必须做的第二和第三解析通拿到这个东西妥善保存。

+0

我无法用XML文件做这件事,它是一个外部源,我需要导入到表中。在这种情况下我可以做什么来插入多个documentNumbers,如果我甚至不知道相同节点的数目?解决方案,你已经描述了我现在正在使用,但我需要有一种动态迭代的东西来连接所有的documentNumber值并插入到一列中? – hgulyan 2011-02-15 09:44:39