<?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; T-SQL</title>
	<atom:link href="http://blog.hoegaerden.be/category/sqlserver/t-sql/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>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>Recursively Delete SSIS Folder</title>
		<link>http://blog.hoegaerden.be/2010/02/28/recursively-delete-ssis-folder/</link>
		<comments>http://blog.hoegaerden.be/2010/02/28/recursively-delete-ssis-folder/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 21:12:51 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[Integration Services]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Script]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/02/28/recursively-delete-ssis-folder/</guid>
		<description><![CDATA[A while ago I posted a query to create a list of all the Integration Services packages deployed to the MSDB.  I am now using that query to take it a step further.
If you’ve been using SSIS for a while you’ve probably noticed that the Management Studio doesn’t like to delete Integration Services folders that [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I posted <a title="List All SSIS Packages Deployed On Your Integration Server" href="http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/" target="_blank">a query to create a list of all the Integration Services packages deployed to the MSDB</a>.  I am now using that query to take it a step further.</p>
<p>If you’ve been using SSIS for a while you’ve probably noticed that the Management Studio doesn’t like to delete Integration Services folders that are not empty.  In fact, it will politely ask you if you’re sure that you want to delete the folder on which you’ve just selected the “Delete” option through the right-click menu.</p>
<p><img style="display: inline; border: 0px;" title="Right-click pop-up menu on SSIS folder" src="http://blog.hoegaerden.be/wp-content/uploads/image195.png" border="0" alt="Right-click pop-up menu on SSIS folder" width="393" height="160" /></p>
<p><img style="display: inline; border: 0px;" title="I am sure I want to delete this non-empty SSIS folder" src="http://blog.hoegaerden.be/wp-content/uploads/image196.png" border="0" alt="I am sure I want to delete this non-empty SSIS folder" width="621" height="137" /></p>
<p>So you click the Yes button.  But then it shows you the following message:</p>
<blockquote><p>SSIS folder &#8216;FolderWithSubfolders&#8217; contains packages and/or other folders. You must drop these first. (Microsoft SQL Server Native Client 10.0)</p></blockquote>
<p>Graphically it looks like this:</p>
<p><img style="display: inline; border: 0px;" title="Object Explorer pop-up: you can't delete SSIS folders that contain packages or other folders" src="http://blog.hoegaerden.be/wp-content/uploads/image197.png" border="0" alt="Object Explorer pop-up: you can't delete SSIS folders that contain packages or other folders" width="621" height="137" /></p>
<p>And this message can be really annoying if you’ve got a main folder with, let’s say, five subfolders, and each subfolder contains about 20-30 packages.  If you want to delete this folder you first need to delete each package separately and then delete the five subfolders, and then you can finally delete the main folder.  And all that through the right-click pop-up menu because you can’t just select the object in the Object Explorer and hit the Delete button on the keyboard – it doesn’t have an action on SSIS objects…</p>
<p>So, I wasn’t planning on doing such a job manually and came up with the following stored procedure.</p>
<p>It’s probably a bit long but don’t run away just yet, I will explain what’s going on down below the code, and there are some comments in the code as well.</p>
<p><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: green;">/*
DESCRIPTION: Deletes all folders and packages under, and including, specified folder.
WRITTEN BY:  Valentino Vranken
CREATED:     2010-02-28
VERSION:     1.0
USAGE:
  -- mind the forward slash
  EXEC dbo.SSIS_RecursiveDeleteFolder '/FolderWithSubfolders'
  -- to delete a subfolder
  EXEC dbo.SSIS_RecursiveDeleteFolder '/FolderWithSubfolders/ASubfolderWithPackages'

COPIED FROM: http://blog.hoegaerden.be

Note 1: folder names are not case-sensitive
Note 2: uses system tables and (undocumented) stored procedures located in MSDB.
Note 3: this code was written for SQL Server 2008. For 2005:
  o sysssispackagefolders -&gt; sysdtspackagefolders90
  o sysssispackages -&gt; sysdtspackages90
  o sp_ssis_deletefolder -&gt; sp_dts_deletefolder
  o sp_ssis_deletepackage -&gt; sp_dts_deletepackage
*/
</span><span style="color: blue;">CREATE PROCEDURE </span>dbo<span style="color: gray;">.</span>SSIS_RecursiveDeleteFolder
    @Folder <span style="color: blue;">varchar</span><span style="color: gray;">(</span>2000<span style="color: gray;">)
</span><span style="color: blue;">AS
BEGIN
    set nocount on</span><span style="color: gray;">;

    </span><span style="color: blue;">declare </span>@foldersToDelete <span style="color: blue;">table
    </span><span style="color: gray;">(
        </span>folderid <span style="color: blue;">uniqueidentifier</span><span style="color: gray;">,
        </span>Lvl <span style="color: blue;">int
    </span><span style="color: gray;">);

    </span><span style="color: blue;">declare </span>@packagesToDelete <span style="color: blue;">table
    </span><span style="color: gray;">(
        </span>PackageName <span style="color: blue;">sysname</span><span style="color: gray;">,
        </span>folderid <span style="color: blue;">uniqueidentifier</span><span style="color: gray;">,
        </span>Lvl <span style="color: blue;">int
    </span><span style="color: gray;">);

    </span><span style="color: green;">--retrieve list of folders to be deleted
    </span><span style="color: blue;">with </span>ChildFolders
    <span style="color: blue;">as
    </span><span style="color: gray;">(
        </span><span style="color: blue;">select </span>PARENT<span style="color: gray;">.</span>parentfolderid<span style="color: gray;">, </span>PARENT<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>PARENT<span style="color: gray;">.</span>foldername<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span><span style="color: red;">'' </span><span style="color: blue;">as sysname</span><span style="color: gray;">) </span><span style="color: blue;">as </span>RootFolder<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>PARENT<span style="color: gray;">.</span>foldername <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">)) </span><span style="color: blue;">as </span>FullPath<span style="color: gray;">,
            </span>0 <span style="color: blue;">as </span>Lvl
        <span style="color: blue;">from </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span>sysssispackagefolders PARENT
        <span style="color: blue;">where </span>PARENT<span style="color: gray;">.</span>parentfolderid <span style="color: gray;">is null
        </span><span style="color: blue;">UNION </span><span style="color: gray;">ALL
        </span><span style="color: blue;">select </span>CHILD<span style="color: gray;">.</span>parentfolderid<span style="color: gray;">, </span>CHILD<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>CHILD<span style="color: gray;">.</span>foldername<span style="color: gray;">,
            </span><span style="color: blue;">case </span>ChildFolders<span style="color: gray;">.</span>Lvl
                <span style="color: blue;">when </span>0 <span style="color: blue;">then </span>CHILD<span style="color: gray;">.</span>foldername
                <span style="color: blue;">else </span>ChildFolders<span style="color: gray;">.</span>RootFolder
            <span style="color: blue;">end as </span>RootFolder<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>ChildFolders<span style="color: gray;">.</span>FullPath <span style="color: gray;">+ </span><span style="color: red;">'/' </span><span style="color: gray;">+ </span>CHILD<span style="color: gray;">.</span>foldername <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">))
                </span><span style="color: blue;">as </span>FullPath<span style="color: gray;">,
            </span>ChildFolders<span style="color: gray;">.</span>Lvl <span style="color: gray;">+ </span>1 <span style="color: blue;">as </span>Lvl
        <span style="color: blue;">from </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span>sysssispackagefolders CHILD
            <span style="color: gray;">inner join </span>ChildFolders <span style="color: blue;">on </span>ChildFolders<span style="color: gray;">.</span>folderid <span style="color: gray;">= </span>CHILD<span style="color: gray;">.</span>parentfolderid
    <span style="color: gray;">)
    </span><span style="color: blue;">insert into </span>@foldersToDelete
    <span style="color: blue;">select </span>F<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>F<span style="color: gray;">.</span>Lvl
    <span style="color: blue;">from </span>ChildFolders F
    <span style="color: blue;">where </span>F<span style="color: gray;">.</span>FullPath <span style="color: gray;">like </span>@Folder <span style="color: gray;">+ </span><span style="color: red;">'%'</span><span style="color: gray;">;

    </span><span style="color: green;">--retrieve list of packages to be deleted
    </span><span style="color: blue;">with </span>ChildFolders
    <span style="color: blue;">as
    </span><span style="color: gray;">(
        </span><span style="color: blue;">select </span>PARENT<span style="color: gray;">.</span>parentfolderid<span style="color: gray;">, </span>PARENT<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>PARENT<span style="color: gray;">.</span>foldername<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span><span style="color: red;">'' </span><span style="color: blue;">as sysname</span><span style="color: gray;">) </span><span style="color: blue;">as </span>RootFolder<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>PARENT<span style="color: gray;">.</span>foldername <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">)) </span><span style="color: blue;">as </span>FullPath<span style="color: gray;">,
            </span>0 <span style="color: blue;">as </span>Lvl
        <span style="color: blue;">from </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span>sysssispackagefolders PARENT
        <span style="color: blue;">where </span>PARENT<span style="color: gray;">.</span>parentfolderid <span style="color: gray;">is null
        </span><span style="color: blue;">UNION </span><span style="color: gray;">ALL
        </span><span style="color: blue;">select </span>CHILD<span style="color: gray;">.</span>parentfolderid<span style="color: gray;">, </span>CHILD<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>CHILD<span style="color: gray;">.</span>foldername<span style="color: gray;">,
            </span><span style="color: blue;">case </span>ChildFolders<span style="color: gray;">.</span>Lvl
                <span style="color: blue;">when </span>0 <span style="color: blue;">then </span>CHILD<span style="color: gray;">.</span>foldername
                <span style="color: blue;">else </span>ChildFolders<span style="color: gray;">.</span>RootFolder
            <span style="color: blue;">end as </span>RootFolder<span style="color: gray;">,
            </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>ChildFolders<span style="color: gray;">.</span>FullPath <span style="color: gray;">+ </span><span style="color: red;">'/' </span><span style="color: gray;">+ </span>CHILD<span style="color: gray;">.</span>foldername <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">))
                </span><span style="color: blue;">as </span>FullPath<span style="color: gray;">,
            </span>ChildFolders<span style="color: gray;">.</span>Lvl <span style="color: gray;">+ </span>1 <span style="color: blue;">as </span>Lvl
        <span style="color: blue;">from </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span>sysssispackagefolders CHILD
            <span style="color: gray;">inner join </span>ChildFolders <span style="color: blue;">on </span>ChildFolders<span style="color: gray;">.</span>folderid <span style="color: gray;">= </span>CHILD<span style="color: gray;">.</span>parentfolderid
    <span style="color: gray;">)
    </span><span style="color: blue;">insert into </span>@packagesToDelete
    <span style="color: blue;">select </span>P<span style="color: gray;">.</span>name<span style="color: gray;">, </span>F<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>F<span style="color: gray;">.</span>Lvl
    <span style="color: blue;">from </span>ChildFolders F
        <span style="color: gray;">inner join </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span>sysssispackages P <span style="color: blue;">on </span>P<span style="color: gray;">.</span>folderid <span style="color: gray;">= </span>F<span style="color: gray;">.</span>folderid
    <span style="color: blue;">where </span>F<span style="color: gray;">.</span>FullPath <span style="color: gray;">like </span>@Folder <span style="color: gray;">+ </span><span style="color: red;">'%'</span><span style="color: gray;">;

    </span><span style="color: green;">--use cursor to loop over objects to be deleted
    </span><span style="color: blue;">declare </span>objectsToDelete_cursor <span style="color: blue;">cursor
    for
        select </span>P<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>P<span style="color: gray;">.</span>Lvl<span style="color: gray;">, </span>P<span style="color: gray;">.</span>PackageName<span style="color: gray;">, </span><span style="color: red;">'P' </span><span style="color: blue;">as </span>ObjectType
        <span style="color: blue;">from </span>@packagesToDelete P
        <span style="color: blue;">UNION </span><span style="color: gray;">ALL
        </span><span style="color: blue;">select </span>F<span style="color: gray;">.</span>folderid<span style="color: gray;">, </span>F<span style="color: gray;">.</span>Lvl<span style="color: gray;">, null, </span><span style="color: red;">'F'
        </span><span style="color: blue;">from </span>@foldersToDelete F
        <span style="color: blue;">order by </span>Lvl <span style="color: blue;">desc</span><span style="color: gray;">, </span>ObjectType <span style="color: blue;">desc</span><span style="color: gray;">;

    </span><span style="color: blue;">open </span>objectsToDelete_cursor<span style="color: gray;">;

    </span><span style="color: blue;">declare </span>@folderid <span style="color: blue;">uniqueidentifier</span><span style="color: gray;">;
    </span><span style="color: blue;">declare </span>@lvl <span style="color: blue;">int</span><span style="color: gray;">;
    </span><span style="color: blue;">declare </span>@packageName <span style="color: blue;">sysname</span><span style="color: gray;">;
    </span><span style="color: blue;">declare </span>@objectType <span style="color: blue;">char</span><span style="color: gray;">;

    </span><span style="color: blue;">fetch next from </span>objectsToDelete_cursor
    <span style="color: blue;">into </span>@folderid<span style="color: gray;">, </span>@lvl<span style="color: gray;">, </span>@packageName<span style="color: gray;">, </span>@objectType<span style="color: gray;">;

    </span><span style="color: blue;">while </span><span style="color: magenta;">@@FETCH_STATUS </span><span style="color: gray;">= </span>0
    <span style="color: blue;">begin
        if </span>@objectType <span style="color: gray;">= </span><span style="color: red;">'F'
        </span><span style="color: blue;">begin
            print </span><span style="color: red;">'exec msdb.dbo.sp_ssis_deletefolder '
                </span><span style="color: gray;">+ </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>@folderid <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">));
            </span><span style="color: blue;">exec </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span><span style="color: maroon;">sp_ssis_deletefolder </span>@folderid<span style="color: gray;">;
        </span><span style="color: blue;">end
        else
        begin
            print </span><span style="color: red;">'exec msdb.dbo.sp_ssis_deletepackage '
                </span><span style="color: gray;">+ </span>@packageName <span style="color: gray;">+ </span><span style="color: red;">', ' </span><span style="color: gray;">+ </span><span style="color: magenta;">cast</span><span style="color: gray;">(</span>@folderid <span style="color: blue;">as varchar</span><span style="color: gray;">(</span><span style="color: magenta;">max</span><span style="color: gray;">));
            </span><span style="color: blue;">exec </span>msdb<span style="color: gray;">.</span>dbo<span style="color: gray;">.</span><span style="color: maroon;">sp_ssis_deletepackage </span>@packageName<span style="color: gray;">, </span>@folderid<span style="color: gray;">;
        </span><span style="color: blue;">end

        fetch next from </span>objectsToDelete_cursor
        <span style="color: blue;">into </span>@folderid<span style="color: gray;">, </span>@lvl<span style="color: gray;">, </span>@packageName<span style="color: gray;">, </span>@objectType<span style="color: gray;">;
    </span><span style="color: blue;">end</span><span style="color: gray;">;

    </span><span style="color: blue;">close </span>objectsToDelete_cursor<span style="color: gray;">;
    </span><span style="color: blue;">deallocate </span>objectsToDelete_cursor<span style="color: gray;">;
</span><span style="color: blue;">END</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Before trying to dismantle this stored procedure, I recommend you to read <a title="List All SSIS Packages Deployed On Your Integration Server" href="http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/" target="_blank">my previous article on retrieving the list of packages</a>.  That already explains half of the code, if not 75%.</p>
<p>Our mission is to find a way to recursively delete packages and folders contained in a specified folder.  To be able to loop over those objects in the correct order (from the deepest level up until the level of the folder specified), the SP creates two table variables: one to hold all folders under the specified folder (@foldersToDelete) and one to hold the packages under the specified folder, including all subfolders (@packagesToDelete).</p>
<p>Based on those two lists I create a cursor that joins these two together, taking their level and object type into consideration.  That’s important because we first need to delete the packages in the lowest level folder, followed by their containing folder, then move one level up and do the same.</p>
<p>We then use the cursor to loop over the packages and folders and use two undocumented system stored procedures – one for each object type- to delete the package or folder.  These system SPs are located in the MSDB.  Here’s how they are defined:</p>
<pre class="code"><span style="color: blue;">ALTER PROCEDURE </span>[dbo]<span style="color: gray;">.</span>[sp_ssis_deletefolder]
  @folderid <span style="color: blue;">uniqueidentifier
AS</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue;">ALTER PROCEDURE </span>[dbo]<span style="color: gray;">.</span>[sp_ssis_deletepackage]
  @name <span style="color: blue;">sysname</span><span style="color: gray;">,
  </span>@folderid <span style="color: blue;">uniqueidentifier
AS</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>As you can see, the parameters for these procedures are not that complicated.  Both of them expect a <em>uniqueidentifier</em> as identification for the folder.  That’s okay, these IDs are stored in the <em>msdb.dbo.sysssispackagefolders</em> table and retrieved by our queries to create the list of to-be-deleted objects.</p>
<p>Furthermore, the <em>sp_ssis_deletepackage</em> SP expects the name of the package to be deleted.  Not a problem either, those names are obtained from the<em> msdb.dbo.sysssispackages</em> table.</p>
<p><strong>Note for SQL Server 2005 users:</strong> this code was written for SQL Server 2008.  The system stored procedures and system tables exist in 2005 as well, but they have different names.  See the comment header of my SP for more details.</p>
<p>So, let’s give it a little test.  Following screenshot shows the setup.  What I will do is use the stored procedure to delete the <em>FolderWithSubfolders</em> folder.  If you’ve been paying close attention, that is the same folder which I tried to delete manually through the Management Studio’s right-click menu (see first screenshot above).</p>
<p><img style="display: inline; border: 0px;" title="Overview of my deployed folders and packages" src="http://blog.hoegaerden.be/wp-content/uploads/image198.png" border="0" alt="Overview of my deployed folders and packages" width="255" height="207" /></p>
<p>After creating the SP, I ran following command:</p>
<pre class="code"><span style="color: blue;">EXEC </span>dbo<span style="color: gray;">.</span>SSIS_RecursiveDeleteFolder <span style="color: red;">'/FolderWithSubfolders'</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>And that gave me the following output in the Messages pane:</p>
<blockquote><p>exec msdb.dbo.sp_ssis_deletepackage AnotherPackage, 7F38288D-4370-40A8-80E3-E92283033E4C</p>
<p>exec msdb.dbo.sp_ssis_deletepackage Package, 7F38288D-4370-40A8-80E3-E92283033E4C</p>
<p>exec msdb.dbo.sp_ssis_deletefolder 4102ED59-ED75-4D93-BBAE-0A162447BF02</p>
<p>exec msdb.dbo.sp_ssis_deletefolder 7F38288D-4370-40A8-80E3-E92283033E4C</p>
<p>exec msdb.dbo.sp_ssis_deletefolder C156B436-8C78-4BF9-99F9-5ABFAB10C405</p></blockquote>
<p>I have deliberately put a couple of print commands in the stored procedure to dump the commands that are actually being executed.  This gives us a good idea of what’s going on.</p>
<p>That’s it for now folks.  Thank you for reading this, and if you found it useful or you’ve got some questions about it: post a comment!</p>
<p>Have fun!</p>
<p>Valentino.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/02/28/recursively-delete-ssis-folder/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Memory Dumps And Crazy Code Samples</title>
		<link>http://blog.hoegaerden.be/2010/02/06/memory-dumps-and-crazy-code-samples/</link>
		<comments>http://blog.hoegaerden.be/2010/02/06/memory-dumps-and-crazy-code-samples/#comments</comments>
		<pubDate>Sat, 06 Feb 2010 10:53:29 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[Reporting Services]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[memory dump]]></category>
		<category><![CDATA[SSRS]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/02/06/memory-dumps-and-crazy-code-samples/</guid>
		<description><![CDATA[I usually don’t write posts just to mention a link to another site.  Except when I’ve come across articles which are so good that I want everyone to know about them.  Here are a couple of articles in that particular category.
What Does Microsoft Do With Those Memory Dumps?
The first one is written by Adam W. [...]]]></description>
			<content:encoded><![CDATA[<p>I usually don’t write posts just to mention a link to another site.  Except when I’ve come across articles which are so good that I want everyone to know about them.  Here are a couple of articles in that particular category.</p>
<h2>What Does Microsoft Do With Those Memory Dumps?</h2>
<p>The first one is written by <strong>Adam W. Saxton</strong>, a member of the <a title="CSS SQL Server Engineers blog" href="http://blogs.msdn.com/psssql/default.aspx" target="_blank">Microsoft Customer Service and Support (CSS) SQL Server Escalation Services team</a>.</p>
<p>The subject of the post is an issue that developers of Reporting Services reports may come across: <strong><em>“InvalidReportParameterException</em></strong> <strong>with Data Driven Subscription”</strong>.  The report complains about an invalid parameter while the parameters seem to be okay, visually.  Then the author goes on to describe the actual issue: trailing spaces!  If you’ve been doing BI for a while, this is a quite common issue.  Adam also shows the difference between the <a title="BOL 2008: LEN (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms190329.aspx" target="_blank">LEN()</a> and the <a title="BOL 2008: DATALENGTH (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms173486.aspx" target="_blank">DATALENGTH()</a> functions.</p>
<p>But that’s not the reason that I’m mentioning that article here.  The best part starts following the Summary chapter, and is entitled <strong>Techie Details</strong>.  In that extra chapter he shows how the CSS team uses those crash memory dumps which I’m sure you’ve all seen now and then. </p>
<p>I won’t give you any details about that, just<strong> </strong><a title="InvalidReportParameterException with Data Driven Subscription" href="http://blogs.msdn.com/psssql/archive/2009/12/10/invalidreportparameterexception-with-data-driven-subscription.aspx" target="_blank"><strong>have a look at the article</strong></a>.  If you’re a developer, there’s some very valuable information there!</p>
<p>I am definitely looking forward to seeing his pre-conference session at the <a title="PASS European Conference 2010" href="http://www.sqlpass.org/summit/eu2010/" target="_blank">SQL PASS European Conference in Germany</a> this year: <a title="Pre-Conference Sessions: PASS European Conference 2010 - Tackling Top Reporting Services Issues" href="http://www.sqlpass.org/summit/eu2010/Agenda/PreConference/TacklingTopReportingServicesIssues.aspx" target="_blank">Tackling Top Reporting Services Issues</a>!</p>
<h2>Some Crazy Code Samples</h2>
<p>The second article that I’d like to mention here is written by <a title="Phil Factor" href="http://www.simple-talk.com/author/phil-factor/" target="_blank">Phil Factor</a>, a regular at the <a title="simple-talk" href="http://www.simple-talk.com" target="_blank">Simple-Talk</a> site.</p>
<p>This article is called <a title="Laying out SQL Code" href="http://www.simple-talk.com/sql/t-sql-programming/laying-out-sql-code" target="_blank">Laying out SQL Code</a> and mentions some database naming conventions and T-SQL coding layout, as the title already implies.  Even if you’re not interested in that (although as a serious developer you should be!!), the article is worth the effort of reading just for its code samples.</p>
<p>Here’s my favorite one:</p>
<pre class="code"><span style="color: blue">CREATE TABLE </span>"╚╦╩╗" <span style="color: gray">( </span>"└┬┴┐" <span style="color: blue">nvarchar</span><span style="color: gray">(</span>10<span style="color: gray">))
</span><span style="color: blue">DECLARE </span>@ <span style="color: blue">nvarchar</span><span style="color: gray">(</span>10<span style="color: gray">)  </span><span style="color: blue">set </span>@<span style="color: gray">=</span><span style="color: red">'═'
</span><span style="color: blue">INSERT  INTO </span>"╚╦╩╗"
        <span style="color: gray">( </span>"└┬┴┐" <span style="color: gray">)
        </span><span style="color: blue">SELECT  </span><span style="color: magenta">replicate</span><span style="color: gray">(</span>@<span style="color: gray">,</span>5<span style="color: gray">)

</span><span style="color: blue">SELECT  </span><span style="color: gray">*
</span><span style="color: blue">FROM    </span>"╚╦╩╗"</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>And just to prove to you that this really is valid code, here’s the result:</p>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Result of crazy query" src="http://blog.hoegaerden.be/wp-content/uploads/image173.png" border="0" alt="Result of crazy query" width="123" height="71" /></p>
<p>So, how about that database for that plumbing company? <img src='http://blog.hoegaerden.be/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>BTW: when running that code without paying attention to the details (such as what DB your SSMS is connected to), you may end up with something like this:</p>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Silly table stored in master DB - that's not a best practice!" src="http://blog.hoegaerden.be/wp-content/uploads/image174.png" border="0" alt="Silly table stored in master DB - that's not a best practice!" width="192" height="94" /> </p>
<p>So you may want to clean up after running the query using this statement:</p>
<pre class="code"><span style="color: blue">drop table </span>"╚╦╩╗"</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/02/06/memory-dumps-and-crazy-code-samples/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>List All SSIS Packages Deployed On Your Integration Server</title>
		<link>http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/</link>
		<comments>http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/#comments</comments>
		<pubDate>Sun, 10 Jan 2010 21:23:40 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[Integration Services]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[ETL]]></category>
		<category><![CDATA[Script]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/</guid>
		<description><![CDATA[When deploying packages to SQL Server Integration Services, it&#8217;s advisable to set up a folder structure so that you can easily distinguish packages belonging to different projects.&#160; Furthermore it may be interesting to create subfolders under the main project folder to separate packages according to the different phases in your ETL (Extract, Transform, Load) process.&#160; [...]]]></description>
			<content:encoded><![CDATA[<p>When deploying packages to SQL Server Integration Services, it&#8217;s advisable to set up a folder structure so that you can easily distinguish packages belonging to different projects.&#160; Furthermore it may be interesting to create subfolders under the main project folder to separate packages according to the different phases in your <a title="Wikipedia: Extract, transform, load" href="http://en.wikipedia.org/wiki/Extract,_transform,_load" target="_blank">ETL (Extract, Transform, Load)</a> process.&#160; When loading a data warehouse, interesting folder names are Dimensions for your dimension ETLs and Facts for the packages that load the fact tables.</p>
<p>After a while you end up with lots of packages spread over lots of folders.&#160; To get a good view of what is deployed on your server, it may be interesting to find a way to list all the packages.&#160; And that&#8217;s exactly the reason why I&#8217;m writing this article.</p>
<p>The query further down generates <strong>a list of all packages deployed in the MSDB database</strong> on your SQL Server.&#160; What you get is the name of the packages, their location and version-related information.&#160; I&#8217;ve also created a&#160; RootFolder column so that it&#8217;s easy to filter on project.&#160; (See now why it&#8217;s interesting to create separate folders per project?)</p>
<p>It’s <strong>important to note</strong> that packages deployed to the <strong>File System will not be shown</strong> in the list.&#160; After all, they are not stored in the MSDB database but in a folder somewhere on the server&#8217;s hard drive, more precisely in a subfolder of where you&#8217;ve installed your SQL Server.&#160; In case you&#8217;ve forgotten where that was, here&#8217;s a small tip.&#160; On your server, open up the list of Windows Services (Start &gt; Run &gt; type &quot;services.msc&quot; &gt; enter) and locate the service called <em>SQL Server Integration Services 10.0</em>.&#160; Open the properties of that service and have a look at the <em>Path to executable</em> value in the General tab.&#160; Take the path, drop the \Binn part and add \Packages instead.&#160; That is where, by default, the packages are deployed.&#160; (If you’re running SQL Server 2005, apply the same procedure but look for a service called <em>SQL Server Integration Services</em>.)</p>
<p>On my system, this is where the packages are located: D:\Program Files\Microsoft SQL Server\100\DTS\Packages.&#160; I will also prove it with following screenshot:</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Packages deployed to the file system on SSIS 2008" border="0" alt="Packages deployed to the file system on SSIS 2008" src="http://blog.hoegaerden.be/wp-content/uploads/image140.png" width="381" height="82" /></p>
<p>Okay, time for the real stuff, the query:</p>
<pre class="code"><span style="color: green">/*
    DESCRIPTION: Lists all SSIS packages deployed to the MSDB database.
    WRITTEN BY: Valentino Vranken
    VERSION: 1.1
    COPIED FROM: http://blog.hoegaerden.be

    Note: this query was written for SQL Server 2008. For SQL2005:
        o sysssispackagefolders =&gt; sysdtspackagefolders90
        o sysssispackages =&gt; sysdtspackages90
*/
</span><span style="color: blue">with </span>ChildFolders
<span style="color: blue">as
</span><span style="color: gray">(
    </span><span style="color: blue">select </span>PARENT<span style="color: gray">.</span>parentfolderid<span style="color: gray">, </span>PARENT<span style="color: gray">.</span>folderid<span style="color: gray">, </span>PARENT<span style="color: gray">.</span>foldername<span style="color: gray">,
        </span><span style="color: magenta">cast</span><span style="color: gray">(</span><span style="color: red">'' </span><span style="color: blue">as sysname</span><span style="color: gray">) </span><span style="color: blue">as </span>RootFolder<span style="color: gray">,
        </span><span style="color: magenta">cast</span><span style="color: gray">(</span>PARENT<span style="color: gray">.</span>foldername <span style="color: blue">as varchar</span><span style="color: gray">(</span><span style="color: magenta">max</span><span style="color: gray">)) </span><span style="color: blue">as </span>FullPath<span style="color: gray">,
        </span>0 <span style="color: blue">as </span>Lvl
    <span style="color: blue">from </span>msdb<span style="color: gray">.</span>dbo<span style="color: gray">.</span>sysssispackagefolders PARENT
    <span style="color: blue">where </span>PARENT<span style="color: gray">.</span>parentfolderid <span style="color: gray">is null
    </span><span style="color: blue">UNION </span><span style="color: gray">ALL
    </span><span style="color: blue">select </span>CHILD<span style="color: gray">.</span>parentfolderid<span style="color: gray">, </span>CHILD<span style="color: gray">.</span>folderid<span style="color: gray">, </span>CHILD<span style="color: gray">.</span>foldername<span style="color: gray">,
        </span><span style="color: blue">case </span>ChildFolders<span style="color: gray">.</span>Lvl
            <span style="color: blue">when </span>0 <span style="color: blue">then </span>CHILD<span style="color: gray">.</span>foldername
            <span style="color: blue">else </span>ChildFolders<span style="color: gray">.</span>RootFolder
        <span style="color: blue">end as </span>RootFolder<span style="color: gray">,
        </span><span style="color: magenta">cast</span><span style="color: gray">(</span>ChildFolders<span style="color: gray">.</span>FullPath <span style="color: gray">+ </span><span style="color: red">'/' </span><span style="color: gray">+ </span>CHILD<span style="color: gray">.</span>foldername <span style="color: blue">as varchar</span><span style="color: gray">(</span><span style="color: magenta">max</span><span style="color: gray">))
            </span><span style="color: blue">as </span>FullPath<span style="color: gray">,
        </span>ChildFolders<span style="color: gray">.</span>Lvl <span style="color: gray">+ </span>1 <span style="color: blue">as </span>Lvl
    <span style="color: blue">from </span>msdb<span style="color: gray">.</span>dbo<span style="color: gray">.</span>sysssispackagefolders CHILD
        <span style="color: gray">inner join </span>ChildFolders <span style="color: blue">on </span>ChildFolders<span style="color: gray">.</span>folderid <span style="color: gray">= </span>CHILD<span style="color: gray">.</span>parentfolderid
<span style="color: gray">)
</span><span style="color: blue">select </span>F<span style="color: gray">.</span>RootFolder<span style="color: gray">, </span>F<span style="color: gray">.</span>FullPath<span style="color: gray">, </span>P<span style="color: gray">.</span>name <span style="color: blue">as </span>PackageName<span style="color: gray">,
    </span>P<span style="color: gray">.</span><span style="color: blue">description as </span>PackageDescription<span style="color: gray">, </span>P<span style="color: gray">.</span>packageformat<span style="color: gray">, </span>P<span style="color: gray">.</span>packagetype<span style="color: gray">,
    </span>P<span style="color: gray">.</span>vermajor<span style="color: gray">, </span>P<span style="color: gray">.</span>verminor<span style="color: gray">, </span>P<span style="color: gray">.</span>verbuild<span style="color: gray">, </span>P<span style="color: gray">.</span>vercomments<span style="color: gray">,
    </span><span style="color: magenta">cast</span><span style="color: gray">(</span><span style="color: magenta">cast</span><span style="color: gray">(</span>P<span style="color: gray">.</span>packagedata <span style="color: blue">as varbinary</span><span style="color: gray">(</span><span style="color: magenta">max</span><span style="color: gray">)) </span><span style="color: blue">as xml</span><span style="color: gray">) </span><span style="color: blue">as </span>PackageData
<span style="color: blue">from </span>ChildFolders F
    <span style="color: gray">inner join </span>msdb<span style="color: gray">.</span>dbo<span style="color: gray">.</span>sysssispackages P <span style="color: blue">on </span>P<span style="color: gray">.</span>folderid <span style="color: gray">= </span>F<span style="color: gray">.</span>folderid
<span style="color: blue">order by </span>F<span style="color: gray">.</span>FullPath <span style="color: blue">asc</span><span style="color: gray">, </span>P<span style="color: gray">.</span>name <span style="color: blue">asc</span><span style="color: gray">;</span></pre>
<p>The query uses a recursive CTE (<a title="BOL 2008: Using Common Table Expressions" href="http://msdn.microsoft.com/en-us/library/ms190766.aspx">Common Table Expression</a>) to get data out of a system table called <a title="BOL 2008: sysssispackagefolders (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms189477.aspx">sysssispackagefolders</a>, located in the MSDB system database.&#160; The CTE gives us a list of all folders stored in the database and at the same time uses the hierarchical structure of the table to build the <em>FullPath</em> and the <em>Lvl</em> columns.</p>
<p><strong>Note:</strong> the <a title="BOL 2008: CAST and CONVERT (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms187928.aspx">CAST()</a> calls are needed because the data type of the <em>foldername</em> column is <a title="BOL 2008: Using Special Data Types" href="http://msdn.microsoft.com/en-us/library/ms191240.aspx">sysname</a>.&#160; And sysname does not implicitly convert to varchar, which is needed for the concatenation building the <em>FullPath</em> column.</p>
<p>The CTE is joined with another system table called <a title="BOL 2008: sysssispackages (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms181582.aspx">sysssispackages</a>, also located in MSDB.&#160; Not all columns are being retrieved from that table but I believe I&#8217;ve selected the most important ones.&#160; Have a look in the Books Online for more info on the columns available.</p>
<p>There’s one column however on which I’d like to add some additional info myself.&#160; That column is called <em>packagedata</em> and it contains the actual SSIS package.&#160; The data type of this column is <a title="BOL 2008: ntext, text, and image (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms187993.aspx">image</a>, not sure why because after all, an SSIS package (or .dtsx file for that matter) is pure XML.&#160; So why isn’t it stored as XML? <strike> If anyone knows the reason: post a comment!</strike></p>
<p><strong>Update:</strong> since I wrote the above paragraph I’ve come across the answer myself.&#160; The reason that the XML is not stored as xml datatype is because of the overhead that this would cause.&#160; So there you go, use image instead of xml if you’re not going to query the xml structure itself.</p>
<p>Anyway, as you can see in the query, to get it converted from image to XML you need to go through varbinary.&#160; The image datatype cannot convert directly to XML.&#160; See the Books Online here on what casts are allowed: <a title="http://msdn.microsoft.com/en-us/library/ms187928.aspx" href="http://msdn.microsoft.com/en-us/library/ms187928.aspx">http://msdn.microsoft.com/en-us/library/ms187928.aspx</a></p>
<p><strong>Note for SQL Server 2005 users:</strong> as mentioned in the query’s comments, these tables don’t exist in SQL Server 2005.&#160; Well, actually they do, they just have different names.&#160; See the comment in the code for their equivalent.</p>
<p>To finish off I&#8217;ll show you what the results look like when executing the query on my test system.&#160; But first, following screenshot shows all deployed packages as reported by the Management Studio.&#160; As you can see, two packages are deployed to the File System.&#160; These two packages were shown earlier in the first screenshot.&#160; Some other packages have been deployed to the MSDB database.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Object Explorer showing all deployed SSIS packages" border="0" alt="Object Explorer showing all deployed SSIS packages" src="http://blog.hoegaerden.be/wp-content/uploads/image141.png" width="329" height="306" /></p>
<p>And here are the results of the query:</p>
<p><a href="http://blog.hoegaerden.be/wp-content/uploads/image143.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="A list of all SSIS packages deployed to my SQL Server 2008 MSDB database" border="0" alt="A list of all SSIS packages deployed to my SQL Server 2008 MSDB database" src="http://blog.hoegaerden.be/wp-content/uploads/image_thumb37.png" width="692" height="84" /></a></p>
<p>To be honest, I added a little filter to keep the results clean.&#160; The <a title="BOL 2008: Introducing the Data Collector" href="http://msdn.microsoft.com/en-us/library/bb677248.aspx">Data Collector</a>, a new feature of SQL Server 2008, also uses some packages so I’ve filtered those out by adding a WHERE clause to the SELECT statement at the bottom of the full query:</p>
<pre class="code"><span style="color: blue">select </span>F<span style="color: gray">.</span>RootFolder<span style="color: gray">, </span>F<span style="color: gray">.</span>FullPath<span style="color: gray">, </span>P<span style="color: gray">.</span>name <span style="color: blue">as </span>PackageName<span style="color: gray">,
    </span>P<span style="color: gray">.</span><span style="color: blue">description as </span>PackageDescription<span style="color: gray">, </span>P<span style="color: gray">.</span>packageformat<span style="color: gray">, </span>P<span style="color: gray">.</span>packagetype<span style="color: gray">,
    </span>P<span style="color: gray">.</span>vermajor<span style="color: gray">, </span>P<span style="color: gray">.</span>verminor<span style="color: gray">, </span>P<span style="color: gray">.</span>verbuild<span style="color: gray">, </span>P<span style="color: gray">.</span>vercomments<span style="color: gray">,
    </span><span style="color: magenta">cast</span><span style="color: gray">(</span><span style="color: magenta">cast</span><span style="color: gray">(</span>P<span style="color: gray">.</span>packagedata <span style="color: blue">as varbinary</span><span style="color: gray">(</span><span style="color: magenta">max</span><span style="color: gray">)) </span><span style="color: blue">as xml</span><span style="color: gray">) </span><span style="color: blue">as </span>PackageData
<span style="color: blue">from </span>ChildFolders F
    <span style="color: gray">inner join </span>msdb<span style="color: gray">.</span>dbo<span style="color: gray">.</span>sysssispackages P <span style="color: blue">on </span>P<span style="color: gray">.</span>folderid <span style="color: gray">= </span>F<span style="color: gray">.</span>folderid
<span style="color: blue">where </span>F<span style="color: gray">.</span>RootFolder <span style="color: gray">&lt;&gt; </span><span style="color: red">'Data Collector'
</span><span style="color: blue">order by </span>F<span style="color: gray">.</span>FullPath <span style="color: blue">asc</span><span style="color: gray">, </span>P<span style="color: gray">.</span>name <span style="color: blue">asc</span><span style="color: gray">;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>If you’ve been paying attention, you’ve noticed that the two packages deployed to the File System are not mentioned in the output of the query, as expected.</p>
<p>Now that you know how to list your packages, <a title="Recursively Delete SSIS Folder" href="http://blog.hoegaerden.be/2010/02/28/recursively-delete-ssis-folder/" target="_blank">check out my article on deleting them</a>.</p>
<p>That’s all for now folks, have fun!</p>
<p><strong>References</strong></p>
<p><a title="BOL 2008: Tutorial: Creating a Simple ETL Package" href="http://msdn.microsoft.com/en-us/library/ms169917.aspx">BOL 2008: Tutorial: Creating a Simple ETL Package</a></p>
<p><a title="BOL 2008: sysssispackagefolders (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms189477.aspx">BOL 2008: sysssispackagefolders (Transact-SQL)</a></p>
<p><a title="BOL 2008: sysssispackages (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms181582.aspx">BOL 2008: sysssispackages (Transact-SQL)</a></p>
<p><a title="BOL 2008: Recursive Queries Using Common Table Expressions" href="http://msdn.microsoft.com/en-us/library/ms186243.aspx">BOL 2008: Recursive Queries Using Common Table Expressions</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/01/10/list-all-ssis-packages-deployed-on-your-integration-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adding Leading Zeroes To A Number</title>
		<link>http://blog.hoegaerden.be/2010/01/06/adding-leading-zeroes-to-a-number/</link>
		<comments>http://blog.hoegaerden.be/2010/01/06/adding-leading-zeroes-to-a-number/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 21:17:45 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2010/01/06/adding-leading-zeroes-to-a-number/</guid>
		<description><![CDATA[After having successfully survived the festivities, here I am again, ready for another year of blogging, article writing, forum answering, conference attending, &#8230;
Happy New Year to anyone reading this!!
In this year&#8217;s first post I&#8217;d like to share my preferred way of adding leading zeroes to a number, useful for any situation where you need to [...]]]></description>
			<content:encoded><![CDATA[<p>After having successfully survived the festivities, here I am again, ready for another year of blogging, article writing, forum answering, conference attending, &#8230;</p>
<p>Happy New Year to anyone reading this!!</p>
<p>In this year&#8217;s first post I&#8217;d like to share my preferred way of adding leading zeroes to a number, useful for any situation where you need to convert a number to a string using SQL.&#160; In fact, this method can be used whenever a certain string needs to get increased to a specific length using a particular character, not just numbers.</p>
<p>And here’s the code sample:</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">declare</span> @number <span style="color: #0000ff">int</span> = 42;
<span style="color: #0000ff">declare</span> @<span style="color: #0000ff">character</span> <span style="color: #0000ff">char</span>(1) = <span style="color: #006080">'0'</span>;
<span style="color: #0000ff">declare</span> @expectedLength <span style="color: #0000ff">int</span> = 8;

<span style="color: #0000ff">select</span> REPLICATE(@<span style="color: #0000ff">character</span>, @expectedLength - LEN(@number)) + <span style="color: #0000ff">CAST</span>(@number <span style="color: #0000ff">as</span> <span style="color: #0000ff">varchar</span>(8)) <span style="color: #0000ff">as</span> <span style="color: #0000ff">Result</span>;</pre>
</div>
<p>&#160;</p>
<p>I’m using <a title="BOL 2008: REPLICATE (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms174383.aspx" target="_blank">the REPLICATE() function</a> to create a string of our leading character, in this case a zero.&#160; The length of this string of zeroes is the expected length minus the length of the actual number.&#160; The <a title="BOL 2008: LEN (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms190329.aspx" target="_blank">LEN() function</a> is used to get the length of our number &#8211; note that LEN() expects a string as parameter so an implicit cast from int to varchar is being performed here.</p>
<p>Then I use the + operator to concatenate the string of zeroes with our actual number.&#160; This number gets converted to varchar using <a title="CAST and CONVERT (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms187928.aspx" target="_blank">the CAST() function</a>.&#160; The length of the varchar should be equal to the maximum length that our output string can be.&#160; This way we ensure that all acceptable values are being converted to string.&#160; In the case that our number is longer than the expected output string, the result will be NULL.</p>
<p>And here’s the result:</p>
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Result of sample query to add leading zeroes to a number" border="0" alt="Result of sample query to add leading zeroes to a number" src="http://blog.hoegaerden.be/wp-content/uploads/image138.png" width="110" height="71" /> </p>
<p>Have fun in 2010!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2010/01/06/adding-leading-zeroes-to-a-number/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generating A List Of Dates Out Of Numbers</title>
		<link>http://blog.hoegaerden.be/2009/12/02/generating-a-list-of-dates-out-of-numbers/</link>
		<comments>http://blog.hoegaerden.be/2009/12/02/generating-a-list-of-dates-out-of-numbers/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 21:57:42 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2009/12/02/generating-a-list-of-dates-out-of-numbers/</guid>
		<description><![CDATA[This post is meant partly as a “reminder to self” but also to show that, if you need to generate a list of dates, all you need are numbers.&#160; Oh well, if that doesn’t make sense: read on!
One of the undocumented tables of SQL Server is called spt_values and it is located in the master [...]]]></description>
			<content:encoded><![CDATA[<p>This post is meant partly as a “reminder to self” but also to show that, if you need to generate a list of dates, all you need are numbers.&#160; Oh well, if that doesn’t make sense: read on!</p>
<p>One of the undocumented tables of SQL Server is called spt_values and it is located in the master database.&#160; This table serves as a lookup table for SQL Server itself, more precisely it’s used by several system stored procedures.</p>
<p>Being a lookup table, it doesn’t consist of many columns.&#160; One of the most important columns though is called <strong>type</strong>.&#160; This one defines the meaning of the record.&#160; An interesting value for this column is “LNG”.&#160; When filtering on “LNG” it returns the following:</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="List of languages with their LCID" border="0" alt="List of languages with their LCID" src="http://blog.hoegaerden.be/wp-content/uploads/image131.png" width="362" height="633" /></p>
<p>I’m quite sure that SharePoint developers recognize these values stored in the <strong>number</strong> column.&#160; That’s the locale identifier of the language mentioned in the <strong>name</strong> column.&#160; Could be interesting in case you need a list of languages to be shown somewhere, in a report parameter for instance.</p>
<p>But anyway, these records are not the point of this blog post so let’s move on.&#160; The title of this post says we’re going to generate some dates out of numbers.&#160; So to get started, what we need are those numbers.&#160; Guess what the spt_values table contains?&#160; Indeed, when filtering the <strong>name</strong> column on “P”, what we get are numbers starting at zero and ending at 2047:</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="List of numbers retrieved from master..spt_values" border="0" alt="List of numbers retrieved from master..spt_values" src="http://blog.hoegaerden.be/wp-content/uploads/image132.png" width="263" height="327" /></p>
<p>And how can we turn these into dates?&#160; Using some creativity it’s not that complicated.&#160; Let’s say we want to generate a list of dates starting at the first of January of the current year up until today, could be interesting for YTD calculations.&#160; Following query does just that:</p>
<pre class="code"><span style="color: blue">select </span><span style="color: magenta">CAST</span><span style="color: gray">(</span><span style="color: magenta">DATEADD</span><span style="color: gray">(</span>dd<span style="color: gray">, -</span>number<span style="color: gray">, </span><span style="color: magenta">GETDATE</span><span style="color: gray">()) </span><span style="color: blue">as date</span><span style="color: gray">) </span>dt
<span style="color: blue">from master</span><span style="color: gray">..</span>spt_values
<span style="color: blue">where type </span><span style="color: gray">= </span><span style="color: red">'P' </span><span style="color: gray">and </span>number <span style="color: gray">&lt; </span><span style="color: magenta">DATEPART</span><span style="color: gray">(</span>dy<span style="color: gray">, </span><span style="color: magenta">GETDATE</span><span style="color: gray">())</span></pre>
<p>As you can see, several datetime-related functions are being used here.&#160; The easiest one is <a title="BOL 2008: GETDATE (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms188383.aspx">GETDATE()</a> which returns the current system timestamp of the database server.</p>
<p>Then we’ve got <a title="BOL 2008: DATEPART (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms174420.aspx">DATEPART()</a> in combination with the “dy” parameter.&#160; This returns the numeric value for the day of the year that the date parameter represents.&#160; The following query returns 336 when ran today (December 2, 2009):</p>
<pre class="code"><span style="color: blue">select </span><span style="color: magenta">DATEPART</span><span style="color: gray">(</span>dy<span style="color: gray">, </span><span style="color: magenta">GETDATE</span><span style="color: gray">())</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>(For readability purposes I will not repeat “when ran today” each time, the remainder of the post assumes everything is being executed on the aforementioned date.)</p>
<p>These two functions are being used in the WHERE clause.&#160;&#160; So what the WHERE clause says is that we want all numbers smaller than 336.</p>
<p>Okay, so let’s move on to the SELECT.&#160; It uses the <a title="BOL 2008: DATEADD (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms186819.aspx">DATEADD()</a> function to subtract the retrieved number values from the current system date.&#160; How does that work?&#160; In combination with the “dd” parameter it tells the function what we’re working on are the days, and the minus sign in front of the <strong>number</strong> field ensures that days are being subtracted instead of added.</p>
<p>And to finish off, the value returned by DATEADD() is being converted to the <strong><a title="BOL 2008: date (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/bb630352.aspx">date</a></strong> type using the <a title="BOL 2008: CAST and CONVERT (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms187928.aspx">CAST()</a> function.&#160; This removes the time value of the datetime type which is good because all we needed are dates.</p>
<p>This is what the query returns:</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="YTD date values" border="0" alt="YTD date values" src="http://blog.hoegaerden.be/wp-content/uploads/image133.png" width="104" height="288" /></p>
<p>As you can see, we get 336 records which matches exactly with the values returned by DATEPART(dy, GETDATE()).&#160; (BTW: the <strong>number</strong> field starts at zero which is why we get 336 instead of 335 records here)</p>
<p>For more advanced usage of a list of numbers I’d like to point you the following article by colleague Experts Exchange Expert <a title="mark_wills" href="http://www.experts-exchange.com/M_4390378.html">Mark Wills</a>: <a title="Fun with MS SQL spt_values for delimited strings and virtual calendars" href="http://www.experts-exchange.com/articles/Microsoft/Development/MS-SQL-Server/Fun-with-MS-SQL-spt-values-for-delimited-strings-and-virtual-calendars.html">Fun with MS SQL spt_values for delimited strings and virtual calendars</a></p>
<p>Have fun!</p>
<p>Valentino.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2009/12/02/generating-a-list-of-dates-out-of-numbers/feed/</wfw:commentRss>
		<slash:comments>2</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>Script: Find All Empty Columns In Database</title>
		<link>http://blog.hoegaerden.be/2009/02/15/script-find-all-empty-columns-in-database/</link>
		<comments>http://blog.hoegaerden.be/2009/02/15/script-find-all-empty-columns-in-database/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 21:06:40 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Script]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2009/02/15/script-find-all-empty-columns-in-database/</guid>
		<description><![CDATA[Earlier this week a colleague had an interesting question.&#160; He was working on an application that uses a database containing more than 200 tables and wanted to find all columns in the database where this column is null for all records, so in other words all empty columns.&#160; This would give him an idea of [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week a colleague had an interesting question.&#160; He was working on an application that uses a database containing more than 200 tables and wanted to find all columns in the database where this column is null for all records, so in other words all empty columns.&#160; This would give him an idea of possibly unused (i.e. obsolete) columns.</p>
<p>Obviously he did not want to do this manually.</p>
<p>So I wrote him this script:</p>
<pre class="code"><span style="color: green">/*
DESCRIPTION: Returns a list of all columns in current database
             where the column's value is null for all records.
WRITTEN BY:  Valentino Vranken
CREATED:     2009-02-15
VERSION:     1.0

COPIED FROM: http://blog.hoegaerden.be
*/
</span><span style="color: blue">declare </span>@tempTable <span style="color: blue">table
</span><span style="color: gray">(
    </span>TableSchema <span style="color: blue">nvarchar</span><span style="color: gray">(</span>256<span style="color: gray">),
    </span>TableName <span style="color: blue">nvarchar</span><span style="color: gray">(</span>256<span style="color: gray">),
    </span>ColumnName <span style="color: blue">sysname</span><span style="color: gray">,
    </span>NotNullCnt <span style="color: blue">bigint
</span><span style="color: gray">);

</span><span style="color: blue">declare </span>@sql <span style="color: blue">nvarchar</span><span style="color: gray">(</span>4000<span style="color: gray">);
</span><span style="color: blue">declare </span>@tableSchema <span style="color: blue">nvarchar</span><span style="color: gray">(</span>256<span style="color: gray">);
</span><span style="color: blue">declare </span>@tableName <span style="color: blue">nvarchar</span><span style="color: gray">(</span>256<span style="color: gray">);
</span><span style="color: blue">declare </span>@columnName <span style="color: blue">sysname</span><span style="color: gray">;
</span><span style="color: blue">declare </span>@cnt <span style="color: blue">bigint</span><span style="color: gray">;

</span><span style="color: blue">declare </span>columnCursor <span style="color: blue">cursor for
    select </span>TABLE_SCHEMA<span style="color: gray">, </span>TABLE_NAME<span style="color: gray">, </span>COLUMN_NAME <span style="color: blue">from </span><span style="color: green">INFORMATION_SCHEMA</span><span style="color: gray">.</span><span style="color: green">COLUMNS
    </span><span style="color: blue">where </span>IS_NULLABLE <span style="color: gray">= </span><span style="color: red">'YES'</span><span style="color: gray">;

</span><span style="color: blue">open </span>columnCursor<span style="color: gray">;

</span><span style="color: blue">fetch next from </span>columnCursor <span style="color: blue">into </span>@tableSchema<span style="color: gray">, </span>@tableName<span style="color: gray">, </span>@columnName<span style="color: gray">;

</span><span style="color: blue">while </span><span style="color: magenta">@@FETCH_STATUS </span><span style="color: gray">= </span>0
<span style="color: blue">begin
    </span><span style="color: green">-- use dynamic sql to get count of records where column is not null
    </span><span style="color: blue">set </span>@sql <span style="color: gray">= </span><span style="color: red">'select @cnt = COUNT(*) from [' </span><span style="color: gray">+ </span>@tableSchema <span style="color: gray">+ </span><span style="color: red">'].[' </span><span style="color: gray">+ </span>@tableName <span style="color: gray">+
        </span><span style="color: red">'] where [' </span><span style="color: gray">+ </span>@columnName <span style="color: gray">+ </span><span style="color: red">'] is not null'</span><span style="color: gray">;
    </span><span style="color: green">-- print @sql; --uncomment for debugging
    </span><span style="color: blue">exec </span><span style="color: maroon">sp_executesql </span>@sql<span style="color: gray">, </span><span style="color: red">N'@cnt bigint output'</span><span style="color: gray">, </span>@cnt <span style="color: gray">= </span>@cnt <span style="color: blue">output</span><span style="color: gray">;

    </span><span style="color: blue">insert into </span>@tempTable <span style="color: blue">select </span>@tableSchema<span style="color: gray">, </span>@tableName<span style="color: gray">, </span>@columnName<span style="color: gray">, </span>@cnt<span style="color: gray">;

    </span><span style="color: blue">fetch next from </span>columnCursor <span style="color: blue">into </span>@tableSchema<span style="color: gray">, </span>@tableName<span style="color: gray">, </span>@columnName<span style="color: gray">;
</span><span style="color: blue">end</span><span style="color: gray">;

</span><span style="color: blue">close </span>columnCursor<span style="color: gray">;
</span><span style="color: blue">deallocate </span>columnCursor<span style="color: gray">;

</span><span style="color: blue">select </span><span style="color: gray">* </span><span style="color: blue">from </span>@tempTable <span style="color: blue">where </span>NotNullCnt <span style="color: gray">= </span>0<span style="color: gray">;</span></pre>
<p>Yes I know, it uses a cursor and dynamic SQL but hey, it&#8217;s not something that will run every minute in a production environment.&#160; And I couldn&#8217;t really think of an easy way to do this without these features.</p>
<p>For more info on dynamic SQL I would like to point you to this excellent website by <a title="Erland Sommarskog&#39;s site" href="http://www.sommarskog.se" target="_blank">Erland Sommarskog</a>.&#160; I&#8217;ve read his articles since several years now and always keep coming back to them to refresh my memory.&#160; The particular article here is called <a title="The Curse and Blessings of Dynamic SQL" href="http://www.sommarskog.se/dynamic_sql.html" target="_blank">The Curse and Blessings of Dynamic SQL</a>.</p>
<p>And finally here&#8217;s a Microsoft Support article that explains <a title="How to specify output parameters when you use the sp_executesql stored procedure in SQL Server" href="http://support.microsoft.com/default.aspx/kb/262499" target="_blank">how to capture the output of a dynamic query executed by sp_executesql</a>.&#160; According to the article this feature is not documented in the BOL.&#160; I think this is no longer a valid statement, there&#8217;s even an example in the <a title="Books Online: sp_executesql (Transact-SQL)" href="http://msdn.microsoft.com/en-us/library/ms188001.aspx" target="_blank">BOL page on sp_executesql</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2009/02/15/script-find-all-empty-columns-in-database/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Avoid looping when inserting data</title>
		<link>http://blog.hoegaerden.be/2009/02/01/avoid-looping-when-inserting-data/</link>
		<comments>http://blog.hoegaerden.be/2009/02/01/avoid-looping-when-inserting-data/#comments</comments>
		<pubDate>Sun, 01 Feb 2009 19:09:01 +0000</pubDate>
		<dc:creator>Valentino Vranken</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Performance Tuning]]></category>

		<guid isPermaLink="false">http://blog.hoegaerden.be/2009/02/01/avoid-looping-when-inserting-data/</guid>
		<description><![CDATA[Sometimes you&#8217;re in a situation where your stored procedure needs to insert several new records and some fields are based on calculations, or one of the fields contains a kind of batch number that needs to increase for every record where another certain field contains the same value.
In this situation you may have a habit [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes you&#8217;re in a situation where your stored procedure needs to insert several new records and some fields are based on calculations, or one of the fields contains a kind of batch number that needs to increase for every record where another certain field contains the same value.</p>
<p>In this situation you may have a habit of building a loop to insert the records, such as the following:</p>
<p>(I&#8217;ve used the Person.Address table from the AdventureWorks DB for demonstration purposes &#8211; it doesn&#8217;t contain too many fields <img src='http://blog.hoegaerden.be/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> )</p>
<div>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<span style="color: #0000ff;">declare</span> @counter <span style="color: #0000ff;">int</span>;
<span style="color: #0000ff;">set</span> @counter = 1;
<span style="color: #0000ff;">while</span> @counter &lt;= 10000
<span style="color: #0000ff;">begin</span>
    insert <span style="color: #0000ff;">into</span> Person.Address (AddressLine1, AddressLine2, City, 

        StateProvinceID, PostalCode, ModifiedDate)
    <span style="color: #0000ff;">values</span> (<span style="color: #006080;">'the first address line'</span>, <span style="color: #006080;">'second add line'</span>, <span style="color: #006080;">'some city'</span>, 1,
        <span style="color: #006080;">'PC-0000'</span> + <span style="color: #0000ff;">cast</span>(@counter <span style="color: #0000ff;">as</span> <span style="color: #0000ff;">varchar</span>(10)), getdate());
    <span style="color: #0000ff;">set</span> @counter = @counter + 1;
<span style="color: #0000ff;">end</span></pre>
</div>
<p>Executing the loop above takes 3.5 seconds on my laptop.  This is not very long, but it can be better.</p>
<p>If you think about this, what is going on in those 3.5 seconds?  Not only are we inserting 10000 records, every index in that table is getting 10000 updates.  Besides the clustered index there are 3 additional indexes.  In total this makes 40000 changes that are being processed on the table.  And that&#8217;s not all, every insert happens inside a transaction, so 10000 transactions.  SQL Server needs to keep track of what has been modified, so writes to the transaction log are going on as well.</p>
<p>Now, how can we avoid this?  The answer lies in the table variable!  Create a table variable that will hold your new records, loop to create the records in the table variable and then, after the loop, insert all records from the table variable into your actual table.</p>
<div class="code"></div>
<div>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<span style="color: #008000;">-- declaration of table var </span>
<span style="color: #0000ff;">declare</span> @<span style="color: #0000ff;">table</span> <span style="color: #0000ff;">table</span>
(
    [AddressLine1] [nvarchar](60) <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">NULL</span>,
    [AddressLine2] [nvarchar](60) <span style="color: #0000ff;">NULL</span>,
    [City] [nvarchar](30) <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">NULL</span>,
    [StateProvinceID] [<span style="color: #0000ff;">int</span>] <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">NULL</span>,
    [PostalCode] [nvarchar](15) <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">NULL</span>,
    [ModifiedDate] [datetime] <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">NULL</span>
);
<span style="color: #0000ff;">declare</span> @counter <span style="color: #0000ff;">int</span>;
<span style="color: #0000ff;">set</span> @counter = 1; 

<span style="color: #0000ff;">while</span> @counter &lt;= 10000
<span style="color: #0000ff;">begin</span>
    <span style="color: #008000;">-- insert in table var instead of actual table  </span>
   insert <span style="color: #0000ff;">into</span> @<span style="color: #0000ff;">table</span> (AddressLine1, AddressLine2, City, 

        StateProvinceID, PostalCode, ModifiedDate)
    <span style="color: #0000ff;">values</span> (<span style="color: #006080;">'the first address line'</span>, <span style="color: #006080;">'second add line'</span>, <span style="color: #006080;">'some city'</span>, 1, 

        <span style="color: #006080;">'PC-0000'</span> + <span style="color: #0000ff;">cast</span>(@counter <span style="color: #0000ff;">as</span> <span style="color: #0000ff;">varchar</span>(10)), getdate());
    <span style="color: #0000ff;">set</span> @counter = @counter + 1;
<span style="color: #0000ff;">end</span> 

<span style="color: #008000;">-- insert in actual table </span>
insert <span style="color: #0000ff;">into</span> Person.Address (AddressLine1, AddressLine2, City, 

    StateProvinceID, PostalCode, ModifiedDate)
<span style="color: #0000ff;">select</span> * <span style="color: #0000ff;">from</span> @<span style="color: #0000ff;">table</span>;</pre>
</div>
<p>This now executes in 453 milliseconds, isn&#8217;t that great?  That&#8217;s an improvement of about 700%!</p>
<p>A good reason for this is that we now reduced the number of transactions to 1 because the data is being inserted in one go.  And the changes to the indexes are happening all at once, which should be better as well.</p>
<p>In my opinion, in specific situations this can be an interesting concept to optimize your code performance.</p>
<p>See Books Online for more info on the table variable itself: <a title="http://msdn.microsoft.com/en-us/library/ms175010.aspx" href="http://msdn.microsoft.com/en-us/library/ms175010.aspx">http://msdn.microsoft.com/en-us/library/ms175010.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hoegaerden.be/2009/02/01/avoid-looping-when-inserting-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
