2012-02-10 3 views
6

Diciamo Ho le seguenti due pezzi di XML nel mio databaseUnione di XML in uno SQL Server

<!-- 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> 

Questi dati vengono memorizzati in due tabelle separate utilizzando il XML tipo di dati, inoltre questa colonna XML è legata ad un schema che descrive il formato del previsto ad esempio XML

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

All'interno di una procedura/funzione memorizzata vorrei unire questi due strutture XML in quanto segue:

articoli

a, b 

dal secondo pezzo di XML che abbiamo preso::

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

articoli Così, dal primo pezzo di XML che abbiamo preso

c, d, e 

Si noti che i due pezzi di XML hanno un elemento comune, con una chiave di:

c 

in questo scenario il valore da XML 2 deve essere utilizzato nella fusione xml (scartando il valore da xml 1). Un altro caso è che XML 1 o 2 potrebbe essere NULL, quindi il processo di unione dovrebbe gestirlo e restituire semplicemente l'altro. O entrambi potrebbero essere NULL, nel qual caso viene restituito NULL.

Per inciso, nella nostra attuale implementazione restituiamo entrambi i documenti XML dal DB e facciamo l'unione nel codice. Tuttavia, preferiremmo che questa unione fosse eseguita all'interno del DB poiché più processi non correlati stanno chiamando questo proc.

+0

La risposta dipende dalla memorizzazione dei dati. (ad esempio, la tua fonte è una tabella, una colonna xml o una stringa di caratteri). Sarebbe bello se tu potessi fornire più informazioni. –

+0

Applausi per il commento, domanda aggiornata. – MrEyes

risposta

5

Usa:

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') 

uscita:

<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

Che funziona perfettamente, solo una piccola domanda come fare per alterare quello in modo che si stia selezionando dalle tabelle piuttosto che dai vars dichiarati. – MrEyes

+0

@MrEyes, ho aggiornato la mia risposta. –

1

Esempio con tavoli:

012.
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