Как я могу запросить значение в столбце XML SQL Server


127

У меня есть следующий XML, хранящийся в столбце XML (называемом Roles) в базе данных SQL Server.

<root>
   <role>Alpha</role>
   <role>Beta</role>
   <role>Gamma</role>
</root>

Я хотел бы перечислить все строки, у которых есть определенная роль. Эта роль передается параметром.

Ответы:


198
select
  Roles
from
  MyTable
where
  Roles.value('(/root/role)[1]', 'varchar(max)') like 'StringToSearchFor'

На этих страницах вы узнаете больше о том, как запрашивать XML в T-SQL:

Запрос полей XML с использованием t-sql

Сглаживание XML-данных в SQL Server

РЕДАКТИРОВАТЬ

Поработав с ним еще немного, я получил удивительный запрос, в котором используется CROSS APPLY. . Он будет искать в каждой строке (роли) значение, которое вы указали в выражении Like ...

Учитывая эту структуру таблицы:

create table MyTable (Roles XML)

insert into MyTable values
('<root>
   <role>Alpha</role>
   <role>Gamma</role>
   <role>Beta</role>
</root>')

Мы можем запросить это так:

select * from 

(select 
       pref.value('(text())[1]', 'varchar(32)') as RoleName
from 
       MyTable CROSS APPLY

       Roles.nodes('/root/role') AS Roles(pref)
)  as Result

where RoleName like '%ga%'

Вы можете проверить скрипт SQL здесь: http://sqlfiddle.com/#!18/dc4d2/1/0


5
Он отвечает на все мои вопросы, что [1]в вашем ответе?
Бистро,

1
Отличный ответ, я голосую за этот, но я думаю, строка должна быть varchar
AaA

7
@Bistro Спрашивать [1]было действительно хорошим вопросом. Это означает, что вы выбираете первое значение роли из XML, а это означает, что это будет работать только для поиска Alphaв вашем образце xml. Если вы выполните поиск, он не найдет строку Beta.
Микаэль Эрикссон

1
В моем случае мне пришлось запрашивать узлы с определенным значением атрибута. Этот ответ привел к моему решению. Мне просто пришлось заключить значение атрибута в двойные кавычки.
John N

Если у XML есть пространство имен, как его запросить?
FMFF

36
declare @T table(Roles xml)

insert into @T values
('<root>
   <role>Alpha</role>
   <role>Beta</role>
   <role>Gamma</role>
</root>')

declare @Role varchar(10)

set @Role = 'Beta'

select Roles
from @T
where Roles.exist('/root/role/text()[. = sql:variable("@Role")]') = 1

Если вы хотите, чтобы запрос работал, where col like '%Beta%'вы можете использоватьcontains

declare @T table(Roles xml)

insert into @T values
('<root>
   <role>Alpha</role>
   <role>Beta</role>
   <role>Gamma</role>
</root>')

declare @Role varchar(10)

set @Role = 'et'

select Roles
from @T
where Roles.exist('/root/role/text()[contains(., sql:variable("@Role"))]') = 1

13

если ваше имя поля - Роли, а имя таблицы - table1, вы можете использовать следующее для поиска

DECLARE @Role varchar(50);
SELECT * FROM table1
WHERE Roles.exist ('/root/role = sql:variable("@Role")') = 1

это хорошо, есть ли здесь какой-либо способ поиска использования like? forexample /root/role like ....
Бистро,

2
используйте .value('(/root/role)[1]', 'varchar(max)') like '%yourtext%'вместо того, existsкак объяснил
Лениэль

4
Вы пробовали это? Он находит все, что бы вы ни вставили @Role.
Микаэль Эрикссон

6

Я придумал простую работу ниже, которую тоже легко запомнить :-)

select * from  
(select cast (xmlCol as varchar(max)) texty
 from myTable (NOLOCK) 
) a 
where texty like '%MySearchText%'

1
Мы не должны искать с помощью манипуляций со строками, так как это приведет к слишком медленному поиску,
Малкольм Сальвадор

5

Вы могли бы сделать следующее

declare @role varchar(100) = 'Alpha'
select * from xmltable where convert(varchar(max),xmlfield) like '%<role>'+@role+'</role>%'

Очевидно, это что-то вроде взлома, и я бы не рекомендовал его для каких-либо официальных решений. Однако я считаю этот метод очень полезным при выполнении специальных запросов к столбцам XML в SQL Server Management Studio для SQL Server 2012.


2

Полезный совет. Запросить значение в столбце XML SQL Server (XML с пространством имен)

например

Table [dbo].[Log_XML] contains columns Parametrs (xml),TimeEdit (datetime)

например, XML в параметрах:

<ns0:Record xmlns:ns0="http://Integration"> 
<MATERIAL>10</MATERIAL> 
<BATCH>A1</BATCH> 
</ns0:Record>

например, запрос:

select
 Parametrs,TimeEdit
from
 [dbo].[Log_XML]
where
 Parametrs.value('(//*:Record/BATCH)[1]', 'varchar(max)') like '%A1%'
 ORDER BY TimeEdit DESC

1

Я использовал приведенный ниже оператор для получения значений в XML в таблице Sql.

with xmlnamespaces(default 'http://test.com/2008/06/23/HL.OnlineContract.ValueObjects')
select * from (
select
            OnlineContractID,
            DistributorID,
            SponsorID,
    [RequestXML].value(N'/OnlineContractDS[1]/Properties[1]/Name[1]', 'nvarchar(30)') as [Name]
   ,[RequestXML].value(N'/OnlineContractDS[1]/Properties[1]/Value[1]', 'nvarchar(30)') as [Value]
     ,[RequestXML].value(N'/OnlineContractDS[1]/Locale[1]', 'nvarchar(30)') as [Locale]
from [OnlineContract]) as olc
where olc.Name like '%EMAIL%' and olc.Value like '%EMAIL%' and olc.Locale='UK EN'

Что, если XML не содержит определения пространства имен?
Muflix

0

Вы можете запросить весь тег или только конкретное значение. Здесь я использую подстановочный знак для пространств имен xml.

declare @myDoc xml
set @myDoc = 
'<Root xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://stackoverflow.com">
    <Child>my value</Child>
 </Root>'

select @myDoc.query('/*:Root/*:Child') -- whole tag
select @myDoc.value('(/*:Root/*:Child)[1]', 'varchar(255)') -- only value
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.