<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>A Developer&#039;s Blog &#187; SQL Server</title>
	<atom:link href="http://blog.hoegaerden.be/tag/sql-server/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.hoegaerden.be</link>
	<description>SQL Server, BI, .NET, IT and anything else I have been playing with.</description>
	<lastBuildDate>Sun, 11 Jul 2010 12:19:25 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A Developer&#8217;s Excel: A Couple Of Tips</title>
		<link>http://blog.hoegaerden.be/2010/06/16/a-developers-excel-a-couple-of-tips/</link>
		<comments>http://blog.hoegaerden.be/2010/06/16/a-developers-excel-a-couple-of-tips/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 15:27:44 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[Office]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Excel]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/06/16/a-developers-excel-a-couple-of-tips/</guid>
		<description><![CDATA[As a BI developer I regularly use Excel to analyze my data on correctness.  In Excel it’s easy to filter out unrelated records, as you’ll probably already know.
How do I get my data in Excel?
With a simple copy/paste.  Since SQL Server 2008, you can just right-click on the results in the Management Studio and select [...]]]></description>
			<content:encoded><![CDATA[<p>As a BI developer I regularly use Excel to analyze my data on correctness.  In Excel it’s easy to filter out unrelated records, as you’ll probably already know.</p>
<h2>How do I get my data in Excel?</h2>
<p>With a simple copy/paste.  Since SQL Server 2008, you can just right-click on the results in the Management Studio and select <em>Copy with Headers</em>.  This will put the selected data into memory, including the column headers.</p>
<p><img style="display: inline; border-width: 0px;" title="SSMS 2008: right-click on results to Copy with Headers" src="http://blog.hoegaerden.be/wp-content/uploads/image293.png" border="0" alt="SSMS 2008: right-click on results to Copy with Headers" width="449" height="256" /></p>
<p>You can even make a selection in the Results pane and only copy that, as shown in the screenshot above.  Here’s what it looks like when pasted into Excel:</p>
<p><img style="display: inline; border-width: 0px;" title="Data with headers pasted into Excel" src="http://blog.hoegaerden.be/wp-content/uploads/image294.png" border="0" alt="Data with headers pasted into Excel" width="347" height="114" /></p>
<h3>How do I make the columns wider?</h3>
<p>Excel will not expand the column widths by default, shown in that last screenshot.  You could manually enlarge them one by one, but that’s not convenient when you last filled column is called “DI”.  Instead, I use the following trick.  First I select the whole sheet by clicking on the grey square in the top-left corner:</p>
<p><img style="display: inline; border-width: 0px;" title="Select the whole sheet using the grey square" src="http://blog.hoegaerden.be/wp-content/uploads/image295.png" border="0" alt="Select the whole sheet using the grey square" width="360" height="149" /></p>
<p>Then I double-click on the vertical divider in between columns A and B.  This will adjust all column widths so that the data fits nicely.</p>
<p><img style="display: inline; border-width: 0px;" title="Double-click the divider in between two columns to adjust width automatically" src="http://blog.hoegaerden.be/wp-content/uploads/image296.png" border="0" alt="Double-click the divider in between two columns to adjust width automatically" width="626" height="116" /></p>
<h2>Does Excel know SELECT DISTINCT?</h2>
<p>The other day I needed to filter out all duplicate records out of a really large dataset.  I first tried by activating the regular filter.  This is an Excel feature that I use a lot.  Just clicking the <strong>Filter</strong> button on the Data ribbon will add the small dropdowns next to each column’s header:</p>
<p><img style="display: inline; border: 0px;" title="Excel's Filter functionality" src="http://blog.hoegaerden.be/wp-content/uploads/image297.png" border="0" alt="Excel's Filter functionality" width="661" height="289" /></p>
<p>But in those dropdowns I couldn’t find an option which would get me to the required result.</p>
<p>(Note that I added a couple of duplicate records in my dataset.)</p>
<p>After a little search, I found the magic checkbox!  I didn’t know that it could be so easy.</p>
<p>To find it, click the <strong>Advanced</strong> button in the Data ribbon.</p>
<p><img style="display: inline; border-width: 0px;" title="The Advanced button on the Data ribbon" src="http://blog.hoegaerden.be/wp-content/uploads/image298.png" border="0" alt="The Advanced button on the Data ribbon" width="389" height="131" /></p>
<p>In the <strong>Advanced Filter</strong> window that appears you see a checkbox called <em>Unique records only</em>.</p>
<p><img style="display: inline; border: 0px;" title="Advanced Filter: Unique records only checkbox" src="http://blog.hoegaerden.be/wp-content/uploads/image299.png" border="0" alt="Advanced Filter: Unique records only checkbox" width="239" height="242" /></p>
<p>There’s your SELECT DISTINCT!</p>
<p>And here’s the sheet with the duplicates filtered out:</p>
<p><img style="display: inline; border: 0px;" title="Excel sheet after filtering out duplicate records with the &quot;Unique records only&quot; option" src="http://blog.hoegaerden.be/wp-content/uploads/image300.png" border="0" alt="Excel sheet after filtering out duplicate records with the &quot;Unique records only&quot; option" width="659" height="117" /></p>
<p>Do you also see that the filter dropdowns are gone, although I did not remove them?  The Advanced Filter cannot be used in combination with the regular filter.  Once you activate the regular filter by clicking the Filter button, your duplicates will re-appear.</p>
<p>If you want to further filter your data after filtering out all duplicate records, you should select the <em>Copy to another location </em>option in the Advanced Filter window.  Copy it below your data on the same sheet and apply the regular filter on that new set of data.</p>
<p><img style="display: inline; border: 0px;" title="Filtered set of data below full dataset on same sheet" src="http://blog.hoegaerden.be/wp-content/uploads/image301.png" border="0" alt="Filtered set of data below full dataset on same sheet" width="664" height="411" /></p>
<p>Copying to another sheet is not supported.  Apparently you can only copy to the active sheet.  Should you try it out anyway, you’ll get this message:</p>
<p><img style="display: inline; border: 0px;" title="Warning: You can only copy filtered data to the active sheet" src="http://blog.hoegaerden.be/wp-content/uploads/image302.png" border="0" alt="Warning: You can only copy filtered data to the active sheet" width="342" height="121" /></p>
<p>Happy filtering!</p>
<p>Valentino.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/06/16/a-developers-excel-a-couple-of-tips/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Cooperation From A Stubborn Data Dude</title>
		<link>http://blog.hoegaerden.be/2010/06/09/getting-cooperation-from-a-stubborn-data-dude/</link>
		<comments>http://blog.hoegaerden.be/2010/06/09/getting-cooperation-from-a-stubborn-data-dude/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 19:59:49 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Visual Studio 2008]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/06/09/getting-cooperation-from-a-stubborn-data-dude/</guid>
		<description><![CDATA[Lately I’ve been using Visual Studio Team System 2008 Database Edition with the GDR R2 add-on, also known as “The Data Dude”, to compare databases with each other.
And during a schema compare I noticed that the dude can be quite stubborn now and then.
Here’s an example and an explanation of why, as far as I [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I’ve been using <a title="Download: Microsoft® Visual Studio Team System 2008 Database Edition GDR R2" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=bb3ad767-5f69-4db9-b1c9-8f55759846ed&amp;displaylang=en" target="_blank">Visual Studio Team System 2008 Database Edition with the GDR R2 add-on</a>, also known as “The Data Dude”, to compare databases with each other.</p>
<p>And during a schema compare I noticed that the dude can be quite stubborn now and then.</p>
<p>Here’s an example and an explanation of why, as far as I can tell, the dude is behaving that way.</p>
<h2>The Scenario</h2>
<p>At work we use the data dude’s schema compare to prepare our deployment scripts.  The most fun can be had when preparing a script to deploy the latest finalized version, <strong>version x</strong>, from the Development (DEV) to the Acceptance (UAT) environment.</p>
<p>In our DEV database there have already been changes for the next version, <strong>version x+1</strong>, so these changes need to be skipped.</p>
<p>Now imagine the following situation:</p>
<ul>
<li>a table called <em>TableA</em> exists</li>
<li>a new field called <em>NewFieldA</em> was added to <em>TableA</em></li>
<li>a view called <em>ViewA</em> exists and was modified – it uses <em>TableA</em> but not <em>NewFieldA</em></li>
</ul>
<p>The changes to <em>ViewA</em> belong with <strong>version x</strong>, while the changes to <em>TableA</em> are part of <strong>version x+1</strong>.  So the script that I’m going to generate should contain an ALTER VIEW ViewA … but not an ALTER TABLE TableA ….</p>
<h2>The Behavior</h2>
<p>Using the dude, I open up the dropdown on the line that states <em>Different definition </em>on <em>TableA</em> and I select <em>Skip</em>.  The value gets changed from <em>Update</em> to <em>Skip</em>.  However, when the focus changes to another line in the grid the value changes back to <em>Update</em>!  Furthermore, it’s now grayed out, impossible to change!</p>
<p>The first time that you see this happening you can’t believe your eyes and try it once more, first closing everything and then re-doing your actions.  Just to see if you didn’t select the wrong option somewhere.  But alas, the dude remains stubborn!</p>
<p><strong>Tip:</strong> if you have just executed the compare and you find that some update actions cannot be modified, try to do a refresh (right-click on the background of the comparison window and click Refresh).  I noticed that after the refresh you will get the dropdown for these lines and thus will be able to change the Update Action.</p>
<h2>The Explanation</h2>
<p>It took me a while to realize, but here’s what seems to be happening.  Like with all things stubborn, it helps if you know what the thing in question is actually being stubborn for.</p>
<p>The dude knows that <em>ViewA</em> depends on <em>TableA</em> and it also knows that both <em>ViewA</em> and <em>TableA</em> where changed.  However, the dude is a little short-sighted, it doesn’t know that <em>NewFieldA</em> is not used in <em>ViewA</em>.  It doesn’t know that the change to <em>ViewA</em> was not related to the change on <em>TableA</em>.  So it automatically assumes that you’re making a mistake and prevents you from messing up.  It thinks, “You stupid user, I know it better, I am smart software!  And that’s not all, I AM THE DATA DUDE! And if there’s one thing you don’t want, that’s to mess with the Data Dude!”.</p>
<p>Here’s a screenshot of the dude’s stubbornness:</p>
<p><img style="display: inline; border-width: 0px;" title="Grayed-out Update Action: the result of a stubborn data dude" src="http://blog.hoegaerden.be/wp-content/uploads/image291.png" border="0" alt="Grayed-out Update Action: the result of a stubborn data dude" width="105" height="182" /></p>
<p>In this particular case it refused to skip certain new tables, even though there were no dependent objects that needed those tables!  The first two lines show the grayed-out items.  These tables were located under a new schema and I had to put the schema’s <strong>Update Action</strong> to <em>Skip</em> to get the tables be skipped as well.  The Update Action for the tables was changed automatically when I modified the action for the schema.</p>
<p>But, if you ask me, I don’t see why I shouldn’t be able to <em>Skip</em> a new table even when I am going to create the new schema to which it belongs?  It’s the table that depends on the schema, not the other way around.</p>
<h2>The Feature Request</h2>
<p>It would have been great if I could manually override the dude’s decision.  As that was not the case, I have to manually change the generated script so that it only contains the changes that I want.  As long as it’s technically feasible, I think manual changes to the <strong>Update Action</strong> should be allowed.</p>
<h2>One More Tip</h2>
<p>Take a good look at the following screenshot.</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image292.png"><img style="display: inline; border: 0px;" title="Beware the miniature exclamation mark in the icon's corner!" src="http://blog.hoegaerden.be/wp-content/uploads/image_thumb70.png" border="0" alt="Beware the miniature exclamation mark in the icon's corner!" width="700" height="328" /></a></p>
<p>By default, the node that reads <em>Different dependencies</em> was collapsed.  So you think, good, the line says <em>Skip</em> so nothing will happen.  Except, did you notice that minuscule exclamation mark in the bottom-left corner of the icon?  That means that other actions may be happening further down the dependency tree, as illustrated in the screenshot.</p>
<p>So don’t let the dude mislead you into thinking nothing will happen when it says <em>Skip</em>.  Sometimes the actual actions are hidden further down and you need to open up every node with the exclamation mark on the icon to verify if that’s what you want.</p>
<p>Have fun training the dude,</p>
<p>Valentino.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/06/09/getting-cooperation-from-a-stubborn-data-dude/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Aggregating Data With The OVER Clause</title>
		<link>http://blog.hoegaerden.be/2010/06/01/aggregating-data-with-the-over-clause/</link>
		<comments>http://blog.hoegaerden.be/2010/06/01/aggregating-data-with-the-over-clause/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 21:12:01 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/06/01/aggregating-data-with-the-over-clause/</guid>
		<description><![CDATA[In this article I will show you a couple of different T-SQL queries to fetch aggregated data.  The main purpose is to illustrate how the OVER clause can be used to aggregate data.
For the examples I will use data from the AdventureWorks2008R2 database, available at CodePlex.
The Data
The AdventureWorks 2008 R2 database contains a view called [...]]]></description>
			<content:encoded><![CDATA[<p>In this article I will show you a couple of different T-SQL queries to fetch aggregated data.  The main purpose is to illustrate how the OVER clause can be used to aggregate data.</p>
<p>For the examples I will use data from the AdventureWorks2008R2 database, <a title="AdventureWorks 2008R2 RTM" href="http://msftdbprodsamples.codeplex.com/releases/view/45907" target="_blank">available at CodePlex</a>.</p>
<h2>The Data</h2>
<p>The AdventureWorks 2008 R2 database contains a view called <em>Sales.vSalesPerson</em>.  This is the data with which I’ll be working in the examples below.  Here’s what it looks like:</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image286.png"><img style="display: inline; border-width: 0px;" title="My Working Data" src="http://blog.hoegaerden.be/wp-content/uploads/image_thumb68.png" border="0" alt="My Working Data" width="700" height="184" /></a></p>
<p>I’ve hidden some fields so that all the relevant ones are in view.</p>
<h2>The Scenario<a href="http://11011.net/software/vspaste"></a></h2>
<p>Your manager has asked you to create one query, to be executed on the <em>Sales.vSalesPerson</em> table, that returns a list of:</p>
<ul>
<li>all employees (FirstName, LastName, JobTitle, CountryRegionName, StateProvinceName, City),</li>
<li>their sales of last year (SalesLastYear),</li>
<li>the sum of the sales of last year for their country,</li>
<li>the average of the sales of last year compared to all employees with the same type of phone (PhoneNumberType)</li>
<li>the overall average and sum of the sales of last year.</li>
</ul>
<h3>Using Derived Tables</h3>
<p>No problem you say, coming right up.  So you start building your query, retrieving all fields as requested.</p>
<p>After quite some typing, here’s what your query looks like:</p>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue;">select </span>S<span style="color: gray;">.</span>FirstName<span style="color: gray;">, </span>S<span style="color: gray;">.</span>LastName<span style="color: gray;">, </span>S<span style="color: gray;">.</span>JobTitle<span style="color: gray;">, </span>S<span style="color: gray;">.</span>PhoneNumberType<span style="color: gray;">, </span>S<span style="color: gray;">.</span>CountryRegionName<span style="color: gray;">,
    </span>S<span style="color: gray;">.</span>StateProvinceName<span style="color: gray;">, </span>S<span style="color: gray;">.</span>City<span style="color: gray;">, </span>S<span style="color: gray;">.</span>SalesLastYear<span style="color: gray;">,
    </span>GeographicSales<span style="color: gray;">.</span>SalesLastYearGeographic_SUM<span style="color: gray;">,
    </span>SalesByPhoneType<span style="color: gray;">.</span>SalesLastYearByPhoneNumberType_AVG<span style="color: gray;">,
    </span>SalesSUM<span style="color: gray;">.</span>SalesLastYear_AVG<span style="color: gray;">, </span>SalesSUM<span style="color: gray;">.</span>SalesLastYear_SUM
<span style="color: blue;">from </span>Sales<span style="color: gray;">.</span>vSalesPerson S
<span style="color: green;">--Derived Table 1: the overall aggregates
</span><span style="color: gray;">cross join (
    </span><span style="color: blue;">select </span><span style="color: magenta;">SUM</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span>SalesLastYear_SUM<span style="color: gray;">, </span><span style="color: magenta;">AVG</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span>SalesLastYear_AVG
    <span style="color: blue;">from </span>Sales<span style="color: gray;">.</span>vSalesPerson
<span style="color: gray;">) </span>SalesSUM
<span style="color: green;">--Derived Table 2: the aggregate on Country level
</span><span style="color: gray;">inner join (
    </span><span style="color: blue;">select </span>CountryRegionName<span style="color: gray;">, </span><span style="color: magenta;">SUM</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span>SalesLastYearGeographic_SUM
    <span style="color: blue;">from </span>Sales<span style="color: gray;">.</span>vSalesPerson
    <span style="color: blue;">group by </span>CountryRegionName
<span style="color: gray;">) </span>GeographicSales <span style="color: blue;">on </span>GeographicSales<span style="color: gray;">.</span>CountryRegionName <span style="color: gray;">= </span>S<span style="color: gray;">.</span>CountryRegionName
<span style="color: green;">--Derived Table 3: the aggregate on phone type
</span><span style="color: gray;">inner join (
    </span><span style="color: blue;">select </span>PhoneNumberType<span style="color: gray;">, </span><span style="color: magenta;">AVG</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span>SalesLastYearByPhoneNumberType_AVG
    <span style="color: blue;">from </span>Sales<span style="color: gray;">.</span>vSalesPerson
    <span style="color: blue;">group by </span>PhoneNumberType
<span style="color: gray;">) </span>SalesByPhoneType <span style="color: blue;">on </span>SalesByPhoneType<span style="color: gray;">.</span>PhoneNumberType<span style="color: gray;">= </span>S<span style="color: gray;">.</span>PhoneNumberType<span style="color: gray;">;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>The main query is retrieving all fields as requested.  Further down there are three derived table queries, each one retrieving aggregates on a different level.</p>
<p>The first derived table is retrieving the overall aggregates.  These are cross-joined with every record in our main query so for each record the totals will be the same, which is what we want.</p>
<p>The second derived table retrieves the aggregates on Country level, including the CountryRegionName.  This is done using the conventional GROUP BY method.  The CountryRegionName is the key on which the derived table is joined to the main table.</p>
<p>The third derived table uses a similar system, this time for the aggregate on phone type.</p>
<p>And here’s the query’s output:</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image287.png"><img style="display: inline; border-width: 0px;" title="Output of the query using subqueries" src="http://blog.hoegaerden.be/wp-content/uploads/image_thumb69.png" border="0" alt="Output of the query using subqueries" width="700" height="174" /></a></p>
<p>Happy with this result, you go up to the cafeteria to finally have lunch with your colleagues (who left 15 minutes earlier but you wanted to get your query finished first).</p>
<h3>Using The OVER Clause</h3>
<p>During lunch you explain to your peers what kind of funny request you got from management and told them how you solved it.</p>
<p>Then one of them speaks up and says: “Want to know how you can avoid all that typing?  Use the OVER clause!  I’ll show you when we are back at our desks.”</p>
<p>After lunch, here’s what your colleague helps to produce:</p>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue;">select </span>S<span style="color: gray;">.</span>FirstName<span style="color: gray;">, </span>S<span style="color: gray;">.</span>LastName<span style="color: gray;">, </span>S<span style="color: gray;">.</span>JobTitle<span style="color: gray;">, </span>S<span style="color: gray;">.</span>PhoneNumberType<span style="color: gray;">, </span>S<span style="color: gray;">.</span>CountryRegionName<span style="color: gray;">,
    </span>S<span style="color: gray;">.</span>StateProvinceName<span style="color: gray;">, </span>S<span style="color: gray;">.</span>City<span style="color: gray;">, </span>S<span style="color: gray;">.</span>SalesLastYear<span style="color: gray;">,
    </span><span style="color: magenta;">SUM</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span><span style="color: blue;">OVER </span><span style="color: gray;">(</span><span style="color: blue;">PARTITION BY </span>CountryRegionName<span style="color: gray;">)
        </span>SalesLastYearGeographic_SUM<span style="color: gray;">,
    </span><span style="color: magenta;">AVG</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span><span style="color: blue;">OVER </span><span style="color: gray;">(</span><span style="color: blue;">PARTITION BY </span>PhoneNumberType<span style="color: gray;">)
        </span>SalesLastYearByPhoneNumberType_AVG<span style="color: gray;">,
    </span>SalesSUM<span style="color: gray;">.</span>SalesLastYear_AVG<span style="color: gray;">, </span>SalesSUM<span style="color: gray;">.</span>SalesLastYear_SUM
<span style="color: blue;">from </span>Sales<span style="color: gray;">.</span>vSalesPerson S
<span style="color: green;">--Derived Table 1: the overall aggregates
</span><span style="color: gray;">cross join (
    </span><span style="color: blue;">select </span><span style="color: magenta;">SUM</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span>SalesLastYear_SUM<span style="color: gray;">, </span><span style="color: magenta;">AVG</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span>SalesLastYear_AVG
    <span style="color: blue;">from </span>Sales<span style="color: gray;">.</span>vSalesPerson
<span style="color: gray;">) </span>SalesSUM<span style="color: gray;">;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>As you can see, derived tables 2 and 3 are gone.  They have been replaced with <a title="OVER Clause (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms189461.aspx" target="_blank">the OVER clause</a>, in combination with PARTITION BY.  What you say with the OVER clause is: “partition the dataset by the fields specified in the PARTITION BY and apply the aggregation on those partitions”.  Another word for this is <strong>aggregate window function</strong>.</p>
<p>As you like the approach, you ask your co-worker how you can get rid of that cross join.  He doesn’t really know but then another colleague who overheard your conversation says: “On this blog the other day I read that you can use the OVER clause and partition by anything you want.  As long as it’s a constant, it will work!”.</p>
<p>So you give that a try and you end up with the following final query:</p>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue;">select </span>FirstName<span style="color: gray;">, </span>LastName<span style="color: gray;">, </span>JobTitle<span style="color: gray;">, </span>PhoneNumberType<span style="color: gray;">, </span>CountryRegionName<span style="color: gray;">,
    </span>StateProvinceName<span style="color: gray;">, </span>City<span style="color: gray;">, </span>SalesLastYear<span style="color: gray;">,
    </span><span style="color: magenta;">SUM</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span><span style="color: blue;">OVER </span><span style="color: gray;">(</span><span style="color: blue;">PARTITION BY </span>CountryRegionName<span style="color: gray;">)
        </span>SalesLastYearGeographic_SUM<span style="color: gray;">,
    </span><span style="color: magenta;">AVG</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span><span style="color: blue;">OVER </span><span style="color: gray;">(</span><span style="color: blue;">PARTITION BY </span>PhoneNumberType<span style="color: gray;">)
        </span>SalesLastYearByPhoneNumberType_AVG<span style="color: gray;">,
    </span><span style="color: magenta;">AVG</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span><span style="color: blue;">OVER </span><span style="color: gray;">(</span><span style="color: blue;">PARTITION BY </span><span style="color: red;">'duh'</span><span style="color: gray;">) </span>SalesLastYear_AVG<span style="color: gray;">,
    </span><span style="color: magenta;">SUM</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span><span style="color: blue;">OVER </span><span style="color: gray;">(</span><span style="color: blue;">PARTITION BY </span>1<span style="color: gray;">) </span>SalesLastYear_SUM
<span style="color: blue;">from </span>Sales<span style="color: gray;">.</span>vSalesPerson<span style="color: gray;">;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>As illustrated in the example, you can use any constant value to calculate overall aggregates over the whole dataset using the OVER clause.</p>
<p>You happily thank your colleagues and tell them that next time you’ll be able to join them for lunch on time.</p>
<p>About a week later you’re explaining to one of your friends how you’ve gotten to know the OVER clause. After hearing how you use it to aggregate over the whole dataset, he smiles and says: “I know how you can simplify it even more! Don’t partition at all!”.</p>
<p>Taking a closer look it turns out that the PARTITION BY is actually optional:</p>
<pre>Ranking Window Functions
&lt; OVER_CLAUSE &gt; :: =     OVER ( [ PARTITION BY value_expression, ... [ n ] ]            &lt;ORDER BY_Clause&gt; )Aggregate Window Functions
&lt; OVER_CLAUSE &gt; :: =     OVER ( [ PARTITION BY value_expression, ... [ n ] ] )</pre>
<p>See those square brackets? Means it’s optional.</p>
<p>So here is the real final query:</p>
<pre class="code"><span style="color: blue;">select </span>FirstName<span style="color: gray;">, </span>LastName<span style="color: gray;">, </span>JobTitle<span style="color: gray;">, </span>PhoneNumberType<span style="color: gray;">, </span>CountryRegionName<span style="color: gray;">,
    </span>StateProvinceName<span style="color: gray;">, </span>City<span style="color: gray;">, </span>SalesLastYear<span style="color: gray;">,
    </span><span style="color: magenta;">SUM</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span><span style="color: blue;">OVER </span><span style="color: gray;">(</span><span style="color: blue;">PARTITION BY </span>CountryRegionName<span style="color: gray;">)
        </span>SalesLastYearGeographic_SUM<span style="color: gray;">,
    </span><span style="color: magenta;">AVG</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span><span style="color: blue;">OVER </span><span style="color: gray;">(</span><span style="color: blue;">PARTITION BY </span>PhoneNumberType<span style="color: gray;">)
        </span>SalesLastYearByPhoneNumberType_AVG<span style="color: gray;">,
    </span><span style="color: magenta;">AVG</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span><span style="color: blue;">OVER </span><span style="color: gray;">() </span>SalesLastYear_AVG<span style="color: gray;">,
    </span><span style="color: magenta;">SUM</span><span style="color: gray;">(</span>SalesLastYear<span style="color: gray;">) </span><span style="color: blue;">OVER </span><span style="color: gray;">() </span>SalesLastYear_SUM
<span style="color: blue;">from </span>Sales<span style="color: gray;">.</span>vSalesPerson<span style="color: gray;">;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h2>Conclusion</h2>
<p>When you compare the final query with the first one, tell me, which one would you prefer to maintain?  Do you prefer to have lunch with your peers or to arrive late and miss all the fun?</p>
<p>Have fun!</p>
<p>Valentino.</p>
<p><strong>References</strong></p>
<p><a title="The OVER Clause (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms189461.aspx" target="_blank">OVER Clause (Transact-SQL)</a></p>
<p><a title="Join Fundamentals" href="http://msdn.microsoft.com/en-us/library/ms191517.aspx" target="_blank">Join Fundamentals</a></p>
<p><a title="SELECT (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms189499.aspx" target="_blank">SELECT (Transact-SQL)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/06/01/aggregating-data-with-the-over-clause/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Retrieving Data From Excel</title>
		<link>http://blog.hoegaerden.be/2010/03/29/retrieving-data-from-excel/</link>
		<comments>http://blog.hoegaerden.be/2010/03/29/retrieving-data-from-excel/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 20:16:53 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/03/29/retrieving-data-from-excel/</guid>
		<description><![CDATA[The purpose of this article is to demonstrate how to retrieve data from an Excel sheet and put it in a table in a SQL Server database.
Introduction
Anyone who&#8217;s ever used a computer for a significant amount of time has probably come into contact with Excel, the spreadsheet application part of the Microsoft Office suite. Its [...]]]></description>
			<content:encoded><![CDATA[<p>The purpose of this article is to demonstrate how to retrieve data from an Excel sheet and put it in a table in a SQL Server database.</p>
<h2>Introduction</h2>
<p>Anyone who&#8217;s ever used a computer for a significant amount of time has probably come into contact with <a title="Excel 2007" href="http://office.microsoft.com/en-us/excel/default.aspx" target="_blank">Excel</a>, the spreadsheet application part of the Microsoft Office suite. Its main purposes are to perform calculations and create charts and pivot tables for analysis.</p>
<p>But people have great imagination and invent new uses for it every day.&#160; I&#8217;ve even seen it used as a picture album.&#160; (Sorry dad, but I know you won’t be reading this anyway. <img src='http://blog.hoegaerden.be/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> )&#160; Ever since he had this specific YACI, or “Yet Another Computer Issue”, because his PC wasn’t powerful enough to open his 45 MB Excel file, uh, “picture collection”, he took some evening classes.&#160; He’s now putting his Photoshopped pictures in PowerPoint…&#160; Anyway, let’s get back on track now.</p>
<p>Another use, and the one that&#8217;s the subject of this article, is when Excel has been used as a database.&#160; Come on, you know what I&#8217;m talking about, with the first row containing the column headers followed by possibly thousands of data rows.&#160; The following screenshot contains an example, and is also the file that I will be using in this article.&#160; I took all records from the <strong>Production.Product</strong> table in the <a title="AdventureWorks 2008R2 November CTP" href="http://msftdbprodsamples.codeplex.com/releases/view/24854" target="_blank">AdventureWorks 2008R2</a> database and dumped them in Excel.</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image206.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="An Excel sheet used as a data store" border="0" alt="An Excel sheet used as a data store" src="http://blog.hoegaerden.be/wp-content/uploads/image_thumb54.png" width="681" height="224" /></a></p>
<p>At some point people will realize, either because someone told them or because they lost some data due to inattentiveness, that it wasn&#8217;t a really good idea to keep all that data in an Excel sheet.&#160; And they&#8217;ll ask you to put it in a real database such as SQL Server.</p>
<p>That&#8217;s what I&#8217;m going to show you in the next paragraphs: how to import data from Excel into SQL Server.</p>
<h2>Using OPENROWSET() To Query Excel Files</h2>
<p>There are actually several different ways to achieve this.&#160; In this article I will use the <a title="BOL2008: OPENROWSET (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms190312.aspx" target="_blank">OPENROWSET()</a> function.&#160; This is a T-SQL function that can be used to access any OLE DB data source.&#160; All you need is the right OLE DB driver.&#160; The oldest version which I could confirm that contains this function is SQL Server 7.0, good enough to say that any version supports it.</p>
<p>My sample Excel files are located in <em>C:\temp\</em>.&#160; This folder contains two files:<em> Products.xls</em> and <em>Products.xlsx</em>.&#160; The first file is saved in the old format, Excel 97-2003, while the second file was saved from Excel 2010.&#160; Both files contain the same data.&#160; The sheet containing the list of products is called <em>ProductList</em>.</p>
<p>And here are the queries:</p>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: green">--Excel 2007-2010
</span><span style="color: blue">SELECT </span><span style="color: gray">* </span><span style="color: green">--INTO #productlist
</span><span style="color: blue">FROM OPENROWSET</span><span style="color: gray">(</span><span style="color: red">'Microsoft.ACE.OLEDB.12.0'</span><span style="color: gray">,
    </span><span style="color: red">'Excel 12.0 Xml;HDR=YES;Database=C:\temp\Products.xlsx'</span><span style="color: gray">,
    </span><span style="color: red">'SELECT * FROM [ProductList$]'</span><span style="color: gray">);

</span><span style="color: green">--Excel 97-2003
</span><span style="color: blue">SELECT </span><span style="color: gray">* </span><span style="color: green">--INTO #productlist
</span><span style="color: blue">FROM OPENROWSET</span><span style="color: gray">(</span><span style="color: red">'Microsoft.Jet.OLEDB.4.0'</span><span style="color: gray">,
    </span><span style="color: red">'Excel 8.0;HDR=YES;Database=C:\temp\Products.xls'</span><span style="color: gray">,
    </span><span style="color: red">'select * from [ProductList$]'</span><span style="color: gray">);</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>These queries are just returning the data from the Excel file into the Results window, when executed using the Management Studio.&#160; To insert the data into a table, uncomment the <a title="BOL2008: INTO Clause (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms188029.aspx" target="_blank">INTO</a> clause.&#160; When uncommented, the statement retrieves the data from the Excel sheet and puts it into a newly-created <a title="BOL2008: Special Table Types" href="http://msdn.microsoft.com/en-us/library/ms186986.aspx" target="_blank">local temporary table</a> called <em>#productlist</em>.</p>
<p>Furthermore, the query assumes that the first row contains the header.&#160; If that’s not the case, replace HDR=YES with HDR=NO.</p>
<p><strong>Note:</strong> if you get an error message when running the query, look further down in this article.&#160; I’ve covered a couple of them.</p>
<p>With the INTO clause uncommented and the query executed, the temporary table can now be queried just like any other table:</p>
<pre class="code"><span style="color: blue">SELECT </span><span style="color: gray">* </span><span style="color: blue">FROM </span>#productlist</pre>
<h3>What Type Is Your Data?</h3>
<p>Let’s have a look if this method of using a SELECT INTO in combination with OPENROWSET and a temporary table is smart enough to interpret the correct data types of the data coming in.&#160; Use the following command to describe the metadata of the temporary table:</p>
<pre class="code"><span style="color: blue">USE </span>tempdb<span style="color: gray">;
</span><span style="color: blue">GO
</span><span style="color: maroon">sp_help </span><span style="color: red">'#productlist'</span><span style="color: gray">;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>Because a temporary table is stored in the <em>tempdb</em>, the <a title="BOL2008: sp_helptext (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms176112.aspx" target="_blank">sp_help</a> command should be issued against that database.</p>
<p>Here’s the part of the output in which we’re interested:</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="The data types used when combining OPENROWSET with SELECT INTO" border="0" alt="The data types used when combining OPENROWSET with SELECT INTO" src="http://blog.hoegaerden.be/wp-content/uploads/image207.png" width="377" height="442" /></p>
<p>As you can see, anything that looks like text will be put in a field of type<em> nvarchar(510)</em> and anything that looks like a number (integers, floating-point numbers, datetime values, …) is put into a <em>float(53)</em>.&#160; Not a lot of intelligence there.&#160; This is the result when no formatting was put on the cells in Excel.</p>
<p>As an experiment I’ve changed the format of some fields in the Excel file and then retried the SELECT INTO statement.&#160; What did I change?&#160; I identified <em>ProductID</em> as being a number without any decimals, changed <em>StandardCost</em> and <em>ListPrice</em> to a currency with four decimal digits and I changed <em>SellStartDate</em> and <em>SellEndDate</em> to a custom date/time format showing both date and time.</p>
<p>The effect on the table creation was not completely as I would have expected:</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="SELECT INTO with some field types changed" border="0" alt="SELECT INTO with some field types changed" src="http://blog.hoegaerden.be/wp-content/uploads/image208.png" width="382" height="446" /></p>
<p><em>ProductID</em> is still being stored into a float field, even though in Excel it’s defined as having no decimals.&#160; And the datetime values are not recognized either.&#160; Okay, I used a custom format there, so maybe it’s due to that.</p>
<p>It’s up to you of course how you use this method of importing the data.&#160; You can put your records into a temporary table to process further, or you can create a table with the expected data types upfront and import the data directly into that one.</p>
<h2>Some Possible Issues</h2>
<p>Let’s cover some issues related to this method.</p>
<h3>Enable ‘AD Hoc Distributed Queries’</h3>
<p>The OPENROWSET() function expects that the <a title="BOL2008: ad hoc distributed queries Option" href="http://msdn.microsoft.com/en-us/library/ms187569.aspx" target="_blank">‘Ad Hoc Distributed Queries’ option</a> is enabled on the server.&#160; When that’s not the case you’ll see the following message:</p>
<blockquote>
<p><span style="color: #ff0000">Msg 15281, Level 16, State 1, Line 1</span> </p>
<p><font color="#ff0000">SQL Server blocked access to STATEMENT &#8216;OpenRowset/OpenDatasource&#8217; of component &#8216;Ad Hoc Distributed Queries&#8217; because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of &#8216;Ad Hoc Distributed Queries&#8217; by using sp_configure. For more information about enabling &#8216;Ad Hoc Distributed Queries&#8217;, see &quot;Surface Area Configuration&quot; in SQL Server Books Online.</font></p>
</p>
</blockquote>
<p>This is one of the advanced options.&#160; To enable it you can use the following command:</p>
<pre class="code"><span style="color: maroon">sp_configure </span><span style="color: red">'show advanced options'</span><span style="color: gray">, </span>1<span style="color: gray">;
</span><span style="color: blue">GO
RECONFIGURE</span><span style="color: gray">;
</span><span style="color: blue">GO

</span><span style="color: maroon">sp_configure </span><span style="color: red">'Ad Hoc Distributed Queries'</span><span style="color: gray">, </span>1<span style="color: gray">;
</span><span style="color: blue">GO
RECONFIGURE</span><span style="color: gray">;
</span><span style="color: blue">GO</span></pre>
<p>To get a good look at all the different settings, just run the <a title="BOL2008: sp_configure (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms188787.aspx" target="_blank">sp_configure</a> procedure without any parameters.</p>
<p><strong>Note:</strong> if you’re not the administrator of the server, you should talk to the DBA who’s responsible before attempting this.</p>
<h3>The File Needs To Be Closed</h3>
<p>When the Excel file is not closed, you’ll end up with the following error:</p>
<blockquote>
<p><span style="color: #ff0000">Msg 7399, Level 16, State 1, Line 1</span> </p>
<p><font color="#ff0000">The OLE DB provider &quot;Microsoft.Jet.OLEDB.4.0&quot; for linked server &quot;(null)&quot; reported an error. The provider did not give any information about the error.</font> </p>
</p>
<p><span style="color: #ff0000">Msg 7303, Level 16, State 1, Line 1 </span></p>
<p><span style="color: #ff0000">Cannot initialize the data source object of OLE DB provider &quot;Microsoft.Jet.OLEDB.4.0&quot; for linked server &quot;(null)&quot;.</span></p>
</blockquote>
<p>So close the file and try the query again.</p>
<h3>OLE DB Driver Not Installed</h3>
<p>The OPENROWSET() function uses OLE DB, so it needs a driver for your data source, in this case for Excel.&#160; If the right driver is not installed, you’ll see the following error (or similar, depends on the version used).</p>
<blockquote>
<p><span style="color: #ff0000">Msg 7302, Level 16, State 1, Line 1</span> </p>
<p><font color="#ff0000">Cannot create an instance of OLE DB provider &quot;Microsoft.ACE.OLEDB.12.0&quot; for linked server &quot;(null)&quot;.</font></p>
</p>
</blockquote>
<p>To solve the issue, install the right driver and try again.</p>
<p>How can you tell what drivers are installed?&#160; Open up the <strong>ODBC Data Source Administrator</strong> window (Start &gt; Run &gt; type ODBCAD32.EXE and enter) and have a look in the <em>Drivers</em> tab.&#160; The following screenshot (taken on a Dutch Windows XP) shows both the JET 4.0 driver for Excel 97-2003 and the fairly-new ACE driver for Excel 2007.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="odbcad32.exe - ODBC Data Source Administrator" border="0" alt="odbcad32.exe - ODBC Data Source Administrator" src="http://blog.hoegaerden.be/wp-content/uploads/image209.png" width="461" height="415" /></p>
<p>The drivers can be downloaded from the following pages on the Microsoft site:</p>
<p><a title="How to obtain the latest service pack for the Microsoft Jet 4.0 Database Engine" href="http://support.microsoft.com/kb/239114/" target="_blank">Excel 97-2003 Jet 4.0 driver</a></p>
<p><a title="2007 Office System Driver: Data Connectivity Components" href="http://www.microsoft.com/downloads/details.aspx?familyid=7554F536-8C28-4598-9B72-EF94E038C891&amp;displaylang=en" target="_blank">Excel 2007 ACE driver &#8211; 12.00.6423.1000</a></p>
<p><a title="2010 Office System Driver Beta: Data Connectivity Components" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=C06B8369-60DD-4B64-A44B-84B371EDE16D&amp;amp;displaylang=ja&amp;displaylang=en" target="_blank">Excel 2010 ACE driver (beta) &#8211; 14.00.4732.1000</a></p>
<p><strong>Sidenote:</strong> the Excel 2010 driver is not supported on Windows XP, but I was able to query the 2010 Excel sheet using the 2007 driver.&#160; I guess that this is the result of the <a title="Wikipedia: Office Open XML" href="http://en.wikipedia.org/wiki/Office_Open_XML" target="_blank">Office Open XML standard</a> which was introduced in Office 2007.</p>
<p><strong>Driver backward-compatibility</strong></p>
<p>The ACE drivers are backwards-compatible.&#160; So the following queries are working perfectly:</p>
<pre class="code"><span style="color: green">--old Excel with new ACE driver - working query 1
</span><span style="color: blue">SELECT </span><span style="color: gray">* </span><span style="color: green">--INTO #productlist
</span><span style="color: blue">FROM OPENROWSET</span><span style="color: gray">(</span><span style="color: red">'Microsoft.ACE.OLEDB.12.0'</span><span style="color: gray">,
    </span><span style="color: red">'Excel 8.0;HDR=YES;Database=C:\temp\Products.xls'</span><span style="color: gray">,
    </span><span style="color: red">'SELECT * FROM [ProductList$]'</span><span style="color: gray">);

</span><span style="color: green">--old Excel with new ACE driver - working query 2
</span><span style="color: blue">SELECT </span><span style="color: gray">* </span><span style="color: green">--INTO #productlist
</span><span style="color: blue">FROM OPENROWSET</span><span style="color: gray">(</span><span style="color: red">'Microsoft.ACE.OLEDB.12.0'</span><span style="color: gray">,
    </span><span style="color: red">'Excel 12.0;HDR=YES;Database=C:\temp\Products.xls'</span><span style="color: gray">,
    </span><span style="color: red">'SELECT * FROM [ProductList$]'</span><span style="color: gray">);</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>In other words, you won’t be needing that first link for the Jet driver.&#160; For the full story have a look at <a title="How to get a x64 version of Jet?" href="http://blogs.msdn.com/psssql/archive/2010/01/21/how-to-get-a-x64-version-of-jet.aspx" target="_blank">this blog post by Adam Saxton</a> of the CSS SQL Server Escalation Services team.</p>
<h3>The 64-bit Story</h3>
<p>So, what if you’re running a 64-bit OS?&#160; I’ll start by saying that I had quite some issues getting OPENROWSET to work, but finally I managed it.&#160; Following is a list of my attempts, each time with the resulting message.&#160; And finally I’ll show you how I got it to work.&#160; The problem was something really unexpected…</p>
<p><strong>ACE 14 64-bit through SSMS</strong></p>
<p>My main laptop is running Windows 7 64-bit, Office 2010 64-bit and SQL Server 2008 R2 64-bit.&#160; So I installed the 64-bit version of the ACE 14 driver, which happens to be the first OLE DB driver for Excel that ships in 64-bit.&#160; But when I execute my query I’m getting the following message:</p>
<blockquote>
<p><span style="color: #ff0000">Msg 7403, Level 16, State 1, Line 1</span> </p>
<p><font color="#ff0000">The OLE DB provider &quot;Microsoft.ACE.OLEDB.14.0&quot; has not been registered.</font></p>
</p>
</blockquote>
<p>Is this because SSMS ships only in 32-bit?&#160; Maybe, but I’m not able to install the 32-bit driver.&#160; It doesn’t allow me to because I’ve got Office in 64-bit installed.&#160; The installer throws me the following error:</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Microsoft Access database engine 2010 (beta) - You cannot install the 32-bit version of Access Database engine for Microsoft Office 2010 because you currently have 64-bit Office products installed..." border="0" alt="Microsoft Access database engine 2010 (beta) - You cannot install the 32-bit version of Access Database engine for Microsoft Office 2010 because you currently have 64-bit Office products installed..." src="http://blog.hoegaerden.be/wp-content/uploads/image210.png" width="416" height="218" /></p>
<p><strong>ACE 12 32-bit on a 64-bit machine</strong></p>
<p>When I check the installed drivers using the 32-bit version of the ODBC Data Source Administrator (located in C:\Windows\SysWOW64), I notice that the ACE 12 driver is installed.&#160; However, trying to use that one from the Management Studio gives me this:</p>
<blockquote>
<p><span style="color: #ff0000">Msg 7399, Level 16, State 1, Line 1</span> </p>
<p><font color="#ff0000">The OLE DB provider &quot;Microsoft.ACE.OLEDB.12.0&quot; for linked server &quot;(null)&quot; reported an error. The provider did not give any information about the error.</font> </p>
</p>
<p><span style="color: #ff0000">Msg 7330, Level 16, State 2, Line 1 </span></p>
<p><span style="color: #ff0000">Cannot fetch a row from OLE DB provider &quot;Microsoft.ACE.OLEDB.12.0&quot; for linked server &quot;(null)&quot;.</span></p>
</blockquote>
<p>The Results pane shows all the columns with the right column names, retrieved from Excel.&#160; But the driver seems to have a problem retrieving the actual data.</p>
<p>This issue with error 7330 is mentioned <a title="OPENROWSET with Excel 2007 -- 7330 Cannot fetch a row from OLE DB provider &quot;Microsoft.ACE.OLEDB.12.0&quot; for linked server &quot;(null)&quot;" href="http://social.msdn.microsoft.com/Forums/en-US/sqldataaccess/thread/8514b4bb-945a-423b-98fe-a4ec4d7366ea" target="_blank">in the following thread</a> on the SQL Server MSDN forum, but unfortunately the proposed solution didn’t solve the problem in my case.</p>
<p><strong>64-bit SQLCMD using ACE 14 driver</strong></p>
<p>I also tried using the 64-bit version of <a title="BOL2008: sqlcmd Utility" href="http://msdn.microsoft.com/en-us/library/ms162773.aspx" target="_blank">sqlcmd.exe</a>, but strangely enough that throws the same error.</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image211.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Using sqlcmd 64-bit to query Excel" border="0" alt="Using sqlcmd 64-bit to query Excel" src="http://blog.hoegaerden.be/wp-content/uploads/image_thumb55.png" width="688" height="377" /></a></p>
<p>I actually expected this last method to work, after all, everything is now running in 64-bit.&#160; But alas, it didn’t…</p>
<p><strong>One more go…</strong></p>
<p>After some more trial and error, I have actually found a way to get the query to work.&#160; I don’t have a logical explanation on why it’s behaving the way it is, but, well, it is working…</p>
<p>This query is running fine:</p>
<pre class="code"><span style="color: blue">SELECT </span><span style="color: gray">* </span><span style="color: green">--INTO #productlist
</span><span style="color: blue">FROM OPENROWSET</span><span style="color: gray">(</span><span style="color: red">'Microsoft.ACE.OLEDB.12.0'</span><span style="color: gray">,
    </span><span style="color: red">'Excel 12.0 Xml;HDR=YES;Database=C:\temp\Products.xlsx'</span><span style="color: gray">,
    </span><span style="color: red">'SELECT * FROM [ProductList$]'</span><span style="color: gray">);</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>But this one isn’t:</p>
<pre class="code"><span style="color: green">--Excel 2007-2010
</span><span style="color: blue">SELECT </span><span style="color: gray">* </span><span style="color: green">--INTO #productlist
</span><span style="color: blue">FROM OPENROWSET</span><span style="color: gray">(</span><span style="color: red">'Microsoft.ACE.OLEDB.12.0'</span><span style="color: gray">,
    </span><span style="color: red">'Excel 12.0 Xml;HDR=YES;Database=C:\temp\Products.xlsx'</span><span style="color: gray">,
    </span><span style="color: red">'SELECT * FROM [ProductList$]'</span><span style="color: gray">);</span></pre>
<p>It’s exactly the same query, only difference is the comment line at the start.&#160; And even weirder, if I add a space after the double-dash, the query works fine as well!</p>
<p>Then I decided to remove the commented INTO clause.&#160; This made the weird behavior disappear.&#160; So for some reason SQL Server doesn’t like the OPENROWSET function combined with comments inside the query.&#160; The strange behavior also disappears when a space is added between the double-dash and the INTO keyword.</p>
<p>Uh, computers can be so much fun, right? <img src='http://blog.hoegaerden.be/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>If anyone has got an explanation on this strange behavior: please do post a comment!&#160; For now my conclusion is: don’t use comments when creating an OPENROWSET query.</p>
<p>&#160;</p>
<p><strong><u>IMPORTANT UPDATE (April 11, 2010)</u>: it seems that the current installer for the ACE 14 driver contains a bug and registers it as being “Microsoft.ACE.OLEDB.12.0” instead of “Microsoft.ACE.OLEDB.14.0” .&#160; This explains some of the issues shown above.&#160; Some evidence on the issue:</strong></p>
<p><strong><a title="Access Database Engine 2010 installation issue to use with ADO access technology to access data from Jet database (.mdb files)" href="https://connect.microsoft.com/data/feedback/details/541090/access-database-engine-2010-installation-issue-to-use-with-ado-access-technology-to-access-data-from-jet-database-mdb-files?wa=wsignin1.0" target="_blank">Microsoft Connect: Access Database Engine 2010 installation issue to use with ADO access technology to access data from Jet database (.mdb files)</a></strong></p>
<p><strong><a title="The &#39;Microsoft.ACE.OLEDB.14.0&#39; provider is not registered ....." href="http://forums.devarticles.com/microsoft-access-development-49/the-microsoft-ace-oledb-14-0-provider-is-not-registered-238601.html" target="_blank">The &#8216;Microsoft.ACE.OLEDB.14.0&#8242; provider is not registered &#8230;.. (see last comment)</a></strong></p>
<p><strong><a title="Excel Services, ODC and Microsoft.ACE.OLEDB.14.0" href="http://blog.sharepointalist.com/2010/03/odc-microsoft-ace-oledb-14-0.html" target="_blank">Excel Services, ODC and Microsoft.ACE.OLEDB.14.0</a></strong></p>
<p>&#160;</p>
<h2>Conclusion</h2>
<p>The above has shown that OPENROWSET() can be a useful function, given the right circumstances.&#160; But in the wrong setting it can be quite cumbersome to get to work.</p>
<p>I would recommend this method only for one-off quick imports, such as when you as a developer are given a bunch of data in a spreadsheet and need to get it into the database, one way or another.&#160; I would not use it for an automated import process.&#160; For that we’ve got a more interesting alternative which I’ll cover <a title="Importing Excel Data Using Integration Services" href="http://blog.hoegaerden.be/2010/04/20/importing-excel-data-using-integration-services/">in an upcoming article</a>.</p>
<p>Have fun!</p>
<p>Valentino.</p>
<p><strong>References</strong></p>
<p><a title="BOL 2008: Special Table Types" href="http://msdn.microsoft.com/en-us/library/ms186986.aspx" target="_blank">BOL 2008: Special Table Types (incl. temporary tables)</a></p>
<p><a title="BOL 2008: OPENROWSET() function" href="http://msdn.microsoft.com/en-us/library/ms190312.aspx" target="_blank">BOL 2008: OPENROWSET() function</a></p>
<p><a title="BOL 2008: the INTO clause" href="http://msdn.microsoft.com/en-us/library/ms188029.aspx" target="_blank">BOL 2008: the INTO clause</a></p>
<p><a title="How to get a x64 version of Jet?" href="http://blogs.msdn.com/psssql/archive/2010/01/21/how-to-get-a-x64-version-of-jet.aspx" target="_blank">CSS SQL Server Engineers: How to get a x64 version of Jet?</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/03/29/retrieving-data-from-excel/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>SQL Server 2008 SP2: Want It? Vote For It!</title>
		<link>http://blog.hoegaerden.be/2010/01/20/sql-server-2008-sp2-want-it-vote-for-it/</link>
		<comments>http://blog.hoegaerden.be/2010/01/20/sql-server-2008-sp2-want-it-vote-for-it/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 21:29:52 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/01/20/sql-server-2008-sp2-want-it-vote-for-it/</guid>
		<description><![CDATA[If you’re interested in seeing the next Service Pack for SQL Server 2008 released, vote for it at this Microsoft Connect page!&#160; Now that the release date for R2 has been announced, hopefully the next one is for SQL 2008 Service Pack 2.
If you’re still on 2005 and thus more interested in an SP4 for [...]]]></description>
			<content:encoded><![CDATA[<p>If you’re interested in seeing the next Service Pack for SQL Server 2008 released, <a title="Microsoft Connect: SQL Server 2008 Service Pack 2" href="https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=522123">vote for it at this Microsoft Connect page</a>!&#160; Now that the release date for R2 has been announced, hopefully the next one is for SQL 2008 Service Pack 2.</p>
<p>If you’re still on 2005 and thus more interested in an SP4 for that version, <a title="Microsoft Connect: Service Pack 4 for SQL Server 2005" href="https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=522122">it has also been posted at Connect</a>.</p>
<p>How did I find out?&#160; Through the following blog posts at SSQA.NET:</p>
<p><a title="SQL Server 2008 SP2" href="http://sqlserver-qa.net/blogs/sql2008/archive/2010/01/14/6210.aspx">SQL Server 2008 SP2</a></p>
<p><a title="SQL Server 2005 SP4" href="http://sqlserver-qa.net/blogs/sql2008/archive/2010/01/14/6211.aspx">SQL Server 2005 SP4</a></p>
<p><strong>Update (27 Feb 2010):</strong></p>
<p>SQL Server 2008 SP2 is scheduled for Q3 2010.</p>
<p>SQL Server 2005 SP4 is scheduled for Q4 2010.</p>
<p><a title="SQL Server Servicing plans" href="http://blogs.msdn.com/sqlreleaseservices/archive/2010/02/12/sql-server-servicing-plans.aspx" target="_blank">See this post on the Microsoft SQL Server Release Services blog</a> for details.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/01/20/sql-server-2008-sp2-want-it-vote-for-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free Event: SQL Server Day 2009</title>
		<link>http://blog.hoegaerden.be/2009/10/14/free-event-sql-server-day-2009/</link>
		<comments>http://blog.hoegaerden.be/2009/10/14/free-event-sql-server-day-2009/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 22:02:09 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Community Event]]></category>
		<category><![CDATA[SQLUG]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2009/10/14/free-event-sql-server-day-2009/</guid>
		<description><![CDATA[
For the second year in a row, the Belgian SQL Server User Group organizes the SQL Server Day.
Like last year, the event will take place at Utopolis Mechelen.
If you’re ready for a day filled with learning and networking opportunities and you can make yourself available at December 3, register at www.sqlserverday.be!
There will be some interesting [...]]]></description>
			<content:encoded><![CDATA[<p><a title="SQL Server Day 2009" href="http://sqlserverday.be/" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" src="http://blog.hoegaerden.be/wp-content/uploads/image77.png" border="0" alt="image" width="540" height="128" /></a></p>
<p>For the second year in a row, the <a title="Belgian SQL Server User Group" href="http://www.sqlug.be/" target="_blank">Belgian SQL Server User Group</a> organizes the SQL Server Day.</p>
<p>Like last year, the event will take place at <a title="http://www.utopolis.be" href="http://www.utopolis.be/" target="_blank">Utopolis Mechelen</a>.</p>
<p>If you’re ready for a day filled with learning and networking opportunities and you can make yourself available at December 3, register at <a title="SQL Server Day site" href="http://www.sqlserverday.be" target="_blank">www.sqlserverday.be</a>!</p>
<p>There will be some interesting speakers such as:</p>
<ul>
<li><a title="Chris Webb's blog" href="http://cwebbbi.spaces.live.com/" target="_blank">Chris Webb</a> – SSAS and Gemini</li>
<li>Henk van der Valk – SSIS world record</li>
<li>Dirk Gubbels – Change tracking</li>
<li>my colleagues Luc Lemaire and Mario Van Hissenhoven – Report Builder 3.0</li>
</ul>
<p><strong>If you&#8217;re attending as well and would like to meet up for a chat, don&#8217;t hesitate to post a comment here!</strong></p>
<p>See you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2009/10/14/free-event-sql-server-day-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fun With Strings</title>
		<link>http://blog.hoegaerden.be/2009/10/04/fun-with-strings/</link>
		<comments>http://blog.hoegaerden.be/2009/10/04/fun-with-strings/#comments</comments>
		<pubDate>Sun, 04 Oct 2009 11:07:48 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[collation]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Integration Services]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2009/10/04/fun-with-strings/</guid>
		<description><![CDATA[Initially I was going to call this article &#8220;Struggling With Collation: The SeQueL&#8221;, but it just doesn&#8217;t have the same ring to it as &#8220;Fun With Strings&#8221;.  In that previous article I showed how you might get different results when loading data from a temporary table or table variable and I suggested that one way [...]]]></description>
			<content:encoded><![CDATA[<p>Initially I was going to call this article &#8220;<a title="Struggling With Collation" href="http://blog.hoegaerden.be/2009/09/20/struggling-with-collation/" target="_blank">Struggling With Collation</a>: The SeQueL&#8221;, but it just doesn&#8217;t have the same ring to it as &#8220;Fun With Strings&#8221;.  In that previous article I showed how you might get different results when loading data from a temporary table or table variable and I suggested that one way of solving this is by switching your data type to nvarchar.</p>
<h2>Unicode Or Not?</h2>
<h3>Reason #1 For Not</h3>
<p>Today I&#8217;m going to show you that nvarchar is not always what we want to use, especially if we don&#8217;t need to support Unicode strings.  Imagine a staging scenario when loading a data warehouse.  Often the Business Keys (BK) are strings, and depending on the source system, sometimes very long strings &#8211; I&#8217;ve seen situations with a combined business key of over 500 bytes!  (You can’t imagine what some data sources look like but that’s another story.)  Do we really want to convert these to Unicode, and thus double their size?  Furthermore, to improve lookups we put indexes on those BKs.  These indexes would double in size as well.  So no, we don&#8217;t really want to make these fields Unicode, and certainly not when we want our ETLs to perform as fast as possible.</p>
<h3>Reason #2 For Not</h3>
<p>That was reason number one why nvarchar is not always the solution.  And here comes reason number two.  In my scenario, the source tables are located in an Oracle database.  And guess what: by default Oracle&#8217;s ORDER BY behaves different than SQL Server&#8217;s ORDER BY (when using the regular Latin1_General_CI_AS or SQL_Latin1_General_CP1_CI_AS collations)!  By default Oracle uses binary string comparison to sort its data and the reason for it appears to be that that&#8217;s the only way to prevent a full table scan.  I&#8217;m no Oracle expert but that&#8217;s <a title="NLS_SORT specifies the collating sequence for ORDER BY queries." href="http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/initparams130.htm" target="_blank">what the documentation states</a>.</p>
<p>Here’s a little demonstration.  The following script prepares a table variable and selects the data from it, sorted ascending.</p>
<div class="code"><span style="color: #0000ff;">declare</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">table</span><span style="color: #000000;">(</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">varchar</span><span style="color: #000000;">(</span><span style="color: #800000;">20</span><span style="color: #000000;">))</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;AA&#8217;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;A&#8217;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;A-&#8217;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;A A&#8217;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;BA&#8217;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;0&#8242;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;1&#8242;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;-0&#8242;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;-1&#8242;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;A0&#8242;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;0A&#8217;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;-A&#8217;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;-B&#8217;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;a&#8217;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;b&#8217;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">insert</span><span style="color: #808080;"> </span><span style="color: #0000ff;">into</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216; &#8216;</span><span style="color: #0000ff;">;</span><span style="color: #808080;"> </span></p>
<p><span style="color: #808080;"> </span><span style="color: #0000ff;">select</span><span style="color: #808080;"> </span><span style="color: #000000;">*</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">order</span><span style="color: #808080;"> </span><span style="color: #0000ff;">by</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">asc;</span></div>
<p>I have executed it once just as stated above (while connected to a database that uses the SQL_Latin1_General_CP1_CI_AS collation) and once more while using nvarchar as data type for the column in the table variable.  The first execution will sort the data using a non-Unicode sorting algorithm, while the second execution will order the data according to the Unicode sorting method.  The results will be shown further below for easier comparison.</p>
<p>On Oracle I performed a similar procedure, as shown in following script.</p>
<div class="code"><span style="color: #0000ff;">select</span><span style="color: #808080;"> </span><span style="color: #000000;">cast(</span><span style="color: #808080;">&#8216;AA&#8217; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #0000ff;">varchar</span><span style="color: #000000;">(</span><span style="color: #800000;">20</span><span style="color: #000000;">))</span><span style="color: #808080;"> </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;A&#8217; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;A-&#8217; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;A A&#8217; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;BA&#8217; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;0&#8242; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;1&#8242; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;-0&#8242; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;-1&#8242; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;A0&#8242; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;0A&#8217; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;-A&#8217; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;-B&#8217; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;a&#8217; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216;b&#8217; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"> </span><span style="color: #0000ff;">union</span></div>
<div class="code"><span style="color: #0000ff;">select</span><span style="color: #808080;"> &#8216; &#8216; </span><span style="color: #0000ff;">as</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">Dual</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">order</span><span style="color: #808080;"> </span><span style="color: #0000ff;">by</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">asc;</span></div>
<p>The Oracle script doesn’t use a table variable, it just creates a result set using several select statements with a union in between.  But for our test that doesn’t matter, the results using this method are suitable.</p>
<p>In the table below you can see the result of the three executions.</p>
<table style="width: 272pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" width="362">
<colgroup>
<col style="width: 90pt;" width="120"></col>
<col style="width: 68pt;" width="90"></col>
<col style="width: 67pt;" width="89"></col>
<col style="width: 47pt;" width="63"></col>
</colgroup>
<tbody>
<tr style="height: 15pt;" height="20">
<td class="xl65" style="background: #4f81bd none repeat scroll 0% 0%; width: 90pt; font-family: calibri; height: 15pt; color: white; font-size: 11pt; font-weight: 700; text-decoration: none; border: medium 0.5pt 1.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" width="120" height="20">SQL non-Unicode</td>
<td class="xl65" style="background: #4f81bd none repeat scroll 0% 0%; width: 68pt; font-family: calibri; color: white; font-size: 11pt; font-weight: 700; text-decoration: none; border: medium 0.5pt 1.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" width="90">SQL Unicode</td>
<td class="xl65" style="background: #4f81bd none repeat scroll 0% 0%; width: 67pt; font-family: calibri; color: white; font-size: 11pt; font-weight: 700; text-decoration: none; border: medium 0.5pt 1.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" width="89">Oracle Binary</td>
<td style="background: #4f81bd none repeat scroll 0% 0%; width: 47pt; font-family: calibri; color: white; font-size: 11pt; font-weight: 700; text-decoration: none; border: medium medium 1.5pt none none solid -moz-use-text-color -moz-use-text-color white;" width="63"><span style="mso-spacerun: yes"> </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20"><span style="mso-spacerun: yes"> </span></td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none"><span style="mso-spacerun: yes"> </span></td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none"><span style="mso-spacerun: yes"> </span></td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">&lt; space</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">-0</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">0</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">-0</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">-1</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">-0</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">-1</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">-A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">0A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">-A</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">-B</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">1</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">-B</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">0</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">-1</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">0</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">0A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">0A</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">1</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">a</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">1</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">-A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">A</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">a</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">A-</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">A A</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">A A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">A A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">A-</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">A-</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">A0</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">A0</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">A0</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">AA</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">AA</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">AA</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">b</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">BA</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" height="20">b</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">-B</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">a</td>
<td style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none"></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl67" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt medium medium none solid none none -moz-use-text-color white -moz-use-text-color -moz-use-text-color;" height="20">BA</td>
<td class="xl66" style="border-bottom: medium none; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">BA</td>
<td class="xl66" style="border-bottom: medium none; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">b</td>
<td style="font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none"></td>
</tr>
</tbody>
</table>
<p>As you can see, they only agree on one thing: space really is the smallest character in my test set!  And that’s not what I want, I want all the data to be sorted consistently, no matter what the source is.</p>
<h2>But Why Sorted?</h2>
<p>You may wonder why I need to sort the data.  Well, some components in Integration Services expect the incoming data flows to be ordered.  One of the standard components that requires this is the <a title="BOL 2008 - Merge Transformation" href="http://msdn.microsoft.com/en-us/library/ms141703.aspx" target="_blank">Merge Transformation</a>.  Another (custom!) component is <a title="TableDifference - a custom SSIS component" href="http://www.sqlbi.eu/Projects/TableDifference/tabid/74/language/en-US/Default.aspx" target="_blank">Table Difference</a>.  I could of course add a Sort Transformation to my Data Flow, but that would not be interesting for performance.  I want the data to come from the database server in the expected order.  So now I&#8217;ll show you how you can do that.</p>
<h2>Taking Control!</h2>
<h3>SQL Server: ORDER BY … COLLATE …</h3>
<p>On SQL Server this was fairly easy.  The <a title="BOL 2008 - ORDER BY Clause (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms188385.aspx" target="_blank">ORDER BY clause</a> has a COLLATE part where you can specify what collation should be used to order the data.  Because Oracle sorts its data using a binary algorithm, I’ll tell SQL Server to do that as well.  More precisely I’ll tell SQL Server to use the Latin1_General_BIN collation.  The updated SELECT statement from the T-SQL script above looks like this:</p>
<div class="code"><span style="color: #0000ff;">select</span><span style="color: #808080;"> </span><span style="color: #000000;">*</span><span style="color: #808080;"> </span><span style="color: #0000ff;">from</span><span style="color: #808080;"> </span><span style="color: #000000;">@tbl</span><span style="color: #808080;"><br />
</span><span style="color: #0000ff;">order</span><span style="color: #808080;"> </span><span style="color: #0000ff;">by</span><span style="color: #808080;"> </span><span style="color: #000000;">col1</span><span style="color: #808080;"> </span><span style="color: #0000ff;">collate</span><span style="color: #808080;"> </span><span style="color: #000000;">Latin1_General_BIN</span><span style="color: #808080;"> </span><span style="color: #0000ff;">asc;</span></div>
<h3>Oracle: ORDER BY NLSSORT()</h3>
<p>To ensure that results from Oracle are always returned using the same sorting algorithm, I will also tell the Oracle server to sort it’s data using the binary algorithm.</p>
<p>The first way I came up with was to change the <a title="NLS_SORT" href="http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/initparams130.htm" target="_blank">NLS_SORT</a> setting on the session.  That can be done by executing the following command before the SELECT statement:</p>
<div class="code"><span style="color: #0000ff;">ALTER</span><span style="color: #808080;"> </span><span style="color: #000000;">SESSION</span><span style="color: #808080;"> </span><span style="color: #0000ff;">SET</span><span style="color: #808080;"> </span><span style="color: #000000;">NLS_SORT</span><span style="color: #0000ff;">=BINARY;</span></div>
<p>This method is fine when you’re running the queries manually from a client such as Oracle SQL Developer.  However, in SSIS the OLE DB Source component will not accept anything else besides the SELECT statement.</p>
<p>Then I found another way.  There’s a function called <a title="NLSSORT function" href="http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions099.htm" target="_blank">NLSSORT()</a> which you can apply to a column in the ORDER BY clause.  The following statement demonstrates how to use this function.  (I only show the ORDER BY clause as it can be applied to the Oracle script mentioned earlier.)</p>
<div class="code"><span style="color: #0000ff;">ORDER</span><span style="color: #808080;"> </span><span style="color: #0000ff;">BY</span><span style="color: #808080;"> </span><span style="color: #000000;">NLSSORT(col1,</span><span style="color: #808080;"> &#8216;NLS_SORT=BINARY&#8217;</span><span style="color: #000000;">)</span></div>
<p>The following table shows the results from both binary sort queries:</p>
<table style="width: 135pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" width="179">
<colgroup>
<col style="width: 68pt;" width="90"></col>
<col style="width: 67pt;" width="89"></col>
</colgroup>
<tbody>
<tr style="height: 15pt;" height="20">
<td class="xl65" style="background: #4f81bd none repeat scroll 0% 0%; width: 68pt; font-family: calibri; height: 15pt; color: white; font-size: 11pt; font-weight: 700; text-decoration: none; border: medium 0.5pt 1.5pt none solid solid -moz-use-text-color white white;" width="90" height="20">SQL Binary</td>
<td class="xl65" style="background: #4f81bd none repeat scroll 0% 0%; width: 67pt; font-family: calibri; color: white; font-size: 11pt; font-weight: 700; text-decoration: none; border: medium 0.5pt 1.5pt medium none solid solid none -moz-use-text-color white white -moz-use-text-color;" width="89">Oracle Binary</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20"><span style="mso-spacerun: yes"> </span></td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none"><span style="mso-spacerun: yes"> </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">-0</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">-0</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">-1</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">-1</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">-A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">-A</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">-B</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">-B</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">0</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">0</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">0A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">0A</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">1</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">1</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">A</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">A A</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">A A</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">A-</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">A-</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">A0</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">A0</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">AA</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">AA</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">BA</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">BA</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #b8cce4 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt 0.5pt none solid solid -moz-use-text-color white white;" height="20">a</td>
<td class="xl66" style="border-bottom: white 0.5pt solid; border-left: medium none; font-family: calibri; background: #b8cce4; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #b8cce4 none">a</td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl66" style="background: #dbe5f1 none repeat scroll 0% 0%; font-family: calibri; height: 15pt; color: black; font-size: 11pt; font-weight: 400; text-decoration: none; border: medium 0.5pt none solid -moz-use-text-color white;" height="20">b</td>
<td class="xl66" style="border-bottom: medium none; border-left: medium none; font-family: calibri; background: #dbe5f1; color: black; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: white 0.5pt solid; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #dbe5f1 none">b</td>
</tr>
</tbody>
</table>
<p>Finally I am able to get data from both Oracle and SQL Server using a consistent sort order.</p>
<h3>But, How Big Is NULL?</h3>
<p>However, even on this straightforward request, both database servers do not fully agree!  Here’s what they have to say about the topic:</p>
<p><a title="BOL 2008 - Null Values" href="http://msdn.microsoft.com/en-us/library/ms191504.aspx" target="_blank">“NULL</a> is the smallest.”</p>
<p>“No, it’s the largest.”</p>
<p>“No, smallest!”</p>
<p>“Largest!!”</p>
<p>“Smallest.”</p>
<p>“Largest I tell you!!!”</p>
<p>“Bladiebla, not hearing you, anyway, it’s NOTHING!”</p>
<p>“No, it isn’t!”</p>
<p><em>*discussion goes on and on*</em></p>
<p>If I add NULL to my test data set, SQL Server will sort it first (thus NULL is the smallest value in my test set), while Oracle will put it last.  In my situation it wasn’t really an issue (the BKs are not supposed to be NULL), but it’s quite important to remember in cases where NULLs are actually possible.</p>
<h2>Conclusion</h2>
<p>When working with strings, always keep collation in mind.  And even more so when dealing with several different source systems!</p>
<p><strong>Additional reference material:</strong></p>
<p><a title="The Globalization of Language in Oracle - The NLS_COMP and NLS_SORT variables" href="http://www.databasejournal.com/features/oracle/article.php/3488751/The-Globalization-of-Language-in-Oracle---The-NLSCOMP-and-NLSSORT-variables.htm" target="_blank">Database Journal: The Globalization of Language in Oracle &#8211; The NLS_COMP and NLS_SORT variables</a></p>
<p><a title="How to: Sort Data for the Merge and Merge Join Transformations" href="http://msdn.microsoft.com/en-us/library/ms137653.aspx" target="_blank">BOL 2008: How to: Sort Data for the Merge and Merge Join Transformations</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2009/10/04/fun-with-strings/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Struggling With Collation</title>
		<link>http://blog.hoegaerden.be/2009/09/20/struggling-with-collation/</link>
		<comments>http://blog.hoegaerden.be/2009/09/20/struggling-with-collation/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 09:46:51 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[collation]]></category>
		<category><![CDATA[data]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2009/09/20/struggling-with-collation/</guid>
		<description><![CDATA[Recently I was investigating an issue related to ordering data.&#160; As a test, I ran the following script:

&#8211; Sorting data from a temporary table&#160; declare&#160;@tbl&#160;table&#160;(&#160;ProductNumber&#160;varchar(25)&#160;);&#160; insert&#160;into&#160;@tbl&#160;select &#8216;BBBB&#8217;;&#160; insert&#160;into&#160;@tbl&#160;select &#8216;AAAA&#8217;;&#160; insert&#160;into&#160;@tbl&#160;select &#8216;A-B&#8217;;&#160; insert&#160;into&#160;@tbl&#160;select &#8216;A123&#8242;;&#160; select&#160;*&#160;from&#160;@tbl&#160;order&#160;by&#160;ProductNumber&#160;asc;      
&#8211; Sorting data from a table variable&#160; create&#160;table&#160;#tbl&#160;(&#160;ProductNumber&#160;varchar(25)&#160;);&#160; insert&#160;into&#160;#tbl&#160;select &#8216;BBBB&#8217;;&#160; insert&#160;into&#160;#tbl&#160;select &#8216;AAAA&#8217;;&#160; insert&#160;into&#160;#tbl&#160;select &#8216;A-B&#8217;;&#160; insert&#160;into&#160;#tbl&#160;select &#8216;A123&#8242;;&#160; [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I was investigating an <strong>issue related to ordering data</strong>.&#160; As a test, I ran the following script:</p>
<p><span style="color: #0000ff"></span></p>
<div class="code"><font color="#006400">&#8211; Sorting data from a temporary table&#160; <br /></font><font color="#0000ff">declare</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">table</font><font color="#808080">&#160;</font><font color="#000000">(</font><font color="#808080">&#160;</font><font color="#000000">ProductNumber</font><font color="#808080">&#160;</font><font color="#0000ff">varchar</font><font color="#000000">(</font><font color="#800000">25</font><font color="#000000">)</font><font color="#808080">&#160;</font><font color="#000000">)</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;BBBB&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;AAAA&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;A-B&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;A123&#8242;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">select</font><font color="#808080">&#160;</font><font color="#000000">*</font><font color="#808080">&#160;</font><font color="#0000ff">from</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">order</font><font color="#808080">&#160;</font><font color="#0000ff">by</font><font color="#808080">&#160;</font><font color="#000000">ProductNumber</font><font color="#808080">&#160;</font><font color="#0000ff">asc;</font><font color="#808080">      </p>
<p></font><font color="#006400">&#8211; Sorting data from a table variable&#160; <br /></font><font color="#0000ff">create</font><font color="#808080">&#160;</font><font color="#0000ff">table</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#000000">(</font><font color="#808080">&#160;</font><font color="#000000">ProductNumber</font><font color="#808080">&#160;</font><font color="#0000ff">varchar</font><font color="#000000">(</font><font color="#800000">25</font><font color="#000000">)</font><font color="#808080">&#160;</font><font color="#000000">)</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;BBBB&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;AAAA&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;A-B&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;A123&#8242;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">select</font><font color="#808080">&#160;</font><font color="#000000">*</font><font color="#808080">&#160;</font><font color="#0000ff">from</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#0000ff">order</font><font color="#808080">&#160;</font><font color="#0000ff">by</font><font color="#808080">&#160;</font><font color="#000000">ProductNumber</font><font color="#808080">&#160;</font><font color="#0000ff">asc;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">drop</font><font color="#808080">&#160;</font><font color="#0000ff">table</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#0000ff">;</font> </div>
<p>&#160;</p>
<p>And it gave me this result:</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Results from script" border="0" alt="Results from script" src="http://blog.hoegaerden.be/wp-content/uploads/image72.png" width="133" height="235" /></p>
<p>As you can see, the order of the data coming from a <strong>temporary table</strong> is different than the data from a <strong>table variable</strong>, even though the same data type is used.&#160; At first I thought, how on earth is this possible?&#160; After spending some time pondering about this problem (and after a colleague reported that when he executed the above script, the result was as expected), it came to me.&#160; Don’t tell me it’s a <a title="BOL 2008 - Working with Collations" href="http://msdn.microsoft.com/en-us/library/ms187582.aspx" target="_blank">collation</a> problem?!&#160; Well, it is.&#160; (In case you don’t know collation, in short “Collations specify the rules for how strings of character data are sorted and compared”.&#160; More info through that previous link and <a title="BOL 2000 - SQL Server Collation Fundamentals" href="http://msdn.microsoft.com/en-us/library/aa174903%28SQL.80%29.aspx" target="_blank">here</a>.)</p>
<p>When I executed the script, my Management Studio session was connected to AdventureWorks2008, one of my test databases.&#160; When I switched to <a title="BOL 2008 - tempdb Database" href="http://msdn.microsoft.com/en-us/library/ms190768.aspx" target="_blank">tempdb</a>, the result was normal – both queries returned the same result.&#160; Then I had a look at the collations.&#160; My tempdb is using Latin1_General_CI_AS while the AdventureWorks2008 database is apparently using SQL_Latin1_General_CP1_CI_AS.</p>
<p>A <a title="BOL 2008 - Special Table Types" href="http://msdn.microsoft.com/en-us/library/ms186986.aspx" target="_blank">temporary table</a> is created in the tempdb and thus uses the collation of the tempdb for its string columns.&#160; And a <a title="BOL 2008 - DECLARE @local_variable (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms188927.aspx" target="_blank">table variable</a> uses the same collation as the database to which the session is connected.&#160; Which is quite logical because otherwise you would get collation conflicts when using the table variable in combination with a table from the active database in the same query.&#160; I will demonstrate that with the following script:</p>
<div class="code"><span style="color: #0000ff">declare</span><span style="color: #808080"> </span><span style="color: #000000">@tbl</span><span style="color: #808080"> </span><span style="color: #0000ff">table</span><span style="color: #808080"> </span><span style="color: #000000">(</span><span style="color: #808080"> </span><span style="color: #000000">ProductNumber</span><span style="color: #808080"> </span><span style="color: #0000ff">varchar</span><span style="color: #000000">(</span><span style="color: #800000">25</span><span style="color: #000000">)</span><span style="color: #808080"> </span><span style="color: #000000">)</span><span style="color: #0000ff">;</span><span style="color: #808080">      <br /></span><span style="color: #0000ff">insert</span><span style="color: #808080"> </span><span style="color: #0000ff">into</span><span style="color: #808080"> </span><span style="color: #000000">@tbl</span><span style="color: #808080"> </span><span style="color: #0000ff">select</span><span style="color: #808080"> &#8216;BBBB&#8217;</span><span style="color: #0000ff">;</span><span style="color: #808080">      <br /></span><span style="color: #0000ff">select</span><span style="color: #808080"> </span><span style="color: #000000">*</span><span style="color: #808080"> </span><span style="color: #0000ff">from</span><span style="color: #808080"> </span><span style="color: #000000">AdventureWorks.Production.Product</span><span style="color: #808080"> </span><span style="color: #000000">P</span><span style="color: #808080">      <br /></span><span style="color: #0000ff">where</span><span style="color: #808080"> </span><span style="color: #000000">P.ProductNumber</span><span style="color: #808080"> </span><span style="color: #0000ff">in</span><span style="color: #808080"> </span><span style="color: #000000">(</span><span style="color: #0000ff">select</span><span style="color: #808080"> </span><span style="color: #000000">ProductNumber</span><span style="color: #808080"> </span><span style="color: #0000ff">from</span><span style="color: #808080"> </span><span style="color: #000000">@tbl)</span><span style="color: #0000ff">;</span></div>
<p>&#160;</p>
<p>On my (SQL Server 2008) server I also have the old SQL2005 AdventureWorks database up and running, which is using the Latin1_General_CI_AS collation.&#160; Executing the above script (which references that AdventureWorks DB) while being connected to AdventureWorks2008 (or any other DB that uses a different collation from Latin1_General_CI_AS) results in the following error:</p>
<blockquote><p><span style="color: #ff0000">Msg 468, Level 16, State 9, Line 3        <br />Cannot resolve the collation conflict between &quot;SQL_Latin1_General_CP1_CI_AS&quot; and &quot;Latin1_General_CI_AS&quot; in the equal to operation.</span></p>
</blockquote>
<p>Changing the active database to any other DB that uses the Latin1_General_CI_AS collation and then executing the query results in a positive execution.</p>
<p>Now, to get back to the initial issue of sorting inconsistency, even though the collations are not exactly the same, they are both Latin1, Case Insensitive, Accent Sensitive and still they don’t sort the data in the same way??&#160; For an explanation on that I found the following page on the Microsoft Support site: <a title="Comparing SQL collations to Windows collations" href="http://support.microsoft.com/kb/322112" target="_blank">Comparing SQL collations to Windows collations</a>.&#160; In short: a Windows collation (such as Latin1_General_CI_AS) uses a different comparison algorithm than a SQL collation (SQL_Latin1_General_CP1_CI_AS).&#160; A Windows collation uses the same algorithm as for Unicode data, even when the data is non-Unicode.</p>
<p>All that means is that in our test example, in order to get the data in the right order all the time, we could switch to Unicode fields:</p>
<p class="code"><span style="color: #0000ff"></span></p>
<div class="code"><font color="#006400">&#8211; Sorting data from a temporary table&#160; <br /></font><font color="#0000ff">declare</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">table</font><font color="#808080">&#160;</font><font color="#000000">(</font><font color="#808080">&#160;</font><font color="#000000">ProductNumber</font><font color="#808080">&#160;</font><font color="#0000ff">nvarchar</font><font color="#000000">(</font><font color="#800000">25</font><font color="#000000">)</font><font color="#808080">&#160;</font><font color="#000000">)</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;BBBB&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;AAAA&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;A-B&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;A123&#8242;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">select</font><font color="#808080">&#160;</font><font color="#000000">*</font><font color="#808080">&#160;</font><font color="#0000ff">from</font><font color="#808080">&#160;</font><font color="#000000">@tbl</font><font color="#808080">&#160;</font><font color="#0000ff">order</font><font color="#808080">&#160;</font><font color="#0000ff">by</font><font color="#808080">&#160;</font><font color="#000000">ProductNumber</font><font color="#808080">&#160;</font><font color="#0000ff">asc;</font><font color="#808080">     </p>
<p></font><font color="#006400">&#8211; Sorting data from a table variable&#160; <br /></font><font color="#0000ff">create</font><font color="#808080">&#160;</font><font color="#0000ff">table</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#000000">(</font><font color="#808080">&#160;</font><font color="#000000">ProductNumber</font><font color="#808080">&#160;</font><font color="#0000ff">nvarchar</font><font color="#000000">(</font><font color="#800000">25</font><font color="#000000">)</font><font color="#808080">&#160;</font><font color="#000000">)</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;BBBB&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;AAAA&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;A-B&#8217;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">insert</font><font color="#808080">&#160;</font><font color="#0000ff">into</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#0000ff">select</font><font color="#808080"> &#8216;A123&#8242;</font><font color="#0000ff">;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">select</font><font color="#808080">&#160;</font><font color="#000000">*</font><font color="#808080">&#160;</font><font color="#0000ff">from</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#808080">&#160;</font><font color="#0000ff">order</font><font color="#808080">&#160;</font><font color="#0000ff">by</font><font color="#808080">&#160;</font><font color="#000000">ProductNumber</font><font color="#808080">&#160;</font><font color="#0000ff">asc;</font><font color="#808080">&#160; <br /></font><font color="#0000ff">drop</font><font color="#808080">&#160;</font><font color="#0000ff">table</font><font color="#808080">&#160;</font><font color="#0000ff">#</font><font color="#000000">tbl</font><font color="#0000ff">;</font> </div>
<p>&#160;</p>
<p>Executing that returns the following result, no matter what the active database is:</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Script result when using Unicode fields" border="0" alt="Script result when using Unicode fields" src="http://blog.hoegaerden.be/wp-content/uploads/image73.png" width="135" height="231" /></p>
<p>And it also means that you need to be careful when retrieving data from different sources (which is how I came across the issue in the first place).&#160; If you need to have your data sorted in a particular, consistent way and you’re doing that by using an ORDER BY in a SELECT statement on the source system, double-check if all sources are using the same collation!</p>
<p>In case the above left you wondering about <strong>what collation to use</strong>: the SQL collations are there for backward compatibility.&#160; For new developments use the Windows collations!</p>
<p>&#160;</p>
<p>See my <a title="Fun With Strings" href="http://blog.hoegaerden.be/2009/10/04/fun-with-strings/" target="_blank">Fun With Strings</a> article for another story related to collation.</p>
<p>&#160;</p>
<p><strong>Additional reference material:</strong></p>
<p><a title="Comparing Table Variables with Temporary Tables" href="http://www.sqlservercentral.com/articles/Temporary+Tables/66720/" target="_blank">SQL Server Central &#8211; Comparing Table Variables with Temporary Tables</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2009/09/20/struggling-with-collation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free Event: 24 Hours of PASS</title>
		<link>http://blog.hoegaerden.be/2009/08/20/free-event-24-hours-of-pass/</link>
		<comments>http://blog.hoegaerden.be/2009/08/20/free-event-24-hours-of-pass/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 20:13:25 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Community Event]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[PASS]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2009/08/20/free-event-24-hours-of-pass/</guid>
		<description><![CDATA[If you don&#8217;t have anything planned on next September 2 and you&#8217;re interested in some free SQL Server-related learning: it&#8217;s the 24 Hours of PASS!

You can even stay in your lazy chair at home because it&#8217;s an online event, no worrying about bus/train/plane/hotel/&#8230;  Just install the software (or browser plug-in, I actually don’t know because [...]]]></description>
			<content:encoded><![CDATA[<p>If you don&#8217;t have anything planned on next September 2 and you&#8217;re interested in some free SQL Server-related learning: it&#8217;s the <a title="September 2, 2009: 24 Hours of PASS" href="http://24hours.sqlpass.org/" target="_blank">24 Hours of PASS</a>!</p>
<p><a href="http://24hours.sqlpass.org/" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" src="http://blog.hoegaerden.be/wp-content/uploads/image66.png" border="0" alt="image" width="505" height="95" /></a></p>
<p>You can even stay in your lazy chair at home because it&#8217;s an online event, no worrying about bus/train/plane/hotel/&#8230;  Just install the software (or browser plug-in, I actually don’t know because I haven’t performed the preparation procedure yet) and off you go.</p>
<p>I have registered for the following 5 sessions myself:</p>
<ul>
<li>Session 10 (Dev) &#8211; Working with Spatial Data in SQL Server 2008 (Greg Low)</li>
<li>Session 11 (DBA) &#8211; Effective Indexing (Gail Shaw)</li>
<li>Session 12 (BI) &#8211; Reporting Services Inside Out the Things You Should Know (Simon Sabin)</li>
<li>Session 13 (Dev) &#8211; Query Performance Tuning 101 (Grant Fritchey)</li>
<li>Session 16 (DBA) &#8211; Database Compatibility Settings: What They Really Do .. and Don’t Do (Don Vilen)</li>
</ul>
<p>Yep, it will be a busy holiday.  That same day they’ll be delivering <a title="Whirlpool AMW 528 IX Combi Oven" href="http://www.whirlpool.be/app.cnt/whr/nl_BE/pageid/pgproddtl001/catid/1/subcatid/5/prodid/29055" target="_blank">our new combi oven</a>, ideally that would be right after session 13 ends.  Fingers crossed.</p>
<p>Anyway, I’ll be seeing you September 2?  Or well, maybe not as it’s an online event…</p>
<p>Happy learning!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2009/08/20/free-event-24-hours-of-pass/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SSRS and MDX: Detecting Missing Fields</title>
		<link>http://blog.hoegaerden.be/2009/07/06/ssrs-and-mdx-detecting-missing-fields/</link>
		<comments>http://blog.hoegaerden.be/2009/07/06/ssrs-and-mdx-detecting-missing-fields/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 18:15:34 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Reporting Services]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[MDX]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SSAS]]></category>
		<category><![CDATA[SSRS]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2009/07/06/ssrs-and-mdx-detecting-missing-fields/</guid>
		<description><![CDATA[For this example I’ll be using the Adventure Works cube running on SQL Server Analysis Services 2008 and Reporting Services 2008.
In case you don’t have the AdventureWorks databases and cubes yet, they’re available at CodePlex.
Scenario
The sales department has asked for a report that displays the number of product items sold during a selected period.&#160; As [...]]]></description>
			<content:encoded><![CDATA[<p>For this example I’ll be using the Adventure Works cube running on SQL Server Analysis Services 2008 and Reporting Services 2008.</p>
<p>In case you don’t have the AdventureWorks databases and cubes yet, they’re available at <a title="SQL Server 2008 sample databases at CodePlex" href="http://msftdbprodsamples.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=18407" target="_blank">CodePlex</a>.</p>
<h2>Scenario</h2>
<p>The sales department has asked for a report that displays the number of product items sold during a selected period.&#160; As the company is active in two different markets, both the internet and reseller numbers should be shown.&#160; The figures need to be grouped by product category, with drilldown to product level through subcategory.</p>
<p>Besides the period filter, it should be possible to filter on product category to limit the number of items shown.</p>
<p>Also, the background of the numeric cells should get a color depending on the value in the cell.&#160; Colors range from red for low sales figures to green for high sale volumes.&#160; The ranges are variable and should thus be configurable using 3 threshold parameters.&#160; Following table shows the ranges as the department has requested them:</p>
<table style="width: 286pt; border-collapse: collapse" border="0" cellspacing="0" cellpadding="0" width="380">
<colgroup>
<col style="width: 188pt; mso-width-source: userset; mso-width-alt: 9142" width="250" />
<col style="width: 98pt; mso-width-source: userset; mso-width-alt: 4754" width="130" /></colgroup>
<tbody>
<tr style="height: 15pt" height="20">
<td style="border-bottom: white 1pt solid; border-left: medium none; width: 188pt; font-family: calibri; background: black; height: 15pt; color: white; font-size: 11pt; border-top: medium none; font-weight: 700; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: black none" height="20" width="250">Value X</td>
<td style="border-bottom: white 1pt solid; border-left: medium none; width: 98pt; font-family: calibri; background: black; color: white; font-size: 11pt; border-top: medium none; font-weight: 700; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: black none" class="xl65" width="130">Background Color</td>
</tr>
<tr style="height: 15pt" height="20">
<td style="font-family: calibri; background: #376091; height: 15pt; color: white; font-size: 11pt; font-weight: 400; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #376091 none" height="20">X &lt; LowThreshold</td>
<td style="font-family: calibri; background: #376091; color: white; font-size: 11pt; font-weight: 400; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #376091 none" class="xl65">Red</td>
</tr>
<tr style="height: 15pt" height="20">
<td style="font-family: calibri; background: #4f81bd; height: 15pt; color: white; font-size: 11pt; font-weight: 400; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #4f81bd none" height="20">LowThreshold &lt;= MiddleThreshold</td>
<td style="font-family: calibri; background: #4f81bd; color: white; font-size: 11pt; font-weight: 400; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #4f81bd none" class="xl65">Orange</td>
</tr>
<tr style="height: 15pt" height="20">
<td style="border-bottom: medium none; border-left: medium none; font-family: calibri; background: #376091; height: 15pt; color: white; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #376091 none" height="20">MiddleThreshold &lt;= X &lt; HighThreshold</td>
<td style="border-bottom: medium none; border-left: medium none; font-family: calibri; background: #376091; color: white; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #376091 none" class="xl65">Yellow</td>
</tr>
<tr style="height: 15pt" height="20">
<td style="border-bottom: medium none; border-left: medium none; font-family: calibri; background: #4f81bd; height: 15pt; color: white; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #4f81bd none" height="20">HighThreshold &lt; X</td>
<td style="border-bottom: medium none; border-left: medium none; font-family: calibri; background: #4f81bd; color: white; font-size: 11pt; border-top: medium none; font-weight: 400; border-right: medium none; text-decoration: none; text-underline-style: none; text-line-through: none; mso-pattern: #4f81bd none" class="xl65">Green</td>
</tr>
</tbody>
</table>
<h2>&#160;</h2>
<h2>Selecting The Data</h2>
<p>At first sight this seems like a fairly simple report.&#160; So you start building your MDX query using the Query Designer:</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image26.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="MDX Query Designer" border="0" alt="MDX Query Designer" src="http://blog.hoegaerden.be/wp-content/uploads/image-thumb13.png" width="486" height="318" /></a></p>
<p>Two filters have been specified: one of them is a date range and the other is based on product category.</p>
<h2>Visualizing The Data</h2>
<p>Then you drag a <a title="BOL - Understanding the Tablix Data Region" href="http://msdn.microsoft.com/en-us/library/bb677552.aspx" target="_blank">tablix</a> onto the report body and play around with it until you get to the following:</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image27.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Tablix in design mode" border="0" alt="Tablix in design mode" src="http://blog.hoegaerden.be/wp-content/uploads/image-thumb14.png" width="489" height="61" /></a></p>
<p>This is what it looks like when rendered, all seems to work fine:</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image28.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Rendered report" border="0" alt="Rendered report" src="http://blog.hoegaerden.be/wp-content/uploads/image-thumb15.png" width="489" height="344" /></a></p>
<p>To get the textbox background coloured based on the thresholds, you’ve produced an expression.&#160; This expression is specified in Textbox Properties &gt; Fill &gt; Fill Color and looks like the following:</p>
<div>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">=Switch
(
    Fields!Internet_Order_Quantity.Value &lt; Parameters!LowThreshold.Value, <span style="color: #006080">&quot;#ff0e0e&quot;</span>,
    Fields!Internet_Order_Quantity.Value &gt;= Parameters!LowThreshold.Value
        <span style="color: #0000ff">and</span> Fields!Internet_Order_Quantity.Value &lt; Parameters!MiddleThreshold.Value, <span style="color: #006080">&quot;#ff922d&quot;</span>,
    Fields!Internet_Order_Quantity.Value &gt;= Parameters!MiddleThreshold.Value
        <span style="color: #0000ff">and</span> Fields!Internet_Order_Quantity.Value &lt; Parameters!HighThreshold.Value, <span style="color: #006080">&quot;#fff70f&quot;</span>,
    Fields!Internet_Order_Quantity.Value &gt;= Parameters!HighThreshold.Value, <span style="color: #006080">&quot;#5cff21&quot;</span>
)</pre>
</div>
<p>It’s a simple Switch statement using the threshold parameters.</p>
<h3>A Missing Field Issue</h3>
<p>So you deploy your report to the server for the users to test.&#160; All is quiet, until someone starts complaining that the colouring doesn’t always work, for instance when filtering on Components.&#160; Of course, you don’t always believe what the user says and try it out for yourself:</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image29.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Rendered report with missing field issue" border="0" alt="Rendered report with missing field issue" src="http://blog.hoegaerden.be/wp-content/uploads/image-thumb16.png" width="494" height="151" /></a></p>
<p>Indeed, the background is no longer coloured for the internet sales.&#160; On top of that, the BIDS shows a couple of warnings in its output window:</p>
<blockquote>
<p>[rsMissingFieldInDataSet] The dataset ‘ProductSales’ contains a definition for the Field ‘Internet_Sales_Amount’. This field is missing from the returned result set from the data source.</p>
<p>[rsErrorReadingDataSetField] The dataset ‘ProductSales’ contains a definition for the Field ‘Internet_Sales_Amount’. The data extension returned an error during reading the field. There is no data for the field at position 4.</p>
</blockquote>
<p>Hang on, but I am selecting the field in my dataset, how can it be missing?&#160; Except, this is MDX and OLAP, not SQL and OLTP.&#160; By default, the MDX Query Designer uses NON EMPTY in the SELECT statement.&#160; This means that the rows where there are no values for the selected measures will not be contained in the result set.&#160; It also means that the complete measure will be omitted in the case that there are no values for it in any of the rows, which is the reason for our problem.</p>
<p>You could choose to not use NON EMPTY in the query.&#160; To achieve this using the designer, right-click in the results pane and click the Include Empty Cells item.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="MDX Query Designer result pane popup menu" border="0" alt="MDX Query Designer result pane popup menu" src="http://blog.hoegaerden.be/wp-content/uploads/image30.png" width="233" height="176" /></p>
<p>Keep in mind that this will result in more rows in your result set because you’re now selecting all the empty measure cells as well.&#160; Depending on your report requirements this may not be the desired effect.&#160; On the other hand, it could be exactly what you want.&#160; If our sales department had asked that the report should always show all products, even when there are no sales for the period, then we’d need to query the cube in this way.</p>
<p>For the sake of the example (and to save some trees in case the sales department is going to print the report <img src='http://blog.hoegaerden.be/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ) we will not choose this option.</p>
<h4>Attempt to fix #1</h4>
<p>As the field does not always exist, you decide that it’s a good idea to test for its existence.&#160; A field in a resultset has an IsMissing property which serves that purpose.&#160; So you adapt your expression to the following:</p>
<div>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">=IIF(Fields!Internet_Order_Quantity.IsMissing, <span style="color: #0000ff">Nothing</span>,
    Switch
    (
        Fields!Internet_Order_Quantity.Value &lt; Parameters!LowThreshold.Value, <span style="color: #006080">&quot;#ff0e0e&quot;</span>,
        Fields!Internet_Order_Quantity.Value &gt;= Parameters!LowThreshold.Value
            <span style="color: #0000ff">and</span> Fields!Internet_Order_Quantity.Value &lt; Parameters!MiddleThreshold.Value, <span style="color: #006080">&quot;#ff922d&quot;</span>,
        Fields!Internet_Order_Quantity.Value &gt;= Parameters!MiddleThreshold.Value
            <span style="color: #0000ff">and</span> Fields!Internet_Order_Quantity.Value &lt; Parameters!HighThreshold.Value, <span style="color: #006080">&quot;#fff70f&quot;</span>,
        Fields!Internet_Order_Quantity.Value &gt;= Parameters!HighThreshold.Value, <span style="color: #006080">&quot;#5cff21&quot;</span>
    )
)</pre>
</div>
<p>However, when filtering on Components the same problem still occurs.&#160; How can this be?&#160; Expressions in SSRS are built using Visual Basic where expressions are evaluated completely.&#160; In our case both the True and the False part of the IIF function are evaluated even when it will always be true.</p>
<p>On to another attempt to get this working.</p>
<h4>(Attempt to) fix #2</h4>
<p>The previous fix attempt has shown that it’s not possible to use an expression for the field validity test.&#160; At least, not in the way we’ve tried until now.&#160; Let’s try using custom code.</p>
<p><a title="BOL - Using Custom Code References in Expressions (Reporting Services)" href="http://msdn.microsoft.com/en-us/library/ms155798.aspx" target="_blank">Custom code</a> can be added to a report through the Code page in the Report Properties dialog box (accessible through the menu Report &gt; Report Properties… or by right-clicking the report’s yellow background).</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Report Properties &gt; Code dialog box" border="0" alt="Report Properties &gt; Code dialog box" src="http://blog.hoegaerden.be/wp-content/uploads/image31.png" width="481" height="399" /></p>
<p>Let’s start with a small extra requirement.&#160; When a measure is not present in a row, such as the Internet Order Quantity for the products in the Components category, the report should display a zero instead of blank space.&#160; To get this done we again need to test on whether or not the field exists in the result set.</p>
<p>The following Visual Basic function accepts a Field object and returns the value of the field when the field exists or zero when the field does not exist.</p>
<div>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">'returns the field's value or zero if the field does not exist</span>
<span style="color: #0000ff">Public</span> <span style="color: #0000ff">Function</span> GetValue(field <span style="color: #0000ff">as</span> Field) <span style="color: #0000ff">as</span> <span style="color: #0000ff">Long</span>
  <span style="color: #0000ff">If</span> (field.IsMissing) <span style="color: #0000ff">Then</span>
    <span style="color: #0000ff">Return</span> 0
  <span style="color: #0000ff">ElseIf</span> (IsNothing(field.Value)) <span style="color: #0000ff">Then</span>
    <span style="color: #0000ff">Return</span> 0
  <span style="color: #0000ff">Else</span>
    <span style="color: #0000ff">Return</span> field.Value
  <span style="color: #0000ff">End</span> <span style="color: #0000ff">If</span>
<span style="color: #0000ff">End</span> Function</pre>
</div>
<p>This function can now be used in an expression anywhere in the report.&#160; Here’s what the expression looks like for the Value of the textbox that shows the Internet Order Quantity:</p>
<div>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">=Code.GetValue(Fields!Internet_Order_Quantity)</pre>
</div>
<p>The same expression is used for the textboxes that display the sum values:</p>
<div>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">=Sum(Code.GetValue(Fields!Internet_Order_Quantity))</pre>
</div>
<p><strong></strong></p>
<p><strong>Attention:</strong> the function calls above are passing the actual Field object, not the Value property of the field, so not Fields!Internet_Order_Quantity.Value.</p>
<p>So, on to getting our coloring working as required.&#160; For this we need a function that returns the right color for the given amount.&#160; Something like this:</p>
<div>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">Public</span> <span style="color: #0000ff">Const</span> ColorLow <span style="color: #0000ff">As</span> <span style="color: #0000ff">String</span> = <span style="color: #006080">&quot;#ff0e0e&quot;</span>      <span style="color: #008000">'red</span>
<span style="color: #0000ff">Public</span> <span style="color: #0000ff">Const</span> ColorLowMid <span style="color: #0000ff">As</span> <span style="color: #0000ff">String</span> = <span style="color: #006080">&quot;#ff922d&quot;</span>   <span style="color: #008000">'orange</span>
<span style="color: #0000ff">Public</span> <span style="color: #0000ff">Const</span> ColorMidHigh <span style="color: #0000ff">As</span> <span style="color: #0000ff">String</span> = <span style="color: #006080">&quot;#fff70f&quot;</span>  <span style="color: #008000">'yellow</span>
<span style="color: #0000ff">Public</span> <span style="color: #0000ff">Const</span> ColorHigh <span style="color: #0000ff">As</span> <span style="color: #0000ff">String</span> = <span style="color: #006080">&quot;#5cff21&quot;</span>     <span style="color: #008000">'green</span>

<span style="color: #0000ff">Public</span> <span style="color: #0000ff">Function</span> GetColor(field <span style="color: #0000ff">as</span> Field, low <span style="color: #0000ff">as</span> <span style="color: #0000ff">Integer</span>, mid <span style="color: #0000ff">as</span> <span style="color: #0000ff">Integer</span>, high <span style="color: #0000ff">as</span> <span style="color: #0000ff">Integer</span>) <span style="color: #0000ff">as</span> <span style="color: #0000ff">String</span>
  <span style="color: #0000ff">If</span> (field.IsMissing) <span style="color: #0000ff">Then</span>
    <span style="color: #0000ff">Return</span> ColorLow
  <span style="color: #0000ff">ElseIf</span> (IsNothing(field.Value)) <span style="color: #0000ff">Then</span>
    <span style="color: #0000ff">Return</span> ColorLow
  <span style="color: #0000ff">Else</span>
    <span style="color: #0000ff">Select</span> <span style="color: #0000ff">Case</span> field.Value
      <span style="color: #0000ff">Case</span> <span style="color: #0000ff">Is</span> &lt; low
        <span style="color: #0000ff">Return</span> ColorLow
      <span style="color: #0000ff">Case</span> <span style="color: #0000ff">Is</span> &lt; mid
        <span style="color: #0000ff">Return</span> ColorLowMid
      <span style="color: #0000ff">Case</span> <span style="color: #0000ff">Is</span> &lt; high
        <span style="color: #0000ff">Return</span> ColorMidHigh
      <span style="color: #0000ff">Case</span> <span style="color: #0000ff">Is</span> &gt;= high
        <span style="color: #0000ff">Return</span> ColorHigh
    <span style="color: #0000ff">End</span> <span style="color: #0000ff">Select</span>
  <span style="color: #0000ff">End</span> <span style="color: #0000ff">If</span>
<span style="color: #0000ff">End</span> Function</pre>
</div>
<p>This function accepts a field plus the three threshold values.&#160; Depending on the value of the field and the thresholds, the expected color string is returned.&#160; The red color is returned as well when the field does not exist.</p>
<p>As a good coding practice I’ve created constants for the color strings.&#160; This method allows you to define constants that are available in the whole report – could be interesting if the same colors are used in different parts of a report for instance.</p>
<p>This is the expression used for the BackgroundColor property of the TextBox:</p>
<div>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">=Code.GetColor(Fields!Internet_Order_Quantity,
    Parameters!LowThreshold.Value,
    Parameters!MiddleThreshold.Value,
    Parameters!HighThreshold.Value)</pre>
</div>
<p>Again the actual Field object gets passed as first parameter, not just the value.</p>
<p>If we now run the report with a filter on Components, the warnings will still appear in the Output window, but the report will function as expected as the following screenshot shows.&#160; (No Photoshop was used in the making of this screenshot.)&#160; Instead of empty cells the report shows zeroes and the background is coloured even when there are no sales.</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image32.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Rendered report - fully functional" border="0" alt="Rendered report - fully functional" src="http://blog.hoegaerden.be/wp-content/uploads/image-thumb17.png" width="496" height="395" /></a></p>
<p>Extra info can be found in <a title="BOL - Using Dataset Fields Collection References in Expressions (Reporting Services)" href="http://msdn.microsoft.com/en-us/library/cc281297.aspx" target="_blank">the MSDN page about Using Dataset Field Collection References in Expressions</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2009/07/06/ssrs-and-mdx-detecting-missing-fields/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
