Today I needed to get a country name from the lat, long of a point, ideally in a stored procedure.
Getting the country name is just a matter of calling the geonames web service via a handy dandy GET... http://ws.geonames.org/countryCode?lat=47.03&lng=10.2&style=full&type=XML
which returns the following xml...
<geonames> <country> <countryCode>AT</countryCode> <countryName>Austria</countryName> <distance>0.0</distance> </country> </geonames>
Great, but how do we call this from inside a stored procedure? Initially I thought of looking at using .NET in the SQL CLR, but found some other code snippets that use OLE Automation in T-SQL to create an instance of 'MSXML2.XMLHTTP' to pull data. I thought I'd share since it could be pretty handy. Here's the stored proc.
CREATE PROCEDURE GetCountry -- Add the parameters for the stored procedure here @lat as float, @lon as float AS BEGIN Declare @Object as Int; Declare @ResponseText as Varchar(8000); Declare @Url as Varchar(MAX); select @Url = 'http://ws.geonames.org/countryCode?lat=' + CAST(@lat as varchar) + '&lng='+ cast(@lon as varchar) +'&type=xml' Exec sp_OACreate 'MSXML2.XMLHTTP', @Object OUT; Exec sp_OAMethod @Object, 'open', NULL, 'get', @Url, 'false' Exec sp_OAMethod @Object, 'send' Exec sp_OAMethod @Object, 'responseText', @ResponseText OUTPUT Exec sp_OADestroy @Object --load into Xml Declare @XmlResponse as xml; select @XmlResponse = CAST(@ResponseText as xml) select @XmlResponse.value('(/geonames/country/countryName)[1]','varchar(50)') as CountryName END The basic idea is to construct the Url, then use the MSXML2.XMLHTTP object to make the request and get the response. From there, we then cast the response into Xml, and pull out the values of interest via xquery.
CREATE PROCEDURE GetCountry -- Add the parameters for the stored procedure here @lat as float, @lon as float AS BEGIN
Declare @Object as Int; Declare @ResponseText as Varchar(8000); Declare @Url as Varchar(MAX);
select @Url = 'http://ws.geonames.org/countryCode?lat=' + CAST(@lat as varchar) + '&lng='+ cast(@lon as varchar) +'&type=xml'
Exec sp_OACreate 'MSXML2.XMLHTTP', @Object OUT; Exec sp_OAMethod @Object, 'open', NULL, 'get', @Url, 'false' Exec sp_OAMethod @Object, 'send' Exec sp_OAMethod @Object, 'responseText', @ResponseText OUTPUT Exec sp_OADestroy @Object
--load into Xml Declare @XmlResponse as xml; select @XmlResponse = CAST(@ResponseText as xml) select @XmlResponse.value('(/geonames/country/countryName)[1]','varchar(50)') as CountryName
END
Since this sproc relies on OLE Automation, you will need to enable this on your SQL box:
On the SQL Server box go to…
Close the tool and then the sproc should work.
As an example, running the stored procedure (i.e. exec dbo.GetCountry 47.03, 10.3) will return "Austria".
This could be easily extended to call any of the GeoNames web services, or any other REST service based on a GET. Heck, if you really get after this, you could do anything you want - you are working with the full blown MSXML2.XMLHTTP object which does all the Ajaxy goodness for Internet Explorer. Have fun!
I'm Dave and this is my blog. I'm usually writing about .NET Software Development, ArcGIS, or Agile Practices, but other stuff does creep in from time to time. I hope you find something of use, and feel free to contact me if you have any questions. You can also check out my profile on LinkedIn
dojo.DTSAgile.com is our technology preview / demo site. As I and my team cook up cool things we post them here.
ArcDeveloper.net is a site that hosts a set of open source projects related to ArcGIS. This includes Tile Cache for .NET (TC4N) and Feature Server for .NET (FS4N). Come over and check it out!
Assembla is a free service that provides Subversion source control, wikis and work Tracking. The ArcDeveloper project is run from here. It rocks. Check them out today.
Agilistas is a LinkedIn group focused on discussing and promoting Agile practices. Everyone is welcome to join in the conversation as we evolve the process of creating software to make it more enjoyable for all involved.