MSSQL : The argument x of the xml data type method "y" must be a string literal.



While playing around with the xml data type in SQL I noticed an interesting issue (maybe it will save someone some time), observe the following snippet:
 
DECLARE @cities AS XML
 
SET @cities =
'<cities>
	<city cityID="1" value="Berlyn" countryID="1" />
	<city cityID="2" value="Hamburg" countryID="1" />
	<city cityID="3" value="Frankfurt" countryID="1" />
	<city cityID="4" value="Rotterdam" countryID="2" />
	<city cityID="5" value="Amsterdam" countryID="2" />
</cities>'
 
SELECT item.value('@cityID', 'INT') cityID,
		item.value('@value', 'VARCHAR(255)') value
FROM @cities.nodes('//city[@countryID = 1]') t (item)
 

Notice the XPath "nodes('//city[@countryID = 1]')", this statement will return all the cities listed for Deutschland in the XML string.

If we want to make this more generic we can always simply pass a value to a where clause on the query like this:
 
SELECT item.value('@cityID', 'INT') cityID,
		item.value('@value', 'VARCHAR(255)') value
FROM @cities.nodes('//city') t (item)
WHERE item.value('@countryID', 'INT') = @countryID
 

But what if we want(perhaps need) to pass a value to a XPath statement? At first we might consider doing the following:
 
SELECT item.value('@cityID', 'INT') cityID,
		item.value('@value', 'VARCHAR(255)') value
FROM @cities.nodes('//city[@countryID = ' + @countryID + ']') t (item)
 

This will however generate an error "The argument 1 of the xml data type method "nodes" must be a string literal", for this purpose e.g. interaction between relational and xml data, one can use expressions like sql:variable & sql:column.
 
DECLARE @countryID AS INT
SET @countryID = 1
SELECT item.value('@cityID', 'INT') cityID,
		item.value('@value', 'VARCHAR(255)') value
FROM @cities.nodes('//city[@countryID = sql:variable("@countryID")]') t (item)
 

sql:variable being a variable available within scope of our stored procedure, sql:column a field available within our query.

Some additional reading.







Comments



more details

In the condition, @cities.nodes('//city[@countryID = sql:variable("@countryID")] What if we need to filter using element value. or we need to give the clause itself, like 'countryid=1' in sql variable and filter nodes? please help out


Thank you very very much. I was in trouble :S


Thanks a lot for the statement: "This will however generate an error "The argument 1 of the xml data type method "nodes" must be a string literal", for this purpose e.g. interaction between relational and xml data, one can use expressions like sql:variable & sql:column." I've asked all of my colleagues but none gave me the answer. You did it tho... )


Thanks a lot. This saved me some time.


Post comment

Name *
Email
Title
Body *
Security Code
*
* Required fields

Related Posts

Latest Posts

Be the best stalker you can be


2011-12-13 22:33:54

Syntactic sugar (C#): Enum


2011-08-04 16:50:18

Top 5 posts

Simple WYSIWYG Editor


Creating a WYSIWYG textbox for your website is actually quite simple.
2007-02-01 12:00:00

Moving items between listboxes in ASP.net/PHP example


Move items between two listboxes in ASP.net(C#, VB.NET) and PHP
2008-06-12 17:07:43

Cross Browser Issues: Firefox Word Wrapping


Firefox word wrapping issues
2008-06-09 09:51:21

Populate a TreeView Control C#


Populate a TreeView control in a windows application.
2009-08-27 16:01:03

C# YouTube : Google API


Post on how to integrate with YouTube using the Google Data API
2011-03-12 08:37:51