2010-02-01 3 views
1

Учитывая таблицу с столбцом XML, как я могу расширить список, хранящийся в нем, в реляционный набор строк?Расширяющийся список из столбца SQL с типом данных XML

Вот пример аналогичной таблицы.

DECLARE @test TABLE 
(
    id int, 
    strings xml 
) 

insert into @test (id, strings) 
select 1, '<ArrayOfString><string>Alpha</string><string>Bravo</string><string>Charlie</string></ArrayOfString>' union 
select 2, '<ArrayOfString><string>Bravo</string><string>Delta</string></ArrayOfString>' 

Я хотел бы получить такой набор строк.

id string 
-- ------ 
1 Alpha 
1 Bravo 
1 Charlie 
2 Bravo 
2 Delta 

Я понял, что можно использовать метод узлов для вывода значения XML для каждого идентификатора, как этот

select id, R.strings.query('/ArrayOfString/string') as string 
from @test cross apply strings.nodes('/ArrayOfString/string') as R(strings) 

возвращающегося

id string 
-- ------ 
1 <string>Alpha</string><string>Bravo</string><string>Charlie</string> 
1 <string>Alpha</string><string>Bravo</string><string>Charlie</string> 
1 <string>Alpha</string><string>Bravo</string><string>Charlie</string> 
2 <string>Bravo</string><string>Delta</string> 
2 <string>Bravo</string><string>Delta</string> 

и что я могу добавить [1 ] к запросу, чтобы получить только первую строку

, но это все еще оставляет меня с этим

id string 
-- ------ 
1 <string>Alpha</string> 
1 <string>Alpha</string> 
1 <string>Alpha</string> 
2 <string>Bravo</string> 
2 <string>Bravo</string> 

Кроме того, если я изменю R.strings.query к R.strings.value, чтобы избавиться от тегов, я получаю сообщение об ошибке; XQuery [@ test.strings.value()]: 'value()' требует одиночного (или пустой последовательности), найденного операнда типа 'xdt: untypedAtomic *'.

Может ли кто-нибудь указать, чего мне не хватает, чтобы получить каждое последующее строковое значение для каждого идентификатора последующих строк и почему метод value() дает мне эту ошибку?

ответ

1

Вот как вы можете сделать это с помощью кросс применить и значение методов XML и узлов:

select 
    id, 
    s2.value('.', 'varchar(max)') as string 
from @test 
cross apply strings.nodes('/*/string') t(s2) 

Вы получали ошибку, потому что вы пропали без вести() по всему XPATH:

select id, 
    R.strings.value('(/ArrayOfString/string)[1]','varchar(max)') as string 
from @test 
    cross apply strings.nodes('/ArrayOfString/string') as R(strings) 

Проблема с вашим скриптом заключается в том, что вы всегда выбираете первую строку. Используя '.' вы получите содержимое строки элемента XML.

+0

Perfect. Большое спасибо. –

0

Возможно, вы можете попробовать использовать функцию string() вместо функции value()? Это должно вернуть фактическое значение узла без xml.

Вот страница MSDN - http://msdn.microsoft.com/en-us/library/ms188692.aspx

Очень надеюсь, что помогает. :)

Смежные вопросы