<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Dr.NETjes : Xml</title><link>http://weblogs.asp.net/drnetjes/archive/tags/Xml/default.aspx</link><description>Tags: Xml</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>XML querying in SQL2000</title><link>http://weblogs.asp.net/drnetjes/archive/2005/03/02/383923.aspx</link><pubDate>Wed, 02 Mar 2005 22:02:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:383923</guid><dc:creator>Dr.NETjes</dc:creator><author>Dr.NETjes</author><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/drnetjes/rsscomments.aspx?PostID=383923</wfw:commentRss><comments>http://weblogs.asp.net/drnetjes/archive/2005/03/02/383923.aspx#comments</comments><description>&lt;p&gt;Do you want to query on unstructured xml data inside SQL2000 text fields? Keep on reading!&lt;/p&gt; &lt;p&gt;I've&amp;nbsp;created a&amp;nbsp;table 'Person' with a text&amp;nbsp;field&amp;nbsp;containing flat xml data (see below):&lt;/p&gt; &lt;table bordercolor="black" cellspacing="0" border="1"&gt; &lt;tbody&gt; &lt;tr bgcolor="lightblue"&gt; &lt;td&gt;Id &lt;br /&gt;[identity]&lt;/td&gt; &lt;td&gt;FirstName&amp;nbsp;&lt;br /&gt;[varchar(50)]&lt;/td&gt; &lt;td&gt;ContentXml &lt;br /&gt;[text]&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;Dion&lt;/td&gt; &lt;td&gt;&amp;lt;content&amp;gt;&amp;lt;birthdate&amp;gt;06/21/1970&amp;lt;/birthdate&amp;gt;&amp;lt;gender&amp;gt;male&amp;lt;/gender&amp;gt;&amp;lt;/content&amp;gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;Rosie&lt;/td&gt; &lt;td&gt;&amp;lt;content&amp;gt;&amp;lt;birthdate&amp;gt;11/30/1969&amp;lt;/birthdate&amp;gt;&amp;lt;gender&amp;gt;female&amp;lt;/gender&amp;gt;&amp;lt;/content&amp;gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;James&lt;/td&gt; &lt;td&gt;&amp;lt;content&amp;gt;&amp;lt;birthdate&amp;gt;05/02/1973&amp;lt;/birthdate&amp;gt;&amp;lt;gender&amp;gt;male&amp;lt;/gender&amp;gt;&amp;lt;/content&amp;gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4&lt;/td&gt; &lt;td&gt;Bill&lt;/td&gt; &lt;td&gt;&amp;lt;content&amp;gt;&amp;lt;birthdate&amp;gt;06/12/1961&amp;lt;/birthdate&amp;gt;&amp;lt;gender&amp;gt;male&amp;lt;/gender&amp;gt;&amp;lt;/content&amp;gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&lt;br /&gt;Now I'd like to query the xml-data in the 'ContentXml' field, for example: &lt;br /&gt;&lt;strong&gt;&lt;br /&gt;“Select all rows where 'birthdate' is at least '1/1/1970',&amp;nbsp;and 'gender' equals 'male'. “&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;Using SQLServer2005, querying on&amp;nbsp;data inside xml fields is as easy as:&lt;/p&gt;&lt;pre class="Code"&gt;SELECT&amp;nbsp;*&lt;br /&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;Person&lt;br /&gt;WHERE&amp;nbsp;&amp;nbsp;ContentXml.value('(//birthdate)[1]', 'DateTime') &amp;gt;= CAST('1/1/1970' AS DateTime)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AND ContentXml.value('(//gender)[1]', 'VarChar') = 'male' &lt;/pre&gt; &lt;p&gt;But what if you're using&amp;nbsp;SQLServer2000 and want a solution right now? SQLServer2000 doesn't “know” xml.....&lt;br /&gt;Well, take a look at the query below, running on SQLServer2000 and returning the&amp;nbsp;same results:&lt;/p&gt;&lt;pre class="Code"&gt;SELECT *&lt;br /&gt;FROM&amp;nbsp;&amp;nbsp; Person&lt;br /&gt;WHERE&amp;nbsp; dbo.fn_XmlElementValue(ContentXML, 'birthdate') &amp;gt;= CAST('1/1/1970' AS DateTime)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AND dbo.fn_XmlElementValue(ContentXML, 'gender') = 'male'&lt;/pre&gt; &lt;p&gt;&lt;br /&gt;You want to see the fn_XmlElementValue function? Here it is:&lt;/p&gt;&lt;pre class="Code"&gt;CREATE FUNCTION dbo.fn_XmlElementValue(@xml text, @tagname varchar(100)) &lt;br /&gt;RETURNS varchar(2000) &lt;br /&gt;AS &lt;br /&gt;BEGIN &lt;br /&gt;&amp;nbsp;DECLARE @startpos int, @endpos int &lt;br /&gt;&amp;nbsp;IF (NOT @tagname IS NULL) &lt;br /&gt;&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;SET @startpos = CHARINDEX('&amp;lt;' + @tagname + '&amp;gt;', @xml) + LEN('&amp;lt;' + @tagname + '&amp;gt;') &lt;br /&gt;&amp;nbsp;&amp;nbsp;IF (@startpos &amp;gt; 0) &lt;br /&gt;&amp;nbsp;&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;SET @endpos = CHARINDEX('&amp;lt;/' + @tagname + '&amp;gt;', @xml, @startpos) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;IF (@endpos &amp;gt; @startpos) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-- Return the requested value &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RETURN (SUBSTRING(@xml, @startpos, @endpos - @startpos)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;END &lt;br /&gt;&amp;nbsp;&amp;nbsp;END &lt;br /&gt;&amp;nbsp;END &lt;br /&gt;&amp;nbsp;--&amp;nbsp; Tag empty or not found &lt;br /&gt;&amp;nbsp;RETURN NULL &lt;br /&gt;END&lt;/pre&gt;&lt;br /&gt;Let me explain what happens here: The&amp;nbsp;field 'ContentXml' is searched for the string-value between the&amp;nbsp;'&amp;lt;birthdate&amp;gt;'&amp;nbsp;and '&amp;lt;/birthdate&amp;gt;' tags,&amp;nbsp;and the result is compared with date '01/01/1970'. Cool, eh? &lt;p&gt;&lt;/p&gt; &lt;p&gt;Is this slow? No, certainly not! I just inserted 10.000 Persons in my table, containing&amp;nbsp;xml data with random birthdates between 1/1/1960 and 1/1/1980. The select query is still very quick, and seems even quicker&amp;nbsp;than the&amp;nbsp;corresponding SQLServer2005 query...&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Note: the given solution is only suitable for flat xml data, where the elements have unique tag-names and don't have attributes but only values. &lt;br /&gt;But then again, it's a pretty powerful solution if you want to add fields to a table without having to change the table's design.&lt;/strong&gt; &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=383923" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/drnetjes/archive/tags/SQLServer/default.aspx">SQLServer</category><category domain="http://weblogs.asp.net/drnetjes/archive/tags/Xml/default.aspx">Xml</category></item></channel></rss>