2011-02-01 16 views
6

Decir que tengo la siguiente tabla (donde la historia es una columna XML):seleccionar varias filas de la columna de la base de datos XML utilizando XPath

Id  Value  History 
1  "Hello" <History> 
        <Node date="1-1-2011">World</Node> 
        <Node date="1-2-2011">Foo</Node> 
        <Node date="1-3-2011">Bar</Node> 
        </History> 
2  "Baz"  <History> 
        <Node date="1-1-2011">Buzz</Node> 
        <Node date="1-2-2011">Fizz</Node> 
        <Node date="1-3-2011">Beam</Node> 
        </History> 

Y desde que yo quería para seleccionar una nueva tabla como:

HistoryId Id  Value  Date 
1   1  "World"  1-1-2011 
2   1  "Foo"  1-2-2011 
3   1  "Bar"  1-3-2011 
4   2  "Buzz"  1-1-2011 
5   2  "Fizz"  1-2-2011 
6   2  "Beam"  1-3-2011 

¿Cómo haré eso?

Si se tratara de un valor XML independiente que podía hacer algo como esto:

DECLARE @xml2 XML = ' 
<History> 
    <Node date="1-1-2011">World</Node> 
    <Node date="1-2-2011">Foo</Node> 
    <Node date="1-3-2011">Bar</Node> 
</History>' 

SELECT 
    x.value('(@date)[1]','date') AS [Date] 
    ,x.value('.', 'nvarchar(50)') AS Value 
FROM @xml2.nodes('/History/Node') temp(x) 

pero no estoy seguro de cómo hacerlo cuando los datos XML es parte de una columna de la tabla. Probablemente podría encontrar una forma de hacerlo imperativamente con un cursor, pero me preguntaba si existe una solución declarativa más elegante de la que no tengo conocimiento.

Respuesta

9

Utilice una cruz aplica

declare @T table (Id int, Value nvarchar(50), History xml) 
insert into @T values (1, 'Hello',' 
<History> 
    <Node date="1-1-2011">World</Node> 
    <Node date="1-2-2011">Foo</Node> 
    <Node date="1-3-2011">Bar</Node> 
</History>') 
insert into @T values (2, 'Baz',' 
<History> 
    <Node date="1-1-2011">Buzz</Node> 
    <Node date="1-2-2011">Fizz</Node> 
    <Node date="1-3-2011">Beam</Node> 
</History>') 

select 
    Id, 
    h.n.value('.', 'varchar(10)') as Value, 
    h.n.value('@date', 'varchar(10)') as Date 
from @T 
    cross apply history.nodes('History/Node') h(n) 
+0

impresionante, gracias! Estaba tratando de ver si podía lograr que funcionara una solución de cursor pero tardaba mucho en ejecutarse incluso en un SELECT TOP 10, esto es elegante y rápido. – Davy8

+0

Gracias Mikael: la cantidad de veces que olvidé cómo hacer esto y terminé aquí por medio de Google es francamente embarazoso. : D Tener un +1 por ser increíble. – mnield

Cuestiones relacionadas