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

In case your column is not XML, you need to convert it. You can also use other syntax to query certain attributes of your XML data. Here is an example...

Let's suppose that data column has this:

<Utilities.CodeSystems.CodeSystemCodes iid="107" CodeSystem="2" Code="0001F" CodeTags="-19-"..../>

... and you only want the ones where CodeSystem = 2 then your query will be:

select 
  [data] 
from
  [dbo].[CodeSystemCodes_data]
  
where
  CAST([data] as XML).value('(/Utilities.CodeSystems.CodeSystemCodes/@CodeSystem)[1]', 'varchar(max)') = '2'

These pages will show you more about how to query XML in T-SQL:

Querying XML fields using t-sql

Flattening XML Data in SQL Server

EDIT

After playing with it a little bit more, I ended up with this amazing query that uses CROSS APPLY. This one will search every row (role) for the value you put in your like expression...

Given this table structure:

create table MyTable (Roles XML)

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

We can query it like this:

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

You can check the SQL Fiddle here: http://sqlfiddle.com/#!18/dc4d2/1/0

Answer from Leniel Maccaferri on Stack Overflow
🌐
Microsoft Learn
learn.microsoft.com › en-us › sql › t-sql › xml › value-method-xml-data-type
value() method (xml data type) - SQL Server | Microsoft Learn
Performs an XQuery against XML and returns a value of SQL type. This method returns a scalar value. You typically use this method to extract a value from an XML instance stored in an xml type column, parameter, or variable.
Top answer
1 of 9
243
select
  Roles
from
  MyTable
where
  Roles.value('(/root/role)[1]', 'varchar(max)') like 'StringToSearchFor'

In case your column is not XML, you need to convert it. You can also use other syntax to query certain attributes of your XML data. Here is an example...

Let's suppose that data column has this:

<Utilities.CodeSystems.CodeSystemCodes iid="107" CodeSystem="2" Code="0001F" CodeTags="-19-"..../>

... and you only want the ones where CodeSystem = 2 then your query will be:

select 
  [data] 
from
  [dbo].[CodeSystemCodes_data]
  
where
  CAST([data] as XML).value('(/Utilities.CodeSystems.CodeSystemCodes/@CodeSystem)[1]', 'varchar(max)') = '2'

These pages will show you more about how to query XML in T-SQL:

Querying XML fields using t-sql

Flattening XML Data in SQL Server

EDIT

After playing with it a little bit more, I ended up with this amazing query that uses CROSS APPLY. This one will search every row (role) for the value you put in your like expression...

Given this table structure:

create table MyTable (Roles XML)

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

We can query it like this:

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

You can check the SQL Fiddle here: http://sqlfiddle.com/#!18/dc4d2/1/0

2 of 9
41
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

If you want the query to work as where col like '%Beta%' you can use 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
🌐
Benjamin's Blog
sqlbenjamin.wordpress.com › 2019 › 09 › 13 › sql-tip-the-query-and-value-methods-xml
SQL Tip: The “query()” and “value()” methods (XML)
February 16, 2022 - It is very similar to the query() method in that it requires an ‘XQuery’ or ‘path’, but it also requires a data type. Therefore, unlike query(), value() isn’t limited to returning the results as XML but will convert the xml to whatever data type you specify.
🌐
Microsoft Learn
learn.microsoft.com › en-us › sql › t-sql › xml › query-method-xml-data-type
query() Method (xml Data Type) - SQL Server | Microsoft Learn
The query() method constructs XML, a <Product> element that has a ProductModelID attribute, in which the ProductModelID attribute value is retrieved from the database.
🌐
Red Gate Software
red-gate.com › home › the xml methods in sql server
The XML Methods in SQL Server | Simple Talk
August 16, 2021 - My goal was to retrieve the value from each instance of that element. I then provided a table alias (Bike) and a column alias (Category) to identify my rowset view. Now I essentially have a table with a single column that contains a row for each <Product> element. When you use the nodes() method to create a rowset view of the XML data, you have to use one of the other XML methods to retrieve the contents of that view. In this case, I used the query() method in the SELECT list to return the value of each row.
🌐
Barney Lawrence
barneylawrence.com › 2021 › 03 › 23 › querying-xml-in-sql-server-part-2-simple-paths-and-attributes-with-the-value-method
Querying XML In SQL Server – Part 2 – Simple Paths and Attributes With the Value Method
April 5, 2021 - With MyNumbers AS ( SELECT N FROM (VALUES(1),(2),(3),(4),(5),(6),(7)) AS N(N) ) SELECT MyNumbers.N, X.MyXML.value( '(/items/item/poll/ results[sql:column("MyNumbers.N")]/ result[@value = "Best"]/ @numvotes)[1]' ,'int' ) AS BestPollVotes FROM #MyXML AS X CROSS JOIN MyNumbers ORDER BY N; The row for N=7 gives a NULL because there is no 7th Element, SQL Server doesn’t know this though and will take a look for you anyway. Don’t go wild with the above. If you want to split repeating XML elements into rows of a table there’s a better way.
Top answer
1 of 4
137

Actually you're close to your goal, you just need to use nodes() method to split your rows and then get values:

select
    s.SqmId,
    m.c.value('@id', 'varchar(max)') as id,
    m.c.value('@type', 'varchar(max)') as type,
    m.c.value('@unit', 'varchar(max)') as unit,
    m.c.value('@sum', 'varchar(max)') as [sum],
    m.c.value('@count', 'varchar(max)') as [count],
    m.c.value('@minValue', 'varchar(max)') as minValue,
    m.c.value('@maxValue', 'varchar(max)') as maxValue,
    m.c.value('.', 'nvarchar(max)') as Value,
    m.c.value('(text())[1]', 'nvarchar(max)') as Value2
from sqm as s
    outer apply s.data.nodes('Sqm/Metrics/Metric') as m(c)

sql fiddle demo

2 of 4
16

I've been trying to do something very similar but not using the nodes. However, my xml structure is a little different.

You have it like this:

<Metrics>
    <Metric id="TransactionCleanupThread.RefundOldTrans" type="timer" ...>

If it were like this instead:

<Metrics>
    <Metric>
        <id>TransactionCleanupThread.RefundOldTrans</id>
        <type>timer</type>
        .
        .
        .

Then you could simply use this SQL statement.

SELECT
    Sqm.SqmId,
    Data.value('(/Sqm/Metrics/Metric/id)[1]', 'varchar(max)') as id,
    Data.value('(/Sqm/Metrics/Metric/type)[1]', 'varchar(max)') AS type,
    Data.value('(/Sqm/Metrics/Metric/unit)[1]', 'varchar(max)') AS unit,
    Data.value('(/Sqm/Metrics/Metric/sum)[1]', 'varchar(max)') AS sum,
    Data.value('(/Sqm/Metrics/Metric/count)[1]', 'varchar(max)') AS count,
    Data.value('(/Sqm/Metrics/Metric/minValue)[1]', 'varchar(max)') AS minValue,
    Data.value('(/Sqm/Metrics/Metric/maxValue)[1]', 'varchar(max)') AS maxValue,
    Data.value('(/Sqm/Metrics/Metric/stdDeviation)[1]', 'varchar(max)') AS stdDeviation,
FROM Sqm

To me this is much less confusing than using the outer apply or cross apply.

I hope this helps someone else looking for a simpler solution!

Find elsewhere
🌐
SQL Shack
sqlshack.com › filtering-xml-columns-using-xquery-in-sql-server
Filtering XML Columns using XQuery in SQL Server
February 6, 2020 - XQuery returns the values from the specified XML node or attribute based on the parameters. XQuery accomplishes business logic with data manipulation on the XML node and attribute values inside the XML data type column with such requests.
🌐
Chad Callihan
callihandata.com › 2021 › 03 › 13 › querying-xml-data-in-sql-server
Querying XML Data in SQL Server – Chad Callihan
March 13, 2021 - Each ComicData XML file follows this type of format: We can first use the query() method in SQL Server. Let’s say we wanted to find Full_Title and Publisher from our data. We could gather that by running this query: SELECT ComicData.query('/comic/Full_Title') AS 'Full_Title' ,ComicData.query('/comic/Publisher_Name') AS 'Publisher' FROM Comic_Collection; GO · This returns the values including “Full_Title” and “Publisher” in the results.
🌐
SQLServerCentral
sqlservercentral.com › blogs › sql-querying-xml-attributes-from-xml-column
SQL- Querying XML attributes from XML Column – SQLServerCentral
January 26, 2015 - create table #demo (field1 xml) insert into #demo (field1) values ('<dimensions> <dimension name="height" value="0.14" /> <dimension name="width" value="12.77"/> </dimensions>') SELECT x.v.value('@name[1]', 'VARCHAR(100)') AS dimtype , x.v.value('@value[1]', 'VARCHAR(100)') AS dimvalue from #demo cross apply field1.nodes('/dimensions/dimension[@name = "height" or @name = "width"]') x(v) Using SQL Where Clause to fetch dimension type data ‘HEIGHT’ or ‘WIDTH’
🌐
MSSQLTips
mssqltips.com › home › basic sql server xml querying
Basic SQL Server XML Querying
February 20, 2013 - We’ve assumed too much – that the value we are looking for in the Education node will exactly match the text ‘Bachelors’. If we look at the sample Demographics XML fragment closely, we see that there is a space after the word. So, if we modify our query and run it again, we get the following: --filtering XML data using XQuery - adding a space to the string ;WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey' AS ns) SELECT COUNT(1) FROM Person.Person WHERE Demographics.exist('(/ns:IndividualSurvey/ns:Education[.="Bachelors "])')=1 GO
🌐
Microsoft Learn
learn.microsoft.com › en-us › sql › relational-databases › xml › for-xml-sql-server
FOR XML (SQL Server) - SQL Server | Microsoft Learn
September 3, 2025 - Learn how to retrieve formal results of a SQL query as XML by specifying the FOR XML clause in the query.
🌐
ArcGIS
desktop.arcgis.com › en › arcmap › latest › manage-data › using-sql-with-gdbs › xml-column-queries.htm
XML column queries—ArcMap | Documentation
Developers using languages such as Java, C++, or C# may prefer to read the document into a Document Object Model (DOM). SQL developers can use database XML functions to retrieve specific values from item definitions using XPath (a query language for XML documents).
🌐
Kodyaz
kodyaz.com › t-sql › query-xml-using-sql-xml-in-sql-server.aspx
Query XML data using SQL XML in SQL Server - Kodyaz.com
Now, let's code in SQL and return the list of SQL Server books out of the XML data. Execute the following SQL XML Select statement to return the values of the XML nodes <book> for the SQL Server books list contained in XML data.
🌐
IBM
ibm.com › docs › en › db2 › 11.1.0
Lesson 6: Querying XML data
This lesson shows you how to query XML data by using SQL, XQuery (with XQuery expressions), or a combination of both.
Top answer
1 of 5
1

Hi @Andrey Piatov ,

A proper answer should follow the same minimal reproducible example paradigm like in my comment to your question. It is copied to SSMS as-is, executed, and you are getting your answer.

SQL

-- DDL and data population, start  
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);  
INSERT INTO @tbl (xmldata) VALUES  
(N'  
   
   
 853  
   
   
   
   
 503  
   
   
 512  
   
   
 511  
   
   
');  
-- DDL and data population, end  
  
SELECT c.value('.', 'INT') as value  
FROM @tbl  
CROSS APPLY xmldata.nodes('/data/user[@name="Executors"]/value/id/text()') t(c);  

Output

+-------+  
| value |  
+-------+  
|   503 |  
|   512 |  
|   511 |  
+-------+  
2 of 5
0

Hi @Andrey Piatov
If you want the id value display in one row, then please check this sample:

DECLARE @tbl TABLE (Xml_ID INT IDENTITY PRIMARY KEY, xmldata XML);  
INSERT INTO @tbl (xmldata) VALUES  
 (N'853503512511'),  
 (N'853555544533522'),  
 (N'853511566'),  
 (N'853');  
  
--Use STRING_AGG (Need SQL Server 2017 (14.x) and later)  
;WITH CTE AS  
(  
 SELECT Xml_ID,n.x.value('id[1]','INT') AS Executors_Value  
 FROM @tbl t  
 OUTER APPLY xmldata.nodes('/data/user[@name="Executors"]/value') n(x) --Use CROSS APPLY instead of OUTER APPLY if you do not want NULL Executors_Value  
)  
SELECT Xml_ID,STRING_AGG(Executors_Value, ',') WITHIN GROUP (ORDER BY Executors_Value) AS Executors_Value  
FROM CTE  
GROUP BY Xml_ID  
  
--Try this query if not support STRING_AGG  
;WITH CTE AS  
(  
 SELECT Xml_ID,n.x.value('id[1]','INT') AS Executors_Value  
 FROM @tbl t  
 OUTER APPLY xmldata.nodes('/data/user[@name="Executors"]/value') n(x)  
)  
SELECT Xml_ID,  
       STUFF((SELECT ',' + CAST(Executors_Value AS VARCHAR) FROM CTE WHERE Xml_ID=T.Xml_ID FOR XML PATH('')),1,1,'')AS Executors_Value  
FROM CTE T  
GROUP BY Xml_ID  

Output:

Best regards,
LiHong


If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our Documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

🌐
MSSQLTips
mssqltips.com › home › working with xml data in sql server
Working with XML data in SQL Server
September 10, 2024 - The value method requires the XPath expression to select just one node, and if it selects multiple nodes, you must use predicates to limit the result to one node, or the method will throw an error.
🌐
T-SQL Tutorial
tsql.info › xml › value.php
SQL Server XML value() method
This query will return 100000 as the value of the first employee's salary. Note that the value() method only returns a single value. If you want to extract multiple values, you need to use the nodes() method to shred the XML into rows and then use value() to extract each value separately.