Comment puis-je interroger une valeur dans la colonne XML SQL Server

127

J'ai le XML suivant stocké dans une colonne XML (appelée Roles) dans une base de données SQL Server.

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

Je voudrais lister toutes les lignes qui y jouent un rôle spécifique. Ce rôle est passé par paramètre.

Bistro
la source

Réponses:

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

Ces pages vous montreront plus sur la façon d'interroger XML dans T-SQL:

Interroger des champs XML à l'aide de t-sql

Aplatissement des données XML dans SQL Server

ÉDITER

Après avoir joué un peu plus, je me suis retrouvé avec cette requête étonnante qui utilise CROSS APPLY . Celui-ci recherchera dans chaque ligne (rôle) la valeur que vous avez mise dans votre expression like ...

Compte tenu de cette structure de table:

create table MyTable (Roles XML)

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

Nous pouvons l'interroger comme ceci:

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

Vous pouvez vérifier le SQL Fiddle ici: http://sqlfiddle.com/#!18/dc4d2/1/0

Leniel Maccaferri
la source
5
Cela répond à toutes mes questions, que fait [1]votre réponse?
Bistro
1
Excellente réponse, je vote pour celle-ci, mais la chaîne devrait être varchar je suppose
AaA
7
@Bistro Demander [1]était une très bonne question. Cela signifie que vous choisissez la première valeur de rôle dans le XML et cela signifie que cela ne fonctionnera que pour la recherche Alphadans votre exemple de xml. Il ne trouvera pas la ligne si vous recherchez Beta.
Mikael Eriksson
1
Dans mon cas, j'ai dû interroger des nœuds avec une valeur d'attribut spécifique. Cette réponse a conduit à ma solution. Je devais juste mettre des guillemets doubles autour de la valeur de l'attribut.
John N
Si le XML a un espace de noms, comment l'interroger?
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

Si vous souhaitez que la requête fonctionne comme where col like '%Beta%'vous pouvez l’utilisercontains

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
Mikael Eriksson
la source
13

si votre nom de champ est Rôles et que le nom de table est table1, vous pouvez utiliser ce qui suit pour rechercher

DECLARE @Role varchar(50);
SELECT * FROM table1
WHERE Roles.exist ('/root/role = sql:variable("@Role")') = 1
AaA
la source
c'est bien, y a-t-il un moyen de rechercher l'utilisation like? forexample /root/role like ....
Bistro
2
utiliser .value('(/root/role)[1]', 'varchar(max)') like '%yourtext%'au lieu de existscomme Leniel a expliqué
AaA
4
Avez-vous essayé cela? Il trouve tout, peu importe ce que vous y mettez @Role.
Mikael Eriksson
6

Je suis venu avec un travail simple ci-dessous qui est facile à retenir aussi :-)

select * from  
(select cast (xmlCol as varchar(max)) texty
 from myTable (NOLOCK) 
) a 
where texty like '%MySearchText%'
Sagar
la source
1
Nous ne sommes pas censés effectuer une recherche par manipulation de chaînes, car cela entraînerait des recherches beaucoup trop lentes
Malcolm Salvador
5

Vous pouvez faire ce qui suit

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

De toute évidence, c'est un peu un hack et je ne le recommanderais pas pour des solutions formelles. Cependant, je trouve cette technique très utile lorsque vous effectuez des requêtes ad hoc sur des colonnes XML dans SQL Server Management Studio pour SQL Server 2012.

Craig B
la source
2

Conseil utile. Interroger une valeur dans la colonne XML SQL Server (XML avec espace de noms)

par exemple

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

par exemple XML dans les paramètres:

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

Par exemple, requête:

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

J'ai utilisé l'instruction ci-dessous pour récupérer les valeurs du XML dans la table 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'
ranjit
la source
Que faire si XML ne contient pas de définition d'espace de noms?
Muflix
0

Vous pouvez interroger la balise entière ou simplement la valeur spécifique. Ici, j'utilise un caractère générique pour les espaces de noms 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
FrankyHollywood
la source