<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/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>Search results matching tags 'PowerShell' and 'sql'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=PowerShell,sql&amp;orTags=0</link><description>Search results matching tags 'PowerShell' and 'sql'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Behind the scenes of PowerShell and SQL</title><link>http://sqlblog.com/blogs/rob_farley/archive/2013/02/11/behind-the-scenes-of-powershell-and-sql.aspx</link><pubDate>Tue, 12 Feb 2013 00:11:46 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:47649</guid><dc:creator>rob_farley</dc:creator><description>&lt;p&gt;Every year, PowerShell increases its stranglehold on the Windows Server system and the applications that run upon it – with good reason too. Its consistent mechanisms for interaction between its scripting interface and the underlying systems make it easy for people to feel comfortable, and there is a discoverability that has been lacking in many other scripting environments.&lt;/p&gt;  &lt;p&gt;Of course, SQL Server hasn’t been overlooked at all, and it’s coming up to five years since the &lt;a href="https://msmvps.com/blogs/robfarley/archive/2008/03/04/sql-server-2008-powershell-snapin.aspx" target="_blank"&gt;SnapIns were made available&lt;/a&gt; (even longer since people started to &lt;a href="http://msmvps.com/blogs/robfarley/archive/2007/01/05/powershell-and-sql.aspx" target="_blank"&gt;dabble with SQL using PowerShell&lt;/a&gt;).&lt;/p&gt;  &lt;p&gt;But what’s going on behind the scenes? Does PowerShell present a threat to those amongst us who will always prefer T-SQL? Does PowerShell give us new options that are not available any other way? Well, let’s have a bit of a look, especially since this month’s T-SQL Tuesday (hosted by &lt;a href="http://blog.waynesheffield.com/wayne/archive/2013/02/invitation-for-t-sql-tuesday-39-can-you-shell-what-the-posh-is-cooking/" target="_blank"&gt;Wayne Sheffield&lt;/a&gt; who tweets as &lt;a href="http://twitter.com/DBAWayne" target="_blank"&gt;@DBAWayne&lt;/a&gt;) is on the topic of PowerShell.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.waynesheffield.com/wayne/archive/2013/02/invitation-for-t-sql-tuesday-39-can-you-shell-what-the-posh-is-cooking/" target="_blank"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:5px;padding-left:0px;padding-right:0px;display:inline;float:right;border-top:0px;border-right:0px;padding-top:0px;" title="TSQL2sDay150x150" border="0" alt="TSQL2sDay150x150" align="right" src="http://sqlblog.com/blogs/rob_farley/TSQL2sDay150x150_41BF631A.jpg" width="170" height="170" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;So we know PowerShell is useful. However we spin it up, we can quickly jump into writing commands, whether it be interacting with WMI, hooking into some .Net assembly we’ve loaded up, or simply browsing the file system. I’ve developed a tendency to use it to start whichever SQL instances I’m needing for the day – by default I have all of them turned off, since I don’t know which one I’ll be wanting most.&lt;/p&gt;  &lt;p&gt;If we’re going to be interacting with SQL, then it’s easiest to either load up the SQLPS environment directly (there’s a PowerShell shortcut within Management Studio), or else (as I do), start a PowerShell window with the Snapin loaded. I prefer this later option, as the SQLPS environment is a slightly cut-back version of PowerShell. But either way – the stuff I’ll continue on with is essentially the same whichever environment you use.&lt;/p&gt;  &lt;p&gt;If you’ve talked about SQL with me long enough, you’ll have come across the fact that I often use SQL Profiler when I’m curious about where to find information. My former colleague &lt;a href="http://www.jimmcleod.net" target="_blank"&gt;Jim McLeod&lt;/a&gt; (&lt;a href="http://twitter.com/jim_mcleod" target="_blank"&gt;@Jim_McLeod&lt;/a&gt;) blogged &lt;a href="http://www.jimmcleod.net/blog/index.php/2012/08/14/t-sql-tuesday-33-trick-shots/" target="_blank"&gt;about this a few months ago&lt;/a&gt;, with an example that I remember looking through with him four or five years ago. It’s a great technique that works on all kinds of things, even across different versions of SQL Server. It also adds as a terrific reminder that Management Studio is not a special application, it simply knows how to ask for the pieces of information that it shows.&lt;/p&gt;  &lt;p&gt;But PowerShell (or SMO, for that matter), that’s in the .Net world. Surely that would be able to bypass the clunky T-SQL stuff that Management Studio does... I mean, Management Studio has to be flexible enough to work across remote servers, talking through firewalls that only allow T-SQL interfaces. Surely PowerShell has access to a deeper magic.&lt;/p&gt;  &lt;p&gt;Well, no. PowerShell still lets you talk to remote servers, and ends up using the same methods.&lt;/p&gt;  &lt;p&gt;Let’s prove it.&lt;/p&gt;  &lt;p&gt;Spin up Profiler, and start a trace against your favourite instance. I like to watch for SQL:BatchCompleted, SP:StmtCompleted and RPC:Completed events when doing this kind of thing. I’m using an instance that isn’t doing anything else, but you could apply a ColumnFilter to filter the events to things with an ApplicationName starting with SQLPS if you prefer.&lt;/p&gt;  &lt;p&gt;With that running, I jump into PowerShell and do something like:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Consolas"&gt;PS SQLSERVER:\sql\localhost\sql2008r2&amp;gt; dir Databases | ft name&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This lists the names of the databases on my SQL2008R2 instances. You don’t need to see the results, you can imagine them for yourself.&lt;/p&gt;  &lt;p&gt;If PowerShell were using some secret interface, it’s unlikely we’d see something in Profiler. But it’s not, and we see a bunch of stuff.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblog.com/blogs/rob_farley/image_56ED68C2.png" width="672" height="468" /&gt;&lt;/p&gt;  &lt;p&gt;We see a bunch of Remote Procedure Calls, each with a Stored Procedure Statement Completed event showing the same information. And look – we see queries against master.sys.databases, asking for the name of each of the databases, passing in the name as a parameter. Brilliant! Notice just a bit earlier though, there’s a SQL:BatchCompleted call. This means that a query has been passed in directly. It’s this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Consolas"&gt;SELECT       &lt;br /&gt;CAST(        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; serverproperty(N'Servername')        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS sysname) AS [Server_Name],        &lt;br /&gt;dtb.name AS [Name]        &lt;br /&gt;FROM        &lt;br /&gt;master.sys.databases AS dtb        &lt;br /&gt;WHERE        &lt;br /&gt;(CAST(case when dtb.name in ('master','model','msdb','tempdb') then 1 else dtb.is_distributor end AS bit)=0)        &lt;br /&gt;ORDER BY        &lt;br /&gt;[Name] ASC&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblog.com/blogs/rob_farley/image_3EB9D89A.png" width="646" height="432" /&gt;&lt;/p&gt;    &lt;p&gt;So it grabs the list of database names first, and then makes extra calls to be able to fetch the list of names again, one by one.&lt;/p&gt;  &lt;p&gt;The reason why it’s grabbing the list of names one by one isn’t because it’s stupid and is asking to be ridiculed. It’s because we've asked to see that property, and I guess the PowerShell people figured that no matter what property you ask for, it’ll go and fetch it to show you.&lt;/p&gt;  &lt;p&gt;When I asked for the CompatibilityLevel property instead, I got some different rows thrown in. Interestingly though, it still asked for the name each time.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblog.com/blogs/rob_farley/image_3862DC3F.png" width="635" height="437" /&gt;&lt;/p&gt;  &lt;p&gt;Also interestingly, when I asked for the CompatibilityLevel a subsequent time, the calls for “SELECT dtb.compatibility_level…” weren’t in there. They’d been cached by the PowerShell environment – important to note if you ever come across PowerShell giving you old values.&lt;/p&gt;  &lt;p&gt;So what about asking something more interesting? Let’s try asking about the IndexSpaceUsage in AdventureWorks.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Consolas"&gt;PS SQLSERVER:\sql\localhost\sql2008r2&amp;gt; gi Databases\AdventureWorks | ft IndexSpaceUsage&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The result tells me it’s 62576. Yeah, but today I’m not interested in that, just what happened in the trace.&lt;/p&gt;  &lt;p&gt;Four entries. An SP:StmtCompleted with matching RPC:Completed, and two SQL:BatchCompleted.&lt;/p&gt;  &lt;p&gt;The SP:StmtCompleted and RPC:Completed were this statement, passing in the parameter value ‘AdventureWorks’. Clearly incredibly informative.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Consolas"&gt;SELECT       &lt;br /&gt;CAST(0 AS float) AS [IndexSpaceUsage],        &lt;br /&gt;dtb.name AS [DatabaseName]        &lt;br /&gt;FROM        &lt;br /&gt;master.sys.databases AS dtb        &lt;br /&gt;WHERE        &lt;br /&gt;(dtb.name=@_msparam_0)&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is getting the value zero. Wow. Brilliant stuff.&lt;/p&gt;  &lt;p&gt;The last entry – the second of the two SQL:BatchCompleted events is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Consolas"&gt;select convert(float,low/1024.) from master.dbo.spt_values where number = 1 and type = 'E'&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If you run this in Management Studio, you’ll discover it gives the value 8. Ok.&lt;/p&gt;  &lt;p&gt;The other entry is more interesting.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Consolas"&gt;use [AdventureWorks]       &lt;br /&gt;SELECT        &lt;br /&gt;SUM(CASE WHEN a.type &amp;lt;&amp;gt; 1 THEN a.used_pages WHEN p.index_id &amp;lt; 2 THEN a.data_pages ELSE 0 END) AS [DataSpaceUsage],        &lt;br /&gt;SUM(a.used_pages) AS [IndexSpaceTotal]        &lt;br /&gt;FROM        &lt;br /&gt;sys.allocation_units AS a INNER JOIN sys.partitions AS p ON (a.type = 2 AND p.partition_id = a.container_id) OR (a.type IN (1,3) AND p.hobt_id = a.container_id)&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is more like it! We run this in Management Studio, and we see two values. DataSpaceUsage is 13682, IndexSpaceTotal is 21504. Neither are our value 62576. But we do have clues in the column names, and in that value 8 that came back too. We can easily deduce that it’s actually (IndexSpaceTotal-DataSpaceUsage)*8, and we have ourselves a nice little method for working out the IndexSpaceUsage ourselves now if we need it.&lt;/p&gt;  &lt;p&gt;Or we can just ask PowerShell next time as well.&lt;/p&gt;  &lt;p&gt;Incidentally – if you’re considering doing the MCM Lab exam some time, then you might find that a familiarity with PowerShell comes in really handy. I’m not saying there are PowerShell questions on the exam at all – I’m just suggesting that you may find that PowerShell becomes a really useful way of getting at some of the information that you’re looking for. If you’re stumbling around the list of DMVs trying to remember which one it is that stores some particular thing, remember that you might be able to get the data out more easily if you use PowerShell instead.&lt;/p&gt;  &lt;p&gt;So can we discover secret things about SQL from PowerShell? Are there things we can do in PowerShell that are impossible through other mechanisms? Hooks that let us break the rules even?&lt;/p&gt;  &lt;p&gt;Recently, Kendal van Dyke asked a question about this kind of thing on Twitter. He was wondering if you could have a default constraint on a column in a view. The reason for his wondering was that he saw a property on a view column in PowerShell that made him wonder. The answer is no though, and there’s a simple reason.&lt;/p&gt;  &lt;p&gt;PowerShell is a programmatic interface. It involves classes and property and methods. It does things row by row, which is why much of what you see in that trace feels amazingly pedantic – asking about things which shouldn’t have to be that complicated. The implication of this though, is that PowerShell reuses the concept of a column, regardless of whether this is a column in a table, a view, or anywhere else it decides to need a column. The fact that columns in tables have some extra properties isn’t enough to make this class re-use pointless. If we try to set a Default constraint for a column in a view though, we get an error, just like if we tried to do it any other way.&lt;/p&gt;  &lt;p&gt;The PowerShell I used was:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Consolas"&gt;$db = Get-Item SQLSERVER:\sql\localhost\sql2008r2\Databases\AdventureWorks       &lt;br /&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;$def = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Default –ArgumentList $db, &amp;quot;ViewDefault&amp;quot;       &lt;br /&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;$def.TextHeader = &amp;quot;CREATE DEFAULT ViewDefault AS&amp;quot;       &lt;br /&gt;$def.TextBody = &amp;quot;'ABC'&amp;quot;        &lt;br /&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;$def.Create()       &lt;br /&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;$def.BindToColumn(&amp;quot;vStateProvinceCountryRegion&amp;quot;,&amp;quot;StateProvinceCode&amp;quot;,&amp;quot;Person&amp;quot;)&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The code that ended up getting called was to the stored procedure &lt;em&gt;sp_bindefault&lt;/em&gt; (despite it being deprecated). Naturally, trying to execute this against a view column gives an error regardless of what wrappers you have put around it – PowerShell or not.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblog.com/blogs/rob_farley/image_125D061C.png" width="813" height="132" /&gt;&lt;/p&gt;  &lt;p&gt;So PowerShell is very useful, and it provides a handy way of getting to a lot of things that could be otherwise hard. But looking below the surface, it isn’t able to circumvent the basic restrictions of SQL Server, because it still ends up doing its work using T-SQL.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://twitter.com/rob_farley" target="_blank"&gt;@rob_farley&lt;/a&gt;&lt;/p&gt;</description></item><item><title>PowerShell script to help uninstall SQL Server 2008 R2 Evaluation Edition</title><link>http://sqlblog.com/blogs/rob_farley/archive/2011/05/23/powershell-script-to-help-uninstall-sql-server-2008-r2-evaluation-edition.aspx</link><pubDate>Mon, 23 May 2011 14:04:23 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:35814</guid><dc:creator>rob_farley</dc:creator><description>&lt;p&gt;If you haven’t been caught by a client (or even yourself) installing SQL 2008 R2 Evaluation Edition and then letting it expire, you might not realise the pain that this causes. To say it’s frustrating is a serious understatement.&lt;/p&gt;  &lt;p&gt;Fellow SQL MVP and SQLBlog blogger &lt;a href="http://sqlblog.com/blogs/aaron_bertrand" target="_blank"&gt;Aaron Bertrand&lt;/a&gt; (&lt;a href="http://twitter.com/aaronbertrand" target="_blank"&gt;@aaronbertrand&lt;/a&gt;) has an &lt;a href="http://sqlblog.com/blogs/aaron_bertrand/archive/2010/10/25/fun-with-software-uninstalling-sql-server-2008-r2-evaluation-edition.aspx" target="_blank"&gt;excellent post on the matter&lt;/a&gt;, which he put together back in October 2010. I had cause to use it recently, but got somewhat put off by searching through the registry.&lt;/p&gt;  &lt;p&gt;So I put a line of PowerShell together (which I’ve split across 5 for easier reading):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Consolas"&gt;Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall |        &lt;br /&gt;select @{Name='Guid';Expression={$_.PSChildName}}, @{Name='Disp';Expression={($_.GetValue(&amp;quot;DisplayName&amp;quot;))}} |         &lt;br /&gt;where-object {$_.Disp -ilike &amp;quot;*SQL*R2*&amp;quot;} |         &lt;br /&gt;where-object {$_.Guid -like '{*'} |         &lt;br /&gt;% {&amp;quot;rem &amp;quot; + $_.Disp; 'msiexec /x &amp;quot;' + $_.Guid + '&amp;quot;'; ''} &amp;gt; uninstallR2.bat&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If you run this, it will produce the file that Aaron recommended. You can look down it for anything you don’t want to get rid of, and maybe reorder the odd thing, and then run it. Then you should be able to install Developer Edition, and breathe much easier.&lt;/p&gt;  &lt;p&gt;The script is quite straight forward, it just lists everything in the uninstall bit of the registry, gets the DisplayName values out, filters them, and outputs the results in a few lines for the batch file. Nothing amazingly complicated, but useful for getting through the list quickly.&lt;/p&gt;  &lt;p&gt;(Big thanks to Aaron for working out what was required for the uninstall, and &lt;a href="http://sqlvariant.com/wordpress/" target="_blank"&gt;Aaron Nelson&lt;/a&gt; (&lt;a href="http://twitter.com/sqlvariant" target="_blank"&gt;@sqlvariant&lt;/a&gt;) for answering a quick question when I was putting the final touches on the script)&lt;/p&gt;</description></item><item><title>Using SQL Execution Plans to discover the Swedish alphabet</title><link>http://sqlblog.com/blogs/rob_farley/archive/2011/01/03/using-sql-execution-plans-to-discover-the-swedish-alphabet.aspx</link><pubDate>Mon, 03 Jan 2011 05:54:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:32237</guid><dc:creator>rob_farley</dc:creator><description>&lt;P&gt;SQL Server is quite remarkable in a bunch of ways. In this post, I’m using the way that the Query Optimizer handles LIKE to keep it SARGable, the Execution Plans that result, Collations, and PowerShell to come up with the Swedish alphabet.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msmvps.com/blogs/robfarley/archive/2010/01/22/sargable-functions-in-sql-server.aspx" target=_blank&gt;SARGability&lt;/A&gt; is the ability to seek for items in an index according to a particular set of criteria. If you don’t have SARGability in play, you need to scan the whole index (or table if you don’t have an index). For example, I can find myself in the phonebook easily, because it’s sorted by LastName and I can find Farley in there by moving to the Fs, and so on. I can’t find everyone in my suburb easily, because the phonebook isn’t sorted that way. I can’t even find people who have six letters in their last name, because also the book is sorted by LastName, it’s not sorted by LEN(LastName). This is all stuff I’ve looked at before, including in the &lt;A href="http://www.sqlbits.com/Sessions/Event7/Understanding_SARGability_to_make_your_queries_run_faster" target=_blank&gt;talk I gave at SQLBits in October 2010&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;If I try to find everyone who’s names start with F, I can do that using a query a bit like:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;SELECT LastName FROM dbo.PhoneBook WHERE LEFT(LastName,1) = 'F';&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Unfortunately, the Query Optimizer doesn’t realise that all the entries that satisfy LEFT(LastName,1) = 'F' will be together, and it has to scan the whole table to find them.&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title=image border=0 alt=image src="http://sqlblog.com/blogs/rob_farley/image_0BB56CF3.png" width=595 height=143&gt;&lt;/P&gt;
&lt;P&gt;But if I write:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;SELECT LastName FROM dbo.PhoneBook WHERE LastName LIKE 'F%';&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;then SQL is smart enough to understand this, and performs an Index Seek instead.&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title=image border=0 alt=image src="http://sqlblog.com/blogs/rob_farley/image_0F7311C3.png" width=566 height=133&gt;&lt;/P&gt;
&lt;P&gt;To see why, I look further into the plan, in particular, the properties of the Index Seek operator. The ToolTip shows me what I’m after:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title=image border=0 alt=image src="http://sqlblog.com/blogs/rob_farley/image_14754F72.png" width=302 height=200&gt;&lt;/P&gt;
&lt;P&gt;You’ll see that it does a Seek to find any entries that are at least F, but not yet G. There’s an extra Predicate in there (a Residual Predicate if you like), which checks that each LastName is really LIKE F% – I suppose it doesn’t consider that the Seek Predicate is quite enough – but most of the benefit is seen by its working out the Seek Predicate, filtering to just the “at least F but not yet G” section of the data.&lt;/P&gt;
&lt;P&gt;This got me curious though, particularly about where the G comes from, and whether I could leverage it to create the Swedish alphabet.&lt;/P&gt;
&lt;P&gt;I know that in the Swedish language, there are three extra letters that appear at the end of the alphabet. One of them is ä that appears in the word Västerås. It turns out that Västerås is quite hard to find in an index when you’re looking it up in a Swedish map. I talked about this briefly in my five-minute &lt;A href="http://bit.ly/RFCollation" target=_blank&gt;talk on Collation&lt;/A&gt; from SQLPASS (the one which was slightly less than serious).&lt;/P&gt;
&lt;P&gt;So by looking at the plan, I can work out what the next letter is in the alphabet of the collation used by the column. In other words, if my alphabet were Swedish, I’d be able to tell what the next letter after F is – just in case it’s not G.&lt;/P&gt;
&lt;P&gt;It turns out it is… Yes, the Swedish letter after F is G. But I worked this out by using a copy of my PhoneBook table that used the Finnish_Swedish_CI_AI collation. I couldn’t find how the Query Optimizer calculates the G, and my friend &lt;A href="http://sqlblog.com/blogs/paul_white/" target=_blank&gt;Paul White&lt;/A&gt; (&lt;A href="http://twitter.com/SQL_Kiwi" target=_blank&gt;@SQL_Kiwi&lt;/A&gt;) tells me that it’s frustratingly internal to the QO. He’s particularly smart, even if he is from New Zealand.&lt;/P&gt;
&lt;P&gt;To investigate further, I decided to do some PowerShell, leveraging the &lt;A href="http://sqlblog.com/blogs/rob_farley/archive/2010/12/07/powershell-to-fetch-a-sql-execution-plan.aspx" target=_blank&gt;Get-SqlPlan function&lt;/A&gt; that I blogged about recently (make sure you also have the SqlServerCmdletSnapin100 snap-in added. To do that, run &lt;EM&gt;get-pssnapin -reg&lt;/EM&gt; to see if it's on the machine, and &lt;EM&gt;get-pssnapin -reg | add-pssnapin&lt;/EM&gt; to make the cmdlet available).&lt;/P&gt;
&lt;P&gt;I started by indicating that I was going to use Finnish_Swedish_CI_AI as my collation of choice, and that I’d start whichever letter came straight after the number 9. I figure that this is a cheat’s way of guessing the first letter of the alphabet (but it doesn’t actually work in Unicode – luckily I’m using varchar not nvarchar. Actually, there are a few aspects of this code that only work using ASCII, so apologies if you were wanting to apply it to Greek, Japanese, etc). I also initialised my $alphabet variable.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;$collation = 'Finnish_Swedish_CI_AI'; &lt;BR&gt;$firstletter = '9'; &lt;BR&gt;$alphabet = '';&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now I created the table for my test. A single field would do, and putting a Clustered Index on it would suffice for the Seeks. &lt;EM&gt;[Edit: You may need to insert some rows if you find that it's producing&amp;nbsp;an Index Scan. Theoretically it should prefer to Scan,&amp;nbsp;knowing there's&amp;nbsp;no rows, but my tests showed it would always Seek]&lt;/EM&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;Invoke-Sqlcmd -server . -data tempdb -query "create table dbo.collation_test (col varchar(10) collate $collation primary key);"&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now I get into the looping. &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;$c = $firstletter; &lt;BR&gt;$stillgoing = $true; &lt;BR&gt;while ($stillgoing) &lt;BR&gt;{&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I construct the query I want, seeking for entries which start with whatever $c has reached, and get the plan for it:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;$query = "select col from dbo.collation_test where col like '$($c)%';"; &lt;BR&gt;[xml] $pl = get-sqlplan $query "." "tempdb";&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;At this point, my $pl variable is a scary piece of XML, representing the execution plan. A bit of hunting through it showed me that the EndRange element contained what I was after, and that if it contained NULL, then I was done.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;$stillgoing = ($pl.ShowPlanXML.BatchSequence.Batch.Statements.StmtSimple.QueryPlan.RelOp.IndexScan.SeekPredicates.SeekPredicateNew.SeekKeys.EndRange -ne $null);&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now I could grab the value out of it (which came with apostrophes that needed stripping), and append that to my $alphabet variable.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;&amp;nbsp; if ($stillgoing) &lt;BR&gt;&amp;nbsp; {&amp;nbsp; &lt;BR&gt;$c=$pl.ShowPlanXML.BatchSequence.Batch.Statements.StmtSimple.QueryPlan.RelOp.IndexScan.SeekPredicates.SeekPredicateNew.SeekKeys.EndRange.RangeExpressions.ScalarOperator.ScalarString.Replace("'",""); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $alphabet += $c; &lt;BR&gt;&amp;nbsp; }&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Finally, finishing the loop, dropping the table, and showing my alphabet!&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;} &lt;BR&gt;Invoke-Sqlcmd -server . -data tempdb -query "drop table dbo.collation_test;"; &lt;BR&gt;$alphabet;&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;When I run all this, I see that the Swedish alphabet is ABCDEFGHIJKLMNOPQRSTUVXYZÅÄÖ, which matches what I see at &lt;A href="http://en.wikipedia.org/wiki/Swedish_orthography" target=_blank&gt;Wikipedia&lt;/A&gt;. Interesting to see that the letters on the end are still there, even with Case Insensitivity. Turns out they’re not just “letters with accents”, they’re letters in their own right.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/rob_farley/image_528E6A23.png"&gt;&lt;IMG style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title=image border=0 alt=image src="http://sqlblog.com/blogs/rob_farley/image_thumb_0511C796.png" width=609 height=292&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;I’m sure you gave up reading long ago, and really aren’t that&amp;nbsp;grabbed about the idea of doing this using PowerShell. I chose PowerShell because I’d already come up with an easy way of grabbing the estimated plan for a query, and PowerShell does allow for easy navigation of XML.&lt;/P&gt;
&lt;P&gt;I find the most interesting aspect of this as the fact that the Query Optimizer uses the next letter of the alphabet to maintain the SARGability of LIKE. &lt;A href="https://connect.microsoft.com/SQLServer/feedback/details/526431/make-more-functions-sargable" target=_blank&gt;I’m hoping they do something similar for a whole bunch of operations&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Oh, and the fact that you know how to find stuff in the IKEA catalogue.&lt;/P&gt;
&lt;HR&gt;

&lt;P&gt;Footnote: &lt;/P&gt;
&lt;P&gt;If you are interested in whether this works in other languages, you might want to consider the following screenshot, which shows that in principle, it should work with Japanese. It might be a bit harder to run this in PowerShell though, as I’m not sure how it translates. In Hiragana, the Japanese alphabet starts あ, ぃ, ぅ, ぇ, ぉ, ...&lt;/P&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/rob_farley/image_20F2D6C1.png"&gt;&lt;IMG style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title=image border=0 alt=image src="http://sqlblog.com/blogs/rob_farley/image_thumb_57DC8F2D.png" width=644 height=413&gt;&lt;/A&gt;&lt;/P&gt;</description></item><item><title>PowerShell to fetch a SQL Execution Plan</title><link>http://sqlblog.com/blogs/rob_farley/archive/2010/12/06/powershell-to-fetch-a-sql-execution-plan.aspx</link><pubDate>Tue, 07 Dec 2010 01:14:32 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:31395</guid><dc:creator>rob_farley</dc:creator><description>&lt;p&gt;With PowerShell becoming the scripting language of choice for many people, I’ve occasionally wondered about using it to analyse execution plans. After all, an execution plan is just XML, and PowerShell is just one tool which will very easily handle xml.&lt;/p&gt;  &lt;p&gt;The thing is – there’s no Get-SqlPlan cmdlet available, which has frustrated me in the past. Today I figured I’d make one.&lt;/p&gt;  &lt;p&gt;I know that I can write T-SQL to get an execution plan using SET SHOWPLAN_XML ON, but the problem is that this must be the only statement in a batch. So I used go, and a couple of newlines, and whipped up the following one-liner:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;function Get-SqlPlan([string] $query, [string] $server, [string] $db)       &lt;br /&gt;{ return ([xml] (invoke-sqlcmd -Server $server -Database $db -Query &amp;quot;set showplan_xml on;`ngo`n$query&amp;quot;).Item( 0)) }&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;(but please bear in mind that I have the SQL Snapins installed, which provides invoke-sqlcmd)&lt;/p&gt;  &lt;p&gt;To use this, I just do something like:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;$plan = get-sqlplan &amp;quot;select name from Production.Product&amp;quot; &amp;quot;.&amp;quot; &amp;quot;AdventureWorks&amp;quot;&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;And then find myself with an easy way to navigate through an execution plan!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/rob_farley/image_13ACC99F.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://sqlblog.com/blogs/rob_farley/image_thumb_6687B703.png" width="644" height="180" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;At some point I should make the function more robust, but this should be a good starter for any SQL PowerShell enthusiasts (like &lt;a href="http://sqlvariant.com/wordpress"&gt;Aaron Nelson&lt;/a&gt;) out there.&lt;/p&gt;</description></item><item><title>Fetching Latitude and Longitude Co-ordinates for Addresses using PowerShell</title><link>http://sqlblog.com/blogs/rob_farley/archive/2010/05/23/fetching-latitude-and-longitude-co-ordinates-for-addresses-using-powershell.aspx</link><pubDate>Sun, 23 May 2010 06:59:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:25440</guid><dc:creator>rob_farley</dc:creator><description>&lt;P&gt;Regular readers of my blog (at &lt;A href="http://sqlblog.com/blogs/rob_farley/" target=_blank&gt;sqlblog.com&lt;/A&gt; – please let me know if you’re reading this elsewhere) may be aware that I’ve been doing more and more with spatial data recently. With the now-available SQL Server 2008 R2 Reporting Services including maps, it’s a topic that interests many people.&lt;/P&gt;
&lt;P&gt;Interestingly though, although many people have plenty of addresses in their various databases (whether they be CRM systems, HR systems or whatever), my experience shows that many people do not store the latitude and longitude co-ordinates for those addresses.&lt;/P&gt;
&lt;P&gt;Luckily, the Bing Maps API provides everything you need!&lt;/P&gt;
&lt;P&gt;Start by going to &lt;A href="https://www.bingmapsportal.com/" target=_blank&gt;bingmapsportal.com&lt;/A&gt;, logging in using a LiveID and creating an account:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/rob_farley/image_56B3B5E3.png"&gt;&lt;IMG style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;" title=image border=0 alt=image src="http://sqlblog.com/blogs/rob_farley/image_thumb_5A651EB6.png" width=570 height=484&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Then you can create a key using the link on the left. This key will be attached to a website, and looks something like: Apsjm7zVthPFMxlfpQqKhPPZrAupI-_aGH-CvT2b... Now you can use the Bing Maps API to fetch the information you need. Obviously check the terms and conditions to see if you will need to pay for your usage or not. The Bing Maps API works through web services, so it’s easy enough to use almost any system for this. You could easily make a CLR Function for use within T-SQL, but I’m going to show you how to do it using PowerShell.&lt;/P&gt;
&lt;P&gt;Let’s start by creating a Web Service Proxy to the URL of the webservice.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;$ws = New-WebServiceProxy -uri http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc?wsdl;&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;By passing $ws into Get-Member (using the command: &lt;EM&gt;$ws | Get-Member&lt;/EM&gt;), we can see that there is a Geocode method, which requires a parameter of type GeocodeRequest. Actually, the type to use is much more complicated, but it’s easy to create a variable for it using:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;$wsgr = new-object Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1ervice_geocodeservice_svc_wsdl.GeocodeRequest;&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This variable will take the address to look up in its Query property, but we’ll do that in a moment. First we need to provide credentials, which is that key we created on the website. I’ve stored mine in a variable called $key, so that I don’t have to display it in demonstrations that might be recorded.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;$wsgrc = new-object Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1ervice_geocodeservice_svc_wsdl.Credentials; &lt;BR&gt;$wsgrc.ApplicationId = $key; &lt;BR&gt;$wsgr.Credentials = $wsgrc;&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now when we call the method on our web service, Bing Maps will know that it’s us that have called it.&lt;/P&gt;
&lt;P&gt;Now I can make a request. If I use a single address, I can just use the Query property of the GeocodeRequest object, as I mentioned earlier. When I get my results from the Geocode() call, I can get multiple lines, and each of them has a bunch of useful information including (as I find most useful), the Formatted Address, and location co-ordinates. I can easily display this by passing the Results into a Select-Object call. I’m just handling the first result of each call, as will become clear in a moment.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;$wsgr.Query = 'Adelaide, Australia'; &lt;BR&gt;$wsr = $ws.Geocode($wsgr); &lt;BR&gt;$wsr.Results[0] | select {$_.Address.FormattedAddress}, {$_.Locations[0].Longitude}, {$_.Locations[0].Latitude};&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;As readers familiar with PowerShell will already appreciate, there is a good potential for looping through many addresses. I did this with locations in the world that have &lt;A href="http://www.sqlpass.org/PASSChapters.aspx" target=_blank&gt;PASS chapters&lt;/A&gt; recently, but to simplify this, my example uses just four.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;$uglist = 'Adelaide, AU', 'Aukland, NZ', 'South Africa', 'San Deigo, USA'; &lt;BR&gt;$uglist | % {$wsgr.Query = [string] $_; $wsr = $ws.Geocode($wsgr); $wsr.Results[0] | select {$_.Address.FormattedAddress}, {$_.Locations[0].Longitude}, {$_.Locations[0].Latitude};} &lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This gives the following results:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Consolas&gt;$_.Address.FormattedAddress&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $_.Locations[0].Longitude&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $_.Locations[0].Latitude &lt;BR&gt;---------------------------&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -------------------------&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ------------------------ &lt;BR&gt;Adelaide, Australia&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 138.599731698632&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -34.925769791007 &lt;BR&gt;Auckland, New Zealand&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 174.765734821558&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -36.8473847955465 &lt;BR&gt;South Africa&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 25.0630002468824&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -29.0459994971752 &lt;BR&gt;San Diego, CA&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -117.161724865437&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 32.7156852185726&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;You’ll notice that the FormattedAddress property shows the address in a standard format. This is great, because it will handle spelling mistakes (see how I left the ‘c’ out of ‘Auckland’ when I wrote it – for me I did this on purpose, but in most user-input systems, spelling mistakes are a common problem), and it will provide a consistency for punctuation, abbreviations, etc. Notice that I used ‘AU’, ‘NZ’ and ‘USA’, which were all transformed into something else in the web-service call.&lt;/P&gt;
&lt;P&gt;With the Lat/Long details here, it’s very simple to get this into a database, or a file, or whatever format is required. For me, I put them into a database along with all the other PASS Chapter locations I had looked up (using the public data from the website), and using the Bing Maps Silverlight control, came up with something like this:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://sqlblog.com/blogs/rob_farley/image_0D913253.png"&gt;&lt;IMG style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;" title=image border=0 alt=image src="http://sqlblog.com/blogs/rob_farley/image_thumb_58940748.png" width=596 height=484&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;It was a bit more work to colour the pushpins by the region, and putting tooltips in with extra information, but bridging the gap between a pile of addresses and a map is actually remarkably straight-forward with the Bing Maps API.&lt;/P&gt;</description></item></channel></rss>