2012-02-10 51 views
6

比方说,我有XML的以下两件在我的数据库在SQL服务器合并XML

<!-- XML 1 --> 
<pairs> 
    <item key="a">xml 1 a value</item> 
    <item key="b">xml 1 b value</item> 
    <item key="c">xml 1 c value</item> 
</pairs> 

<!-- XML 2 -->  
<pairs> 
    <item key="c">xml 2 c value</item> 
    <item key="d">xml 2 d value</item> 
    <item key="e">xml 1 e value</item> 
</pairs> 

该数据是使用XML数据类型存储在两个单独的表,另外这个XML列链接到描述预期的XML如

[PairData] [xml](CONTENT [foo].[Pairs]) NULL 

的格式在存储过程/函数模式,我想这两个XML结构合并到以下几点:

<pairs> 
    <item key="a">xml 1 a value</item> 
    <item key="b">xml 1 b value</item> 
    <item key="c">xml 2 c value</item> 
    <item key="d">xml 2 d value</item> 
    <item key="e">xml 2 e value</item> 
</pairs> 

所以,从第一支XML的,我们已经采取的项目:

a, b 

从第二块XML的,我们已经采取的项目:

c, d, e 

注意,XML的两件有一个共同的项目有一个关键:

c 

在这种情况下,从XML 2的值应在合并中使用xml(放弃xml 1中的值)。另一种情况是XML 1或2可能是NULL,因此合并过程应该处理这个并简单地返回另一个。或者,在这种情况下,返回NULL可能都是NULL。另外,在我们当前的实现中,我们从数据库返回两个XML文档并在代码中进行合并。然而,我们宁愿在数据库中完成这种合并,因为多个不相关的进程正在调用这个过程。

+0

答案取决于数据存储。 (例如,您的源是一个表,一个xml列或一个字符串)。如果你能提供更多的信息,那将会很好。 – 2012-02-10 13:05:55

+0

欢呼的评论,问题更新。 – MrEyes 2012-02-10 13:12:49

回答

5

使用:

declare @x1 xml ='<pairs> 
    <item key="a">xml 1 a value</item> 
    <item key="b">xml 1 b value</item> 
    <item key="c">xml 1 c value</item> 
</pairs>' 

declare @x2 xml ='<pairs> 
    <item key="c">xml 2 c value</item> 
    <item key="d">xml 2 d value</item> 
    <item key="e">xml 2 e value</item> 
</pairs>' 

select * 
from 
(
    select isnull(t2.a, t1.a) [@key], isnull(t2.b, t1.b) [text()] 
    from 
    (
     select t.c.value('@key', 'nvarchar(max)') [a], t.c.value('.', 'nvarchar(max)') [b] 
     from @x1.nodes('/*/item') t(c) 
    )t1 
    full join 
    (
     select t.c.value('@key', 'nvarchar(max)') [a], t.c.value('.', 'nvarchar(max)') [b] 
     from @x2.nodes('/*/item') t(c) 
    )t2 on t2.a = t1.a 
)t 
for xml path('item'), root('pairs') 

输出:

<pairs> 
    <item key="a">xml 1 a value</item> 
    <item key="b">xml 1 b value</item> 
    <item key="c">xml 2 c value</item> 
    <item key="d">xml 2 d value</item> 
    <item key="e">xml 2 e value</item> 
</pairs> 

UPDATE:

declare @x1 xml ='<pairs> 
    <item key="a">xml 1 a value</item> 
    <item key="b">xml 1 b value</item> 
    <item key="c">xml 1 c value</item> 
</pairs>' 

declare @x2 xml ='<pairs> 
    <item key="c">xml 2 c value</item> 
    <item key="d">xml 2 d value</item> 
    <item key="e">xml 2 e value</item> 
</pairs>' 

declare @t1 table(id int, data xml) 
insert @t1 values(1, @x1) 

declare @t2 table(id int, data xml) 
insert @t2 values(1, @x2) 

select isnull(t2.a, t1.a) [@key], isnull(t2.b, t1.b) [text()] 
from 
(
    select t.c.value('@key', 'nvarchar(max)') [a], t.c.value('.', 'nvarchar(max)') [b] 
    from @t1 ta 
    cross apply ta.data.nodes('/*/item') t(c) 
)t1 
full join 
(
    select t.c.value('@key', 'nvarchar(max)') [a], t.c.value('.', 'nvarchar(max)') [b] 
    from @t2 ta 
    cross apply ta.data.nodes('/*/item') t(c) 
)t2 on t2.a = t1.a 
for xml path('item'), root('pairs') 
+0

这是完美的,只是一个小问题,我将如何去改变,以便它从表中选择而不是声明变量。 – MrEyes 2012-02-10 14:13:22

+0

@MeEyes,我已经更新了我的答案。 – 2012-02-10 16:46:49

1

实施例与表:

CREATE TABLE #x1 (row_key int, source_xml xml) 
CREATE TABLE #x2 (row_key int, source_xml xml) 

DECLARE @x1 xml = 
'<pairs> 
    <item key="a">xml 1 a value</item> 
    <item key="b">xml 1 b value</item> 
    <item key="c">xml 1 c value</item> 
</pairs>' 


DECLARE @x2 xml = 
'<pairs> 
    <item key="c">xml 2 c value</item> 
    <item key="d">xml 2 d value</item> 
    <item key="e">xml 1 e value</item> 
</pairs>' 

INSERT INTO #x1 VALUES (1, @x1) 
INSERT INTO #x2 VALUES (1, @x2) 

SELECT 
    ISNULL(a.item_key, b.item_key) [@key] 
    ,ISNULL(b.item_value, a.item_value) [text()] 
FROM 
(
SELECT 
    b.value('@key', 'char(1)') item_key, b.value('.', 'nvarchar(100)') item_value 
FROM 
    #x1 cross apply #x1.source_xml.nodes('./pairs/item') a(b) 
WHERE 
    row_key = 1 
) a 
FULL JOIN 
( 
SELECT 
    b.value('@key', 'char(1)') item_key, b.value('.', 'nvarchar(100)') item_value 
FROM 
    #x2 cross apply #x2.source_xml.nodes('pairs/item') a(b) 
WHERE 
    row_key = 1 
) b 
ON 
    a.item_key = b.item_key 
ORDER BY 
    ISNULL(a.item_key, b.item_key) 
FOR XML PATH ('item'), ROOT ('pairs') 

DROP TABLE #x1 
DROP TABLE #x2