Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите сделать фильтр по полю xml  [new]
monheim
Guest
Доброго времени суток, уважаемые коллеги !
Дайте добрый совет, есть таблица, которая содержит поле типа xml и хранит некоторый xml-документ, например
<root>
 <data id="1" />
 ..
</root>

Возможно ли как-нибудь сделать select с фильтром в операторе where по значению, скажем, атрибута id ?
Премного благодарен за внимание !
27 янв 14, 15:36    [15475975]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать фильтр по полю xml  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 5975
;with cte as (
  select 123 id, CONVERT(xml, N'<root><data id="1" /></root>') xdata
)
select * from cte where xdata.exist('/root/data/@id=1')=1
27 янв 14, 15:54    [15476205]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать фильтр по полю xml  [new]
monheim
Guest
Сон Веры Павловны,
Спасибо большое !
Сам еще нашел такое решение
select * from [table] where [field].value('(/root/data/@id)[1]', 'int') = 1
27 янв 14, 16:02    [15476309]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать фильтр по полю xml  [new]
invm
Member

Откуда: Москва
Сообщений: 9404
monheim
Сам еще нашел такое решение
select * from [table] where [field].value('(/root/data/@id)[1]', 'int') = 1
Это вообще не решение, ибо:
;with cte as (
  select 123 id, CONVERT(xml, N'<root><data id="2" /><data id="1" /></root>') xdata
)
select * from cte where xdata.value('(/root/data/@id)[1]', 'int') = 1
27 янв 14, 16:26    [15476531]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать фильтр по полю xml  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 5975
monheim
Сон Веры Павловны,
Спасибо большое !

Не стоит - там ошибка :)
Правильно вот так:
;with cte as (
  select 123 id, CONVERT(xml, N'<root><data id="2" /><data id="1" /></root>') xdata
)
select * from cte where xdata.exist('/root/data[@id=1]')=1

В первом варианте вычисляется значение типа bool, и, видимо, неявно преобразуется в строку, а в случае непустых строк exist всегда вернет true. В вышеприведенном примере условие exist('/root/data/@id=100')=1 тоже будет истинным. Оно будет истинным при любых сравниваемых внутри exist значениях.
27 янв 14, 17:08    [15476940]     Ответить | Цитировать Сообщить модератору
 Re: Помогите сделать фильтр по полю xml  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 5975
Сон Веры Павловны
В первом варианте вычисляется значение типа bool, и, видимо, неявно преобразуется в строку, а в случае непустых строк exist всегда вернет true.

Да, так и есть:
select CONVERT(xml, N'<root><data id="1" /></root>').value('/root/data/@id=1','int')

Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the nvarchar value 'true' to data type int.
27 янв 14, 18:08    [15477430]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить