Come posso eseguire una query su un valore nella colonna XML di SQL Server


127

Ho seguito XML archiviato in una colonna XML (chiamata Roles) in un database di SQL Server.

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

Vorrei elencare tutte le righe che hanno un ruolo specifico in esse. Questo ruolo è passato per parametro.

Risposte:


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

Queste pagine ti mostreranno di più su come interrogare XML in T-SQL:

Richiesta di campi XML mediante t-sql

Appiattimento dei dati XML in SQL Server

MODIFICARE

Dopo averci giocato un po 'di più, ho finito con questa fantastica query che utilizza CROSS APPLY . Questo cercherà in ogni riga (ruolo) il valore che hai inserito nella tua espressione simile ...

Data questa struttura della tabella:

create table MyTable (Roles XML)

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

Possiamo interrogarlo in questo modo:

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

È possibile controllare il violino SQL qui: http://sqlfiddle.com/#!18/dc4d2/1/0


5
Risponde a tutte le mie domande, cosa fa [1]nella tua risposta?
Bistro

1
Ottima risposta, voto per questo, ma la stringa dovrebbe essere varchar credo
AaA

7
@Bistro Fare [1]una domanda è stata davvero una bella domanda. Significa che scegli il primo valore del ruolo dall'XML e ciò significa che funzionerà solo per la ricerca Alphanel tuo XML di esempio. Non troverà la riga se cerchi Beta.
Mikael Eriksson,

1
Nel mio caso, ho dovuto interrogare nodi con un valore di attributo specifico. Questa risposta ha portato alla mia soluzione. Ho solo dovuto mettere virgolette doppie attorno al valore dell'attributo.
John N,

Se l'XML ha uno spazio dei nomi, come possiamo interrogarlo?
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

Se vuoi che la query funzioni come where col like '%Beta%'puoi usarecontains

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

se il nome del tuo campo è Ruoli e il nome della tabella è table1, puoi utilizzare la seguente ricerca

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

questo va bene, è qui un modo per cercare l'utilizzo like? forexample /root/role like ....
Bistro

2
usa .value('(/root/role)[1]', 'varchar(max)') like '%yourtext%'invece di existscome ha spiegato
Leniel

4
Hai provato questo? Trova tutto, indipendentemente da ciò che hai inserito @Role.
Mikael Eriksson,

6

Ho escogitato un semplice lavoro in giro che è anche facile da ricordare :-)

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

1
Non dovremmo cercare tramite manipolazione di stringhe, poiché ciò comporterebbe ricerche troppo lente
Malcolm Salvador,

5

Potresti fare quanto segue

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

Ovviamente questo è un po 'un trucco e non lo consiglierei per nessuna soluzione formale. Tuttavia trovo questa tecnica molto utile quando si eseguono query ad hoc su colonne XML in SQL Server Management Studio per SQL Server 2012.


2

Consiglio utile Richiesta di un valore nella colonna XML di SQL Server (XML con spazio dei nomi)

per esempio

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

ad es. XML in Parametri:

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

ad es. query:

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

1

Ho usato la seguente istruzione per recuperare i valori nell'XML nella tabella 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'

Cosa succede se XML non contiene la definizione dello spazio dei nomi?
Muflix,

0

Puoi interrogare l'intero tag o solo il valore specifico. Qui uso un carattere jolly per gli spazi dei nomi 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.