with raw leer generar for sql xml tsql xpath xquery

raw - sql server select xml format



Fusionando XML en un Servidor SQL (2)

Digamos que tengo las siguientes dos piezas de XML en mi base de datos

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

Estos datos se almacenan en dos tablas separadas usando el tipo de datos XML , adicionalmente esta columna XML está vinculada a un esquema que describe el formato del xml esperado, por ejemplo

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

Dentro de un procedimiento / función almacenada me gustaría fusionar estas dos estructuras XML en lo siguiente:

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

Entonces, desde la primera pieza de xml hemos tomado elementos:

a, b

de la segunda pieza de xml hemos tomado elementos:

c, d, e

Tenga en cuenta que las dos piezas de XML tienen un elemento común con una clave de:

c

En este escenario, el valor de xml 2 se debe usar en el xml fusionado (descartando el valor de xml 1). Otro caso es que XML 1 o 2 podrían ser NULL, por lo que el proceso de fusión debería manejar esto y simplemente devolver el otro. O ambos podrían ser NULL, en cuyo caso se devuelve NULL.

Como un aparte, en nuestra implementación actual estamos devolviendo ambos documentos XML desde el DB y haciendo la fusión en código. Sin embargo, preferiríamos hacer esta fusión dentro de la base de datos ya que varios procesos no relacionados están llamando a este proceso.


Ejemplo con tablas:

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


Utilizar:

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

Salida:

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

ACTUALIZAR:

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