<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8754068738496607590</id><updated>2012-02-10T22:12:56.090Z</updated><category term='Denali'/><category term='MCM'/><category term='CLR'/><category term='VMWare'/><category term='SQL Agent'/><category term='Performance Point Server 2007'/><category term='MOSS 2007'/><category term='SQL Server 2008'/><category term='BI Test Environement'/><category term='Project Crescent'/><category term='DW'/><category term='BIDS'/><category term='WQL'/><category term='SQL Server'/><category term='SharePoint'/><category term='Hierarchies'/><category term='XML'/><category term='XMLA'/><category term='Virtual Environment'/><category term='VB.NET Script'/><category term='Oracle'/><category term='Gemini'/><category term='Business Intelligence'/><category term='TSQL'/><category term='Analysis Services'/><category term='MSDN'/><category term='RSinteract'/><category term='SMTP'/><category term='Parent Child Hierarchy'/><category term='WMI'/><category term='Power Pivot For Excel'/><category term='SQL 2008 R2 CTP'/><category term='Report Builder 2.0'/><category term='Linux'/><category term='SSAS'/><category term='PPS'/><category term='SSRS'/><category term='SQL 2008 R2'/><category term='SSRS 2008'/><category term='Load Test'/><category term='MOSS'/><category term='Virtual Machines'/><category term='Spatial Data'/><category term='SQL Server 2008 R2'/><category term='SSIS'/><category term='Map Report Item'/><category term='MDX'/><category term='VBscript'/><title type='text'>Business Intelligence Chronicles</title><subtitle type='html'>Everything and anything related to Business Intelligence and Microsoft SQL Server</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>63</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8240337003026117065</id><published>2011-11-30T22:08:00.000Z</published><updated>2012-02-10T22:09:26.711Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Machines'/><category scheme='http://www.blogger.com/atom/ns#' term='VMWare'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>The impact of the host OS on virtual machine performance</title><content type='html'>&lt;p&gt;If you use virtual machines on a daily basis then I am sure you would have at some point wondered which host OS is the best to run your VM's on. So I decided to do a very quick basic benchmark of a Windows Server 2008 R2 virtual machine on both Windows 7 and Ubuntu 11.10 as hosts. For the benchmark I used PassMark PerformanceTest 7 (installed on the VM).&lt;/p&gt; &lt;p&gt;The machine that I ran this on was my Sony Vaio VPCF115FM latop. It has a core i7 1.60 processor with 8GB of RAM. The VM was on a Seagate 1TB external drive which runs at 5400rpm.&lt;/p&gt; &lt;p&gt;The file system on the external drive was NTFS and remained NTFS for both Windows and Ubuntu tests.&lt;/p&gt; &lt;p&gt;The Windows 7 with SP1 host OS installation only included Office 2010 and all anti virus and firewall software turned off and closed down. I also set the Removal Policy of the external drive to Better Performance instead of the Quick Removal default.&lt;/p&gt; &lt;p&gt;The Ubuntu host OS was stock standard Ubuntu 11.10 with the Nvidia drivers from the Ubuntu package library. It also had all firewall and anti virus software disabled and turned off.&lt;/p&gt; &lt;p&gt;After three executions on each machine I got a proper baseline and the results are displayed in the two images included.&lt;/p&gt; &lt;p&gt;Ubuntu 11.10&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/11/PerfRes_Ubuntu11_10_run3.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="PerfRes_Ubuntu11_10_run3" border="0" alt="PerfRes_Ubuntu11_10_run3" src="http://www.beeii.com/wp-content/uploads/2011/11/PerfRes_Ubuntu11_10_run3_thumb.jpg" width="126" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Windows 7 SP1&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/11/PerfRes_Windows_7_run3.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="PerfRes_Windows_7_run3" border="0" alt="PerfRes_Windows_7_run3" src="http://www.beeii.com/wp-content/uploads/2011/11/PerfRes_Windows_7_run3_thumb.jpg" width="126" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;It seems that Ubuntu has the upper hand in CPU, Memory and HDD performance and Windows only beat it (although by quite a bit) on 3D performance. (Which I expected as the Nvidia GT330M graphics card seems to always be a sticking point for Linux distro's)&lt;/p&gt; &lt;p&gt;I was rather surprised by the difference in performance of the CPU and especially the HDD. Since we know that disk performance is always the biggest bottleneck for VM's then it seems that if you want to squeeze the maximum performance out of your VM's using Ubuntu as a host OS might just be a good choice.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8240337003026117065?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8240337003026117065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8240337003026117065&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8240337003026117065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8240337003026117065'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/11/impact-of-host-os-on-virtual-machine.html' title='The impact of the host OS on virtual machine performance'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-4843754597799644145</id><published>2011-10-07T23:07:00.000+01:00</published><updated>2012-02-10T22:07:53.813Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Denali'/><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><title type='text'>Running Total using Window Functions in Denali</title><content type='html'>&lt;p&gt;At the SQLRelay event in London last night Itzik Ben-Gan did a great session on the Window Functions in Denali. This session got me thinking about the benchmarking that I did a while ago for &lt;a href="http://www.beeii.com/?p=485"&gt;running totals&lt;/a&gt;. In this benchmark the Quirky update performed the fastest by far, however using an update statement is sometimes just not feasible in certain scenarios.&lt;/p&gt; &lt;p&gt;The Window Functions in Denali introduces another way to calculate running total and I thought I would give this a try to see how it stacked up against the quirky update.&lt;/p&gt; &lt;p&gt;Here is the code to create the base table:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;CREATE TABLE RunningBalance (Ident INT IDENTITY(1,1) PRIMARY KEY, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CustomerName VARCHAR(50), &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value INT, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RunningBalance INT) &lt;br&gt;DECLARE @Start INT = 1, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @End INT = 1000000 &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;WHILE @Start &amp;lt;= @End &lt;br&gt;BEGIN &lt;br&gt;&amp;nbsp; &lt;br&gt;&amp;nbsp; INSERT INTO RunningBalance (CustomerName, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value) &lt;br&gt;&amp;nbsp; VALUES('Customer1',1); &lt;br&gt;&amp;nbsp; &lt;br&gt;&amp;nbsp; SET @Start += 1 &lt;br&gt;&amp;nbsp; &lt;br&gt;END&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Since the tests were done on a VM I did a run of the quirky update on the VM and it returned completed in 11 seconds and if we enable the discarding of results after execution in SSMS then the result is 7 seconds.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/10/image.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/10/image_thumb.png" width="420" height="304"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;So next up was the SELECT statement that used the Window Function to calculate the running total.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;SELECT&amp;nbsp; Ident, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CustomerName, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SUM(Value) OVER (PARTITION BY CustomerName &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ORDER BY Ident ASC &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS RunningBalance &lt;br&gt;FROM RunningBalance &lt;br&gt;ORDER BY Ident ASC&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;This statement returned the results in 14 seconds. Which is fantastic as this includes the time to return the results to the grid control in SSMS.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/10/image1.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/10/image_thumb1.png" width="420" height="316"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;If we enable the discarding of results after execution to eliminate the amount of time it takes to populate the grid control in SSMS then the SELECT with the Window Function returns in 6 seconds. This is truly great performance for this type of query!&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/10/image2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/10/image_thumb2.png" width="420" height="302"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The Window Functions in Denali will definitely be adding some fantastic options for solving some of the rather thorny challenges in previous versions of SQL.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-4843754597799644145?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/4843754597799644145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=4843754597799644145&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4843754597799644145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4843754597799644145'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/10/running-total-using-window-functions-in.html' title='Running Total using Window Functions in Denali'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-4406045204395902012</id><published>2011-10-02T23:04:00.000+01:00</published><updated>2012-02-10T22:05:39.142Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Environment'/><category scheme='http://www.blogger.com/atom/ns#' term='BI Test Environement'/><title type='text'>Setting up a virtual BI environment</title><content type='html'>&lt;p&gt;For anyone wanting to setup a test BI environment and looking for a step by step guide have a look at the following TechNet articles &lt;a href="http://technet.microsoft.com/en-us/library/hh223286.aspx"&gt;http://technet.microsoft.com/en-us/library/hh223286.aspx&lt;/a&gt; The step by step guide has both written instructions and webcasts so you can take your pick of the format you like most.&lt;/p&gt; &lt;p&gt;Remember if you are using virtual machines and you copy them from a base line virtual machine you will need to reset the SID of the copied virtual machines using SYSPREP, ensure you have the Generalize checkbox ticked to generate a new SID.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-4406045204395902012?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/4406045204395902012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=4406045204395902012&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4406045204395902012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4406045204395902012'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/10/setting-up-virtual-bi-environment.html' title='Setting up a virtual BI environment'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8746935922399707394</id><published>2011-07-07T23:02:00.000+01:00</published><updated>2012-02-10T22:03:01.503Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='PPS'/><category scheme='http://www.blogger.com/atom/ns#' term='SSAS'/><title type='text'>PerformancePoint Analytic Chart showing unformatted value of SSAS measure</title><content type='html'>&lt;p&gt;I have recently come across some very peculiar behaviour of the PPS Analytic Chart where it for some reason showed values with a scale of 7 instead of the formatted value which has a scale of 2. To make this even more bizarre when you change the chart type to grid and look at the same data it shows all the values as zero (zero is the expected value in this case) with a scale of 2 (0.00).&lt;/p&gt; &lt;p&gt;In the screenshots below the value should display a flat line of 0. As you can see the chart does not display this but shows some very small value with a scale of 7. &lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/07/image.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/07/image_thumb.png" width="374" height="435"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;To make things even stranger when you hover the mouse over the chart the tool tip that displays the value for the particular area on the chart displays the measure value of 0.00 and not the value shown on the y axis as can be seen below.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/07/image4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/07/image_thumb4.png" width="374" height="423"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;If the same analytic chart is changed by right clicking on it and choosing the Grid report type then the values are shown correctly as being 0.00&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/07/image1.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/07/image_thumb1.png" width="374" height="452"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;So this made me think that for some reason the Analytic Chart is not plotting the formatted values received from the SSAS server but that the Analytic grid does. To ensure that this is the case I ran the MDX query that returned the results with CELL PROPERTIES VALUE to return the unformatted value from the cube. The result confirmed my suspicion as can be seen in the screenshot below.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/07/image2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/07/image_thumb2.png" width="117" height="404"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;So PPS is not plotting the formatted value but the actual unformatted value of the measure. When you look at the MDX generated by the Analytic Chart you see that it brings back both the unformatted and formatted Cell Properties and from what I can tell it plots the chart using the unformatted value but uses the formatted value for the tool tip. If you change the MDX generated you lose the interactivity of the Analytic Chart so that is not the solution in this case.&lt;/p&gt; &lt;p&gt;We have only one option and that is to use Currency as the data type in SSAS for the measure, which ensures we will not have the scale issues as it is an exact numeric data type, it does have some great performance benefits too which can be seen in &lt;a href="http://sqlcat.com/technicalnotes/archive/2008/09/25/the-many-benefits-of-money-data-type.aspx"&gt;this&lt;/a&gt; blog post from the SQL CAT team.&lt;/p&gt; &lt;p&gt;After making this change the PPS Analytic Chart is behaving the way we want it to as can be seen in the screenshot below.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/07/image3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/07/image_thumb3.png" width="374" height="495"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;So in conclusion it does look like PerformancePoint has a bug on the Analytic Chart component which in certain cases let it plot the unformatted value of a measure. The one way around this is to change the data type to an exact numeric such as Currency. In this example we could make that change but if we truly needed to use the Double data type for a measure in SSAS then we would have had some serious problems trying to get PPS to display the correct values in the Analytic Chart.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8746935922399707394?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8746935922399707394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8746935922399707394&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8746935922399707394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8746935922399707394'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/07/performancepoint-analytic-chart-showing.html' title='PerformancePoint Analytic Chart showing unformatted value of SSAS measure'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-4512808074464786272</id><published>2011-04-27T22:49:00.000+01:00</published><updated>2012-02-10T21:50:04.911Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='MDX'/><category scheme='http://www.blogger.com/atom/ns#' term='SSAS'/><title type='text'>Create a Last 30 Weekdays Named Set in SSAS</title><content type='html'>&lt;p&gt;One of the most common Sets to be create is the “Last N Days” type of set which is normally just the last 30 or last 60 days from the current day. Another common request is for a Last N Working Days or Weekdays. Lets have a look at how we can create a Named Set that will always provide the last 30 Weekdays using the Adventure Works cube solution.&lt;/p&gt; &lt;p&gt;Lets have a look at the MDX statement that will do the work for us.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Tail &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Extract &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {NULL &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].[Date].MEMBERS &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Current Day].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ).Item(0) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Weekday].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Date] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,30 &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Lets break the MDX down into the main parts and explaining each step in the above statement.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Tail &lt;br&gt;( &lt;br&gt;&amp;nbsp; Extract &lt;br&gt;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {NULL &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &lt;br&gt;&lt;font style="background-color: #ffff00"&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].[Date].MEMBERS &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Current Day].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ).Item(0)&lt;/font&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Weekday].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;br&gt;&amp;nbsp;&amp;nbsp; ,[Date].[Date] &lt;br&gt;&amp;nbsp; ) &lt;br&gt;,30 &lt;br&gt;)&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The highlighted piece of MDX above will get the current day member from the Date attribute hierarchy in the Date dimension. The method used here is described in detail in a previous blog post &lt;a href="http://www.beeii.com/?p=495"&gt;here&lt;/a&gt;. This can be replaced with any MDX that will return the Current Day member.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Tail &lt;br&gt;( &lt;br&gt;&amp;nbsp; Extract &lt;br&gt;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {NULL &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&lt;/font&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].[Date].MEMBERS &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Current Day].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ).Item(0) &lt;br&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/font&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Weekday].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;br&gt;&amp;nbsp;&amp;nbsp; ,[Date].[Date] &lt;br&gt;&amp;nbsp; ) &lt;br&gt;,30 &lt;br&gt;)&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The above highlighted part of the code will create a set containing all the members of the Date attribute hierarchy in the Date dimension before and up to the current day (including the current day).&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Tail &lt;br&gt;( &lt;br&gt;&amp;nbsp; Extract &lt;br&gt;&amp;nbsp; ( &lt;br&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/font&gt;&lt;font color="#ffff00"&gt; &lt;br&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {NULL &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].[Date].MEMBERS &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Current Day].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ).Item(0) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Weekday].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/font&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp; ,[Date].[Date] &lt;br&gt;&amp;nbsp; ) &lt;br&gt;,30 &lt;br&gt;)&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Next we use the Exists function highlighted above to return only the members that are weekdays. This uses an attribute, “Is Weekday”, on the Date dimension that has a True or False as value similar to the “Is Current Day” attribute.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Tail &lt;br&gt;( &lt;br&gt;&lt;font color="#0000ff"&gt;&amp;nbsp; Extract &lt;br&gt;&amp;nbsp; (&lt;/font&gt;&lt;font color="#ffff00"&gt; &lt;br&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {NULL &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].[Date].MEMBERS &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Current Day].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ).Item(0) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Weekday].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;br&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp; ,[Date].[Date] &lt;br&gt;&amp;nbsp; )&lt;/font&gt; &lt;br&gt;,30 &lt;br&gt;)&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Our second last part of the MDX expression is highlighted above. The Extract function is used to only return only the tuples from the Date attribute hierarchy from the current set.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font color="#0000ff"&gt;Tail &lt;br&gt;(&lt;/font&gt; &lt;br&gt;&amp;nbsp; Extract &lt;br&gt;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {NULL &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exists &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].[Date].MEMBERS &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Current Day].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ).Item(0) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,[Date].[Is Weekday].[True] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;br&gt;&amp;nbsp;&amp;nbsp; ,[Date].[Date] &lt;br&gt;&amp;nbsp; ) &lt;br&gt;&lt;font color="#0000ff"&gt;,30 &lt;br&gt;)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The last part of the MDX is to use the Tail function to get the last 30 tuples and thus create a set that contains the last 30 weekdays.&lt;/p&gt; &lt;p&gt;Since the Adventure Works demo DW does not have data for 2011 in it I forced the 31st of August 2004 to be my current day in the cube. The result of using the above MDX in a query is shown below.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/04/image4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/04/image_thumb4.png" width="154" height="415"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;All that is left is to add the MDX to a Named Set in the Adventure Works cube in BIDS.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/04/image5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/04/image_thumb5.png" width="367" height="329"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This method of creating an attribute that indicates if a specific date is a weekday can be modified and used in many different ways to create sets containing specific tuples.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-4512808074464786272?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/4512808074464786272/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=4512808074464786272&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4512808074464786272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4512808074464786272'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/04/create-last-30-weekdays-named-set-in.html' title='Create a Last 30 Weekdays Named Set in SSAS'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-6949289795811875846</id><published>2011-04-26T22:45:00.000+01:00</published><updated>2012-02-10T21:46:32.908Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='MDX'/><category scheme='http://www.blogger.com/atom/ns#' term='SSAS'/><title type='text'>Getting the Current Date in SSAS</title><content type='html'>&lt;p&gt;So there is a few ways that you can go about getting the Current Day in SSAS. It is very often a requirement to have the ability to get the Current Day in an MDX select statement or in a Calculated Member in the cube. Below are a few ways of achieving thins.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Method 1 – The GETDATE() option&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Matt Winslade did a very nice post on this on his blog &lt;a title="http://devmau5.com/blog/?p=47" href="http://devmau5.com/blog/?p=47"&gt;http://devmau5.com/blog/?p=47&lt;/a&gt;&amp;nbsp;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;code&gt;&lt;font color="#000000" face="Trebuchet MS"&gt;StrToMember("[Date].[Date].[" + Format(now(), "yyyyMMdd") + "]")&lt;/font&gt;&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The biggest issue with this method is if your Date attribute hierarchy uses a Key or a Name property that does not conform to one of the standard date formats, sequential numbers for surrogate keys like the Adventure Works demo comes to mind. This would make it quite difficult to construct the correct string to convert to a member.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Method 2 – The IsCurrentDay attribute &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;u&gt;Part 1 using the DSV&lt;/u&gt;&lt;/p&gt; &lt;p&gt;One of my favourite ways is to include an IsCurrentDay attribute on the Date dimension. This attribute will only be “True” for the specific date on the dimension that matches the current date when processing the dimension. In its simplest form (and not best practice) this can be implemented in the DSV of the cube with a new Named Calculation. The DSV should only be used if you do not have access to the underlying tables and views that the SSAS solution is built from.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/04/image.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/04/image_thumb.png" width="141" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/04/image3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/04/image_thumb3.png" width="508" height="252"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/04/image2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/04/image_thumb2.png" width="137" height="316"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The above screenshots is using the Adventure Works demo cube. You can modify the following code snippet by changing the FullDateAlternateKey to the column in your date dimension that contains the date.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;CASE WHEN CONVERT(DATE,FullDateAlternateKey) = CONVERT(DATE,GETDATE()) THEN CONVERT(BIT,1) ELSE CONVERT(BIT,0) END&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Once you have the IsCurrentDay attribute on the Date dimension you will be able to get the current date member by using the following MDX.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Exists([Date].[Date].[Date].MEMBERS,[Date].[Is Current Day].&amp;amp;[True]).Item(0)&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;u&gt;Part 2 using a view for the source of the Date dimension&lt;/u&gt;&lt;/p&gt; &lt;p&gt;Best practice is to use a views as the source for your cube’s dimensions and measure groups. The exact same method described in Part 1 above could be used to create the IsCurrentDay. This would be the best option if you want the IsCurrentDay attribute to be updated automatically each time the cube is processed.&lt;/p&gt; &lt;p&gt;&lt;u&gt;Part 3 using the ETL to update the Date table in the database&lt;/u&gt;&lt;/p&gt; &lt;p&gt;Option 3 is to add a IsCurrentDay column to the date table that the Date dimension is built from. This column is then updated each time the ETL runs. It give more flexibility over which day gets flagged as the Current Day since the ETL can be made much more complex by using ETL execution tables or anything for that matter to update a specific record in the Date Dimension as the Current Day.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The above methods allow us to get the Current day in a cube. Method 1 will always be the most dynamic as it will update based on the system time of the server the SSAS cube is on. This can be either a desired result or a hindrance when a cube is not processed or a backup restored since the Current Day will then be incorrect.&lt;/p&gt; &lt;p&gt;Method 2 is a more controlled method that give the same ability to identify the Current Day but with the ability to have control over which day is flagged as being “Current”. The 3 ways of implementing this is entirely up to the developer’s choice but the recommendation would be to use a View or the ETL to achieve this. If this second method is used you will need to at least do a Process Update on the Date dimension for the changes in current day to take effect.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-6949289795811875846?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/6949289795811875846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=6949289795811875846&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6949289795811875846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6949289795811875846'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/04/getting-current-date-in-ssas.html' title='Getting the Current Date in SSAS'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-3374209356007921774</id><published>2011-04-26T22:43:00.000+01:00</published><updated>2012-02-10T21:44:06.641Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Determine if a day is a weekday using TSQL</title><content type='html'>&lt;p&gt;I have seen a few places where people have created elaborate functions to determine if a day is a week day or not. The easiest way that I have come across and which I personally use is the following statement.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;CASE WHEN DATENAME(DW, GETDATE()) NOT IN ('Saturday', 'Sunday') THEN 1 ELSE 0 END&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The “GETDATE()” part of the code should be changed to the column name which contains your date. If you would rather create a function that uses the above statement then replace the “GETDATE()” with the variable that you use to pass the date into your function.&lt;/p&gt; &lt;p&gt;The nice thing about this is that you can also alter the section that contains you weekend days, by replacing the day names in the brackets at the end with the the days that are not week days.&lt;/p&gt; &lt;p&gt;Keep in mind that if your database language changes to anything other than English then you will need to update the Day Names that you have supplied to be in the correct language. If you are looking for a more universal way which is independent of the Language settings of the database then have a look at the following blog post by Ryan Farley &lt;a title="http://ryanfarley.com/blog/archive/2005/02/14/1685.aspx" href="http://ryanfarley.com/blog/archive/2005/02/14/1685.aspx"&gt;http://ryanfarley.com/blog/archive/2005/02/14/1685.aspx&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-3374209356007921774?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/3374209356007921774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=3374209356007921774&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/3374209356007921774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/3374209356007921774'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/04/determine-if-day-is-weekday-using-tsql.html' title='Determine if a day is a weekday using TSQL'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-128477927780426060</id><published>2011-04-10T22:41:00.000+01:00</published><updated>2012-02-10T21:42:22.250Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Benchmark results for the fastest way to calculate Running Totals in SQL Server</title><content type='html'>&lt;p&gt;I have recently had a challenge to calculate running balances over a very large set of data. This had to be done in TSQL and I found a great article on SQL Server Central by Jeff Moden &lt;a title="http://www.sqlservercentral.com/articles/T-SQL/68467/" href="http://www.sqlservercentral.com/articles/T-SQL/68467/"&gt;http://www.sqlservercentral.com/articles/T-SQL/68467/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The article covers the different methods extensively so I won’t be repeating anything with regards to the methods. I will however post some of the results I achieved using three of the methods.&lt;/p&gt; &lt;p&gt;In the examples I will be using a table with an Identity Column which serves as the Primary Key and thus full fill the requirement of the Quirky update to have a Clustered index in the order of the update. The Identity column will allow the verification of the Running Balance to be much easier as well. We will use a loop to populate the table with a million records.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;CREATE TABLE RunningBalance (Ident INT IDENTITY(1,1) PRIMARY KEY, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CustomerName VARCHAR(50), &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value INT, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RunningBalance INT)&lt;/p&gt; &lt;p&gt;DECLARE @Start INT = 1, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @End INT = 1000000 &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt; &lt;p&gt;WHILE @Start &amp;lt;= @End &lt;br&gt;BEGIN &lt;br&gt;&amp;nbsp; &lt;br&gt;&amp;nbsp; INSERT INTO RunningBalance (CustomerName, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value) &lt;br&gt;&amp;nbsp; VALUES('Customer1',1); &lt;br&gt;&amp;nbsp; &lt;br&gt;&amp;nbsp; SET @Start += 1 &lt;br&gt;&amp;nbsp; &lt;br&gt;END&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The Value field will contain a value of 1 and if the running balance is calculated correctly then the value of the RunningBalance column will equal the Ident column value.&lt;/p&gt; &lt;p&gt;The first method is the Triangular join method and was done using the following code:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;-- Triangular Join Method &lt;br&gt;UPDATE RunningBalance&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET&amp;nbsp;&amp;nbsp;&amp;nbsp; Value = Value + (SELECT ISNULL(SUM(Value),0) FROM RunningBalance WHERE Ident &amp;lt;&amp;nbsp; r.Ident) &lt;br&gt;FROM RunningBalance r&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I stopped the query after 28 minutes as it was clear that this was not a viable method.&lt;/p&gt; &lt;p&gt;Don't forget to reset the RunningBalance table’s RunningBalance column to NULL before testing the different methods.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;UPDATE RunningBalance &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET RunningBalance = NULL&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The next method was to loop through the records using a While Loop and calculate the running balance.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;-- While Loop &lt;br&gt;DECLARE @Start INT = 1, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @End INT = 1000000, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @PrevValue INT &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;WHILE @Start &amp;lt;= @End &lt;br&gt;BEGIN &lt;br&gt;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET @PrevValue = ISNULL((SELECT RunningBalance FROM RunningBalance WHERE Ident = @Start - 1),0)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; UPDATE RunningBalance &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET RunningBalance = Value + @PrevValue &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM RunningBalance r &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE Ident = @Start &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET @Start += 1 &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;END&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This method was much faster and completed the calculation in 7 minutes and 39 seconds.&lt;/p&gt; &lt;p&gt;The last method was the Quirky update and this was performed using the following code.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;-- Quirky Update &lt;br&gt;DECLARE @RunningBalance INT&lt;/p&gt; &lt;p&gt;UPDATE RunningBalance &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET @RunningBalance = RunningBalance = r.Value + ISNULL(@RunningBalance,0) &lt;br&gt;FROM RunningBalance r WITH (TABLOCKX) &lt;br&gt;OPTION (MAXDOP 1)&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The Quirky update performed the calculation in 4 seconds. This is by far the fastest method of all and is definitely worth having a look at when the circumstances allows for its use.&lt;/p&gt; &lt;p&gt;The article by Jeff Moden mentioned at the start of this post covers all the details about the method and is a definite must read.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-128477927780426060?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/128477927780426060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=128477927780426060&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/128477927780426060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/128477927780426060'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/04/benchmark-results-for-fastest-way-to.html' title='Benchmark results for the fastest way to calculate Running Totals in SQL Server'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8662300992931845633</id><published>2011-03-08T21:39:00.000Z</published><updated>2012-02-10T21:40:25.537Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><category scheme='http://www.blogger.com/atom/ns#' term='DW'/><title type='text'>Using a Translation Mart for translations in Data Warehouses, Reports and Cubes</title><content type='html'>&lt;p&gt;In most BI or DW solutions that span different countries and regions there is always a requirement to accommodate multiple languages. There are multiple solutions to this issue especially considering that SSAS has great Multi Language support. However there are normally some challenges with labels in Reporting Services not to mention maintaining one central repository for the translations that can be used across multiple systems.&lt;/p&gt; &lt;p&gt;I have put together a prototype of a database that can be used to achieve the above requirements while storing all translations centrally.&lt;/p&gt; &lt;h3&gt;Installation&lt;/h3&gt; &lt;ol&gt; &lt;li&gt;Create a database on your SQL Server Instance called TranslationMart&amp;nbsp; &lt;li&gt;Run the scripts that form part of the solution in the following order (the scripts can be downloaded &lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/TranslationMart.zip"&gt;here&lt;/a&gt;):  &lt;ul&gt; &lt;li&gt;Create Tables.sql  &lt;li&gt;Create UDF TransPivotResult.sql  &lt;li&gt;Create Function udfTranslate.sql  &lt;li&gt;Create uspReturnTranslationPivot.sql  &lt;li&gt;Create uspReturnTranslationUnPivot.sql &lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Use the “Execute Proc Example.sql” script to test the working of the solution &lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Overview&lt;/h3&gt; &lt;p&gt;The translation solution allows for the easy translating of key business terms that are used in a BI solution. The database structure is a star schema and is shown in the below database diagram.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image0021.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image002_thumb1.jpg" width="309" height="294"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;DimLabel&lt;/b&gt; will contain the term or word that will be translated. The LabelName field will be in the chosen base language.&lt;/p&gt; &lt;p&gt;&lt;b&gt;DimLanguage&lt;/b&gt; will contain all the Microsoft Language codes with their descriptions.&lt;/p&gt; &lt;p&gt;&lt;b&gt;DimGroup&lt;/b&gt; will contain any user created groups. These groups will be used to retrieve sets of translations, for example when you need to translate the labels and report headings of a particular SSRS report. The stored procs that form part of the system will allow you to specify either a group or a particular label that you want to translate. (You do not need to create groups in order to use the solution, they are there to help make retrieving groups of translation easier)&lt;/p&gt; &lt;p&gt;&lt;b&gt;LnkGoupLabel&lt;/b&gt; will contain the mapping between the groups and the labels that form part of a particular group. This allows you to list a label in multiple groups without having to store a label per group in the fact table.&lt;/p&gt; &lt;p&gt;&lt;b&gt;FctTranslation&lt;/b&gt; will contain the translated Label value stored against each of the specific languages.&lt;/p&gt; &lt;h3&gt;Using the solution&lt;/h3&gt; &lt;p&gt;The TranslationMart contains two stored procedures and one Scalar function. The two stored procedures will mainly be used when retrieving translations in batches for use, such as the creation of datasets in SSRS.&lt;/p&gt; &lt;p&gt;Both stored procedures accept three parameters:&lt;/p&gt; &lt;p&gt;&lt;b&gt;@LanguageCode:&lt;/b&gt; This parameter is the language in which you want to translate the Label into.&lt;/p&gt; &lt;p&gt;&lt;b&gt;@LabelName:&lt;/b&gt; This is a label that exists in the DimLabel table which you want to translate; this can be left blank in which case a group name must be provided.&lt;/p&gt; &lt;p&gt;&lt;b&gt;@GroupName: &lt;/b&gt;This is a valid group name that exists in the DimGroup table. If this value is specified the stored procedure will return translated values in the language identified by the @LanguageCode parameter for each label that is linked to the group.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;uspReturnTranslationPivot&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;This stored procedure will create a pivoted result set that has the LabelName values as the column names and one row in the result set with the translated value corresponding to each LabelName.&lt;/p&gt; &lt;p&gt;Due to the fact that you cannot pass a dataset easily to a SSRS function, you cannot retrieve the values in a normal two column result set without having to use a data region, such as a list, to then filter out all values except the one you are interested in.&lt;/p&gt; &lt;p&gt;This stored procedure helps you get around that because SSRS allows you to specify a specific column from a dataset that you would be able to specify for a specific Report Header or textbox. An example of the expression that will be used in a particular textbox or report header is as follows:&lt;/p&gt; &lt;p&gt;=First(Fields!SubHeading.Value, "dsetTestGroup")&lt;/p&gt; &lt;p&gt;&lt;strong&gt;uspReturnTranslationUnPivot&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;This stored procedure is included for use in scenarios where you would like to retrieve translation in a two column result set consisting of LabelName and the translation Value. It works exactly as the above procedure and only differs in that it does not pivot the result set into columns for each LabelName.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The solution also contains a scalar function which can be used to retrieve translations in SELECT statements.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;udfTranslate&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The function accepts two parameters namely @LangaugeCode and @LabelName. It will then return the translated value.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;Examples Results&lt;/h3&gt; &lt;p&gt;The scripts loads data into the tables and translate them into Afrikaans for demo purposes. Below are two queries that show how the data is stored in the database.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;-- Data stored in the fact table &lt;br&gt;SELECT * &lt;br&gt;FROM dbo.FctTranslation FT &lt;br&gt;INNER JOIN DimLabel DL ON FT.LabelID = DL.LabelID &lt;br&gt;INNER JOIN DimLanguage L ON FT.LanguageID = L.LanguageID &lt;br&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;-- Data used to group labels &lt;br&gt;SELECT * &lt;br&gt;FROM dbo.DimGroup DG &lt;br&gt;INNER JOIN LnkGoupLabel GL ON DG.GroupID = GL.GroupID &lt;br&gt;INNER JOIN DimLabel DL ON GL.LabelID = DL.LabelID&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The results are:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/image.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/03/image_thumb.png" width="449" height="178"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Lets look at the data that is returned from the &lt;strong&gt;uspReturnTranslationPivot&lt;/strong&gt; stored procedure.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;-- PIVOT &lt;br&gt;-- Return English Values &lt;br&gt;EXEC [dbo].[uspReturnTranslationPivot] 'en-GB','','TestGroup'&lt;/p&gt; &lt;p&gt;EXEC [dbo].[uspReturnTranslationPivot] 'en-GB','SubHeading',''&lt;/p&gt; &lt;p&gt;-- Return Afrikaans Values &lt;br&gt;EXEC [dbo].[uspReturnTranslationPivot] 'af','','TestGroup'&lt;/p&gt; &lt;p&gt;EXEC [dbo].[uspReturnTranslationPivot] 'af','SubHeading',''&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The results are:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/image1.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/03/image_thumb1.png" width="210" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The &lt;strong&gt;uspReturnTranslationUnPivot &lt;/strong&gt;return the following results.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;-- UNPIVOT &lt;br&gt;-- Return English Values &lt;br&gt;EXEC [dbo].[uspReturnTranslationUnPivot] 'en-GB','','TestGroup'&lt;/p&gt; &lt;p&gt;EXEC [dbo].[uspReturnTranslationUnPivot] 'en-GB','SubHeading',''&lt;/p&gt; &lt;p&gt;-- Return Afrikaans Values &lt;br&gt;EXEC [dbo].[uspReturnTranslationUnPivot] 'af','','TestGroup'&lt;/p&gt; &lt;p&gt;EXEC [dbo].[uspReturnTranslationUnPivot] 'af','SubHeading',''&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/image2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/03/image_thumb2.png" width="210" height="291"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In query translations could be achieved by using the function.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;SELECT&amp;nbsp; L.LabelName, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dbo.udfTranslate('af',LabelName) AS Translation &lt;br&gt;FROM DimLabel L&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/image3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/03/image_thumb3.png" width="199" height="83"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;Maintaining the translations&lt;/h3&gt; &lt;p&gt;It will be possible to maintain the translations in multiple ways. One would be to create a data spec for loading the translations from CSV files using SSIS. Another, which will be the most user friendly, will be to develop a custom front end application to allow users to make changes to the translations.&lt;/p&gt; &lt;h3&gt;Conclusion&lt;/h3&gt; &lt;p&gt;The solution will allow a central place to store all translations which could then be used to translate data in data warehouses or other databases. Performance with a properly partitioned fact table would be very fast.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8662300992931845633?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8662300992931845633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8662300992931845633&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8662300992931845633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8662300992931845633'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/03/using-translation-mart-for-translations.html' title='Using a Translation Mart for translations in Data Warehouses, Reports and Cubes'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-1931152812984926935</id><published>2011-03-03T21:36:00.000Z</published><updated>2012-02-10T21:37:39.555Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Load Test'/><category scheme='http://www.blogger.com/atom/ns#' term='SSAS'/><title type='text'>Quick Installation Guide for Analysis Services Load Testing using ASLoadSim and ASQueryGenerator</title><content type='html'>&lt;p&gt;There are two projects available on the CodePlex &lt;a href="http://sqlsrvanalysissrvcs.codeplex.com/"&gt;website&lt;/a&gt; that allows load testing against Analysis Services. These two projects are ASLoadSim and ASQueryGenerator. The two projects are used in conjunction with each other in order to allow for load testing of a specific SSAS cube. They have been around since 2007 with the most recent update being in 2009.&lt;/p&gt; &lt;p&gt;I recently had to use these two projects to do Load Testing of a Cube and decided to put together a short step by step guide for installation and execution. The ASLoadSim project comes with the &lt;i&gt;SSAS Load Testing Best Practices - Draft v1.3b.doc &lt;/i&gt;document which I will refer to for detailed information regarding certain installation and execution steps.&lt;/p&gt; &lt;p&gt;This is a quick guide to installing the two projects and configuring them to perform Load Testing. This guide assumes that you have the following software installed on your machine.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Microsoft Visual Studio 2010 Premium (Or a version that allows you to create Load Tests) &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You will also require access to the Adventure Works DW Cube as well as a SQL Server instance in which you will create the LoadTest database to capture all the results of the load test.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Quick installation and execution guide&lt;/b&gt;&lt;/p&gt; &lt;p&gt;1. Create a folder on your client machine that you will extract the solutions to. (In this scenario we will call it &lt;i&gt;SSAS Load Test&lt;/i&gt;)&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image002.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image002_thumb.jpg" width="261" height="181"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;2. Create a folder called Queries.&lt;/p&gt; &lt;p&gt;3. Extract the ASLoadSim.zip and ASQueryGenerator.zip files into the folder.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image004.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image004_thumb.jpg" width="322" height="134"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;4. Check the folder properties of both folders to ensure that they are &lt;b&gt;not&lt;/b&gt; set to &lt;i&gt;Read Only&lt;/i&gt;.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image006.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image006_thumb.jpg" width="215" height="262"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;5. Navigate to the ASQueryGenerator folder and double click on the &lt;i&gt;ASQueryGenerator.sln&lt;/i&gt; file to open the solution. (Or open the solution from Visual Studio 2010)&lt;/p&gt; &lt;p&gt;6. Convert the project to using the Visual Studio Conversion Wizard.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image008.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image008" border="0" alt="clip_image008" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image008_thumb.jpg" width="244" height="189"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;7. In the Solution Configuration drop down select &lt;i&gt;Release&lt;/i&gt; and then click on &lt;i&gt;Start Debugging&lt;/i&gt;.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image0094.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image009[4]" border="0" alt="clip_image009[4]" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image0094_thumb.png" width="313" height="72"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This will build the ASQueryGenerator executable in the &lt;i&gt;C:\SSAS Load Test\ASQueryGen\bin\Release\&lt;/i&gt; folder.&lt;/p&gt; &lt;p&gt;8. Open the Template file &lt;i&gt;AdventureWorks_template.XML &lt;/i&gt;in the folder &lt;i&gt;C:\SSAS Load Test\ASQueryGen\Query Templates\ &lt;/i&gt;and make the required changes. (download the AdventureWorks_Template.XML file &lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/AdventureWorks_Template.zip"&gt;here&lt;/a&gt; and add it to the Query Templates folder)&lt;/p&gt; &lt;p&gt;For more information regarding how to make changes to the template file, or for generating a new template file, refer to the document &lt;i&gt;SSAS Load Testing Best Practices - Draft v1.3b.doc p10 (CollectingLoad Queries) and p30 (Generating MDX Client Files)&lt;/i&gt;&lt;/p&gt; &lt;p&gt;9. Open the command prompt.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image011.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image011" border="0" alt="clip_image011" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image011_thumb.jpg" width="232" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;10. In the command prompt navigate to the folder &lt;i&gt;C:\SSAS Load Test\ASQueryGen\bin\Release\&lt;/i&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image013.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image013" border="0" alt="clip_image013" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image013_thumb.jpg" width="404" height="206"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;11. Type the following in the command prompt to generate the Client MDX files. &lt;i&gt;ASQueryGenerator.exe "C:\SSAS Load Test\ASQueryGen\Query Templates\Adventureworks_Template.xml"&lt;/i&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image015.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image015" border="0" alt="clip_image015" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image015_thumb.jpg" width="404" height="206"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;12. Hit &lt;i&gt;Ente&lt;/i&gt;r. You should now see the output of the ASQueryGenerator.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image017.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image017" border="0" alt="clip_image017" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image017_thumb.jpg" width="404" height="206"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;13. Move the &lt;i&gt;Adventureworks_query.xml &lt;/i&gt;files from the &lt;i&gt;C:\SSAS Load Test\ASQueryGen\bin\Release\&lt;/i&gt; folder to the&lt;i&gt; C:\SSAS Load Test\Queries\ &lt;/i&gt;folder.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image019.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image019" border="0" alt="clip_image019" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image019_thumb.jpg" width="404" height="212"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;14. Open the &lt;i&gt;loadtestresultsrepository.sql&lt;/i&gt; SQL Script located in the &lt;i&gt;C:\SSAS Load Test\ASLoadSim\ &lt;/i&gt;folder in SQL Server Management Studio and run the script. (This will create the LoadTest database which is required to log the load test results to.)&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image021.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image021" border="0" alt="clip_image021" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image021_thumb.jpg" width="404" height="243"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;15. Open the &lt;i&gt;UpgradeLoadTestResultsRepository.sql &lt;/i&gt;SQL Script located in the folder C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\ (Remember that if you are running a 64bit Operating System the path will be&lt;i&gt; C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE&lt;/i&gt;)&lt;/p&gt; &lt;p&gt;16. Run the script to upgrade the LoadTest database to the 2010 version.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image023.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image023" border="0" alt="clip_image023" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image023_thumb.jpg" width="404" height="242"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;17. Navigate to the ASLoadSim folder and double click on the &lt;i&gt;ASLoadSim.sln&lt;/i&gt; file to open the solution. (Or open the solution from Visual Studio 2010)&lt;/p&gt; &lt;p&gt;18. Convert the project to using the Visual Studio Conversion Wizard.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image024.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image024" border="0" alt="clip_image024" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image024_thumb.jpg" width="244" height="189"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;19. Click on the &lt;i&gt;Test&lt;/i&gt; menu in the menu bar in Visual Studio.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image025.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image025" border="0" alt="clip_image025" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image025_thumb.png" width="244" height="241"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;20. Click on &lt;i&gt;Manage Test Controllers.&lt;/i&gt;&lt;/p&gt; &lt;p&gt;21. Click on the ellipse next to the connection string shown for &lt;i&gt;Load test results store.&lt;/i&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image027.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image027" border="0" alt="clip_image027" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image027_thumb.jpg" width="281" height="243"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;22. Configure the connection to point to the LoadTest database.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image029.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image029" border="0" alt="clip_image029" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image029_thumb.jpg" width="217" height="316"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;23. Click &lt;i&gt;OK &lt;/i&gt;and then &lt;i&gt;Close &lt;/i&gt;to return to the Visual Studio IDE.&lt;/p&gt; &lt;p&gt;24. Double click on the LoadPlugin.cs file in the Solution Explorer window.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image031.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image031" border="0" alt="clip_image031" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image031_thumb.jpg" width="158" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;25. Scroll down until you find the string&lt;b&gt; &lt;i&gt;private string m_configFileName&lt;/i&gt;&lt;/b&gt; change it to point to the configuration.xml file in the ASLoadSim project folder. Below is an example, remember to use two "\" characters in the path as you can see below.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image033.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image033" border="0" alt="clip_image033" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image033_thumb.jpg" width="448" height="43"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Click on the save button to save the changes made.&lt;/p&gt; &lt;p&gt;26. Double click on the &lt;i&gt;configuration.xml&lt;/i&gt; file to open it.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image035.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image035" border="0" alt="clip_image035" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image035_thumb.jpg" width="162" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;27. Edit the configuration file to correspond to the servers and folders of your deployment.&lt;/p&gt; &lt;p&gt;28. &lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image037.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image037" border="0" alt="clip_image037" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image037_thumb.jpg" width="404" height="151"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;For more details about the configuration file refer to the document &lt;em&gt;SSAS Load Testing Best Practices - Draft v1.3b.doc&lt;/em&gt; &lt;em&gt;p32 (Configure Load Simulator)&lt;/em&gt;&lt;/p&gt; &lt;p&gt;29. Double click the &lt;i&gt;LoadTest1.loadtest &lt;/i&gt;This will open the load test in Visual Studio.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image039.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image039" border="0" alt="clip_image039" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image039_thumb.jpg" width="244" height="240"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Ensure that you change the &lt;i&gt;ConfigFileName&lt;/i&gt; property under the Context Parameters to point to the configuration file inside the ASLoadSim folder if it does not point to it already.&lt;/p&gt; &lt;p&gt;30. Click on the &lt;i&gt;Run Test &lt;/i&gt;button in the top left.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image040.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image040" border="0" alt="clip_image040" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image040_thumb.png" width="285" height="174"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;31. The test will now run and you should see the following screen.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/03/clip_image042.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image042" border="0" alt="clip_image042" src="http://www.beeii.com/wp-content/uploads/2011/03/clip_image042_thumb.jpg" width="404" height="243"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;For more information on editing or creating new load tests refer to the document SSAS Load Testing Best Practices - Draft v1.3b.doc&lt;em&gt; p33 (Configure Visual Studio for Load Test Run)&lt;/em&gt;&lt;/p&gt; &lt;p&gt;For information regarding querying the LoadTest database for Load Test results refer to the document &lt;em&gt;SSAS Load Testing Best Practices - Draft v1.3b.doc&lt;/em&gt; &lt;em&gt;p42 (Reporting Performance Test Results)&lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-1931152812984926935?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/1931152812984926935/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=1931152812984926935&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1931152812984926935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1931152812984926935'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/03/quick-installation-guide-for-analysis.html' title='Quick Installation Guide for Analysis Services Load Testing using ASLoadSim and ASQueryGenerator'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-6508900337912064152</id><published>2011-02-10T21:34:00.000Z</published><updated>2012-02-10T21:35:15.237Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSAS'/><title type='text'>Account Balances and retrieving the last record in Fact Tables</title><content type='html'>&lt;p&gt;Everyone knows how LastNonEmpty behaves according to the official documentation, however recently I looked at a very unique situation in which I had to retrieve the last record in the fact table for a particular time period and I thought I would share this in case anyone found themselves facing the same set of user requirements. Keep in mind that under normal circumstances you would use an ETL and modelling solution to solve the issue but in this case the user requirements and technologies made available prevented it.&lt;/p&gt; &lt;p&gt;Lets say you are busy working with Account Balances. With some example data below:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/02/image.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/02/image_thumb.png" width="346" height="255"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In the above records we see that we have account balance movements for a Customer on a Date at a Time. This means we might have many account movements within a second. Under normal circumstances we would simply take the last movement in the ETL and load that into our fact table or we might try to get the data at a lower level of granularity. However in this example we have the requirement that we load all the records into the fact table because we want the end users to be able to use the “Show Details” option in PerformancePoint graphs and grids to bring back all the movements that happened in a particular time period. (Keep in mind that we do not have SSRS available to us in this example)&lt;/p&gt; &lt;p&gt;So with the stage set lets look at some default aggregation behaviour. If we build the cube with the Account, Date and Time dimensions and use LastNonEmpty as the aggregation for our Value measure we end up with the below results.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/02/image1.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/02/image_thumb1.png" width="305" height="104"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This is exactly the correct behaviour of LastNonEmpty, all the records in our fact table that fall into the lowest level of our time dimension, the second level, are aggregated together and this aggregate is returned. LastNonEmpty as per the documentation does not return the last record in the fact table but the last non empty value for the member on your time hierarchy that you have selected in your cube. (Keep in mind you need to assign the correct dimension types and attribute types to both the Date and Time dimension)&lt;/p&gt; &lt;p&gt;If we want to achieve the desired behaviour mentioned in the beginning we will need to achieve this by changing our model slightly. We will need to introduce and Order dimension.&lt;/p&gt; &lt;p&gt;The Order dimension will simply have a key attribute that runs from 1 to the maximum number of movements you will have within a second for a customer within a second.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/02/image2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/02/image_thumb2.png" width="137" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In our fact table we will add an OrderID column which we will use to link the Order dimension to the fact table but which will also play an important role as a measure to perform a bit of trickery later on. So with this column added the records in the fact table will look as follows.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/02/image8.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/02/image_thumb8.png" width="244" height="201"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The next step is to create a new measure on the measure group with an aggregate function of Max over the OrderID column in the fact table. Lets call it MaxOrder. This measure will be hidden as it will only be used for our calculated measure that will depend on it.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/02/image4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/02/image_thumb4.png" width="154" height="191"&gt;&lt;/a&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/02/image5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/02/image_thumb5.png" width="177" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The next step is to create our calculated member that will work out our account balance. (This looks a little messy and I will add a more elegant method as soon as possible)&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/02/image6.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/02/image_thumb6.png" width="451" height="265"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In the calculation we build a tuple that will always have the Order attribute that is the last one for a specific time period for a customer. This is where the MaxOrder measure is used as it is converted to string and then is used to construct our tuple.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;(STRTOMEMBER("[Order].[Order].[" + CSTR([Measures].[MaxOrder]) + "]"), [Measures].[Value])&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The end result of this is a tuple that would look like this.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;([Order].[Order].[4],[Measures].[Value])&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;After we have create this calculated member we can browse the cube and the result would looks as follows.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/02/image7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/02/image_thumb7.png" width="389" height="101"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Look at the AccountBalance field and you will see that this is now returning the correct results as we would have expected. Also when a user uses PerformancePoint to look at the details of the data they will see all the individual transactions that happened as was the original requirement.&lt;/p&gt; &lt;p&gt;If we want to hide the Order dimension from the users we can simply add a perspective over the cube to achieve this.&lt;/p&gt; &lt;p&gt;It has to be said that there will be a performance cost to all of this and if its possible the best solution will always be to use the correct model with the data at the lowest possible grain or to use the ETL to only bring in the last record at the correct level of granularity. However if like in this example these options are not going to work given the user requirements then its still possible to achieve the desired result as has been shown above.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;&lt;strong&gt;&lt;em&gt;Another Method&lt;/em&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;Another method that works that is more elegant than creating the MaxOrder measure and dynamically building the tuple in a calculated measure is to use the following MDX.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;SUM(TAIL(NonEmptyCrossJoin([Order].[Order].[Order].Members),1),[Measures].[Value])&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/02/image9.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/02/image_thumb9.png" width="454" height="158"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In this case you don’t need to create the MaxOrder measure in the measure group and you only have the calculated member with the above MDX. You still need the Order dimension as in the first method above. From my testing this method works well and is by far a much neater method as it requires much less effort to achieve the result.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-6508900337912064152?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/6508900337912064152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=6508900337912064152&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6508900337912064152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6508900337912064152'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/02/account-balances-and-retrieving-last.html' title='Account Balances and retrieving the last record in Fact Tables'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-3509279638725098730</id><published>2011-02-08T21:32:00.000Z</published><updated>2012-02-10T21:33:13.597Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Power Pivot For Excel'/><title type='text'>Very Useful PowerPivot Diagrams</title><content type='html'>&lt;p&gt;There are two very useful PowerPivot diagrams that illustrates both the client/server architecture as well as the security architecture. These diagrams are available with some more details from the below links.&lt;/p&gt; &lt;p&gt;PowerPivot Client/Server Architecture&lt;/p&gt; &lt;p&gt;&lt;a title="http://sqlcat.com/whitepapers/archive/2010/04/23/powerpivot-technical-diagram-powerpivot-client-server-architecture.aspx" href="http://sqlcat.com/whitepapers/archive/2010/04/23/powerpivot-technical-diagram-powerpivot-client-server-architecture.aspx"&gt;http://sqlcat.com/whitepapers/archive/2010/04/23/powerpivot-technical-diagram-powerpivot-client-server-architecture.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;PowerPivot Security Architecture&lt;/p&gt; &lt;p&gt;&lt;a title="http://technet.microsoft.com/en-us/library/ff955761.aspx" href="http://technet.microsoft.com/en-us/library/ff955761.aspx"&gt;http://technet.microsoft.com/en-us/library/ff955761.aspx&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-3509279638725098730?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/3509279638725098730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=3509279638725098730&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/3509279638725098730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/3509279638725098730'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/02/very-useful-powerpivot-diagrams.html' title='Very Useful PowerPivot Diagrams'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-5178668430243300219</id><published>2011-01-19T21:30:00.000Z</published><updated>2012-02-10T21:31:15.992Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSAS'/><title type='text'>SSAS with Type 2 Slowly Changing Dimensions and Duplicate Members in Attribute Hierarchies</title><content type='html'>&lt;p&gt;Slowly changing dimensions are an integral part of any BI project and while most people are familiar with handling this in the data warehouse, exposing these dimensions to end users through an Analysis Services cube can sometimes be confusing for the end users if not done properly.&lt;/p&gt; &lt;p&gt;Having had such a case recently I have decided to do a quick post explaining some pitfalls as well as ways to deal with Type 2 SCDs in SSAS. There was a lot of questions and answers on the MSDN forums as well as other blog posts but few addressed the issue of having duplicate member names in an attribute hierarchy in an easy and straight forward way.&lt;/p&gt; &lt;p&gt;Lets look at an example of a very easy Type 2 slowly changing dimension table.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb.png" width="482" height="82"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The above table shows a very simple Product dimension with each product rolling up into a Category and the ProductID field being the surrogate key. Records 1 to 3 were the original records in the table and record 4 is a new record inserted when the “Trek Riding Gloves” moved from the “Accessories” category to the “Gloves” category. All of this is normal SCD Type 2 changes handled in the ETL.&lt;/p&gt; &lt;p&gt;When we build the dimension in SSAS from the table you will create two attribute hierarchies namely Product and Category.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image1.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb1.png" width="238" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The Product attribute will be the Key Attribute and you could use the ProductID surrogate key as the KeyColumns property and the Product Name column for the NameColumn property.&lt;/p&gt; &lt;p&gt;If you do not use the Surrogate Key for the KeyColumns property you will need to create a ProductID attribute as the Key Attribute and a Product attribute with a composite key which includes the ProductName field and the CategoryName field for the KeyColumns property and the ProductName field for the NameColumn property. If you do not create this you will end up with the following error:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Errors in the OLAP storage engine: A duplicate attribute key has been found when processing: Table: 'dbo_dimProduct', Column: 'ProductName', Value: 'Trek Riding Gloves'. The attribute is 'Product'.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The reason for this error is that when you have the Attribute Relationships defined in the way the natural hierarchy rolls up in the table (Product rolling up into Category) you will have “Trek Riding Gloves” rolling up into two categories. The attribute relationship we defined expects a Many – to – One rollup from the child level to the parent level.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb2.png" width="256" height="150"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;For this example we will use the Surrogate Key as the KeyColumns property of the Product attribute and not create the composite example mentioned above. It is important to note that both methods will produce the same effect we will look at next.&lt;/p&gt; &lt;p&gt;We create a User Defined Hierarchy that rolls from Category to Product to help with easier navigation.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb3.png" width="303" height="155"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;After processing the dimension we can browse it and have a look at how it will look to the user. The effect is correct for the Products hierarchy which we have defined drilling down as would be expected with “Trek Riding Gloves” appearing under both the “Gloves” and “Accessories” categories.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb4.png" width="166" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The problem comes in when we browse the Product attribute hierarchy where you will see a duplicate entry for “Trek Riding Gloves”.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb5.png" width="164" height="206"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This behaviour is exactly correct because the key for the Product attribute has changed and SSAS uses the KeyColumn of an attribute to identify each member. This is why even if you created a composite key it would still have a duplicate as the combination of ProductName and GroupName would result in a new value. The fact data is being captured against the new record in our dimension and when we browse our cube by Date and the Products User Defined Hierarchy we will see the data split correctly.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image6.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb6.png" width="500" height="213"&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The challenge comes in when a user wants to view the sales at the Product level alone. This will show two lines for “Trek Riding Gloves”.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb7.png" width="500" height="250"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This is confusing to a user and will surely not be welcomed. So we need to ensure that users have the ability to see the sales captured by product without having the duplicates displayed.&lt;/p&gt; &lt;p&gt;The best way to achieve this is to add a new Attribute to the Product dimension which we will call “Product Name”. This attribute will use the ProductName column as its KeyColumns and its NameColumn properties and will have an Attribute Relationship with the Product attribute rolling into the “Product Name” attribute.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image8.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb8.png" width="303" height="155"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image9.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb9.png" width="244" height="164"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;We will in turn hide the Product attribute by setting the AttributeHierarchyVisable property to False. Note that we do not replace the Product attribute in the Products User Defined Hierarchy with our new “Product Name” attribute as this would cause us to have an Unnatural Hierarchy which has a detrimental impact on cube performance etc. (More info about this is available in the SQL Server 2008 White Paper – SSAS Performance Guide available for download here &lt;a title="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3be0488d-e7aa-4078-a050-ae39912d2e43&amp;amp;DisplayLang=en" href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3be0488d-e7aa-4078-a050-ae39912d2e43&amp;amp;DisplayLang=en"&gt;http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3be0488d-e7aa-4078-a050-ae39912d2e43&amp;amp;DisplayLang=en&lt;/a&gt; )&lt;/p&gt; &lt;p&gt;When the user now browses the cube he would have the ability to use the Products hierarchy to view the data drilling down from a Category level to the Product. The user will also then have the ability to look at the data from a product only point of view and this will be achieved by using our new “Product Name” attribute hierarchy and will show only one line per product as can be seen below.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beeii.com/wp-content/uploads/2011/01/image10.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.beeii.com/wp-content/uploads/2011/01/image_thumb10.png" width="500" height="213"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-5178668430243300219?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/5178668430243300219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=5178668430243300219&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/5178668430243300219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/5178668430243300219'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2011/01/ssas-with-type-2-slowly-changing.html' title='SSAS with Type 2 Slowly Changing Dimensions and Duplicate Members in Attribute Hierarchies'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-6196278898467055060</id><published>2010-12-08T21:29:00.000Z</published><updated>2012-02-10T21:29:34.979Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSAS'/><title type='text'>Changing SQL Server Browser Account Using Configuration Manager Fails</title><content type='html'>&lt;p&gt;I have recently run into a rather niggling issue when I tried to change the account under which my SQL Server Browser Service was running.&lt;/p&gt; &lt;p&gt;The issue came to light after realising that I have specified the LocalSystem account for my SSAS service and the NetworkService account for the SQL Server Browser service during a quick installation on a development virtual machine.&amp;nbsp; (Have a look at &lt;a href="http://msdn.microsoft.com/en-us/library/ms143504.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms143504.aspx&lt;/a&gt; for the best practice recommendations regarding the SQL Server service accounts’ setup)&lt;/p&gt; &lt;p&gt;When trying to connect SSAS in Management studio I received the following error:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;A connection cannot be made to redirector. Ensure that 'SQL Browser' service is running. (Microsoft.AnalysisServices.AdomdClient)&lt;/p&gt; &lt;p&gt;No connection could be made because the target machine actively refused it 127.0.0.1:2382 (System)&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This in turn led me to a &lt;a href="http://forums.learnsqlserver.com/SqlServerTopic271.aspx" target="_blank"&gt;blog post&lt;/a&gt; where it was suggested that the SQL Server Browser Service be run under the LocalSystem account instead of the NetworkService account.&lt;/p&gt; &lt;p&gt;When I tried to change this in the SQL Configuration Manager I encountered the following error:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;WMI Provider Error: The group name could not be found. [0x800708ac]&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The solution to this was to change the account under Windows Services instead which worked perfectly and resolved all the above issues.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-6196278898467055060?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/6196278898467055060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=6196278898467055060&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6196278898467055060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6196278898467055060'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/12/changing-sql-server-browser-account.html' title='Changing SQL Server Browser Account Using Configuration Manager Fails'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-7224689607237769514</id><published>2010-12-03T21:27:00.000Z</published><updated>2012-02-10T21:28:06.728Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='MCM'/><title type='text'>SQL Server 2008 Microsoft Certified Master Readiness Videos</title><content type='html'>&lt;p&gt;For anyone looking to achieve the SQL Server 2008 Microsoft Certified Master credentials there are some great readiness videos available at &lt;a title="http://technet.microsoft.com/en-us/sqlserver/ff977043.aspx" href="http://technet.microsoft.com/en-us/sqlserver/ff977043.aspx"&gt;http://technet.microsoft.com/en-us/sqlserver/ff977043.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Even if you are not looking at achieving the MCM certification these videos contain some great content.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-7224689607237769514?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/7224689607237769514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=7224689607237769514&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/7224689607237769514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/7224689607237769514'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/12/sql-server-2008-microsoft-certified.html' title='SQL Server 2008 Microsoft Certified Master Readiness Videos'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-3215646148269698911</id><published>2010-12-02T13:39:00.001Z</published><updated>2010-12-02T13:39:09.598Z</updated><title type='text'>Moving my blog</title><content type='html'>&lt;p&gt;I have recently decided to wind down my blogging on here and have opted to move my blog to &lt;a href="http://www.beeii.com"&gt;www.beeii.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;All the current content has been moved over and in future all new content will be added to the new site. Head over and have a look.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-3215646148269698911?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/3215646148269698911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=3215646148269698911&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/3215646148269698911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/3215646148269698911'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/12/moving-my-blog.html' title='Moving my blog'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-3900157040343159942</id><published>2010-12-01T14:50:00.001Z</published><updated>2010-12-01T15:30:00.702Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='CLR'/><title type='text'>Creating an IsDecimal CLR function for use in TSQL</title><content type='html'>&lt;p&gt;This morning I saw a SQL Server Central &lt;a href="http://www.sqlservercentral.com/articles/IsNumeric/71512/"&gt;article&lt;/a&gt; about the ISNUMERIC function in SQL Server and the fact that it does not always behave the way that people expect it to behave. This reminded me about the first time that I used it and was also surprised when my conversions in my scripts failed after using ISNUMERIC to test for what I believe would be values that would successfully convert to DECIMAL or NUMERIC data types.&lt;/p&gt;  &lt;p&gt;As my experience was during some ETL work I promptly decided to use SSIS and a script task in which I could use the VB.NET Isnumeric() function that provided the desired result. &lt;/p&gt;  &lt;p&gt;However what would you do if you need this functionality in your stored procs or TSQL scripts. One solution is to create the function that is shown at the end of the article, the other solution would be to use a CLR function written in C#. &lt;/p&gt;  &lt;p&gt;The CLR function is really simple to write and the function itself consists mainly of the lines below.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static SqlBoolean IsDecimal(SqlString Value)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; decimal decValue;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (decimal.TryParse(Convert.ToString(Value), out decValue))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new SqlBoolean(true);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new SqlBoolean(false);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The function will use the TryParse method of the decimal type. After deploying the function I ran a test using the same SELECT statements used in the article to make sure that the CLR function returns the desired result.&lt;/p&gt;  &lt;p&gt;Modified SQL statements:&lt;/p&gt; &lt;blockquote&gt;   &lt;p&gt;&lt;script class="brush: sql" type="syntaxhighlighter"&gt;-- Return all characters that ISNUMERIC thinks is numeric &lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;SELECT [Ascii Code]&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; = STR(Number), &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [Ascii Character]&amp;#160;&amp;#160; = CHAR(Number), &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [ISNUMERIC Returns] = ISNUMERIC(CHAR(Number)), &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [IsDecimal Returns] = dbo.IsDecimal(CHAR(Number)) &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160; FROM Master.dbo.spt_Values &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160; WHERE Type = 'P' &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND Number BETWEEN 0 AND 255 &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND ISNUMERIC(CHAR(Number)) = 1 &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;-- Sets of Charachters treat as &amp;quot;Numeric&amp;quot; by ISNUMERIC &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;SELECT dbo.IsDecimal('0d2345') AS [IsDecimal Returns] &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;SELECT dbo.IsDecimal('12e34') AS [IsDecimal Returns]&lt;/script&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The results were spot on with the behaviour I was looking to achieve:&lt;/p&gt;  &lt;table style="border-collapse: collapse" border="0" cellspacing="0" cellpadding="0" width="417"&gt;&lt;colgroup&gt;&lt;font color="#000000"&gt;&lt;col style="width: 53pt; mso-width-source: userset; mso-width-alt: 2596" width="71" /&gt;&lt;col style="width: 74pt; mso-width-source: userset; mso-width-alt: 3620" width="99" /&gt;&lt;col style="width: 97pt; mso-width-source: userset; mso-width-alt: 4717" width="129" /&gt;&lt;col style="width: 89pt; mso-width-source: userset; mso-width-alt: 4352" width="119" /&gt;&lt;/font&gt;&lt;/colgroup&gt;&lt;tbody&gt;     &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" height="20" width="70"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;Ascii Code&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" width="98"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;Ascii Character&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" width="129"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;ISNUMERIC Returns&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" width="118"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;IsDecimal Returns&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;9&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;&amp;#160;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;10&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;&amp;#160;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;11&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;12&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;13&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;&amp;#160;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;36&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;$&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;43&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;+&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;44&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;,&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;45&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;-&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;46&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;.&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;48&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;49&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;50&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;2&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;51&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;3&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;52&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;4&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;53&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;5&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;54&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;6&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;55&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;7&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;56&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;8&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;57&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;9&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;92&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;\&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;128&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;€&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;160&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;&amp;#160;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;162&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;¢&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;163&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;£&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;164&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;¤&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="height: 15pt" height="20"&gt;       &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;165&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;¥&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;        &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: bottom; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt" color="#000000"&gt;0&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The function also worked great for the last two SELECT statements in the above modified code.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/TPZoMPjmG7I/AAAAAAAAAdE/7j1fiX7xnUg/s1600-h/image%5B7%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/TPZoMgQAT0I/AAAAAAAAAdI/272vTBmqeTk/image_thumb%5B3%5D.png?imgmax=800" width="140" height="173" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;If you want to grab a copy of the CLR Project you can download it &lt;a href="http://public.blu.livefilestore.com/y1pt00l8GPMJmEXyOVHaq5mOUUbriOgSp06K5EJ16AdAXb7PhzAOhRKDViqA_btWmf6xhHjOLDO4YZZLdkuo8gykQ/SQLCLRFunctions.zip?download&amp;amp;psid=1"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-3900157040343159942?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/3900157040343159942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=3900157040343159942&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/3900157040343159942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/3900157040343159942'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/12/creating-isdecimal-clr-function-for-use.html' title='Creating an IsDecimal CLR function for use in TSQL'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_eSBtF1cAQjQ/TPZoMgQAT0I/AAAAAAAAAdI/272vTBmqeTk/s72-c/image_thumb%5B3%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-4043132454196240163</id><published>2010-11-30T08:45:00.000Z</published><updated>2010-11-30T08:45:02.839Z</updated><title type='text'>Simon Munro on Professional Tools</title><content type='html'>I thought I would share a blog post by Simon Munro which I thought was brilliant! &lt;a href="http://simonmunro.com/2010/11/23/professional-tools/"&gt;http://simonmunro.com/2010/11/23/professional-tools/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Have a look at the end where he breaks down the cost of a developer using a sub par computer for development. Its always good to see the real cost of decisions and not the window dressing that is so many times held up as the truth.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-4043132454196240163?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/4043132454196240163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=4043132454196240163&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4043132454196240163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4043132454196240163'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/11/simon-munro-on-professional-tools.html' title='Simon Munro on Professional Tools'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-5591160074461607144</id><published>2010-11-22T13:04:00.000Z</published><updated>2010-11-22T13:04:38.574Z</updated><title type='text'>Getting the last occurrence of a character in SSIS using FINDSTRING</title><content type='html'>&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;o:OfficeDocumentSettings&gt;   &lt;o:AllowPNG/&gt;  &lt;/o:OfficeDocumentSettings&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:WordDocument&gt;   &lt;w:View&gt;Normal&lt;/w:View&gt;   &lt;w:Zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:TrackMoves/&gt;   &lt;w:TrackFormatting/&gt;   &lt;w:PunctuationKerning/&gt;   &lt;w:ValidateAgainstSchemas/&gt;   &lt;w:SaveIfXMLInvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:IgnoreMixedContent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:AlwaysShowPlaceholderText&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:DoNotPromoteQF/&gt;   &lt;w:LidThemeOther&gt;EN-GB&lt;/w:LidThemeOther&gt;   &lt;w:LidThemeAsian&gt;X-NONE&lt;/w:LidThemeAsian&gt;   &lt;w:LidThemeComplexScript&gt;X-NONE&lt;/w:LidThemeComplexScript&gt;   &lt;w:Compatibility&gt;    &lt;w:BreakWrappedTables/&gt;    &lt;w:SnapToGridInCell/&gt;    &lt;w:WrapTextWithPunct/&gt;    &lt;w:UseAsianBreakRules/&gt;    &lt;w:DontGrowAutofit/&gt;    &lt;w:SplitPgBreakAndParaMark/&gt;    &lt;w:EnableOpenTypeKerning/&gt;    &lt;w:DontFlipMirrorIndents/&gt;    &lt;w:OverrideTableStyleHps/&gt;   &lt;/w:Compatibility&gt;   &lt;m:mathPr&gt;    &lt;m:mathFont m:val="Cambria Math"/&gt;    &lt;m:brkBin m:val="before"/&gt;    &lt;m:brkBinSub m:val="&amp;#45;-"/&gt;    &lt;m:smallFrac m:val="off"/&gt;    &lt;m:dispDef/&gt;    &lt;m:lMargin m:val="0"/&gt;    &lt;m:rMargin m:val="0"/&gt;    &lt;m:defJc m:val="centerGroup"/&gt;    &lt;m:wrapIndent m:val="1440"/&gt;    &lt;m:intLim m:val="subSup"/&gt;    &lt;m:naryLim m:val="undOvr"/&gt;   &lt;/m:mathPr&gt;&lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"  DefSemiHidden="true" DefQFormat="false" DefPriority="99"  LatentStyleCount="267"&gt;   &lt;w:LsdException Locked="false" Priority="0" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Normal"/&gt;   &lt;w:LsdException Locked="false" Priority="9" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="heading 1"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/&gt;   &lt;w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 1"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 2"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 3"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 4"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 5"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 6"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 7"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 8"/&gt;   &lt;w:LsdException Locked="false" Priority="39" Name="toc 9"/&gt;   &lt;w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/&gt;   &lt;w:LsdException Locked="false" Priority="10" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Title"/&gt;   &lt;w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/&gt;   &lt;w:LsdException Locked="false" Priority="11" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/&gt;   &lt;w:LsdException Locked="false" Priority="22" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Strong"/&gt;   &lt;w:LsdException Locked="false" Priority="20" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="59" SemiHidden="false"   UnhideWhenUsed="false" Name="Table Grid"/&gt;   &lt;w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/&gt;   &lt;w:LsdException Locked="false" Priority="1" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/&gt;   &lt;w:LsdException Locked="false" Priority="34" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/&gt;   &lt;w:LsdException Locked="false" Priority="29" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Quote"/&gt;   &lt;w:LsdException Locked="false" Priority="30" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/&gt;   &lt;w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/&gt;   &lt;w:LsdException Locked="false" Priority="19" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="21" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/&gt;   &lt;w:LsdException Locked="false" Priority="31" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/&gt;   &lt;w:LsdException Locked="false" Priority="32" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/&gt;   &lt;w:LsdException Locked="false" Priority="33" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Book Title"/&gt;   &lt;w:LsdException Locked="false" Priority="37" Name="Bibliography"/&gt;   &lt;w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt; /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin-top:0cm; mso-para-margin-right:0cm; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;}&lt;/style&gt; &lt;![endif]--&gt;  &lt;br /&gt;When looping through a folder containing files to upload it is always much easier to have the For Each Loop container retrieve the filename "Fully Qualified". This allows you to simply specify one variable in the expression used to configure your Flat File Source connection string.&lt;br /&gt;&lt;br /&gt;When you then want to include the name of the file being loaded in the data flow you will have to use a Derived Column Transformation to find the last occurrence of the "\" in the string contained in your filename variable. This can be done using a combination of the FINDSTRING and REVERSE functions, after which you then use the RIGHT function to only retrieve the name of the file with its extension.&lt;br /&gt;&lt;br /&gt;If we look at the below example of a fully qualified filename you will see that there could be any number of "\" characters when your For Each Loop also traverse sub folder.&lt;br /&gt;&lt;blockquote&gt;C:\Test\Upload\DummyFile.csv &lt;/blockquote&gt;&lt;br /&gt;As the FINDSTRING function does not allow built in functionality to allow you to specify that you want the last occurrence we use the REVERSE function to reverse the string and thus give us the first occurrence of the "\" character. After we have determined this we simply subtract the value from the total length of the string and this gives us the position of the last "\" in our fully qualified filename. We then simply use the RIGHT function to retrieve all characters from the last position -1 (remember we want to exclude the character itself from the returned value and only want the filename.). Always remember that you will need to convert your DT_STR (string) datatypes to DT_WSTR (unicode string) as the FINDSTRING expression only works with the latter.&lt;br /&gt;&lt;br /&gt;If we use a variable called strFilename the expression will look like this:&lt;br /&gt;&lt;blockquote&gt;RIGHT(@[User::strFilename],(LEN(@[User::strFilename]) - FINDSTRING(REVERSE((DT_WSTR,50)@[User::strFilename]),"\\",1) -1))&lt;/blockquote&gt;&lt;br /&gt;This will then bring the filename into the data flow.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_eSBtF1cAQjQ/TOpqUJ9GarI/AAAAAAAAAdA/hK6eVVbVOBw/s1600/FilenameDataViewer.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="277" src="http://2.bp.blogspot.com/_eSBtF1cAQjQ/TOpqUJ9GarI/AAAAAAAAAdA/hK6eVVbVOBw/s400/FilenameDataViewer.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-5591160074461607144?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/5591160074461607144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=5591160074461607144&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/5591160074461607144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/5591160074461607144'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/11/getting-last-occurrence-of-character-in.html' title='Getting the last occurrence of a character in SSIS using FINDSTRING'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_eSBtF1cAQjQ/TOpqUJ9GarI/AAAAAAAAAdA/hK6eVVbVOBw/s72-c/FilenameDataViewer.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-6040808122605852091</id><published>2010-11-19T11:25:00.000Z</published><updated>2010-11-19T11:25:09.965Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Project Crescent'/><title type='text'>Project Crescent links and teaser video</title><content type='html'>In case you have missed it here are some links to resources about Project Crescent, the new data visualization tool.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/b/sqlrsteamblog/archive/2010/11/09/a-glimpse-at-project-crescent.aspx"&gt;http://blogs.msdn.com/b/sqlrsteamblog/archive/2010/11/09/a-glimpse-at-project-crescent.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The teaser video can be found here &lt;a href="http://blogs.msdn.com/b/bi/archive/2010/11/09/data-visualization-done-right-project-crescent.aspx"&gt;http://blogs.msdn.com/b/bi/archive/2010/11/09/data-visualization-done-right-project-crescent.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-6040808122605852091?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/6040808122605852091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=6040808122605852091&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6040808122605852091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6040808122605852091'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/11/project-crescent-links-and-teaser-video.html' title='Project Crescent links and teaser video'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-6817075891704605309</id><published>2010-11-10T11:42:00.000Z</published><updated>2010-11-10T11:42:23.272Z</updated><title type='text'>Project Crescent not part of Denali CTP1</title><content type='html'>If you have had a look at the PASS keynote of yesterday ( 9th of November 2010) you will have seen a demo of Project Crescent. Unfortunately a CTP of Crescent will not be shipping with SQl Server Denali CTP1, according to the SQL Server Reporting Services Team Blog &lt;a href="http://blogs.msdn.com/b/sqlrsteamblog/archive/2010/11/09/a-glimpse-at-project-crescent.aspx"&gt;http://blogs.msdn.com/b/sqlrsteamblog/archive/2010/11/09/a-glimpse-at-project-crescent.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Project Crescent's interactivity has reminded me of the data visualizations used by Hans Rosling in his presentations at TED. For those who have never seen one of his presentations and his truly amazing way of letting data tell its story head over to this TED presentation &lt;a href="http://www.ted.com/talks/lang/eng/hans_rosling_at_state.html"&gt;http://www.ted.com/talks/lang/eng/hans_rosling_at_state.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;By the looks of it Project Crescent will, through the interactivity and functionality, give a loud voice to the data in any organization.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-6817075891704605309?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/6817075891704605309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=6817075891704605309&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6817075891704605309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6817075891704605309'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/11/project-crescent-not-part-of-denali.html' title='Project Crescent not part of Denali CTP1'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-266334754167778745</id><published>2010-11-10T09:55:00.001Z</published><updated>2010-11-10T11:21:26.883Z</updated><title type='text'>SQL Server Denali on Technet Wiki</title><content type='html'>Have a look at some of the content that has started to appear on the Technet Wiki for SQL Server Denali. At the moment these are mostly about the changes in SSIS, hopefully we will see more about the other features. I am personally looking forward to seeing some more details regarding Crescent.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://social.technet.microsoft.com/wiki/contents/articles/tags/Denali/default.aspx"&gt;http://social.technet.microsoft.com/wiki/contents/articles/tags/Denali/default.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Books Online for SQL Server Denali has also been made available (in Pre Release format) &lt;a href="http://msdn.microsoft.com/en-us/library/ms130214%28v=SQL.110%29.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms130214%28v=SQL.110%29.aspx &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-266334754167778745?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/266334754167778745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=266334754167778745&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/266334754167778745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/266334754167778745'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/11/sql-server-denali-on-technet-wiki.html' title='SQL Server Denali on Technet Wiki'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8219028457894188488</id><published>2010-11-09T22:52:00.000Z</published><updated>2010-11-09T22:52:28.322Z</updated><title type='text'>SQL Server Denali CTP</title><content type='html'>The CTP of SQL Server Codename Denali (SQL 2011) has bee released and for those who would like to download it you can get it &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6a04f16f-f6be-4f92-9c92-f7e5677d91f9"&gt;here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For a look at some of the new features, which is honestly some of the most amazing functionality to have graced the SQL Server platform, have a look at the SQL PASS Keynote &lt;a href="http://www.sqlpass.org/summit/na2010/LiveKeynotes/Tuesday.aspx"&gt;http://www.sqlpass.org/summit/na2010/LiveKeynotes/Tuesday.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Some of the feature that I have to point (which you will see in the keynote) are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Project Crescent - One of the most exciting web based reporting tools I have ever seen. Think of all the greatest features of all the web based reporting tools you have come across and add to it even more phenomenal interactivity and integration.&lt;/li&gt;&lt;li&gt;Column based storage in SQL Server - This truly delivers amazing performance and is now fully implemented, yes its not some sort of hybrid implementation, its proper fully fledged column based storage in SQL Server.&lt;/li&gt;&lt;/ul&gt;There is a mention of big change to SSIS but no demo in the above keynote. This should all be revealed in the next presentation at SQL PASS.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8219028457894188488?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8219028457894188488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8219028457894188488&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8219028457894188488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8219028457894188488'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/11/sql-server-denali-ctp.html' title='SQL Server Denali CTP'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-5275702974262158354</id><published>2010-11-03T21:47:00.000Z</published><updated>2010-11-03T21:47:51.522Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><category scheme='http://www.blogger.com/atom/ns#' term='BIDS'/><title type='text'>SSIS Formatting Shortcut Keys</title><content type='html'>Have you ever wondered what the shortcut keys are for the Formatting options in a SSIS solution?&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_eSBtF1cAQjQ/TNHWTxX3o1I/AAAAAAAAAcs/4fRq3K4Tpnw/s1600/Formatting+Menu.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="184" src="http://2.bp.blogspot.com/_eSBtF1cAQjQ/TNHWTxX3o1I/AAAAAAAAAcs/4fRq3K4Tpnw/s320/Formatting+Menu.png" width="299" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;br /&gt;These options do not have any shortcut keys assigned to them by default, however you can assign your own. By clicking on "Tools" and then "Options" and finally selecting "Keyboard" you will be able to assign your own shortcut keys to the Formatting options available to you in a SSIS solution in BIDS.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_eSBtF1cAQjQ/TNHWZvkoaNI/AAAAAAAAAc0/idgiRN87XXQ/s1600/Formatting+Shortcut.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="371" src="http://2.bp.blogspot.com/_eSBtF1cAQjQ/TNHWZvkoaNI/AAAAAAAAAc0/idgiRN87XXQ/s640/Formatting+Shortcut.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-5275702974262158354?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/5275702974262158354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=5275702974262158354&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/5275702974262158354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/5275702974262158354'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/11/ssis-formatting-shortcut-keys.html' title='SSIS Formatting Shortcut Keys'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_eSBtF1cAQjQ/TNHWTxX3o1I/AAAAAAAAAcs/4fRq3K4Tpnw/s72-c/Formatting+Menu.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-6184544871681717635</id><published>2010-10-12T11:33:00.000+01:00</published><updated>2010-10-12T11:33:15.180+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><category scheme='http://www.blogger.com/atom/ns#' term='Oracle'/><title type='text'>High Speed Connectors for Oracle and Teradata in SSIS</title><content type='html'>If you have never needed to extract data from Oracle or insert data into an Oracle database in your ETL then you might not know of the Attunity connectors that are available for free (When you use Enterprise Edition of SQL SErver 2008). Its been around for quite a while but definitely worth checking out.&lt;br /&gt;&lt;br /&gt;If you experiece slow performance with the built in connectors for Oracle then have a look at the Attunity connectors. &lt;a href="http://blogs.msdn.com/b/mattm/archive/2008/10/02/attunity-connectors-for-oracle-and-teradata-are-now-available.aspx"&gt;http://blogs.msdn.com/b/mattm/archive/2008/10/02/attunity-connectors-for-oracle-and-teradata-are-now-available.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-6184544871681717635?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/6184544871681717635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=6184544871681717635&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6184544871681717635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6184544871681717635'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/10/high-speed-connectors-for-oracle-and.html' title='High Speed Connectors for Oracle and Teradata in SSIS'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-7029395160498176092</id><published>2010-10-11T13:42:00.001+01:00</published><updated>2010-10-11T13:44:15.866+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><category scheme='http://www.blogger.com/atom/ns#' term='SSAS'/><title type='text'>SSIS Error when connecting to OLAP using OLE DB</title><content type='html'>When connecting to an OLAP SSAS database using an OLE DB Source in SSIS you might see the following error when running the package:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Error: 0xC004701A at Data Flow Task  SSIS.Pipeline: component "OLE DB Source" (1) failed the pre-execute phase and returned error code 0xC0202009.&lt;/blockquote&gt;&lt;br /&gt;The best solution to his has been to add the &lt;blockquote&gt;Format=Tabular&lt;/blockquote&gt;&lt;br /&gt;This is an issue that should be fixed in SP3 of SQL 2005 but I have recently encountered it again and think its worth knowing incase you ever require it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-7029395160498176092?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/7029395160498176092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=7029395160498176092&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/7029395160498176092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/7029395160498176092'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/10/ssis-error-when-connecting-to-olap.html' title='SSIS Error when connecting to OLAP using OLE DB'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8217396852389655825</id><published>2010-10-03T15:51:00.003+01:00</published><updated>2010-10-03T15:57:50.415+01:00</updated><title type='text'>Letting go of the TSQL legacy when using SSIS</title><content type='html'>&lt;p&gt;After reading Johan Åhlén blog &lt;a href=" http://blogical.se/blogs/jahlen/archive/2010/09/19/why-skilled-developers-will-be-even-more-important-in-the-future-with-the-cloud.aspx?CommentPosted=true#commentmessage"&gt;post&lt;/a&gt; about why he believes the cloud will increase the demand for skilled developers it made me think of one of the things in SSIS that has been highlighted many a time but still occurs on occasion. I am talking about the excessive use of TSQL inside SSIS packages for data transformation and loading.&lt;/p&gt;&lt;p&gt;DTS packages made extensive use of TSQL to load data and it is this legacy that has been carried over incorrectly into SSIS development. It is thus no wonder that almost every SSIS training course that is presented starts with telling the delegates on training to forget about what they use to do in DTS as it will only detract from the quality of their work.&lt;/p&gt;&lt;p&gt;Lets have a look at some of the TSQL legacy habits that should be avoided at all cost when using SSIS.&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;h3&gt;Transforming data&lt;/h3&gt;&lt;p&gt;SSIS is an ETL platform that is phenomenal at transforming data in memory thus making it quicker and more robust than performing these transformations in TSQL. The bad practice of using Convert and Cast in your OLE DB Source components in your data flow does not only reduce the speed of your ETL but it also introduces conversion errors that cannot be handled efficiently. &lt;/p&gt;&lt;p&gt;Here is a quick example, if we have to convert nvarchar values to numeric we could encounter a value that might be stored in exponential format for any number of reasons. If we perform our conversion in the TSQL for example: &lt;/p&gt;&lt;p&gt;&lt;script type="syntaxhighlighter" class="brush: sql"&gt;&lt;![CDATA[SELECT CONVERT(NUMERIC(17,8),‘2.0E08’) AS NumericValue]]&gt;&lt;/script&gt; &lt;/p&gt;&lt;p&gt;This conversion will fail and the only way to get around it in TSQL would be to convert it to float first and then to numeric (we are purely talking about conversion and not looking at fixing this at the source which will always be the best solution when possible). This will thus be two conversion that need to take place.&lt;/p&gt;&lt;p&gt;If we chose to do this conversion using a Data Conversion transformation in our Data Flow then this conversion will succeed without any problems. On top of that if any conversion errors do occur SSIS gives you the ability to handle these error rows and thus will allow you to load them into error tables and continue the loading of your data without bringing the whole ETL routine to a grinding halt as will be the case if the TSQL example is used.&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;h3&gt;Inserting Data&lt;/h3&gt;&lt;p&gt;The use of TSQL insert statements instead of proper Data Flow tasks is another big legacy problem. By using these statements you are eliminating the use of proper logging in your ETL. Using these insert statements requires the data to be staged somewhere before the loading of the records into your destination tables and thus is not taking advantage of the SSIS Data Flow engine to reduce staging by performing transformations in memory. If TSQL insert statements are used in SSIS it is normally preceded by TSQL statements that perform transformations on the data and relegates SSIS to be a work flow tool instead of the ETL platform it is. All of this is classic ELT (Extract Load Transform) which was used in DTS and some other ETL tools. It increases disk IO and reduces ETL performance.&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;h3&gt;Using TSQL statements in SSIS instead of stored procedures&lt;/h3&gt;&lt;p&gt;When TSQL statements are used directly in SSIS Execute SQL Tasks it increases the maintenance of your SSIS packages considerably. This means that when a change to the TSQL code needs to be made you will have to edit your SSIS package, retest it and then redeploy the package. &lt;/p&gt;&lt;p&gt;In contrast when stored procedures are used you can be confident that when a change needs to be made this change can be made in the database and there will be no need to redeploy the package provided that, if the stored procedure returns a values to SSIS, it still returns the values in the same structure and order. Due to some intricacies in OLE DB Source components it is perfectly fine to use a simple select statement in them provided you do not fall into the habit of adding your data conversions to these select statements as explained in the first section above.&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;p&gt;I do hear the argument from time to time where people say that “if it works why do I have to change or fix it”, I am sure the same people would agree with me that a Model T Ford would still be perfectly capable of driving down today’s roads but none of them would want to do their daily commute using one. The other argument is normally “We don't deal with large volumes of data so we won’t benefit from the performance increase”, that might be true but you will benefit from a more robust ETL solution and I am sure that with the extra time you will have available to you due to the reduced maintenance requirements of your ETL routines you will discover many other capabilities that SSIS provide on which you were missing out previously. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8217396852389655825?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8217396852389655825/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8217396852389655825&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8217396852389655825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8217396852389655825'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/10/letting-go-of-tsql-legacy-when-using.html' title='Letting go of the TSQL legacy when using SSIS'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-254690245361043051</id><published>2010-09-11T12:27:00.001+01:00</published><updated>2010-09-11T12:52:46.507+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008 R2'/><title type='text'>Microsoft SQL Server 2008 R2 Best Practice Analyzer</title><content type='html'>&lt;p&gt;The SQL Server 2008 R2 best practice analyzer tool has recently been released by Microsoft. To quote from the Microsoft Site:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“The Microsoft SQL Server 2008 R2 BPA is a diagnostic tool that performs the following functions:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Gathers information about a Server and a Microsoft SQL Server 2008 or 2008 R2 instance installed on that Server &lt;/li&gt;      &lt;li&gt;Determines if the configurations are set according to the recommended best practices &lt;/li&gt;      &lt;li&gt;Reports on all configurations, indicating settings that differ from recommendations &lt;/li&gt;      &lt;li&gt;Indicates potential problems in the installed instance of SQL Server &lt;/li&gt;      &lt;li&gt;Recommends solutions to potential problems “ &lt;/li&gt;   &lt;/ul&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The tool can be downloaded &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&amp;amp;FamilyID=0fd439d7-4bff-4df7-a52f-9a1be8725591"&gt;here&lt;/a&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-254690245361043051?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/254690245361043051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=254690245361043051&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/254690245361043051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/254690245361043051'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/09/microsoft-sql-server-2008-r2-best.html' title='Microsoft SQL Server 2008 R2 Best Practice Analyzer'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-7945282851636827229</id><published>2010-09-10T20:14:00.001+01:00</published><updated>2010-09-10T20:14:51.171+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008 R2'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Inserts in your ETL routines slow down for no reason</title><content type='html'>&lt;p&gt;If your ETL loading process has become extremely slow and you cannot figure out why a simple insert of 10 000 records is dragging on for a minute or even more (a simple insert from a source to a target with virtually no transformations in-between should never take that long) then maybe you need to look at your database auto growth settings.&lt;/p&gt;  &lt;p&gt;The database initial size and the database auto growth should always be correctly set according to best practice &lt;a title="http://technet.microsoft.com/en-us/magazine/2008.08.database.aspx" href="http://technet.microsoft.com/en-us/magazine/2008.08.database.aspx"&gt;http://technet.microsoft.com/en-us/magazine/2008.08.database.aspx&lt;/a&gt; In SQL Server 2005 the default setting of auto growth when creating a new database using the GUI was 10%. In SQL Server 2008 this has been changed to 1 MB. If for some reason you do not follow the advice of the above link and set a correct auto growth size this can severely impact database performance. &lt;/p&gt;  &lt;p&gt;The performance degradation can be as severe as a recent case where I was asked to investigate an extremely slow SSIS package. The inserting of 40 000 rows of a fairly wide table with large string columns was taking up to 10 minutes. After confirming that the SSIS package itself was not the problem I had a look at the auto growth of the database and discovered that this had left on the default of SQL Server 2008 which was 1 MB. After setting this to a larger value the same SSIS package loaded the records in 8 seconds. &lt;/p&gt;  &lt;p&gt;So before you try to optimize your SSIS or ETL routines, make sure that you have followed best practice from the start, and that would be right from the very first step of creating your database.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-7945282851636827229?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/7945282851636827229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=7945282851636827229&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/7945282851636827229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/7945282851636827229'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/09/inserts-in-your-etl-routines-slow-down.html' title='Inserts in your ETL routines slow down for no reason'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-2949386378089102040</id><published>2010-08-15T16:25:00.001+01:00</published><updated>2010-08-15T16:25:13.524+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008 R2'/><category scheme='http://www.blogger.com/atom/ns#' term='SMTP'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><title type='text'>Configure Reporting Services to use basic authentication with a SMTP server</title><content type='html'>&lt;p&gt;For anyone that has had the requirement to configure a Reporting Services instance to use a remote SMTP server using basic authentication it is sure a great frustration that basic authentication against a SMTP server is not support. There is however a way to get around this problem. &lt;/p&gt;  &lt;p&gt;All of this can be achieved by using your own virtual SMTP server and setting up message relay with basic authentication to the remote SMTP server. Lets go through the steps to achieve this. &lt;/p&gt;  &lt;p&gt;First you need to install the SMTP feature on your Windows Server instance. In this example I am using Windows Server 2008 R2. In Server Manager go to the features section and click on Add Features.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGnzKShSI/AAAAAAAAAaM/lB6mgEX_A60/s1600-h/image%5B9%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgGoXzhtdI/AAAAAAAAAaQ/o9wZBVh-rzg/image_thumb%5B5%5D.png?imgmax=800" width="374" height="156" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Select SMTP from the list of feature.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgGoxjzhTI/AAAAAAAAAaU/V6dacSoK2Dw/s1600-h/image%5B19%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/TGgGpR_CrVI/AAAAAAAAAaY/Q5FqlhJgMh8/image_thumb%5B9%5D.png?imgmax=800" width="388" height="290" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click on “Add Required Role Services” when you are prompted. (This will added IIS and all the other services that are needed to run the SMTP server)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGp4MKSBI/AAAAAAAAAac/cqJ14509JzA/s1600-h/image%5B20%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/TGgGqJ7M_sI/AAAAAAAAAag/wGgZPeEpxus/image_thumb%5B10%5D.png?imgmax=800" width="288" height="145" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click “Next” until you get the “Confirm Installation Selection” window and then click on “Install”.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgGqnUMViI/AAAAAAAAAak/1AWoVGedmP0/s1600-h/image%5B22%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/TGgGrVx_eAI/AAAAAAAAAao/_pBy-m60CAQ/image_thumb%5B12%5D.png?imgmax=800" width="388" height="293" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click on “Close” after the installation completes.&lt;/p&gt;  &lt;p&gt;Next we need to setup our SMTP server to relay our emails via the remote SMTP server. Click on Start, Administrative Tools and then on Internet Information Services (IIS) 6.0 Manager. (Make sure to select the IIS 6.0 Manager)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGsGmxH7I/AAAAAAAAAas/G8BDbYB9RS4/s1600-h/image%5B62%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGsoi7NYI/AAAAAAAAAaw/QiPJpSF2b_U/image_thumb%5B28%5D.png?imgmax=800" width="388" height="295" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click on the + sign next to the server name to reveal the virtual SMTP server.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGtFF9dhI/AAAAAAAAAa0/Fk-nZqslF2Y/s1600-h/image%5B63%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgGtWNlF9I/AAAAAAAAAa4/bGTOqXZ53fA/image_thumb%5B29%5D.png?imgmax=800" width="388" height="285" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Right click on the SMTP Virtual Server and click on Properties. Under the general tab, select the IP address of for the SMTP server.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgGtkZEsEI/AAAAAAAAAa8/p1AFJNIAS5M/s1600-h/image%5B34%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGuBf5dqI/AAAAAAAAAbA/UVLFHZyHl7I/image_thumb%5B18%5D.png?imgmax=800" width="220" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On the Access tab click on “Relay”.&amp;#160; If you wish to limit the computers that are allowed to relay through this virtual SMTP server by specifying them explicitly then keep the “Only the list below” option selected and add the IP addresses, Domain or group of computers to the list by clicking on the “Add” button. If you want to allow all machines except certain ones to relay emails through the virtual SMTP server then you can select the “All except the list below” option and add machines you specifically want to deny access to into the list by click on the “add” button. (Keep in mind this will allow any machine to relay mail through this virtual SMTP server unless it is specifically blocked. As this is a testing Virtual Machine I have selected the second option)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgGubT5OmI/AAAAAAAAAbE/E8j2fDoEO3E/s1600-h/image%5B37%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGupt3GwI/AAAAAAAAAbI/XN3anNZiMkw/image_thumb%5B19%5D.png?imgmax=800" width="244" height="238" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click “OK” and then click on the Delivery tab. On the Delivery tab click on “Outbound security”.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/TGgGvGwfKhI/AAAAAAAAAbM/Z3YQsYOhTEA/s1600-h/image%5B40%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgGvU3hOAI/AAAAAAAAAbQ/Xaz3mRAxurc/image_thumb%5B20%5D.png?imgmax=800" width="220" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Select “Basic authentication” and specify the username and password that you need to use to authenticate to the remote SMTP server.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGvlEfHMI/AAAAAAAAAbU/c32LGoJxB0M/s1600-h/image%5B43%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgGwDZKLHI/AAAAAAAAAbY/ZrVu-dOAd7E/image_thumb%5B21%5D.png?imgmax=800" width="240" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click on “OK”. Next click on “Outbound connections”. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgGwTA1NbI/AAAAAAAAAbc/9L-oNHc6UGM/s1600-h/image%5B46%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGwxUqT0I/AAAAAAAAAbg/Y6xRrCjHd4k/image_thumb%5B22%5D.png?imgmax=800" width="220" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here we will set the TCP port on which to connect to the SMTP server.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/TGgGxCazFKI/AAAAAAAAAbk/Fybin21Xh1I/s1600-h/image%5B52%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/TGgGxc0iIjI/AAAAAAAAAbs/ugcCnQEBlLk/image_thumb%5B24%5D.png?imgmax=800" width="244" height="131" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click on “OK”. Next click on “Advanced” on the Delivery tab.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGxk5PWAI/AAAAAAAAAbw/X7NPnfVpWsw/s1600-h/image%5B55%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/TGgGyA-kFzI/AAAAAAAAAb0/CqJ7y9ecxs0/image_thumb%5B25%5D.png?imgmax=800" width="220" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here we will specify the address of the remote SMTP server in the “Smart host” textbox.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/TGgGyQ32YCI/AAAAAAAAAb4/2pGUDXGGRdk/s1600-h/image%5B58%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgGy34OFCI/AAAAAAAAAb8/p6EkbYpRSSQ/image_thumb%5B26%5D.png?imgmax=800" width="244" height="236" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click on “OK” twice to complete the setup of the SMTP server. The last thing that remains to be done is to configure Reporting Services to use our virtual SMTP server. You can do that by running the Reporting Services Configuration Manager utility.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/TGgGzj9-DdI/AAAAAAAAAcA/ycCQu6d6RHk/s1600-h/image%5B64%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/TGgG0DhEiZI/AAAAAAAAAcE/PnEhHnGqGus/image_thumb%5B30%5D.png?imgmax=800" width="388" height="292" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Connect to you SSRS instance and then click on the “Email Settings” option.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgG0kAQ5UI/AAAAAAAAAcI/p0IHwnEJXaI/s1600-h/image%5B68%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/TGgG1D5IjNI/AAAAAAAAAcM/jGGNzo9Dx-g/image_thumb%5B32%5D.png?imgmax=800" width="388" height="294" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Type in the email address that will be shown as the sender when SSRS sends emails. (This may be over written by the remote SMTP server so check to see if this is the case. In this example the Google SMTP server will replace any address that you enter here with the email address of the account used to authenticate to it and send emails with.)&lt;/p&gt;  &lt;p&gt;In the “SMTP Server” textbox type the IP address that you selected for the virtual SMTP server. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgG1kKwIsI/AAAAAAAAAcQ/z2_5mHoNcfU/s1600-h/image%5B72%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/TGgG2HGVebI/AAAAAAAAAcU/DLhPPpAATuw/image_thumb%5B34%5D.png?imgmax=800" width="388" height="294" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click on “Apply” and then “Exit” after the settings have been applied successfully.&lt;/p&gt;  &lt;p&gt;Reporting Services is now configured to send emails via the local virtual SMTP server which will relay the emails using the Remote SMTP server using basic authentication. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-2949386378089102040?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/2949386378089102040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=2949386378089102040&amp;isPopup=true' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/2949386378089102040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/2949386378089102040'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/08/configure-reporting-services-to-use.html' title='Configure Reporting Services to use basic authentication with a SMTP server'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_eSBtF1cAQjQ/TGgGoXzhtdI/AAAAAAAAAaQ/o9wZBVh-rzg/s72-c/image_thumb%5B5%5D.png?imgmax=800' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-4485183752171848958</id><published>2010-06-25T13:15:00.001+01:00</published><updated>2010-06-25T13:33:32.421+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>Splitting very large delimited strings in SQL</title><content type='html'>&lt;p&gt;Previously I blogged about how to &lt;a href="http://businessintelligencechronicles.blogspot.com/2009/01/another-take-on-splitting-reporting.html"&gt;split multi valued&lt;/a&gt; report parameters for Reporting Service. In this post I gave the code for a very simple function that will split the values of a delimited string and return them as separate values in result set. This works extremely well for small delimited string values such as those you would normally encounter when working with Reporting Services parameters. However sometimes you might run into a situation where you need to split much larger sets of values (delimited stings with a length of say 200 000 characters or more). In these circumstances a function splitting the values might not perform as optimally as you would have wished. There is an alternative to this, so lets have a look at using a stored procedure and some SQL Server XML functionality to get the same result.&lt;/p&gt;  &lt;h4&gt;Speed comparison between different methods&lt;/h4&gt;  &lt;p&gt;Lets compare two different methods, namely the previous NonXML method (using loops) and the XML method. We will then test this using two different database objects, Functions and Stored Procedures. This should give us a very good indication of the performance in both objects, which would be used to solve different challenges.&lt;/p&gt;  &lt;p&gt;So the first thing we would need to do is construct a very large delimited string value. This can be done using a simple WHILE loop:&lt;/p&gt;  &lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: sql"&gt;&lt;![CDATA[DECLARE @Start INT = 1,&lt;br /&gt;		@End INT = 50000,&lt;br /&gt;		@Text VARCHAR(MAX)&lt;br /&gt;		&lt;br /&gt;WHILE @Start &lt;= @End&lt;br /&gt; BEGIN&lt;br /&gt;	SET @Text = (COALESCE(@Text + ',','') +  CONVERT(VARCHAR(10),@Start))&lt;br /&gt;	SET @Start += 1&lt;br /&gt; END]]&gt;&lt;/script&gt;  &lt;br /&gt;  &lt;p&gt;Lets get a benchmark for the time it takes to construct a concatenated string value consisting of 50 000 values by running the piece of SQL.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/TCSd6GVJnhI/AAAAAAAAAZ8/9T_ut5UrqyU/s1600-h/image%5B3%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/TCSd6ubNkVI/AAAAAAAAAaA/IKZx3fg0Q1k/image_thumb%5B1%5D.png?imgmax=800" width="304" height="74" /&gt;&lt;/a&gt;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;The result in this case is 6 seconds to generate our list of values. The size of the list in, number of characters, is 288 893.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/TCSd7TgTpHI/AAAAAAAAAaE/X4s19gh6AVo/s1600-h/image%5B14%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/TCSd8Tbu1_I/AAAAAAAAAaI/ODWvfmlwrUA/image_thumb%5B10%5D.png?imgmax=800" width="411" height="279" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Next we look at the four SQL Objects that we will examine during our testing. First up is the two functions:&lt;/p&gt;  &lt;p&gt;&lt;u&gt;udf_SplitValuesNonXML&lt;/u&gt;&lt;/p&gt;  &lt;br /&gt;  &lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: sql"&gt;&lt;![CDATA[CREATE FUNCTION [dbo].[udf_SplitValuesNonXML]&lt;br /&gt;(&lt;br /&gt;&lt;br /&gt;--The actual multi-value parameter from reporting services &lt;br /&gt;@String NVARCHAR(MAX),&lt;br /&gt;&lt;br /&gt;--The separator that will is used to delimit each new value in the string&lt;br /&gt;@Seperator NVARCHAR(1)&lt;br /&gt;)&lt;br /&gt;RETURNS @Table TABLE(Result NVARCHAR(4000))&lt;br /&gt;AS&lt;br /&gt;  BEGIN&lt;br /&gt;   --Loop through the string and insert each section into the return table of the table valued function&lt;br /&gt;   WHILE CHARINDEX(@Seperator,@String) &lt;&gt; 0&lt;br /&gt;    BEGIN&lt;br /&gt;    --Insert the value into the return table of the table valued function&lt;br /&gt;    INSERT INTO @Table (Result)&lt;br /&gt;    SELECT SUBSTRING(@String,1,CHARINDEX(@Seperator,@String) - 1)&lt;br /&gt;    --Remove the inserted string from the original string&lt;br /&gt;    SET @String = RIGHT(@String, LEN(@String) - CHARINDEX(@Seperator,@String))&lt;br /&gt;    END&lt;br /&gt;   --Insert the last value in the string into the return table of the table valued function&lt;br /&gt;   INSERT INTO @Table (Result)&lt;br /&gt;   SELECT SUBSTRING(@String,1,LEN(@String))&lt;br /&gt;   RETURN&lt;br /&gt;  END ]]&gt;&lt;/script&gt;  &lt;br /&gt;  &lt;p&gt;As you can see this is the exact same function I posted in the previous post. Next up is our function that makes use of XML.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;udf_SplitValuesXML&lt;/u&gt;&lt;/p&gt;  &lt;br /&gt;  &lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: sql"&gt;&lt;![CDATA[CREATE FUNCTION [dbo].[udf_SplitValuesXML] &lt;br /&gt;(&lt;br /&gt;	-- Declare the variables to be used to pass the text and the delimiter&lt;br /&gt;	@Value VARCHAR(MAX), &lt;br /&gt;	@Delimiter CHAR&lt;br /&gt;)&lt;br /&gt;RETURNS &lt;br /&gt;@SplitValues TABLE &lt;br /&gt;(&lt;br /&gt;	Result VARCHAR(800)&lt;br /&gt;)&lt;br /&gt;AS&lt;br /&gt; BEGIN&lt;br /&gt;	-- Declare an XML variable that will be used to break the text into its seperate values&lt;br /&gt;	DECLARE @XML XML  &lt;br /&gt;&lt;br /&gt;	-- Convert Text To XML&lt;br /&gt;	SET @XML = N'&lt;root&gt;&lt;r&gt;' + replace(@Value,@Delimiter,'&lt;/r&gt;&lt;r&gt;') + '&lt;/r&gt;&lt;/root&gt;'&lt;br /&gt;&lt;br /&gt;	-- Select from the XML into the Temporary table &lt;br /&gt;	INSERT INTO @SplitValues (Result)&lt;br /&gt;	SELECT r.value('.','VARCHAR(800)') as Result&lt;br /&gt;	FROM @XML.nodes('//root/r') as Records(r)  &lt;br /&gt;	&lt;br /&gt;	RETURN &lt;br /&gt; END]]&gt;&lt;/script&gt;  &lt;br /&gt;  &lt;p&gt;The function transforms the delimited text into XML which is stored in an variable of the data type XML. Each delimited value becomes an element node (r) value in the XML that is created. These values are then retrieved using a select statement and inserted into the temporary table that the function returns.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In order to determine the execution time of each procedure we will deduct the time it takes to create the delimited string (6 seconds in our test) from the total time it takes to run the whole statment including the function. For example:&lt;/p&gt;  &lt;br /&gt;  &lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: sql"&gt;&lt;![CDATA[DECLARE @Start INT = 1,&lt;br /&gt;		@End INT = 50000,&lt;br /&gt;		@Text VARCHAR(MAX)&lt;br /&gt;		&lt;br /&gt;WHILE @Start &lt;= @End&lt;br /&gt; BEGIN&lt;br /&gt;	SET @Text = (COALESCE(@Text + ',','') +  CONVERT(VARCHAR(10),@Start))&lt;br /&gt;	SET @Start += 1&lt;br /&gt; END&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;SELECT Result FROM udf_SplitValuesNonXML (@Text,',')]]&gt;&lt;/script&gt;  &lt;br /&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So lets see how these two functions perform when splitting out text value.&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="399"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="201"&gt;&lt;strong&gt;&lt;u&gt;Function&lt;/u&gt;&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="196"&gt;         &lt;p align="center"&gt;&lt;strong&gt;&lt;u&gt;Execution Time&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="202"&gt;udf_SplitValuesNonXML&lt;/td&gt;        &lt;td valign="top" width="195"&gt;         &lt;p align="center"&gt;17sec&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="203"&gt;udf_SplitValuesXML&lt;/td&gt;        &lt;td valign="top" width="195"&gt;         &lt;p align="center"&gt;Stopped after 5minutes&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So clearly using the XML code is not the way forward when you want to split a large delimited text value. Lets see what happens when we use stored procedures.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;usp_SplitValuesNonXML&lt;/u&gt;&lt;/p&gt;  &lt;br /&gt;  &lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: sql"&gt;&lt;![CDATA[CREATE PROCEDURE [dbo].[usp_SplitValuesNonXML]&lt;br /&gt;(&lt;br /&gt;&lt;br /&gt;--The delimited text value&lt;br /&gt;@String NVARCHAR(MAX),&lt;br /&gt;&lt;br /&gt;--The separator that will is used to delimit each new value in the string&lt;br /&gt;@Seperator NVARCHAR(1)&lt;br /&gt;)&lt;br /&gt;AS&lt;br /&gt;  BEGIN&lt;br /&gt;   -- Declare the temporary table&lt;br /&gt;   DECLARE @Table TABLE(Result NVARCHAR(4000))&lt;br /&gt;  &lt;br /&gt;   --Loop through the string and insert each section into the temporary table&lt;br /&gt;   WHILE CHARINDEX(@Seperator,@String) &lt;&gt; 0&lt;br /&gt;    BEGIN&lt;br /&gt;   &lt;br /&gt;     --Insert the value into the temporary table&lt;br /&gt;     INSERT INTO @Table (Result)&lt;br /&gt;     SELECT SUBSTRING(@String,1,CHARINDEX(@Seperator,@String) - 1)&lt;br /&gt;    &lt;br /&gt;     --Remove the inserted string from the original string&lt;br /&gt;     SET @String = RIGHT(@String, LEN(@String) - CHARINDEX(@Seperator,@String))&lt;br /&gt;    &lt;br /&gt;    END&lt;br /&gt;   &lt;br /&gt;    --Insert the last value in the string into the temporary table&lt;br /&gt;    INSERT INTO @Table (Result)&lt;br /&gt;    SELECT SUBSTRING(@String,1,LEN(@String))&lt;br /&gt;   &lt;br /&gt;    -- Select the final result&lt;br /&gt;    SELECT Result FROM @Table&lt;br /&gt;   &lt;br /&gt;  END]]&gt;&lt;/script&gt;  &lt;br /&gt;  &lt;p&gt;This stored proc uses the same logic as the non XML function.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;usp_SplitValuesXML&lt;/p&gt;  &lt;br /&gt;  &lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: sql"&gt;&lt;![CDATA[CREATE PROCEDURE [dbo].[usp_SplitValuesXML] &lt;br /&gt;(&lt;br /&gt;	-- Declare the variables to be used to pass the text and the delimiter&lt;br /&gt;	@Value VARCHAR(MAX), &lt;br /&gt;	@Delimiter CHAR&lt;br /&gt;)&lt;br /&gt;AS&lt;br /&gt; BEGIN&lt;br /&gt;	SET NOCOUNT ON&lt;br /&gt;	-- Declare an XML variable that will be used to break the text into its seperate values&lt;br /&gt;	DECLARE @XML XML  &lt;br /&gt;&lt;br /&gt;	-- Convert Text To XML&lt;br /&gt;	SET @XML = N'&lt;root&gt;&lt;r&gt;' + replace(@Value,@Delimiter,'&lt;/r&gt;&lt;r&gt;') + '&lt;/r&gt;&lt;/root&gt;'&lt;br /&gt;&lt;br /&gt;	-- Select from the XML  &lt;br /&gt;	SELECT r.value('.','VARCHAR(800)') as Result&lt;br /&gt;	FROM @XML.nodes('//root/r') as Records(r)  &lt;br /&gt;	&lt;br /&gt;	RETURN &lt;br /&gt; END]]&gt;&lt;/script&gt;  &lt;br /&gt;  &lt;p&gt;As you can see its the exact same XML logic as we had in the XML function.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Lets see what the performance is like this time round.&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="202"&gt;&lt;strong&gt;&lt;u&gt;Procedure&lt;/u&gt;&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="196"&gt;         &lt;p align="center"&gt;&lt;strong&gt;&lt;u&gt;Execution Time&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="204"&gt;usp_SplitValuesNonXML&lt;/td&gt;        &lt;td valign="top" width="195"&gt;         &lt;p align="center"&gt;35sec&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="205"&gt;usp_SplitValuesXML&lt;/td&gt;        &lt;td valign="top" width="195"&gt;         &lt;p align="center"&gt;2sec&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Clearly the XML logic outperforms the non XML logic by an extremely large margin when it is used in a stored procedure.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Conclusion&lt;/h4&gt;  &lt;p&gt;When you need to split a large delimited text value and you are forced to use a function, then the non XML logic seems to be you best bet. However if you need the fastest performance possible and can use a stored procedure instead of a function then the XML logic shown here outperforms the non XML logic by a huge margin.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-4485183752171848958?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/4485183752171848958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=4485183752171848958&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4485183752171848958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4485183752171848958'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/06/splitting-very-large-delimited-strings.html' title='Splitting very large delimited strings in SQL'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_eSBtF1cAQjQ/TCSd6ubNkVI/AAAAAAAAAaA/IKZx3fg0Q1k/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-7449269456605026474</id><published>2010-04-09T18:18:00.001+01:00</published><updated>2010-04-09T18:18:14.642+01:00</updated><title type='text'>Wayne Eckerson makes a very interesting point</title><content type='html'>&lt;p&gt;Wayne Eckerson has written a very interesting article on the TDWI’s site. It is definitely worth a read and from personal experience I completely agree that industrialized BI teams achieve far less in the same amount of time than their cross skilled counter parts do.&lt;/p&gt;  &lt;p&gt;Have a look at the article here &lt;a title="http://tdwi.org/Articles/2010/04/08/experts-revolutionary-BI.aspx" href="http://tdwi.org/Articles/2010/04/08/experts-revolutionary-BI.aspx"&gt;http://tdwi.org/Articles/2010/04/08/experts-revolutionary-BI.aspx&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-7449269456605026474?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/7449269456605026474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=7449269456605026474&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/7449269456605026474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/7449269456605026474'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/04/wayne-eckerson-makes-very-interesting.html' title='Wayne Eckerson makes a very interesting point'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-1642820635799952669</id><published>2010-04-02T21:56:00.003+01:00</published><updated>2010-04-02T22:04:02.633+01:00</updated><title type='text'>Never use FLOAT as the data type for a measure in a fact table.</title><content type='html'>&lt;p&gt;As a best practise you should never use a Float, Real or Money data for a measure in a fact table. The reason for this is that if you are doing aggregations you are possibly going to receive incorrect result due to the above mentioned types being approximate data types.&lt;/p&gt;&lt;p&gt;Lets have a quick look at an example. On SQLServerCentral.com you can find a good example of this aggregation error. (&lt;a title="http://www.sqlservercentral.com/questions/T-SQL/64521/" href="http://www.sqlservercentral.com/questions/T-SQL/64521/"&gt;http://www.sqlservercentral.com/questions/T-SQL/64521/&lt;/a&gt;) This got me thinking about what the impact would be on a Analysis Services cube.&lt;/p&gt;&lt;p&gt;I changed the code slightly so that I can build a very basic cube.&lt;/p&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: sql"&gt;&lt;![CDATA[DECLARE @SumA float, @SumB float   DECLARE @MyFloat1 float, @MyFloat2 float, @MyFloat3 float    CREATE TABLE MyTable     (    ID int identity,    NumA float,    NumB float    )    SET @MyFloat1 = 10000000000020000    SET @MyFloat2 = -10000000000010000    SET @MyFloat3 = 1    INSERT INTO MyTable    SELECT @MyFloat1, @MyFloat3    UNION    SELECT @MyFloat2, @MyFloat1    UNION ALL    SELECT @MyFloat3, @MyFloat2CREATE TABLE Dim (ID INT,   Descption VARCHAR(50)    )    INSERT INTO Dim    SELECT 1, 'Row1'    UNION ALL    SELECT 2, 'Row2'    UNION ALL    SELECT 3, 'Row3']]&gt;&lt;/script&gt;&lt;br /&gt;&lt;p&gt;I then created a simple cube with the “MyTable” as the fact table and the “Dim” table as the dimension table. When the values are displayed at the all level of the Dim dimension the results are exactly the same as when you do the sum in TSQL. Even if you change the data type of the measures from Inherited to Double in the Analysis Services project you still get the incorrect aggregation.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/S7ZZ51bpyRI/AAAAAAAAAZs/OyUSQgoLk2M/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/S7ZZ6bfey6I/AAAAAAAAAZw/kO1JG0f21xk/image_thumb%5B2%5D.png?imgmax=800" width="557" height="241" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;&lt;p&gt;Always use precision data types for the measures in your cube to avoid these aggregation errors.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-1642820635799952669?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/1642820635799952669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=1642820635799952669&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1642820635799952669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1642820635799952669'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/04/never-use-float-as-data-type-for.html' title='Never use FLOAT as the data type for a measure in a fact table.'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_eSBtF1cAQjQ/S7ZZ6bfey6I/AAAAAAAAAZw/kO1JG0f21xk/s72-c/image_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8394926254425880230</id><published>2010-03-25T09:51:00.002Z</published><updated>2010-03-25T12:47:03.801Z</updated><title type='text'>Syntax Highlighter offline</title><content type='html'>&lt;p&gt;It seems that currently the syntax highlighter developed by Alex Gorbatchev is offline. The URL &lt;a title="http://alexgorbatchev.com/" href="http://alexgorbatchev.com/"&gt;http://alexgorbatchev.com/&lt;/a&gt; give a 403 Error. As a result all the code formatted by it is not displaying. This should be fixed soon and everything will hopefully be back to normal in a short while.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8394926254425880230?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8394926254425880230/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8394926254425880230&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8394926254425880230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8394926254425880230'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/03/syntax-highlighter-offline.html' title='Syntax Highlighter offline'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-1172565084853024668</id><published>2010-03-18T07:22:00.004Z</published><updated>2010-03-18T07:37:55.033Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='XMLA'/><category scheme='http://www.blogger.com/atom/ns#' term='Analysis Services'/><category scheme='http://www.blogger.com/atom/ns#' term='SSAS'/><title type='text'>Combining multiple XMLA commands into one script</title><content type='html'>&lt;p&gt;If you have just started using XMLA to perform some actions against Analysis Services you might be wondering how to combine multiple actions (like create partition actions) into one executable script.&lt;/p&gt;&lt;p&gt;Lets say you have the following two Create Partition scripts.&lt;/p&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;![CDATA[&lt;create xmlns="http://schemas.microsoft.com/analysisservices/2003/engine"&gt;  &lt;parentobject&gt;    &lt;databaseid&gt;DemoCube&lt;/DatabaseID&gt;    &lt;cubeid&gt;DemoSales&lt;/CubeID&gt;    &lt;measuregroupid&gt;FactInternetSales&lt;/MeasureGroupID&gt;  &lt;/ParentObject&gt;  &lt;objectdefinition&gt;    &lt;partition xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ddl2="http://schemas.microsoft.com/analysisservices/2003/engine/2" xmlns:ddl2_2="http://schemas.microsoft.com/analysisservices/2003/engine/2/2" xmlns:ddl100_100="http://schemas.microsoft.com/analysisservices/2008/engine/100/100"&gt;      &lt;id&gt;Fact Internet Sales_1&lt;/ID&gt;      &lt;name&gt;Fact Internet Sales_1&lt;/Name&gt;      &lt;source xsi:type="QueryBinding"&gt;        &lt;datasourceid&gt;DS_DemoDW&lt;/DataSourceID&gt;        &lt;querydefinition&gt;SELECT FS.* FROM FactSales FS INNER JOIN Dim_Time DT ON FS.TimeSK =  DT.TimeSK WHERE DT.Month BETWEEN 0 AND 6&lt;/QueryDefinition&gt;      &lt;/Source&gt;      &lt;storagemode&gt;Molap&lt;/StorageMode&gt;      &lt;processingmode&gt;Regular&lt;/ProcessingMode&gt;      &lt;estimatedrows&gt;1000000&lt;/EstimatedRows&gt;      &lt;aggregationdesignid&gt;AggDesignDemo&lt;/AggregationDesignID&gt;    &lt;/Partition&gt;  &lt;/ObjectDefinition&gt;&lt;/Create&gt;&lt;create xmlns="http://schemas.microsoft.com/analysisservices/2003/engine"&gt;  &lt;parentobject&gt;    &lt;databaseid&gt;DemoCube&lt;/DatabaseID&gt;    &lt;cubeid&gt;DemoSales&lt;/CubeID&gt;    &lt;measuregroupid&gt;FactInternetSales&lt;/MeasureGroupID&gt;  &lt;/ParentObject&gt;  &lt;objectdefinition&gt;    &lt;partition xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ddl2="http://schemas.microsoft.com/analysisservices/2003/engine/2" xmlns:ddl2_2="http://schemas.microsoft.com/analysisservices/2003/engine/2/2" xmlns:ddl100_100="http://schemas.microsoft.com/analysisservices/2008/engine/100/100"&gt;      &lt;id&gt;Fact Internet Sales_2&lt;/ID&gt;      &lt;name&gt;Fact Internet Sales_2&lt;/Name&gt;      &lt;source xsi:type="QueryBinding"&gt;        &lt;datasourceid&gt;DS_DemoDW&lt;/DataSourceID&gt;        &lt;querydefinition&gt;SELECT FS.* FROM FactSales FS INNER JOIN Dim_Time DT ON FS.TimeSK =  DT.TimeSK WHERE DT.Month BETWEEN 7 AND 12&lt;/QueryDefinition&gt;      &lt;/Source&gt;      &lt;storagemode&gt;Molap&lt;/StorageMode&gt;      &lt;processingmode&gt;Regular&lt;/ProcessingMode&gt;      &lt;estimatedrows&gt;1000000&lt;/EstimatedRows&gt;      &lt;aggregationdesignid&gt;AggDesignDemo&lt;/AggregationDesignID&gt;    &lt;/Partition&gt;  &lt;/ObjectDefinition&gt;&lt;/Create&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;If you want to execute both of these statements as one statement you need to enclose them in a Batch using the following XMLA at the beginning and end.&lt;/p&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: xml"&gt;&lt;![CDATA[&lt;batch xmlns="http://schemas.microsoft.com/analysisservices/2003/engine" Transaction="true"&gt;  &lt;create&gt;    &lt;parentobject&gt;      &lt;databaseid&gt;DemoCube&lt;/DatabaseID&gt;      &lt;cubeid&gt;DemoSales&lt;/CubeID&gt;      &lt;measuregroupid&gt;FactInternetSales&lt;/MeasureGroupID&gt;    &lt;/ParentObject&gt;    &lt;objectdefinition&gt;      &lt;partition xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ddl2="http://schemas.microsoft.com/analysisservices/2003/engine/2" xmlns:ddl2_2="http://schemas.microsoft.com/analysisservices/2003/engine/2/2" xmlns:ddl100_100="http://schemas.microsoft.com/analysisservices/2008/engine/100/100"&gt;        &lt;id&gt;Fact Internet Sales_1&lt;/ID&gt;        &lt;name&gt;Fact Internet Sales_1&lt;/Name&gt;        &lt;source xsi:type="QueryBinding"&gt;          &lt;datasourceid&gt;DS_DemoDW&lt;/DataSourceID&gt;          &lt;querydefinition&gt;SELECT FS.* FROM FactSales FS INNER JOIN Dim_Time DT ON FS.TimeSK =  DT.TimeSK WHERE DT.Month BETWEEN 0 AND 6&lt;/QueryDefinition&gt;        &lt;/Source&gt;        &lt;storagemode&gt;Molap&lt;/StorageMode&gt;        &lt;processingmode&gt;Regular&lt;/ProcessingMode&gt;        &lt;estimatedrows&gt;1000000&lt;/EstimatedRows&gt;        &lt;aggregationdesignid&gt;AggDesignDemo&lt;/AggregationDesignID&gt;      &lt;/Partition&gt;    &lt;/ObjectDefinition&gt;  &lt;/Create&gt;  &lt;create xmlns="http://schemas.microsoft.com/analysisservices/2003/engine"&gt;    &lt;parentobject&gt;      &lt;databaseid&gt;DemoCube&lt;/DatabaseID&gt;      &lt;cubeid&gt;DemoSales&lt;/CubeID&gt;      &lt;measuregroupid&gt;FactInternetSales&lt;/MeasureGroupID&gt;    &lt;/ParentObject&gt;    &lt;objectdefinition&gt;      &lt;partition xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ddl2="http://schemas.microsoft.com/analysisservices/2003/engine/2" xmlns:ddl2_2="http://schemas.microsoft.com/analysisservices/2003/engine/2/2" xmlns:ddl100_100="http://schemas.microsoft.com/analysisservices/2008/engine/100/100"&gt;        &lt;id&gt;Fact Internet Sales_2&lt;/ID&gt;        &lt;name&gt;Fact Internet Sales_2&lt;/Name&gt;        &lt;source xsi:type="QueryBinding"&gt;          &lt;datasourceid&gt;DS_DemoDW&lt;/DataSourceID&gt;          &lt;querydefinition&gt;SELECT FS.* FROM FactSales FS INNER JOIN Dim_Time DT ON FS.TimeSK =  DT.TimeSK WHERE DT.Month BETWEEN 7 AND 12&lt;/QueryDefinition&gt;        &lt;/Source&gt;        &lt;storagemode&gt;Molap&lt;/StorageMode&gt;        &lt;processingmode&gt;Regular&lt;/ProcessingMode&gt;        &lt;estimatedrows&gt;1000000&lt;/EstimatedRows&gt;        &lt;aggregationdesignid&gt;AggDesignDemo&lt;/AggregationDesignID&gt;      &lt;/Partition&gt;    &lt;/ObjectDefinition&gt;  &lt;/Create&gt;&lt;/Batch&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Notice that in the opening tag of the Batch statement you can specify whether the batch needs to run in a transaction or not but setting the value for “Transaction” to “True“ or “False”. The script can now be executed and all the commands inside the batch will be run one after the other. This becomes really handy if you need to execute a big batch of commands and want to run them all as one single script.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-1172565084853024668?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/1172565084853024668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=1172565084853024668&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1172565084853024668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1172565084853024668'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/03/combining-multiple-xmla-commands-into.html' title='Combining multiple XMLA commands into one script'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-4531578967933291959</id><published>2010-01-20T09:14:00.000Z</published><updated>2010-01-20T09:14:06.451Z</updated><title type='text'>SQL Server 2008 R2 Release Date</title><content type='html'>SQL Server 2008 R2 has now received its official release date. It is set for May 2010.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.technet.com/dataplatforminsider/archive/2010/01/19/sql-server-2008-r2-gets-an-official-date.aspx"&gt;http://blogs.technet.com/dataplatforminsider/archive/2010/01/19/sql-server-2008-r2-gets-an-official-date.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-4531578967933291959?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/4531578967933291959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=4531578967933291959&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4531578967933291959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4531578967933291959'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/01/sql-server-2008-r2-release-date.html' title='SQL Server 2008 R2 Release Date'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-383860596380369409</id><published>2010-01-14T16:46:00.000Z</published><updated>2010-01-14T16:46:13.587Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><title type='text'>Maximum number of foreign key table references per table</title><content type='html'>Under normal circumstances you would not easily exceed 253 foreign key table references to a particular table in your database; however in the off chance that you do you might receive the same error as I did.&lt;br /&gt;&lt;br /&gt;When doing a delete from the table that was being referenced I received the following error message.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;The query processor ran out of stack space during query optimization. Please simplify the query.&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;After reading the following MSDN &lt;a href="http://msdn.microsoft.com/en-us/library/ms143432.aspx"&gt;article&lt;/a&gt; it was clear that the 253 limit was exceeded and that it took its toll on the hardware that was allocated for our SQL Server 2008 instance. We reduced the number of foreign key references after which the delete worked without any problems.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-383860596380369409?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/383860596380369409/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=383860596380369409&amp;isPopup=true' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/383860596380369409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/383860596380369409'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2010/01/maximum-number-of-foreign-key-table.html' title='Maximum number of foreign key table references per table'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-6888513292552141926</id><published>2009-11-30T21:21:00.006Z</published><updated>2009-12-01T19:45:09.475Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Agent'/><title type='text'>Start a SQL Server Job synchronously using a stored procedure</title><content type='html'>When starting a SQL Server Agent job from your TSQL statements or stored procedures you will notice that the &lt;i&gt;msdb.dbo.sp_start_job &lt;/i&gt;system stored procedure starts this job asynchronously. Meaning that the job will be started but that the stored procedure immediately returns after starting the job and does not wait for it to finish executing. &lt;br /&gt;&lt;br /&gt;Below is a screenshot of the &lt;i&gt;msdb.dbo.sp_start_job&lt;/i&gt; stored procedure starting a job.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SxQ3azpxHfI/AAAAAAAAAZM/KtuOF6IF4BA/s1600-h/ASyncResult%5B4%5D.jpg"&gt;&lt;img alt="ASyncResult" border="0" height="127" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/SxQ3bpNa8jI/AAAAAAAAAZQ/qQqPxQoEHi4/ASyncResult_thumb%5B2%5D.jpg?imgmax=800" style="border-width: 0px; display: inline;" title="ASyncResult" width="368" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;This is understandable as these jobs could run for an indefinite amount of time and undoubtedly you would not want the connection to remain open and possibly timing out. However sometimes due to requirements you might need to start the job synchronously and thus wait for the job to finish running before the stored procedure will finish running. In order to do the I have written the following stored procedure that will do exactly that.&lt;br /&gt;&lt;br /&gt;The code for the stored procedure is below.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: sql"&gt;&lt;![CDATA[-- ==========================================================================================-- Author:        Christo Olivier-- Create date: 30 November 2009-- Description:    This stored procedure will start a job and only exit once it has finished--                executing-- ==========================================================================================ALTER PROCEDURE dbo.SP00StartJobSynchronously( @JobName NVARCHAR(255) = NULL, -- This is the name of the job you want to start @JobID UNIQUEIDENTIFIER = NULL, -- This is the unique identifier of the job @Delay INT = 5 -- This is the delay in seconds to wait before polling the job information)ASBEGIN    -- SET NOCOUNT ON added to prevent extra result sets from    -- interfering with SELECT statements.    SET NOCOUNT ON;    -- Declare parameters    DECLARE @WaitTime NVARCHAR(8)    DECLARE @JobOwner SYSNAME    DECLARE @can_see_all_running_jobs INT    DECLARE @Running INT       -- Declare temporary tables    DECLARE @xp_results TABLE (job_id UNIQUEIDENTIFIER NOT NULL,                               last_run_date INT NOT NULL,                               last_run_time INT NOT NULL,                               next_run_date INT NOT NULL,                               next_run_time INT NOT NULL,                               next_run_schedule_id INT NOT NULL,                               requested_to_run INT NOT NULL, -- BOOL                               request_source INT NOT NULL,                               request_source_id sysname COLLATE database_default NULL,                               running INT NOT NULL, -- BOOL                               current_step INT NOT NULL,                               current_retry_attempt INT NOT NULL,                               job_state INT NOT NULL)       -- Check to see that the @Delay variable is not smaller than 1    IF (@Delay &amp;lt; 1)     SET @Delay = 1    -- Convert the wait time for the delay from integer into the time format hh:mm:ss    SELECT @WaitTime = CONVERT(NVARCHAR(8), DATEADD(second, @Delay, '20090101'), 108);    -- Remove all leading and trailing spaces    SELECT @JobName = LTRIM(RTRIM(@JobName))    -- Set all empty sting values to NULL    IF(@JobName = N'') SELECT @JobName = NULL    -- Check that at least one of the job identifying variables exist    IF ((@JobName IS NULL) AND (@JobID IS NULL))     BEGIN        RAISERROR('At least one of the variables @JobName or @JobID needs to be specified',16,1)        RETURN(1) -- Failure     END    -- Verify the job identifiers and retieve the JobId and JobName and start the job    IF ((@JobId IS NOT NULL) OR (@JobName IS NOT NULL))     BEGIN      DECLARE @retval INT      EXECUTE @retval = msdb.dbo.sp_verify_job_identifiers '@JobName',                                                           '@JobID',                                                            @JobName OUTPUT,                                                            @JobID   OUTPUT                                                      IF (@retval &amp;lt;&amp;gt; 0)        RETURN(1) -- Failure     END    -- Try to start the job    BEGIN      DECLARE @RetVal2 INT          -- Start the SQL Job     EXEC @RetVal2 = msdb.dbo.sp_start_job @job_id = @JobID        -- Job successfully started     IF (@RetVal2 = 0)     -- Set the running variable equal to 1 as the job has just been started     SET @Running = 1            -- Job failed to start     IF (@RetVal2 &amp;lt;&amp;gt; 0)      RETURN(1) -- Failure         END    -- Loop until the job stops running but use the delay to stop hitting the database    -- repeatedly    WHILE @Running &amp;lt;&amp;gt; 0     BEGIN        -- Delay the querying of the job information by the specified amount of seconds        WAITFOR DELAY @WaitTime          -- Capture the job execution information using        SELECT @can_see_all_running_jobs = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)         IF (@can_see_all_running_jobs = 0)          BEGIN          SELECT @can_see_all_running_jobs = ISNULL(IS_MEMBER(N'SQLAgentReaderRole'), 0)         END        SELECT @JobOwner = SUSER_SNAME()         IF ((@@microsoftversion / 0x01000000) &amp;gt;= 8) -- SQL Server 8.0 or greater          INSERT INTO @xp_results          EXECUTE master.dbo.xp_sqlagent_enum_jobs @can_see_all_running_jobs, @JobOwner, @JobId         ELSE          INSERT INTO @xp_results          EXECUTE master.dbo.xp_sqlagent_enum_jobs @can_see_all_running_jobs, @JobOwner                   -- Get the result of wheather the job is still running        SET @Running = (SELECT running                        FROM @xp_results R                        WHERE job_id = @JoBID)               -- Truncate the @xp_results temporary table        DELETE @xp_results            END  -- Print that the job has finished running PRINT('Job ''' + @JobName + ''' has finished.')     SET NOCOUNT OFFEND]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The stored procedure accepts 3 parameters of which only two are required to successfully run.&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;JobName&lt;/i&gt; parameter can be used to pass the name of the SQL Server Job which you want to start while the &lt;i&gt;JobID&lt;/i&gt;&amp;nbsp; parameter can be used to pass the Job Id of the job. In order to run the stored procedure only one of these parameters need to be specified. &lt;br /&gt;&lt;br /&gt;The &lt;i&gt;Delay&lt;/i&gt; parameter is used to specify the interval in seconds that will be waited before polling the database to check if the job has completed running. This parameter is optional and will default to 5 seconds if not specified. &lt;br /&gt;&lt;br /&gt;Below is a screenshot of the stored procedure when used to execute a job. Note that the job that is being executed takes 10 seconds to complete.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SxQ3b8URwcI/AAAAAAAAAZU/DpHI20YM4EM/s1600-h/SynchProcResult%5B8%5D.jpg"&gt;&lt;img alt="SynchProcResult" border="0" height="278" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/SxQ3cpP46CI/AAAAAAAAAZY/me_r52KC-ho/SynchProcResult_thumb%5B4%5D.jpg?imgmax=800" style="border-width: 0px; display: inline;" title="SynchProcResult" width="347" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The proc ran for 12 seconds before finishing. This is due to the job taking 10 seconds to run and the proc being executed with a &lt;i&gt;Delay &lt;/i&gt;of 2 seconds.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-6888513292552141926?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/6888513292552141926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=6888513292552141926&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6888513292552141926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6888513292552141926'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/11/start-sql-server-job-synchronously.html' title='Start a SQL Server Job synchronously using a stored procedure'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_eSBtF1cAQjQ/SxQ3bpNa8jI/AAAAAAAAAZQ/qQqPxQoEHi4/s72-c/ASyncResult_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8325509657935914393</id><published>2009-10-20T09:06:00.008+01:00</published><updated>2009-12-08T12:53:11.178Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL 2008 R2'/><category scheme='http://www.blogger.com/atom/ns#' term='Business Intelligence'/><category scheme='http://www.blogger.com/atom/ns#' term='Power Pivot For Excel'/><category scheme='http://www.blogger.com/atom/ns#' term='MOSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Gemini'/><title type='text'>Project Gemini is SQL Server Power Pivot for Excel 2010</title><content type='html'>Microsoft yesterday announced at the SharePoint conference in Las Vegas that project Gemini is SQL Server Power Pivot for Excel 2010. Not only will this in memory analytics tool be available for Excel but it will also be available in SharePoint. For more information have a look at the following blog post &lt;a href="http://blogs.technet.com/dataplatforminsider/archive/2009/10/19/at-sharepoint-conference-project-gemini-name-officially-revealed-as-microsoft-sql-server-powerpivot-for-excel.aspx"&gt;here&lt;/a&gt; while the official Microsoft site for Power Pivot can be found &lt;a href="http://www.powerpivot.com/"&gt;here&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;This will definitely add a lot of value to the Microsoft BI offering.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8325509657935914393?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8325509657935914393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8325509657935914393&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8325509657935914393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8325509657935914393'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/10/project-gemini-is-sql-server-power.html' title='Project Gemini is SQL Server Power Pivot for Excel 2010'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8663702293224765913</id><published>2009-10-09T23:45:00.001+01:00</published><updated>2009-10-10T01:29:40.825+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSRS 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><title type='text'>One or more parameters were not specified for the subreport</title><content type='html'>&lt;p&gt;When using subreports in Reporting Services you are sure to come across the following warning message, “One or more parameters were not specified for the subreport”. This normally is accompanied by the actual report displaying the message “Error: Subreport could not be shown” in the place where your subreport was to appear.&lt;/p&gt;  &lt;p&gt;This message is normally generated by not passing an actual value to one of the parameters of the subreport but in some cases you might actually be passing values for all the parameters. The most probable reason for this problem is likely to be that you have some “available values” set on your subreport parameters. &lt;/p&gt;  &lt;p&gt;In the example we will use the AdventureWorks database and Reporting Services 2008 with Service Pack 1 applied to our SQL Server instance. We will use one query for the subreport to get all the values form the Sales.SalesOrderDetails table for a specific SalesOrderID. The query is as follows:&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000a0"&gt;SELECT&lt;/font&gt; SalesOrderDetailID,&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CarrierTrackingNumber,&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; OrderQty,&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; UnitPrice&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000a0"&gt;FROM&lt;/font&gt; Sales.SalesOrderDetail&lt;/p&gt;  &lt;p&gt;&lt;font color="#000080"&gt;WHERE&lt;/font&gt; SalesOrderID = @SalesOrderID&lt;/p&gt;  &lt;p&gt;The value for the @SalesOrderID parameter will be supplied form the Main report in which the subreport will run. The query used in the main report is the following:&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;SELECT DISTINCT TOP&lt;/font&gt; 20 SalesOrderID,&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; OrderDate &lt;/p&gt;  &lt;p&gt;&lt;font color="#000080"&gt;FROM&lt;/font&gt; Sales.SalesOrderHeader&lt;/p&gt;  &lt;p&gt;Below is a screenshot of the subreport.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/Ss-85KsqVzI/AAAAAAAAAXw/Ns53diTYY4E/s1600-h/Subreport_Design%5B5%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Subreport_Design" border="0" alt="Subreport_Design" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/Ss-85qkVbTI/AAAAAAAAAX0/_rdHAvXeJm4/Subreport_Design_thumb%5B3%5D.jpg?imgmax=800" width="466" height="161" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Note that at this stage we have no values set for the @SalesOrderID parameter. When the subreport is previewed the user is prompted for the value of the @SalesOrderID parameter. When we provide a valid value the subreport executes and returns the corresponding records for the SalesOrderID value.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/Ss-86IgkjpI/AAAAAAAAAX4/kIStVj49j9Q/s1600-h/Subreport_Preview%5B3%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Subreport_Preview" border="0" alt="Subreport_Preview" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/Ss-861l9sHI/AAAAAAAAAX8/6nolC37c3To/Subreport_Preview_thumb%5B1%5D.jpg?imgmax=800" width="466" height="250" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The main report that will be used is composed of a table with a grouping on the SalesOrderID. The subreport the subreport is added in the details row of the table and is executed for each one of the SalesOrderID values. Below is a screenshot of the report.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/Ss-87MAqo7I/AAAAAAAAAYA/jTdFCC-QHtM/s1600-h/MainReport_Design%5B3%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="MainReport_Design" border="0" alt="MainReport_Design" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/Ss-87pYxHNI/AAAAAAAAAYE/ZNUQWcpGRog/MainReport_Design_thumb%5B1%5D.jpg?imgmax=800" width="466" height="118" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When the report is previewed the subreport is executed for each one of the SalesOrderID values as expected.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/Ss-88IhCHiI/AAAAAAAAAYI/QY4WwRaROLo/s1600-h/MainReport_Preview%5B3%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="MainReport_Preview" border="0" alt="MainReport_Preview" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/Ss-88XSAQsI/AAAAAAAAAYM/dyv8QS1r6Ec/MainReport_Preview_thumb%5B1%5D.jpg?imgmax=800" width="466" height="356" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Lets now change our subreport and add an available value to the SalesOrderID parameter. This can either be a valid value or simply any value that the parameter will accept. This is shown in the screenshot below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/Ss-88yI3dRI/AAAAAAAAAYQ/UXmcHDkUJtI/s1600-h/SubReport_AvailableValue%5B3%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="SubReport_AvailableValue" border="0" alt="SubReport_AvailableValue" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/Ss-89X1gEBI/AAAAAAAAAYU/RVcI57YfLrk/SubReport_AvailableValue_thumb%5B1%5D.jpg?imgmax=800" width="336" height="281" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;It is very important to note that although we are using specific values provided at design time for the subreport, the same behavior will occur when using a dataset to provide the values for the parameter in the subreport.&lt;/p&gt;  &lt;p&gt;When the report is previewed the user is prompted to select the value for the SalesOrderID parameter from the drop down list. Once the value is selected the subreport executes and displays as expected.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/Ss-89vRz_mI/AAAAAAAAAYY/WdwPXbtZ9Bw/s1600-h/SubReport_AvailableValue_Preview%5B3%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="SubReport_AvailableValue_Preview" border="0" alt="SubReport_AvailableValue_Preview" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/Ss-8-BL41uI/AAAAAAAAAYc/6YRqr-Bbv0k/SubReport_AvailableValue_Preview_thumb%5B1%5D.jpg?imgmax=800" width="466" height="212" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When we now switch back to the main report and preview it you will see that only the first instance of the subreport renders correctly, all the subsequent executions of the subreport provides the error “Error: Subreport could not be shown”&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/Ss-8-0NLQlI/AAAAAAAAAYg/Hg5J3N2JVqM/s1600-h/MainReport_AvailableValues_Preview%5B3%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="MainReport_AvailableValues_Preview" border="0" alt="MainReport_AvailableValues_Preview" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/Ss-8_QU-mWI/AAAAAAAAAYk/pEsxKsynZfs/MainReport_AvailableValues_Preview_thumb%5B1%5D.jpg?imgmax=800" width="466" height="406" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If we change our subreport and set the available values to “None” the subreport will once again render correctly in the main report. (We will need to preview the subreport and provide a value as we did in the first instance where we previewed the subreport. This ensures that BIDS will reload the subreport when you run the main report, otherwise it is possible that the older version of it will still be used from the cache and the error will remain the same in the main report)&lt;/p&gt;  &lt;p&gt;Once these changes are made the report again executes correctly.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/Ss-8_gdi9fI/AAAAAAAAAYo/gdBIVXrY-6k/s1600-h/MainReport_Preview%5B7%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="MainReport_Preview" border="0" alt="MainReport_Preview" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/Ss-9AB8GjnI/AAAAAAAAAYs/n5MTub_rzLI/MainReport_Preview_thumb%5B3%5D.jpg?imgmax=800" width="466" height="356" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8663702293224765913?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8663702293224765913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8663702293224765913&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8663702293224765913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8663702293224765913'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/10/one-or-more-parameters-were-not_09.html' title='One or more parameters were not specified for the subreport'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_eSBtF1cAQjQ/Ss-85qkVbTI/AAAAAAAAAX0/_rdHAvXeJm4/s72-c/Subreport_Design_thumb%5B3%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-5381151786888962620</id><published>2009-08-27T19:27:00.001+01:00</published><updated>2009-08-27T19:28:32.617+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS 2008'/><title type='text'>Report Name built in field includes .rdl extension in SharePoint Integrated mode</title><content type='html'>&lt;p&gt;When your Reporting Services 2008 reports use the Report Name built in field you will be interested to know that based on the type of SSRS installation (Native Mode or SharePoint Integrated) you will receive different values.&lt;/p&gt;  &lt;p&gt;Below is an example of a report with the name TestReportName.rdl This report only has the Report Name built in field displayed in a textbox on the report.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SpbP-o4cHTI/AAAAAAAAAWI/Xd3uittVkPU/s1600-h/TestReportName%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="TestReportName" border="0" alt="TestReportName" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/SpbP-2YkgJI/AAAAAAAAAWM/2A1pOF2Xm1M/TestReportName_thumb%5B2%5D.jpg?imgmax=800" width="473" height="189" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When this report is previewed inside Visual Studio or executed using Report Manager in a native mode installation the value of the Report Name built in field is the name of the RDL file excluding the “.rdl” file extension.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/SpbP_WqA8II/AAAAAAAAAWQ/8yy0iT5nIXA/s1600-h/TestReportNameVSPreview%5B4%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="TestReportNameVSPreview" border="0" alt="TestReportNameVSPreview" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/SpbP__tou3I/AAAAAAAAAWU/7ePiRAgX7vs/TestReportNameVSPreview_thumb%5B2%5D.jpg?imgmax=800" width="519" height="163" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;When the same report is deployed to a SharePoint Integrate Reporting Services installation the value of the Report Name built in function will include the “.rdl” file extension as in the example below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SpbQAQUDiDI/AAAAAAAAAWY/ITWGk5_0x7I/s1600-h/TestReportNameSIView%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="TestReportNameSIView" border="0" alt="TestReportNameSIView" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/SpbQA33VwMI/AAAAAAAAAWc/KoyjCuBmSp0/TestReportNameSIView_thumb%5B1%5D.jpg?imgmax=800" width="473" height="168" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In order to remove this you could use an expression in every instance where you use the Report Name built in field. However it would be much better to create a function in the custom code section. This would allow one central place where the code can reside and should you want to make any changes you would not need to change each expression. &lt;/p&gt;  &lt;p&gt;The following expression will strip the “.rdl” section from the Report Name.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#0000a0"&gt;Public Function&lt;/font&gt; RepName(&lt;font color="#0000a0"&gt;ByVal&lt;/font&gt; BIReportName &lt;font color="#0000a0"&gt;As String&lt;/font&gt;) &lt;font color="#0000a0"&gt;As String&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;RepName = Left(BIReportName, IIf(BIReportName.LastIndexOf(&lt;font color="#ff0000"&gt;&amp;quot;.&amp;quot;&lt;/font&gt;) = -1, BIReportName.Length, BIReportName.LastIndexOf(&lt;font color="#ff0000"&gt;&amp;quot;.&amp;quot;&lt;/font&gt;)))&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000a0"&gt;End Function&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/SpbQBee0jrI/AAAAAAAAAWg/x9S6ZUSKD5s/s1600-h/CustomCodeFuction%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="CustomCodeFuction" border="0" alt="CustomCodeFuction" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/SpbQBmxYoFI/AAAAAAAAAWk/IzB7UhhfXpU/CustomCodeFuction_thumb%5B2%5D.jpg?imgmax=800" width="435" height="278" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Simply use the function created above in the expression as shown below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SpbQCGUecqI/AAAAAAAAAWo/ne5Habz6BRo/s1600-h/Expression%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Expression" border="0" alt="Expression" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/SpbQCmexPsI/AAAAAAAAAWs/5am_BkEy9t0/Expression_thumb%5B1%5D.jpg?imgmax=800" width="328" height="299" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-5381151786888962620?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/5381151786888962620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=5381151786888962620&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/5381151786888962620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/5381151786888962620'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/08/reportname-built-in-field-includes-rdl.html' title='Report Name built in field includes .rdl extension in SharePoint Integrated mode'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_eSBtF1cAQjQ/SpbP-2YkgJI/AAAAAAAAAWM/2A1pOF2Xm1M/s72-c/TestReportName_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-6416027386624693808</id><published>2009-08-23T15:31:00.001+01:00</published><updated>2009-08-23T15:31:20.544+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Map Report Item'/><category scheme='http://www.blogger.com/atom/ns#' term='Spatial Data'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008 R2'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL 2008 R2 CTP'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS 2008'/><title type='text'>Map report item in SQL Server 2008 R2 August CTP</title><content type='html'>&lt;p&gt;The August CTP for SQL Server 2008 R2 was made available on the 10th of August and one of the features available is the new Map report item in Reporting Services.&lt;/p&gt;  &lt;p&gt;The map report item can be used to visualize business data against a geographical background. This is a really nice feature that will surely add a lot of value to Reporting Services.&lt;/p&gt;  &lt;p&gt;The Map report item is visible on the screenshot as a globe in the toolbox.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SpFStFZHETI/AAAAAAAAAV4/RFGKYbIiCvA/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/SpFSt6_qQDI/AAAAAAAAAV8/lTJQu3OMAY8/image_thumb%5B2%5D.png?imgmax=800" width="455" height="273" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The Map report item supports the&amp;#160; the following spatial data sources:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Map Gallery reports&lt;/li&gt;    &lt;li&gt;ESRI shapefiles&lt;/li&gt;    &lt;li&gt;SQL Server spatial data stored in a database&lt;/li&gt;    &lt;li&gt;Custom locations created by the developer&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In the next post I will explore the capabilities of the Map report item and create a few reports that take advantage of this new feature.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-6416027386624693808?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/6416027386624693808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=6416027386624693808&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6416027386624693808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6416027386624693808'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/08/map-report-item-in-sql-server-2008-r2.html' title='Map report item in SQL Server 2008 R2 August CTP'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_eSBtF1cAQjQ/SpFSt6_qQDI/AAAAAAAAAV8/lTJQu3OMAY8/s72-c/image_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8743801016514598059</id><published>2009-07-25T18:30:00.001+01:00</published><updated>2009-07-25T18:32:47.259+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS 2008'/><title type='text'>Header row does not repeat on subsequent pages</title><content type='html'>&lt;p&gt;If you want the header row of a table to repeat in a Reporting Services 2008 report you might find that setting the “Repeat header rows on each page” setting (shown in the below screenshot) does not produce the desired results.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SmtBCURiPpI/AAAAAAAAAVI/9Eg9lb7H_VY/s1600-h/image%5B3%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/SmtBC6EntII/AAAAAAAAAVM/QNdRIw19oXM/image_thumb%5B1%5D.png?imgmax=800" width="269" height="277" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt; This normally happens when you have a table with no groupings, which would just contain the details group and a header row as in the screenshot below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SmtBDdYM9cI/AAAAAAAAAVQ/T-AYtTRYQSo/s1600-h/image%5B23%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SmtBEfuPnbI/AAAAAAAAAVU/9uikNm-0UZc/image_thumb%5B13%5D.png?imgmax=800" width="317" height="150" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;In order to get the header row to repeat you need to enable “Advanced Mode” on the groupings panes at the bottom of the report designer.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/SmtBE6-xBRI/AAAAAAAAAVY/8HwUPAEWcBo/s1600-h/image%5B16%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/SmtBFZTASTI/AAAAAAAAAVc/W_oeVDRThF0/image_thumb%5B10%5D.png?imgmax=800" width="299" height="70" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Once you have done this you will see that you are presented with a couple of static groups that now appear in the Row Groups and Column Groups panes.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SmtBF4XEsLI/AAAAAAAAAVg/WSEGO2WERbk/s1600-h/image%5B12%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/SmtBGdIu9iI/AAAAAAAAAVk/99-Fv6hs0Pg/image_thumb%5B6%5D.png?imgmax=800" width="299" height="71" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Select the static group above the Details group in the Row Groups pane. This is the header row of the details group. In the properties window scroll down and find the “RepeatOnNewPage” property. Set this property’s value to “True”&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/SmtBG_tnwTI/AAAAAAAAAVo/q0_essVRvXk/s1600-h/image%5B19%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SmtBHLZElSI/AAAAAAAAAVs/qOz8wgNXqQ8/image_thumb%5B11%5D.png?imgmax=800" width="194" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;After you have set this property run the report again. You will now see that the header row repeats on each page.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SmtBp_hMvfI/AAAAAAAAAVw/UGzpIv9fy3E/s1600-h/image%5B27%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/SmtBqQCCRTI/AAAAAAAAAV0/cmXqCZOn0ms/image_thumb%5B15%5D.png?imgmax=800" width="327" height="201" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8743801016514598059?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8743801016514598059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8743801016514598059&amp;isPopup=true' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8743801016514598059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8743801016514598059'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/07/header-row-does-not-repeat-on.html' title='Header row does not repeat on subsequent pages'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_eSBtF1cAQjQ/SmtBC6EntII/AAAAAAAAAVM/QNdRIw19oXM/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-588453620950770057</id><published>2009-07-21T20:23:00.001+01:00</published><updated>2009-07-21T20:23:43.997+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008'/><title type='text'>Error restoring a database (Operating system error 5(Access is denied.))</title><content type='html'>&lt;p&gt;A while ago I had to do a seemingly trivial task. Copy a database backup file to a server and restore the database. I was busy using SQL Server 2008 and the database backups were also made on a SQL Server 2008 instance.&lt;/p&gt;  &lt;p&gt;After copying the files onto the machine I set about trying to restore the backup in the normal way through SQL Server Management Studio. I made sure that the files were not marked as read only. I received the following error.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#ff0000"&gt;Cannot open backup device 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Backup\Staging.bak'. Operating system error 5(Access is denied.).       &lt;br /&gt;RESTORE HEADERONLY is terminating abnormally. (.Net SqlClient Data Provider)&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I followed the link that it provides with the error &lt;a title="http://go.microsoft.com/fwlink?ProdName=Microsoft+SQL+Server&amp;amp;ProdVer=10.00.2531&amp;amp;EvtSrc=MSSQLServer&amp;amp;EvtID=3201&amp;amp;LinkId=20476" href="http://go.microsoft.com/fwlink?ProdName=Microsoft+SQL+Server&amp;amp;ProdVer=10.00.2531&amp;amp;EvtSrc=MSSQLServer&amp;amp;EvtID=3201&amp;amp;LinkId=20476"&gt;http://go.microsoft.com/fwlink?ProdName=Microsoft+SQL+Server&amp;amp;ProdVer=10.00.2531&amp;amp;EvtSrc=MSSQLServer&amp;amp;EvtID=3201&amp;amp;LinkId=20476&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;At first it all seemed to be very strange as none of the conditions they were described was actually applicable to my situation. I then decided to check the permission of the account under which SQL Server was setup to run.&lt;/p&gt;  &lt;p&gt;This account was part of the administrators group but yet I kept receiving the error. I then added the account to the security permission of the file and gave it full access, after which I could restore the backup with no problem.&lt;/p&gt;  &lt;p&gt;To try and replicate this I ended up removing the permission I added but to my surprise I was still able to restore the database from the backup with no problem. For some strange reason things were now working exactly the way it should have from the beginning.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-588453620950770057?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/588453620950770057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=588453620950770057&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/588453620950770057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/588453620950770057'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/07/error-restoring-database-operating.html' title='Error restoring a database (Operating system error 5(Access is denied.))'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-4386241915249683106</id><published>2009-06-06T16:59:00.000+01:00</published><updated>2009-06-06T17:00:16.360+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Business Intelligence'/><category scheme='http://www.blogger.com/atom/ns#' term='MSDN'/><title type='text'>Microsoft BI MSDN Videos</title><content type='html'>&lt;p&gt;I have been searching for some good exam prep material for the 70-455 exam and posted a question regarding it on the Microsoft Learning forum. I got a few responses and one of them had this link to some very nice MSDN Videos regarding SQL Server 2008 BI.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.microsoft.com/events/series/bi.aspx?tab=videos"&gt;How Do I - BI Videos&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-4386241915249683106?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/4386241915249683106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=4386241915249683106&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4386241915249683106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/4386241915249683106'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/06/microsoft-bi-msdn-videos.html' title='Microsoft BI MSDN Videos'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-889843733564566220</id><published>2009-05-12T09:31:00.001+01:00</published><updated>2009-05-12T09:31:28.618+01:00</updated><title type='text'>SQL Server 2008 R2 (Formerly codenamed “Kilimanjaro”) CTP</title><content type='html'>&lt;p&gt;Microsoft has announced that a CTP of SQL Server 2008 R2 (formerly codenamed “Kilimanjaro”) will be made available in the summer of 2009. This was announced at Tech Ed North America on the 11th of May along with a host of other announcements regarding Windows 7 and Server 2008. The press release can be found &lt;a href="http://www.microsoft.com/presspass/press/2009/May09/05-11TechEd09PR.mspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;There is also a SQL Server 2008 R2 website where you can sign up for an email notification when the CTP is made available. The SQL Server R2 site can be found &lt;a href="http://www.microsoft.com/sqlserver/2008/en/us/r2.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;SQL Server 2008 R2 is set to have many tons of added functionality and feature. Here is a list of the new BI functionalities:&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="400"&gt;&lt;b&gt;Master Data Services (MDS)&lt;/b&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="400"&gt;&lt;b&gt;Self Service Analysis with “Project Gemini”&lt;/b&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="400"&gt;&lt;b&gt;Self Service Reporting with SQL Server 2008 R2 Reporting Services&lt;/b&gt;&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;We have all been treated to the hype around Project Gemini and I do hope it delivers to the community’s expectations. One interesting thing I noticed was the details around the self service reporting with Reporting Services. More specifically the Shared Library approach to accelerate report development. To quite the site &lt;em&gt;“Central, secure location for IT administrators and users to publish content objects that can be broadly reused and easily customized to meet the users’ needs”&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;This is something that many organisations have been trying to achieve through all sorts of ways. But did not have a straight forward approach, resulting in some trade offs between performance and functionality.&lt;/p&gt;  &lt;p&gt;It seems that the Microsoft BI Stack is set for a brilliant functionality update with the coming SQL Server 2008 R2 release.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-889843733564566220?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/889843733564566220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=889843733564566220&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/889843733564566220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/889843733564566220'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/05/sql-server-2008-r2-formerly-codenamed.html' title='SQL Server 2008 R2 (Formerly codenamed “Kilimanjaro”) CTP'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-2078767995982374848</id><published>2009-05-08T16:00:00.001+01:00</published><updated>2009-05-08T16:00:38.141+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance Point Server 2007'/><title type='text'>Dual Y-axis charts in Performance Point Server</title><content type='html'>&lt;p&gt;Ever wondered how to create a dual y-axis chart like the one below in Performance Point Server?&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/SgRJE2-yF3I/AAAAAAAAAUw/Qp2gvzDiYjQ/s1600-h/PPSDualYChart%5B5%5D.jpg"&gt;&lt;img title="PPSDualYChart" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="269" alt="PPSDualYChart" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/SgRJFUl8YOI/AAAAAAAAAU0/N0-SRmrcHDw/PPSDualYChart_thumb%5B3%5D.jpg?imgmax=800" width="443" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Have a look at the &lt;strong&gt;Microsoft Performance Point Team Blog&lt;/strong&gt; &lt;a href="http://blogs.msdn.com/performancepoint/archive/2008/02/12/creating-a-second-y-axis-on-an-analytic-chart.aspx"&gt;here&lt;/a&gt; to see how to do it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-2078767995982374848?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/2078767995982374848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=2078767995982374848&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/2078767995982374848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/2078767995982374848'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/05/dual-y-axis-charts-in-performance-point.html' title='Dual Y-axis charts in Performance Point Server'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_eSBtF1cAQjQ/SgRJFUl8YOI/AAAAAAAAAU0/N0-SRmrcHDw/s72-c/PPSDualYChart_thumb%5B3%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8416211796481678929</id><published>2009-05-08T12:34:00.001+01:00</published><updated>2009-05-08T12:35:45.159+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Report Builder 2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><category scheme='http://www.blogger.com/atom/ns#' term='MOSS 2007'/><title type='text'>Some SharePoint and Reporting Services Integration notes</title><content type='html'>&lt;p&gt;I have recently been busy integrating SQL Server Reporting Services 2008 into Microsoft Office SharePoint Server 2007. What made this particularly interesting was that MOSS was being used as source control in conjunction with Report Builder 2.0. &lt;/p&gt;  &lt;p&gt;So after this experience I decided that I will point out one or two of the things that we ran into that you might want to consider when doing a implementation.&lt;/p&gt;  &lt;h4&gt;Language and localisation&lt;/h4&gt;  &lt;p&gt;The first thing has to do with language and localisation. It is very easy to use the language settings of a client’s browser to localise your reports as well as the report manager. If you plan to use the Language ID of the client running your report you need to realise that once Reporting Services has been deployed in SharePoint Integrated Mode the Language ID being passed to your reports will be that of the SharePoint site and not the language of the user’s browser.&lt;/p&gt;  &lt;p&gt;Now this makes complete sense as you would not want to display reports in a different language than the one your SharePoint site is in. It is however something that you need to be aware if you make use of this functionality (which was what our solution was doing). You could use the UserID (which is still passed correctly to Reporting Services) and keep information regarding your users’ language preferences in the database but this then adds to the maintenance of your solution.&lt;/p&gt;  &lt;h4&gt;Using Report Builder 2.0 to access report libraries in MOSS 2007&lt;/h4&gt;  &lt;p&gt;Report Builder 2.0 works very nicely with SharePoint. Combine that with the fact that Report Builder 2.0 now allows users the full report authoring capabilities, which use to be the sole domain of report developers using Visual Studio, and you have the makings of a very business friendly report authoring environment.&lt;/p&gt;  &lt;p&gt;Make sure that you have SP1 for SQL 2008 installed as well as the latest Reporting Services add on for SharePoint. This will allow you to use ClickOnce Report Builder 2.0 which is extremely useful for allowing users to simply click on a report in a report library and selecting to open it with Report Builder.&lt;/p&gt;  &lt;p&gt;One thing to keep in mind when using Report Builder and SharePoint in this type of scenario is that Report Builder will not check out the .rdl file from the report library in SharePoint. It will however save it as a new version so you will be able to roll back to previous versions. If you want to check out the report before editing you have to do it manually on your SharePoint site. Report Builder will allow a users to open a report that has been checked out by another user but it will not allow any changes to be saved to that report.&lt;/p&gt;  &lt;h4&gt;Conclusion&lt;/h4&gt;  &lt;p&gt;The experience of using Report&amp;#160; Builder 2.0 and SharePoint to enable the business power users have been a pleasant one. Business power users find Report Builder 2.0 less intimidating due to the Office look and feel. Combining Report Builder 2.0 with SharePoint proved to be a very effective business enabler allowing business users to be in control of their own report development.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8416211796481678929?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8416211796481678929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8416211796481678929&amp;isPopup=true' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8416211796481678929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8416211796481678929'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/05/some-sharepoint-and-reporting-services.html' title='Some SharePoint and Reporting Services Integration notes'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-871832243601542019</id><published>2009-05-01T11:35:00.001+01:00</published><updated>2009-05-01T13:01:08.278+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VB.NET Script'/><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><category scheme='http://www.blogger.com/atom/ns#' term='WMI'/><category scheme='http://www.blogger.com/atom/ns#' term='WQL'/><title type='text'>SSIS script task to monitor if remote process is still running</title><content type='html'>&lt;p&gt;A while ago I posted about how you can use a SSIS script task to start a process on a remote machine. (you can find that post here &lt;a title="http://businessintelligencechronicles.blogspot.com/2009/02/using-ssis-script-task-to-executing.html" href="http://businessintelligencechronicles.blogspot.com/2009/02/using-ssis-script-task-to-executing.html"&gt;http://businessintelligencechronicles.blogspot.com/2009/02/using-ssis-script-task-to-executing.html&lt;/a&gt;) &lt;/p&gt;  &lt;p&gt;That approach would work perfectly if you wanted to start a process and not have to wait until it finishes before continuing with the rest of your SSIS package tasks, however this is not always the case. Say for example you were starting the Performance Point PPSCmd.exe process to synchronise your staging database. You would want to wait for that process to complete before you continue with the rest of the SSIS tasks. In order to get this done you need to make some change to the script that was used in the above mentioned post.&lt;/p&gt;  &lt;h4&gt;Changing the script to monitor if the process is still running&lt;/h4&gt;  &lt;p&gt;After finding the following article regarding monitoring processes on a remote machine (&lt;a title="http://vbnet.mvps.org/index.html?code/wmi/wmi_processmonitor.htm" href="http://vbnet.mvps.org/index.html?code/wmi/wmi_processmonitor.htm"&gt;http://vbnet.mvps.org/index.html?code/wmi/wmi_processmonitor.htm&lt;/a&gt;) I made changes to the original script. Below is the updated script that contains a new function and some code changes in the main section that will loop until the process stops executing on the remote machine.&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;pre id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span style="color: #008000"&gt;' Microsoft SQL Server Integration Services Script Task&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;' Write scripts using Microsoft Visual Basic&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;' The ScriptMain class is the entry point of the Script Task.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;Imports&lt;/span&gt; System&lt;br /&gt;&lt;span style="color: #0000ff"&gt;Imports&lt;/span&gt; System.Data&lt;br /&gt;&lt;span style="color: #0000ff"&gt;Imports&lt;/span&gt; System.Math&lt;br /&gt;&lt;span style="color: #0000ff"&gt;Imports&lt;/span&gt; Microsoft.SqlServer.Dts.Runtime&lt;br /&gt;&lt;span style="color: #0000ff"&gt;Imports&lt;/span&gt; System.Management&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Class&lt;/span&gt; ScriptMain&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt; Main()&lt;br /&gt;        &lt;span style="color: #008000"&gt;'Declare variables that will be used in the script&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; retValue &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; retCode &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; Command &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt; = Dts.Variables(&lt;span style="color: #006080"&gt;&amp;quot;AppToStgCommand&amp;quot;&lt;/span&gt;).Value.ToString&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; TargetMachine &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt; = Dts.Variables(&lt;span style="color: #006080"&gt;&amp;quot;TargetMachine&amp;quot;&lt;/span&gt;).Value.ToString&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; User &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt; = Dts.Variables(&lt;span style="color: #006080"&gt;&amp;quot;User&amp;quot;&lt;/span&gt;).Value.ToString&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; Password &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt; = Dts.Variables(&lt;span style="color: #006080"&gt;&amp;quot;Password&amp;quot;&lt;/span&gt;).Value.ToString&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; WMIQuery &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #008000"&gt;'Add the correct Collection to the end of the Command variable&lt;/span&gt;&lt;br /&gt;        Command = Command + &lt;span style="color: #006080"&gt;&amp;quot; &amp;quot;&lt;/span&gt; + &lt;span style="color: #006080"&gt;&amp;quot;Dimensions&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #008000"&gt;'Use a try catch block to handle for any exceptions &lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;&lt;br /&gt;            retValue = RunCommand(Command, TargetMachine, User, Password)&lt;br /&gt;            &lt;span style="color: #008000"&gt;'get the return code out of the string that is returned&lt;/span&gt;&lt;br /&gt;            retCode = retValue.Substring((retValue.IndexOf(&lt;span style="color: #006080"&gt;&amp;quot;;&amp;quot;&lt;/span&gt;) + 1))&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;'get the return value out of the string that is returned&lt;/span&gt;&lt;br /&gt;            retValue = retValue.Substring(0, retValue.IndexOf(&lt;span style="color: #006080"&gt;&amp;quot;;&amp;quot;&lt;/span&gt;))&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;'Set the value of the WMIQuery variable&lt;/span&gt;&lt;br /&gt;            WMIQuery = &lt;span style="color: #006080"&gt;&amp;quot;SELECT * FROM Win32_Process WHERE ProcessId=&amp;quot;&lt;/span&gt; &amp;amp; retCode &lt;span style="color: #008000"&gt;'w3wp.exe'&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;'Determine based on the value returned if the script task should fail or succeed &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;Select&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Case&lt;/span&gt; retValue&lt;br /&gt;                &lt;span style="color: #008000"&gt;'If 0 is returned the process was successfully executed &lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;Case&lt;/span&gt; &lt;span style="color: #006080"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #008000"&gt;'Monitor if the process is till running&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;While&lt;/span&gt; GetProcessInfo(User, Password, TargetMachine, retCode, WMIQuery) = &lt;span style="color: #006080"&gt;&amp;quot;True&amp;quot;&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;While&lt;/span&gt;&lt;br /&gt;                    Dts.TaskResult = Dts.Results.Success&lt;br /&gt;&lt;br /&gt;                    &lt;span style="color: #008000"&gt;'If 2 is returned access to the remote machine was denied &lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;Case&lt;/span&gt; &lt;span style="color: #006080"&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;br /&gt;                    Dts.Events.FireError(2, &lt;span style="color: #006080"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Access(denied)&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;)&lt;br /&gt;                    Dts.TaskResult = Dts.Results.Failure&lt;br /&gt;&lt;br /&gt;                    &lt;span style="color: #008000"&gt;'If 3 is returned the account specified has insufficient privileges to perform the action &lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;Case&lt;/span&gt; &lt;span style="color: #006080"&gt;&amp;quot;3&amp;quot;&lt;/span&gt;&lt;br /&gt;                    Dts.Events.FireError(2, &lt;span style="color: #006080"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Insufficient(privilege)&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;)&lt;br /&gt;                    Dts.TaskResult = Dts.Results.Failure&lt;br /&gt;&lt;br /&gt;                    &lt;span style="color: #008000"&gt;'If 8 is eturned an unknown failure occured &lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;Case&lt;/span&gt; &lt;span style="color: #006080"&gt;&amp;quot;8&amp;quot;&lt;/span&gt;&lt;br /&gt;                    Dts.Events.FireError(2, &lt;span style="color: #006080"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Unknown(failure)&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;)&lt;br /&gt;                    Dts.TaskResult = Dts.Results.Failure&lt;br /&gt;&lt;br /&gt;                    &lt;span style="color: #008000"&gt;'If 9 is returned the path for the executable was not found &lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;Case&lt;/span&gt; &lt;span style="color: #006080"&gt;&amp;quot;9&amp;quot;&lt;/span&gt;&lt;br /&gt;                    Dts.Events.FireError(2, &lt;span style="color: #006080"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Path(Not found)&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;)&lt;br /&gt;                    Dts.TaskResult = Dts.Results.Failure&lt;br /&gt;&lt;br /&gt;                    &lt;span style="color: #008000"&gt;'if 21 is returned an invalid parameter was specified &lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;Case&lt;/span&gt; &lt;span style="color: #006080"&gt;&amp;quot;21&amp;quot;&lt;/span&gt;&lt;br /&gt;                    Dts.Events.FireError(2, &lt;span style="color: #006080"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Invalid(parameter)&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;)&lt;br /&gt;                    Dts.TaskResult = Dts.Results.Failure&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Select&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Catch&lt;/span&gt; ex &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; Exception&lt;br /&gt;            &lt;span style="color: #008000"&gt;'Fire an error event if an exception occurs &lt;/span&gt;&lt;br /&gt;            Dts.Events.FireError(1, &lt;span style="color: #006080"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/span&gt;, ex.ToString, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;)&lt;br /&gt;            Dts.TaskResult = Dts.Results.Failure&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;Function&lt;/span&gt; RunCommand(&lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; strCommand &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; strMachineName &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; strUserName &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; strPassword &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; options &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; System.Management.ConnectionOptions&lt;br /&gt;        options.Username = strUserName&lt;br /&gt;        options.Password = strPassword&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; path &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; System.Management.ManagementPath(&lt;span style="color: #006080"&gt;&amp;quot;\\&amp;quot;&lt;/span&gt; &amp;amp; strMachineName &amp;amp; &lt;span style="color: #006080"&gt;&amp;quot;\root\cimv2:Win32_Process&amp;quot;&lt;/span&gt;)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; scope &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; System.Management.ManagementScope(path, options)&lt;br /&gt;&lt;br /&gt;        scope.Connect()&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; opt &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; System.Management.ObjectGetOptions()&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; classInstance &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; System.Management.ManagementClass(scope, path, opt)&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; inParams &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; System.Management.ManagementBaseObject = classInstance.GetMethodParameters(&lt;span style="color: #006080"&gt;&amp;quot;Create&amp;quot;&lt;/span&gt;)&lt;br /&gt;        inParams(&lt;span style="color: #006080"&gt;&amp;quot;CommandLine&amp;quot;&lt;/span&gt;) = strCommand&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #008000"&gt;' Execute the method and obtain the return values.&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; outParams &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; System.Management.ManagementBaseObject = classInstance.InvokeMethod(&lt;span style="color: #006080"&gt;&amp;quot;Create&amp;quot;&lt;/span&gt;, inParams, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;)&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CStr&lt;/span&gt;(outParams(&lt;span style="color: #006080"&gt;&amp;quot;returnValue&amp;quot;&lt;/span&gt;)) &amp;amp; &lt;span style="color: #006080"&gt;&amp;quot;;&amp;quot;&lt;/span&gt; &amp;amp; &lt;span style="color: #0000ff"&gt;CStr&lt;/span&gt;(outParams(&lt;span style="color: #006080"&gt;&amp;quot;processId&amp;quot;&lt;/span&gt;))&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Function&lt;/span&gt; GetProcessInfo(&lt;span style="color: #0000ff"&gt;ByRef&lt;/span&gt; User &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByRef&lt;/span&gt; Password &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByRef&lt;/span&gt; TargetMachine &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByRef&lt;/span&gt; retCode &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByRef&lt;/span&gt; WMIQuery &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;'Declare variables&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; options &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; ConnectionOptions()&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; scope &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; ManagementScope(&lt;span style="color: #006080"&gt;&amp;quot;\\&amp;quot;&lt;/span&gt; &amp;amp; TargetMachine &amp;amp; &lt;span style="color: #006080"&gt;&amp;quot;\root\cimv2&amp;quot;&lt;/span&gt;, options)&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; selectQuery &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; SelectQuery(WMIQuery)&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; searcher &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; ManagementObjectSearcher(scope, selectQuery)&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; IsProcessRunning &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt; = &lt;span style="color: #006080"&gt;&amp;quot;False&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;'Set the values of the Options variables&lt;/span&gt;&lt;br /&gt;            options.Username = User&lt;br /&gt;            options.Password = Password&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;'Connect to the remote server &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;                scope.Connect()&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;Catch&lt;/span&gt; f &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; Exception&lt;br /&gt;&lt;br /&gt;                Dts.Events.FireError(1, &lt;span style="color: #006080"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/span&gt;, f.ToString(), &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;Exit&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;'Get the data of the currently running process&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;For&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Each&lt;/span&gt; queryObj &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; ManagementObject &lt;span style="color: #0000ff"&gt;In&lt;/span&gt; searcher.&lt;span style="color: #0000ff"&gt;Get&lt;/span&gt;()&lt;br /&gt;                &lt;span style="color: #008000"&gt;'Test to see if the process is running&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; queryObj(&lt;span style="color: #006080"&gt;&amp;quot;ProcessID&amp;quot;&lt;/span&gt;).ToString = retCode &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt;&lt;br /&gt;                    IsProcessRunning = &lt;span style="color: #006080"&gt;&amp;quot;True&amp;quot;&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;Next&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;'Return the vale of the IsProcessRunning variable&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;Return&lt;/span&gt; IsProcessRunning&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;Catch&lt;/span&gt; f &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; Exception&lt;br /&gt;&lt;br /&gt;            Dts.Events.FireError(1, &lt;span style="color: #006080"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/span&gt;, f.ToString(), &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Class&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The script task will now only exit successfully after the process that was started finishes.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-871832243601542019?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/871832243601542019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=871832243601542019&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/871832243601542019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/871832243601542019'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/05/ssis-script-task-to-monitor-if-remote.html' title='SSIS script task to monitor if remote process is still running'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-6608669271265206638</id><published>2009-04-16T09:05:00.001+01:00</published><updated>2009-04-16T09:07:00.011+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><title type='text'>Extending SSIS with 3rd party components</title><content type='html'>&lt;p&gt;Every time I present an SSIS training course I make the comment that “SSIS can connect to anything and be extended to do almost anything”. I always get people looking at me like I have been abducted by a Microsoft UFO and brainwashed, so when I came across the blog post of Andy Leonard (&lt;a title="http://sqlblog.com/blogs/andy_leonard/archive/2007/12/18/ssis-third-party-components-cozyroc.aspx" href="http://sqlblog.com/blogs/andy_leonard/archive/2007/12/18/ssis-third-party-components-cozyroc.aspx"&gt;http://sqlblog.com/blogs/andy_leonard/archive/2007/12/18/ssis-third-party-components-cozyroc.aspx&lt;/a&gt;) talking about CozyRoc &lt;a title="http://www.cozyroc.com/" href="http://www.cozyroc.com/"&gt;http://www.cozyroc.com/&lt;/a&gt; and their library of advanced custom SSIS 2005 and 2008 tasks, I thought that this was the perfect example to illustrate my point (as well as get people to realise there were no UFO abductions).&lt;/p&gt;  &lt;p&gt;They have some brilliant components available and at an extremely reasonable price. Check it out today, it might just save you tons of time or solve a problem you thought was unsolvable.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-6608669271265206638?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/6608669271265206638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=6608669271265206638&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6608669271265206638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/6608669271265206638'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/04/extending-ssis-with-3rd-party.html' title='Extending SSIS with 3rd party components'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8483333610385865371</id><published>2009-03-12T11:43:00.001Z</published><updated>2009-03-12T16:20:07.961Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='RSinteract'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><title type='text'>Extending Reporting Services to your end users</title><content type='html'>&lt;p&gt;No one can argue against the fact that the current economic environment is forcing people to look at how much they are spending and how these funds are allocated. So without me repeating all the information that has already provided on this topic I would rather like to focus your attention on a product that could really help those organisations that have invested in the Microsoft BI stack.&lt;/p&gt;  &lt;h4&gt;Filling the gap&lt;/h4&gt;  &lt;p&gt;It is a well known fact that easy end user report creation is a gap that rears its head in any Microsoft BI implementation. I am not talking about your power users here. Microsoft has done an excellent job with Report Builder 2.0 in SQL Server 2008 to address the needs of power users and I would definitely recommend Report Builder 2.0 to any client wanting to enable their power users.&lt;/p&gt;  &lt;p&gt;The gap I am talking about filling is the need to have your end users access data from your already existing cubes and data warehouses with as little disruption to their daily routine as possible. Of course there are many tools out there that can perform advanced visualisation when deployed against your cubes but to be honest, and I know I might be stepping on some toes here, those tools are rarely adopted by the end users we are talking about.&lt;/p&gt;  &lt;p&gt;So what if you could allow these users to author their own reports quickly and easily in their web browser utilising Reporting Services? &lt;/p&gt;  &lt;h4&gt;RSinteract for end user report authoring&lt;/h4&gt;  &lt;p&gt;RSinteract is a web application that works with Reporting Services 2005 and 2008 and allows your end users to create their own reports from either a normal relational data source or from an OLAP data source. It is extremely simple to use, yet it has almost all the functionality of Reporting Service.&lt;/p&gt;  &lt;p&gt;It is fully integrated with the Reporting Services meaning that all security and permissions are inherited form Reporting Services. This ensures that you incur no additional administration overheads when deploying the product.&lt;/p&gt;  &lt;p&gt;Below is a video that illustrates how an end user would build a report from an OLAP data source.&lt;/p&gt;  &lt;div class="wlWriterEditableSmartContent" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:24098f5c-8e17-4bd7-8069-f80b642e642c" style="padding-right: 0px; display: block; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px auto; width: 482px; padding-top: 0px"&gt;&lt;div id="175bf4a7-0c37-4b2f-aa04-26f06fbee729" style="margin: 0px; padding: 0px; display: inline;"&gt;&lt;div&gt;&lt;a href="http://www.youtube.com/watch?v=diO-FmqLjhc" target="_new"&gt;&lt;img src="http://lh5.ggpht.com/_eSBtF1cAQjQ/Sbk2NiY9rFI/AAAAAAAAAUU/44lNR24UuHY/videob75a9acc599c%5B2%5D.jpg?imgmax=800" style="border-style: none" galleryimg="no" onload="var downlevelDiv = document.getElementById('175bf4a7-0c37-4b2f-aa04-26f06fbee729'); downlevelDiv.innerHTML = &amp;quot;&amp;lt;div&amp;gt;&amp;lt;object width=\&amp;quot;482\&amp;quot; height=\&amp;quot;403\&amp;quot;&amp;gt;&amp;lt;param name=\&amp;quot;movie\&amp;quot; value=\&amp;quot;http://www.youtube.com/v/diO-FmqLjhc&amp;amp;hl=en\&amp;quot;&amp;gt;&amp;lt;\/param&amp;gt;&amp;lt;embed src=\&amp;quot;http://www.youtube.com/v/diO-FmqLjhc&amp;amp;hl=en\&amp;quot; type=\&amp;quot;application/x-shockwave-flash\&amp;quot; width=\&amp;quot;482\&amp;quot; height=\&amp;quot;403\&amp;quot;&amp;gt;&amp;lt;\/embed&amp;gt;&amp;lt;\/object&amp;gt;&amp;lt;\/div&amp;gt;&amp;quot;;" alt=""&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;  &lt;p&gt;If you would like to download a trial version of the software or perhaps look at the other video demos they have available visit their website at &lt;a href="http://www.rsinteract.com"&gt;www.rsinteract.com&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8483333610385865371?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8483333610385865371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8483333610385865371&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8483333610385865371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8483333610385865371'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/03/extending-reporting-services-to-your.html' title='Extending Reporting Services to your end users'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_eSBtF1cAQjQ/Sbk2NiY9rFI/AAAAAAAAAUU/44lNR24UuHY/s72-c/videob75a9acc599c%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-1843167870927153027</id><published>2009-02-15T11:50:00.001Z</published><updated>2009-03-25T15:53:11.809Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><category scheme='http://www.blogger.com/atom/ns#' term='WMI'/><category scheme='http://www.blogger.com/atom/ns#' term='VBscript'/><title type='text'>Using a SSIS Script task to execute a process (exe) on a remote machine</title><content type='html'>&lt;p&gt;I am sure that sooner rather than later anyone that is involved in developing ETL routines will have the need to execute an exe (process) on a remote machine. For example your SSIS packages are scheduled to executing on Server 1 and need to start or execute a process on Server 2. (In my case I needed to execute the “PPSCmd.exe” process to synchronise the Performance Point staging and application databases)&lt;/p&gt;  &lt;p&gt;I found the following post by Steve Schofield to be extremely useful &lt;a title="http://weblogs.asp.net/steveschofield/archive/2006/06/06/WMI---start-a-process-on-remote-machine-passing-credentials_2E00_.aspx" href="http://weblogs.asp.net/steveschofield/archive/2006/06/06/WMI---start-a-process-on-remote-machine-passing-credentials_2E00_.aspx"&gt;http://weblogs.asp.net/steveschofield/archive/2006/06/06/WMI---start-a-process-on-remote-machine-passing-credentials_2E00_.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I took the scripts that he has given on his blog and changed it to be parameterised in a SSIS 2008 Script Task. The SSIS package contains the following variables.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SZgBf02Py5I/AAAAAAAAATE/dALk3A0RNMo/s1600-h/image4.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="129" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/SZgBggNGaPI/AAAAAAAAATI/nRb81o4bT48/image_thumb2.png?imgmax=800" width="327" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;u&gt;Command: &lt;/u&gt;The Command variable will contain the command we want to execute on the remote machine. In our case we are going to execute the Calculator application on the target machine.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;TargetMachine&lt;/u&gt;: This variable contains the name of the remote machine or the IP address.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;User:&lt;/u&gt; The User variable contains the username of an account on the machine or the username of an Active Directory account. If you use and Active Directory account remember to prefix the username with the correct domain.&lt;/p&gt;  &lt;p&gt;&lt;u&gt;Password:&lt;/u&gt; The Password variable is the password for the specified username&lt;/p&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h4&gt;Configuring the Script Task&lt;/h4&gt;  &lt;p&gt;As you can see in the screenshot below, all the variables are listed as read only variables. &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/SZgBhZem2sI/AAAAAAAAATM/zuRJjxtuZX0/s1600-h/image9.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="394" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/SZgBiEW4uoI/AAAAAAAAATQ/9SdQhzaYXGw/image_thumb5.png?imgmax=800" width="457" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Next we need to reference the System.Management. Right click on the script project in the Project Explorer and click on the “Add Reference” option.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SZgBi8vt2rI/AAAAAAAAATU/bxgUGVacHsY/s1600-h/image%5B17%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SZgBjY1qeAI/AAAAAAAAATY/DWnH-gfHioM/image_thumb%5B8%5D.png?imgmax=800" width="159" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This will open the “Add Reference” window. Under the “.NET” tab scroll down until you find the “System.Management” component and click on “OK”&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/SZgBjxZYLzI/AAAAAAAAATc/2On1ViJP7N4/s1600-h/image%5B25%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="269" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/SZgBklCUuVI/AAAAAAAAATg/CtmBITZZr3Y/image_thumb%5B12%5D.png?imgmax=800" width="325" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h4&gt;The Script&lt;/h4&gt;  &lt;p&gt;Next we are going to have a look at the modified script that we will use to execute our process on the remote machine. Below is the code we are going to use.&lt;/p&gt;  &lt;p&gt;Public Sub Main() &lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160; 'Declare variables and set them equal to the relevant variables in the SSIS package&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; retValue &lt;font color="#0000ff"&gt;As String      &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; Command &lt;font color="#0000ff"&gt;As String&lt;/font&gt; = Dts.Variables(&lt;font color="#800000"&gt;&amp;quot;Command&amp;quot;&lt;/font&gt;).Value.ToString     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; TargetMachine &lt;font color="#0000ff"&gt;As String&lt;/font&gt; = Dts.Variables(&lt;font color="#800000"&gt;&amp;quot;TargetMachine&amp;quot;&lt;/font&gt;).Value.ToString     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; User &lt;font color="#0000ff"&gt;As String&lt;/font&gt; = Dts.Variables(&lt;font color="#800000"&gt;&amp;quot;User&amp;quot;&lt;/font&gt;).Value.ToString     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; Password &lt;font color="#0000ff"&gt;As String&lt;/font&gt; = Dts.Variables(&lt;font color="#800000"&gt;&amp;quot;Password&amp;quot;&lt;/font&gt;).Value.ToString &lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160; 'Use a try catch block to cater for any exceptions&lt;/font&gt;     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160;&amp;#160; Try&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; retValue = RunCommand(Command, TargetMachine, User, Password) &lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'Determine based on the value returned if the script task should fail or succeed      &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Select Case&lt;/font&gt; retValue     &lt;br /&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'If 0 is returned the process was successfully executed&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Case&lt;/font&gt; &lt;font color="#800000"&gt;&amp;quot;0&amp;quot;      &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.TaskResult = ScriptResults.Success &lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'If 2 is returned access to the remote machine was denied&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Case&lt;/font&gt; &lt;font color="#800000"&gt;&amp;quot;2&amp;quot;      &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.Events.FireError(2, &lt;font color="#800000"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/font&gt;, &lt;font color="#800000"&gt;&amp;quot;Access(denied)&amp;quot;&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.TaskResult = ScriptResults.Failure &lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'If 3 is returned the account specified has insufficient privileges to perform the action&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Case&lt;/font&gt; &lt;font color="#800000"&gt;&amp;quot;3&amp;quot;&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.Events.FireError(2, &lt;font color="#800000"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/font&gt;, &lt;font color="#800000"&gt;&amp;quot;Insufficient(privilege)&amp;quot;&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.TaskResult = ScriptResults.Failure &lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'If 8 is eturned an unknown failure occured&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Case&lt;/font&gt; &lt;font color="#800000"&gt;&amp;quot;8&amp;quot;      &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.Events.FireError(2, &lt;font color="#800000"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/font&gt;, &lt;font color="#800000"&gt;&amp;quot;Unknown(failure)&amp;quot;&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.TaskResult = ScriptResults.Failure &lt;/p&gt;  &lt;p&gt;&amp;#160; &lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'If 9 is returned the path for the executable was not found&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Case&lt;/font&gt; &lt;font color="#800000"&gt;&amp;quot;9&amp;quot;      &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.Events.FireError(2, &lt;font color="#800000"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/font&gt;, &lt;font color="#800000"&gt;&amp;quot;Path(Not found)&amp;quot;&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.TaskResult = ScriptResults.Failure &lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'if 21 is returned an invalid parameter was specified&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Case&lt;/font&gt; &lt;font color="#800000"&gt;&amp;quot;21&amp;quot;      &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.Events.FireError(2, &lt;font color="#800000"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/font&gt;, &lt;font color="#800000"&gt;&amp;quot;Invalid(parameter)&amp;quot;&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.TaskResult = ScriptResults.Failure     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; End Select&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Catch&lt;/font&gt; ex &lt;font color="#0000ff"&gt;As&lt;/font&gt; Exception     &lt;br /&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'Fire an error event if an exception occurs&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.Events.FireError(1, &lt;font color="#800000"&gt;&amp;quot;stSyncPPSDatabases&amp;quot;&lt;/font&gt;, ex.ToString, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dts.TaskResult = ScriptResults.Failure&amp;#160; &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160;&amp;#160; End Try&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;End Sub&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;Function&lt;/font&gt; RunCommand(&lt;font color="#0000ff"&gt;ByVal&lt;/font&gt; strCommand &lt;font color="#0000ff"&gt;As String&lt;/font&gt;, &lt;font color="#0000ff"&gt;ByVal&lt;/font&gt; strMachineName&lt;font color="#0000ff"&gt; As String&lt;/font&gt;, &lt;font color="#0000ff"&gt;ByVal&lt;/font&gt; strUserName &lt;font color="#0000ff"&gt;As String&lt;/font&gt;, &lt;font color="#0000ff"&gt;ByVal&lt;/font&gt; strPassword &lt;font color="#0000ff"&gt;As String&lt;/font&gt;) &lt;font color="#0000ff"&gt;As String      &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; options &lt;font color="#0000ff"&gt;As New&lt;/font&gt; System.Management.ConnectionOptions     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; options.Username = strUserName     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; options.Password = strPassword &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; path &lt;font color="#0000ff"&gt;As New&lt;/font&gt; System.Management.ManagementPath(&lt;font color="#800000"&gt;&amp;quot;\\&amp;quot;&lt;/font&gt; &amp;amp; strMachineName &amp;amp; &lt;font color="#800000"&gt;&amp;quot;\root\cimv2:Win32_Process&amp;quot;&lt;/font&gt;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; scope &lt;font color="#0000ff"&gt;As New&lt;/font&gt; System.Management.ManagementScope(path, options) &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; scope.Connect() &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; opt &lt;font color="#0000ff"&gt;As New&lt;/font&gt; System.Management.ObjectGetOptions()     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; classInstance &lt;font color="#0000ff"&gt;As New&lt;/font&gt; System.Management.ManagementClass(scope, path, opt) &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; Dim inParams As System.Management.ManagementBaseObject = classInstance.GetMethodParameters(&lt;font color="#800000"&gt;&amp;quot;Create&amp;quot;&lt;/font&gt;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; inParams(&lt;font color="#800000"&gt;&amp;quot;CommandLine&amp;quot;&lt;/font&gt;) = strCommand &lt;/p&gt;  &lt;p&gt;&amp;#160; &lt;font color="#008000"&gt;&amp;#160; ' Execute the method and obtain the return values.&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Dim&lt;/font&gt; outParams &lt;font color="#0000ff"&gt;As&lt;/font&gt; System.Management.ManagementBaseObject = classInstance.InvokeMethod(&lt;font color="#800000"&gt;&amp;quot;Create&amp;quot;&lt;/font&gt;, inParams, &lt;font color="#0000ff"&gt;Nothing&lt;/font&gt;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Return CStr&lt;/font&gt;(outParams(&lt;font color="#800000"&gt;&amp;quot;returnValue&amp;quot;&lt;/font&gt;)) &lt;font color="#008000"&gt;'&amp;amp; &amp;quot; Process ID: {0}&amp;quot; &amp;amp; CStr(outParams(&amp;quot;processId&amp;quot;))&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;End Function&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Like I indicated earlier, just a couple of small changes to the script Steve Schofield provided on his blog. When we execute the SSIS package the “Calc.exe” process will be started on the remote machine that we have specified. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SZgBlkdgLNI/AAAAAAAAATk/JRdtX7nBRjU/s1600-h/image%5B33%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/SZgBmRR4oTI/AAAAAAAAATo/tLXv_3osWUQ/image_thumb%5B16%5D.png?imgmax=800" width="280" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When you have a look at the processes in the Task Manager on the remote machine you will now see the “Calc.exe” process running. (Make sure you tick the tick box stating that you want to show processes from all users if you used a username and password that is different from the one you have logged onto the target machine with) &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SZgBm5DnXjI/AAAAAAAAATs/oT8Pf9ygl80/s1600-h/image%5B32%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="297" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SZgBnjJBy3I/AAAAAAAAATw/SRUnqOoJYzQ/image_thumb%5B15%5D.png?imgmax=800" width="270" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I hope the above comes in handy should you ever have the requirement to execute a process on a remote machine from a SSIS package.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-1843167870927153027?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/1843167870927153027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=1843167870927153027&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1843167870927153027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1843167870927153027'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/02/using-ssis-script-task-to-executing.html' title='Using a SSIS Script task to execute a process (exe) on a remote machine'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_eSBtF1cAQjQ/SZgBggNGaPI/AAAAAAAAATI/nRb81o4bT48/s72-c/image_thumb2.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8776098221373585430</id><published>2009-01-29T10:36:00.001Z</published><updated>2009-01-29T10:36:24.509Z</updated><title type='text'>Microsoft’s Performance Point announcement and the opportunistic marketing strategies of competitors</title><content type='html'>&lt;p&gt;I am going to warn you from the start that this will be a rant. I am extremely disappointed in the post Performance Point marketing propaganda of some of Redmond’s competitors/partners.&lt;/p&gt;  &lt;p&gt;Let me start by saying that I completely understand that a lot of Microsoft partners are now feeling the pain due to the loss of investment in the to be discontinued Performance Point Planning module. This is something that no one can deny will cause a shock to the Microsoft partner network. It is also regrettable that there will no longer be a stand alone planning module as part of the Microsoft BI offering. The official&amp;#160; stance on this is that budgeting and planning will be implemented through Microsoft Dynamics and the office 14 suite.&lt;/p&gt;  &lt;p&gt;On the other hand the future looks much brighter for Microsoft’s vision of bringing BI to the masses. Not only have they reduced the total cost of ownership of a Microsoft BI solution even further, but they have now made dashboarding, scorecarding and analytic reporting FREE for their Enterprise SharePoint licence holders.&lt;/p&gt;  &lt;p&gt;Now for the part that I warned you about. I find it shocking that there are some vendors out there that jumped at the opportunity to bash the Microsoft BI offering. These vendors now proclaim that they will ease the pain for Microsoft customers due to the incomplete Microsoft BI offering. All of this when they do not even have a planning product as part of their own proposed offering. Yes you have guessed it, they only do dashboarding, scorecarding and reporting, on top of that these products merely extend the capabilities of the platforms they are deployed on. In other word they still require a BI platform, such as the Microsoft SQL Server BI stack, or that of another vendor in order to be functional at all!&lt;/p&gt;  &lt;p&gt;All I can say is shame on you for deceiving customers! As for the Microsoft announcement as I previously mentioned, yes it is a disappointment but there is also a tremendous upside for those partners willing to embrace the change and target the new market that has just been made available to them. The Microsoft BI offering (one of the best available if I may say so) just got even cheaper and the future has never looked brighter!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8776098221373585430?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8776098221373585430/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8776098221373585430&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8776098221373585430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8776098221373585430'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/01/microsofts-performance-point.html' title='Microsoft’s Performance Point announcement and the opportunistic marketing strategies of competitors'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-1088893299278063784</id><published>2009-01-28T22:08:00.002Z</published><updated>2009-01-28T22:10:36.760Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><title type='text'>Another take on splitting Reporting Services multi-value parameters using a SQL function</title><content type='html'>&lt;p&gt;This is more of a quick post that I thought I would share. I have been meaning to add the SQL function that I use to split Reporting Services multi-value parameters in my stored procedures of my reports for a long time.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;This topic has been covered extensively on many forums and blogs so without me retyping what has already been said here are a few of the links:    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;The MSDN article regarding single and multi-value parameters.    &lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/aa337292.aspx"&gt;http://msdn.microsoft.com/en-us/library/aa337292.aspx&lt;/a&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Simon Sabin's blog on SQL Server stuff    &lt;br /&gt;&lt;a href="http://sqlblogcasts.com/blogs/simons/archive/2007/11/22/RS-HowTo---Pass-a-multivalue-parameter-to-a-query-using-IN.aspx"&gt;http://sqlblogcasts.com/blogs/simons/archive/2007/11/22/RS-HowTo---Pass-a-multivalue-parameter-to-a-query-using-IN.aspx&lt;/a&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Now I know that there are many variations on this type of &amp;quot;split&amp;quot; function and I thought it useful to share the function &lt;font color="#404040"&gt;that I have used on occasions in the past as it is very simple and easy to understand.&lt;/font&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;CREATE FUNCTION&lt;/font&gt; udf_SplitParameter     &lt;br /&gt;( &lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;--The actual multi-value parameter from reporting services&lt;/font&gt;&amp;#160; &lt;br /&gt; @String &lt;font color="#0000ff"&gt;NVARCHAR&lt;/font&gt;(4000), &lt;/p&gt;  &lt;p&gt;&lt;font color="#008000"&gt;--The separator that will is used to delimit each new value in the string&lt;/font&gt;    &lt;br /&gt; @Seperator &lt;font color="#0000ff"&gt;NVARCHAR&lt;/font&gt;(1)     &lt;br /&gt;)     &lt;br /&gt;&lt;font color="#0000ff"&gt;RETURNS&lt;/font&gt; @Table &lt;font color="#0000ff"&gt;TABLE&lt;/font&gt;(Result &lt;font color="#0000ff"&gt;NVARCHAR&lt;/font&gt;(4000))     &lt;br /&gt;&lt;font color="#0000ff"&gt; AS      &lt;br /&gt;&amp;#160; BEGIN&lt;/font&gt;     &lt;br /&gt;&lt;font color="#00ff80"&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160; --Loop through the string and insert each section into the return table of the table valued function&lt;/font&gt;       &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; WHILE&lt;/font&gt; &lt;font color="#ff00ff"&gt;CHARINDEX&lt;/font&gt;(@Seperator,@String) &amp;lt;&amp;gt; 0     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160;&amp;#160; BEGIN &lt;/font&gt;&lt;font color="#0000ff"&gt;     &lt;br /&gt;&lt;/font&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160; --Insert the value into the return table of the table valued function&lt;/font&gt;     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160;&amp;#160; INSERT INTO&lt;/font&gt; @Table (Result)     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160;&amp;#160; SELECT&lt;/font&gt; &lt;font color="#ff00ff"&gt;SUBSTRING&lt;/font&gt;(@String,1,&lt;font color="#ff00ff"&gt;CHARINDEX&lt;/font&gt;(@Seperator,@String) - 1)     &lt;br /&gt;&lt;font color="#008000"&gt;&amp;#160;&amp;#160;&amp;#160; --Remove the inserted string from the original string      &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160;&amp;#160; SET&lt;/font&gt; @String = &lt;font color="#808080"&gt;RIGHT&lt;/font&gt;(@String, &lt;font color="#ff00ff"&gt;LEN&lt;/font&gt;(@String) - &lt;font color="#ff00ff"&gt;CHARINDEX&lt;/font&gt;(@Seperator,@String))     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160;&amp;#160; END      &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160; &lt;font color="#008000"&gt;--Insert the last value in the string into the return table of the table valued function      &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; INSERT INTO&lt;/font&gt; @Table (Result)     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; SELECT&lt;/font&gt; &lt;font color="#ff00ff"&gt;SUBSTRING&lt;/font&gt;(@String,1,&lt;font color="#ff00ff"&gt;LEN&lt;/font&gt;(@String))     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; RETURN      &lt;br /&gt;&amp;#160; END       &lt;br /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;As you can see it is quite a simple function and works really well. For example you do not have to write any dynamic SQL to build up the string when you pass an integer surrogate key value (Using a multi-value parameter in SSRS) to a stored procedure. For example the following stored procedure would give and error.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;CREATE PROCEDURE&lt;/font&gt; GetSales     &lt;br /&gt;(     &lt;br /&gt;@Parameter &lt;font color="#0000ff"&gt;NVARCHAR&lt;/font&gt;(800)     &lt;br /&gt;)     &lt;br /&gt;&lt;font color="#0000ff"&gt; AS      &lt;br /&gt;&amp;#160; BEGIN&lt;/font&gt;     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; SELECT&lt;/font&gt; *     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; FROM&lt;/font&gt; dbo.FactInternetSales     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; WHERE&lt;/font&gt; ProductKey &lt;font color="#808080"&gt;IN&lt;/font&gt; (@Parameter)     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160; END &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;It would give an error stating that it could &lt;font color="#000000"&gt;&lt;font color="#404040"&gt;not&lt;/font&gt; &lt;/font&gt;convert the nvarchar value to integer. That is because Reporting Services converts the result that is returned when you select multiple values in the parameter drop down into a string value separated by commas (,). &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;When you use the split function instead it will work perfectly. Below is an example. &lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;CREATE PROCEDURE&lt;/font&gt; GetSales     &lt;br /&gt;(     &lt;br /&gt;@Parameter &lt;font color="#0000ff"&gt;NVARCHAR&lt;/font&gt;(800)     &lt;br /&gt;)     &lt;br /&gt;&lt;font color="#0000ff"&gt; AS      &lt;br /&gt;&amp;#160; BEGIN&lt;/font&gt;     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; SELECT&lt;/font&gt; *     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; FROM&lt;/font&gt; dbo.FactInternetSales     &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; WHERE&lt;/font&gt; ProductKey &lt;font color="#808080"&gt;IN&lt;/font&gt; (&lt;font color="#0000ff"&gt;SELECT&lt;/font&gt; Result &lt;font color="#0000ff"&gt;FROM&lt;/font&gt; dbo.udf_SplitParameter(@Parameter,&lt;font color="#ff0000"&gt;','&lt;/font&gt;))&amp;#160;&amp;#160; &lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;#160; END &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#404040"&gt;Have a look at the result returned by the splitting function below.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/SYDXaKqL2uI/AAAAAAAAAS8/ult8PdbZ5J0/s1600-h/image%5B4%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="191" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SYDXamaRICI/AAAAAAAAATA/J4aI9EWve_M/image_thumb%5B2%5D.png?imgmax=800" width="368" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The @Parameter variable simulates the way that reporting services will pass a multi-value parameter to your SQL Server stored procedure. As you can see the function returns the string of the parameter in a table and this eliminates any dynamic SQL that you might have had to write in the past.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-1088893299278063784?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/1088893299278063784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=1088893299278063784&amp;isPopup=true' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1088893299278063784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1088893299278063784'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2009/01/another-take-on-splitting-reporting.html' title='Another take on splitting Reporting Services multi-value parameters using a SQL function'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_eSBtF1cAQjQ/SYDXamaRICI/AAAAAAAAATA/J4aI9EWve_M/s72-c/image_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-5341914525403340706</id><published>2008-12-27T23:00:00.003Z</published><updated>2009-03-25T16:08:14.014Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='Business Intelligence'/><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Parent Child Hierarchy'/><category scheme='http://www.blogger.com/atom/ns#' term='Analysis Services'/><category scheme='http://www.blogger.com/atom/ns#' term='Hierarchies'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Allowing users to create their own hierarchies in a cube</title><content type='html'>&lt;p&gt;I have recently been tasked with a somewhat challenging, yet very interesting, request by a client. The request was to allow the users of a BI solution to create their own hierarchies with unlimited levels and leaf members in a cube. &lt;/p&gt;  &lt;p&gt;From a business point of view this makes perfect sense. It will allow the users to slice and dice their data in any way that they want or need to. &lt;/p&gt;  &lt;p&gt;For example lets say that the users need to restructure their sales teams or that they want to create a special hierarchy that contains all products that were part of a specific sale. By allowing the users to create their own hierarchies they can move the products that were on sale or restructure the sales teams in the desired way and analyse their data according to the new hierarchies.&lt;/p&gt;  &lt;p&gt;Sounds like a great plan? Well lets have a look at how you can achieve this.&lt;/p&gt;  &lt;h3&gt;Creating the tables&lt;/h3&gt;  &lt;p&gt;So the first thing to do is to create the tables needed for the task at hand. Lets first look at the tables used by the users to create their hierarchies. The database diagram of the tables are shown below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SVazM69ja3I/AAAAAAAAARA/8omBNwacjbA/s1600-h/image%5B27%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="126" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/SVazN3J_EXI/AAAAAAAAARE/2-ouRUaDRvM/image_thumb%5B14%5D.png?imgmax=800" width="473" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The three tables are used to allow the users to create the hierarchies through a .NET front end. The CustomHierarchy table will contain all the different hierarchies that the users create. The CustomHierarchyLevel table will contain the hierarchy levels that the users create and the CustomHierarchyLeaf table will contain the actual leaf level members as they are assigned by the users. &lt;em&gt;(We will cover the .NET front end in another post, in this post we will be focus on the database and Analysis Services solution) &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Next we have a look at the table that we will use to build the parent child hierarchy in Analysis services.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/SVazOd4WPRI/AAAAAAAAARI/jsJ6oJFAoes/s1600-h/image9.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="156" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SVazPPjFjQI/AAAAAAAAARM/qYqnElevgTI/image_thumb5.png?imgmax=800" width="175" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The DimCustomHierarchy table will be populated using the three tables previously discussed. This is the table that will be used in Analysis Services to build a parent child hierarchy that will allow the users to explore the data in the cube according to their create hierarchies.&lt;/p&gt;  &lt;p&gt;In order to link the DimCustomHierarchy table to the fact table in the cube we will need a intermediate fact table, for this we create the FactHierarchy table.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SVazPy6Lp5I/AAAAAAAAARQ/QsuWCNigCyg/s1600-h/image%5B46%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="101" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SVazQq_jvZI/AAAAAAAAARU/RVaxR7nyKSA/image_thumb%5B25%5D.png?imgmax=800" width="187" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This table will contain the surrogate key of the relevant leaf level members as well as the surrogate key of the custom hierarchies.&lt;/p&gt;  &lt;p&gt;The last table we create is the CustomHierarchyHistory table that will contain the CustomHierarchyID of each hierarchy that has already been added to the DimCustomHierarchy table. This is done as to reduce the amount of time spent building the DimCustomHierarchy table. A screenshot of the table is shown below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/SVazRGH1j4I/AAAAAAAAARY/LcnZ0Dz-H_0/s1600-h/image%5B37%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="81" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/SVazSIvXY5I/AAAAAAAAARc/6Ot3UydQ7VU/image_thumb%5B20%5D.png?imgmax=800" width="180" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The code to create the tables are as follows:&lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;--Create the table that will contain the names of the Custom Hierarchies      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;CREATE TABLE&lt;/span&gt; CustomHierarchy(CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;INT IDENTITY&lt;/span&gt;(1,1) &lt;span style="color: rgb(0,0,255)"&gt;PRIMARY KEY CLUSTERED&lt;/span&gt;,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyName &lt;span style="color: rgb(0,0,255)"&gt;VARCHAR&lt;/span&gt;(100),     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Modified &lt;span style="color: rgb(0,0,255)"&gt;BIT&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );     &lt;br /&gt;&lt;span style="color: rgb(0,128,0)"&gt;--Create the table that will contain the Custom Hierarchy Nodes&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;CREATE TABLE&lt;/span&gt; CustomHierarchyLevel(CustomHierarchyLevelID &lt;span style="color: rgb(0,0,255)"&gt;INT IDENTITY&lt;/span&gt;(1,1) &lt;span style="color: rgb(0,0,255)"&gt;PRIMARY KEY CLUSTERED&lt;/span&gt;,&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLevelName &lt;span style="color: rgb(0,0,255)"&gt;VARCHAR&lt;/span&gt;(100),     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyParentLevelID &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;INT FOREIGN KEY REFERENCES&lt;/span&gt; CustomHierarchy(CustomHierarchyID)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ); &lt;/p&gt;  &lt;p&gt;--Create the table that will contain the Custom Hierarchy Leaf Level members    &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;CREATE TABLE&lt;/span&gt; CustomHierarchyLeaf(CustomHierarchyLeafID &lt;span style="color: rgb(0,0,255)"&gt;INT IDENTITY&lt;/span&gt;(1,1) &lt;span style="color: rgb(0,0,255)"&gt;PRIMARY KEY CLUSTERED&lt;/span&gt;,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLeafName &lt;span style="color: rgb(0,0,255)"&gt;VARCHAR&lt;/span&gt;(100),     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLeafKey &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLevelID &lt;span style="color: rgb(0,0,255)"&gt;INT FOREIGN KEY REFERENCES&lt;/span&gt; CustomHierarchyLevel(CustomHierarchyLevelID)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );&lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;--Create the table that contains the user create parent child hierarchies      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;CREATE TABLE&lt;/span&gt; DimCustomHierarchy(CustomHierarchySK &lt;span style="color: rgb(0,0,255)"&gt;INT IDENTITY&lt;/span&gt;(1,1),     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyParentSK &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;,&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyDescription &lt;span style="color: rgb(0,0,255)"&gt;VARCHAR&lt;/span&gt;(100),     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLevelID &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyParentLevelID &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLeafID &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLeafKey &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );&lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;--Create the table that will contain the history of the custom hierarchies      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;CREATE TABLE&lt;/span&gt; CustomHierarchyHistory(CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;)&lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;--Create the intermadiate fact table for use in Analysis Services&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;CREATE TABLE&lt;/span&gt; FactHierarchy (CustomHierarchySK &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLeafKey &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ); &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;Creating a custom hierarchy&lt;/h3&gt;  &lt;p&gt;Now that we have had a look at the tables that we will use lets create a custom hierarchy and look at the data that will be contained in the first three tables we discussed. The hierarchy we will be creating will be a hierarchy that contains all the items used in a specific sale. &lt;/p&gt;  &lt;p&gt;Below is the structure of the hierarchy as the users will have created it by dragging and dropping the items under the levels in the custom hierarchy.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SVazTce5TUI/AAAAAAAAARg/IjFez5gez7Y/s1600-h/image%5B14%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="300" alt="image" src="http://lh6.ggpht.com/_eSBtF1cAQjQ/SVazUXWOl8I/AAAAAAAAARk/IrSHaZWOh0I/image_thumb%5B7%5D.png?imgmax=800" width="470" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In the structure above you will see that we have a new user created hierarchy called &lt;em&gt;Sales 2008. &lt;/em&gt;This hierarchy has got three levels called &lt;em&gt;Unassigned, End of range, New lines. &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The &lt;em&gt;Unassigned&lt;/em&gt; level will contain all the leaf level members that are not used in any other levels in the hierarchy.&lt;/p&gt;  &lt;p&gt;The &lt;em&gt;End of range&lt;/em&gt; level contains two sub levels &lt;em&gt;50%&lt;/em&gt; off and &lt;em&gt;75%&lt;/em&gt; off. These two sub levels have got the leaf level members assigned to them.&lt;/p&gt;  &lt;p&gt;The &lt;em&gt;New lines&lt;/em&gt; level contains no sub levels and have the leaf level members assigned directly to it.&lt;/p&gt;  &lt;p&gt;Lets have a look at how the three tables we discussed first look after the records have been added to them. The CustomHierarchy table will contain one record and is shown below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/SVazU1cUfvI/AAAAAAAAARo/_7u-B-mRjQI/s1600-h/image%5B18%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="65" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/SVazVkY6YsI/AAAAAAAAARs/Ja7X095AAJM/image_thumb%5B9%5D.png?imgmax=800" width="288" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The CustomHierarchyLevel table will contain 5 records. Those levels that are the parent level of others will have a NULL value in the field CustomHierarchyParentLevelID.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SVazWkaMBOI/AAAAAAAAARw/sDAByhFcu4k/s1600-h/image%5B22%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="104" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SVazXpgPNbI/AAAAAAAAAR0/OUYGu04kPAw/image_thumb%5B11%5D.png?imgmax=800" width="416" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The CustomHierarchyLeaf table will contain all the leaf level members that have been assigned to the levels in the hierarchy. Below is a screen shot of what the table looks like.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SVazYeG7nbI/AAAAAAAAAR4/zh2fdJrQOQQ/s1600-h/image%5B33%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="335" alt="image" src="http://lh5.ggpht.com/_eSBtF1cAQjQ/SVazYw_X-gI/AAAAAAAAAR8/JPMtiGOETQ0/image_thumb%5B18%5D.png?imgmax=800" width="424" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h3&gt;Building the hierarchies&lt;/h3&gt;  &lt;p&gt;So the next thing we do is insert the rows into the DimCustomHierarchy table. For that we use the following stored procedure.&lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,0,255)"&gt;CREATE PROCEDURE&lt;/span&gt; prc_LoadCustomHierarchies     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;AS      &lt;br /&gt;&amp;#160; BEGIN       &lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Declare table variables      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; DECLARE&lt;/span&gt; @LoadHierarchies &lt;span style="color: rgb(0,0,255)"&gt;TABLE&lt;/span&gt; (CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;INT&lt;/span&gt;) &lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Insert new hierarchies to be loaded into the temp table&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; INSERT INTO&lt;/span&gt; @LoadHierarchies(CustomHierarchyID)     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; SELECT&lt;/span&gt; CustomHierarchyID     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; FROM&lt;/span&gt; CustomHierarchy CH     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; WHERE&lt;/span&gt; CH.CustomHierarchyID &lt;span style="color: rgb(128,128,128)"&gt;NOT IN&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;SELECT&lt;/span&gt; CustomHierarchyID     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FROM&lt;/span&gt; CustomHierarchyHistory     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ) &lt;span style="color: rgb(128,128,128)"&gt;OR&lt;/span&gt; CH.Modified = 1; &lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Insert the new hierarchies into the DimCustomHierarchy table      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; INSERT INTO&lt;/span&gt; DimCustomHierarchy (CustomHierarchyDescription,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyID     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )&amp;#160; &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; SELECT&lt;/span&gt; CustomHierarchyName,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyID     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; FROM&lt;/span&gt; CustomHierarchy CH     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; WHERE&lt;/span&gt; CH.CustomHierarchyID &lt;span style="color: rgb(128,128,128)"&gt;IN&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;SELECT&lt;/span&gt; CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;FROM&lt;/span&gt; @LoadHierarchies); &lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Insert the levels into the DimCustomHierarchy table&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; INSERT INTO&lt;/span&gt; DimCustomHierarchy(CustomHierarchyParentSK,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyDescription,&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLevelID,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyParentLevelID,&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyID     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; SELECT&lt;/span&gt; DC.CustomHierarchySK,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CL.CustomHierarchyLevelName,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CL.CustomHierarchyLevelID,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CL.CustomHierarchyParentLevelID,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CL.CustomHierarchyID     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; FROM&lt;/span&gt; CustomHierarchyLevel CL     &lt;br /&gt;&lt;span style="color: rgb(128,128,128)"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; INNER JOIN&lt;/span&gt; DimCustomHierarchy DC &lt;span style="color: rgb(0,0,255)"&gt;ON&lt;/span&gt; CL.CustomHierarchyID = DC.CustomHierarchyID     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; WHERE&lt;/span&gt; CL.CustomHierarchyID &lt;span style="color: rgb(128,128,128)"&gt;IN&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;SELECT&lt;/span&gt; CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;FROM&lt;/span&gt; @LoadHierarchies);&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Update the CustomHierarchyParentSK field for the Hierarchy records      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; UPDATE&lt;/span&gt; DC     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SET&lt;/span&gt; DC.CustomHierarchyParentSK = DC.CustomHierarchySK     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; FROM&lt;/span&gt; DimCustomHierarchy DC     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; WHERE&lt;/span&gt; DC.CustomHierarchyParentSK &lt;span style="color: rgb(128,128,128)"&gt;IS NULL AND      &lt;br /&gt;&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DC.CustomHierarchyID &lt;span style="color: rgb(128,128,128)"&gt;IN&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;SELECT&lt;/span&gt; CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;FROM&lt;/span&gt; @LoadHierarchies);&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Update the CustomHierarchyParentSK field for the level records&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; UPDATE&lt;/span&gt; DC     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; SET&lt;/span&gt; DC.CustomHierarchyParentSK = DC2.CustomHierarchySK     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; FROM&lt;/span&gt; DimCustomHierarchy DC     &lt;br /&gt;&lt;span style="color: rgb(128,128,128)"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; INNER JOIN&lt;/span&gt; DimCustomHierarchy DC2 &lt;span style="color: rgb(0,0,255)"&gt;ON&lt;/span&gt; DC.CustomHierarchyParentLevelID = DC2.CustomHierarchyLevelID     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; WHERE&lt;/span&gt; DC.CustomHierarchyID &lt;span style="color: rgb(128,128,128)"&gt;IN&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;SELECT&lt;/span&gt; CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;FROM&lt;/span&gt; @LoadHierarchies); &lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Insert the leaf level members into the DimCustomHierarchy table&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; INSERT INTO&lt;/span&gt; DimCustomHierarchy(CustomHierarchyDescription,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLeafID,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLeafKey,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyParentSK     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; SELECT &lt;/span&gt;CL.CustomHierarchyLeafName,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CL.CustomHierarchyLeafID,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CL.CustomHierarchyLeafKey,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DC.CustomHierarchySK     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; FROM&lt;/span&gt; CustomHierarchyLeaf CL     &lt;br /&gt;&lt;span style="color: rgb(128,128,128)"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; INNER JOIN&lt;/span&gt; DimCustomHierarchy DC &lt;span style="color: rgb(0,0,255)"&gt;ON&lt;/span&gt; CL.CustomHierarchyLevelID = DC.CustomHierarchyLevelID     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; WHERE&lt;/span&gt; DC.CustomHierarchyID&lt;span style="color: rgb(128,128,128)"&gt; IN&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;SELECT&lt;/span&gt; CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;FROM&lt;/span&gt; @LoadHierarchies) &lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Truncate the many to many fact table for the DimCustomHierarchy table&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; TRUNCATE TABLE&lt;/span&gt; FactHierarchy &lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Create the many to many fact table for the DimCustomHierarchy dimension&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; INSERT INTO&lt;/span&gt; FactHierarchy(CustomHierarchySK,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLeafKey&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; SELECT&lt;/span&gt; CustomHierarchySK,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CustomHierarchyLeafKey     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; FROM&lt;/span&gt; DimCustomHierarchy     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; WHERE&lt;/span&gt; CustomHierarchyLeafKey &lt;span style="color: rgb(128,128,128)"&gt;IS NOT NULL&lt;/span&gt;; &lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Insert new hierarchies into the CustomHierarchyHistory table      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; INSERT INTO&lt;/span&gt; CustomHierarchyHistory(CustomHierarchyID)     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; SELECT&lt;/span&gt; CustomHierarchyID     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; FROM&lt;/span&gt; @LoadHierarchies LH     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; WHERE&lt;/span&gt; LH.CustomHierarchyID &lt;span style="color: rgb(128,128,128)"&gt;NOT IN&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;SELECT&lt;/span&gt; CustomHierarchyID     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FROM&lt;/span&gt; CustomHierarchyHistory     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );     &lt;br /&gt;&lt;span style="color: rgb(0,128,0)"&gt;&amp;#160;&amp;#160; --Reset modified field on CustomHierarchy table      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; UPDATE CH&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SET&lt;/span&gt; Modified = 0     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; FROM&lt;/span&gt; CustomHierarchy CH     &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160;&amp;#160; WHERE&lt;/span&gt; CustomHierarchyID &lt;span style="color: rgb(128,128,128)"&gt;IN&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;SELECT&lt;/span&gt; CustomHierarchyID &lt;span style="color: rgb(0,0,255)"&gt;FROM&lt;/span&gt; @LoadHierarchies);&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;span style="color: rgb(0,0,255)"&gt;&amp;#160; END&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: rgb(0,0,255)"&gt;&lt;span style="color: #404040"&gt;The result of the stored procedure is displayed below.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SVpoFl5i-TI/AAAAAAAAAS0/ebqpZDYYxUY/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="268" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SVpoG4q2v7I/AAAAAAAAAS4/cy4D09ifUDg/image_thumb%5B2%5D.png?imgmax=800" width="571" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;As you can see we now have all the records inserted into the DimCustomHierarchy table ready to be utilised in the creation of the parent child hierarchy in Analysis Services.&lt;/p&gt;  &lt;h3&gt;Creating the cube&lt;/h3&gt;  &lt;p&gt;So now that our hierarchies have been built it is time to create the cube. Below is the data source view of our cube.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SVazZl-yoMI/AAAAAAAAASA/rTUTtrONMqo/s1600-h/image%5B53%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="395" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/SVazaR_zARI/AAAAAAAAASE/stPo4lQZvyI/image_thumb%5B30%5D.png?imgmax=800" width="542" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In the cube we create a couple of dimension as can be seen in the screenshot below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/SVazbEW5nbI/AAAAAAAAASI/I1fb6R917SE/s1600-h/image%5B57%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="291" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SVazbwwKEOI/AAAAAAAAASM/GypmM-11TwE/image_thumb%5B32%5D.png?imgmax=800" width="211" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Of the dimension in the solution the most important one is the &lt;em&gt;Custom Hierarchy&lt;/em&gt; dimension. This dimension contains a parent child hierarchy, that has been created using the CustomHierarchySK, CustomHierarchyParentSK and CustomHierarchyDescription fields.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_eSBtF1cAQjQ/SVazceA_b-I/AAAAAAAAASQ/C2ctyrsxoqQ/s1600-h/image%5B69%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="293" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/SVazc76Z0EI/AAAAAAAAASY/tBiOD6UJWNA/image_thumb%5B40%5D.png?imgmax=800" width="591" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This is the dimension that will allow the users to slice and dice their information according to the hierarchies they have created. This dimension is linked through the FactHierarchy table with the FactSales table. This is displayed in the screnshot of the dimension usage tab of the cube below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_eSBtF1cAQjQ/SVazdBdZPWI/AAAAAAAAASc/FYtrbTs0Nos/s1600-h/image%5B75%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="225" alt="image" src="http://lh3.ggpht.com/_eSBtF1cAQjQ/SVazdgWaS3I/AAAAAAAAASg/HTZl9bqlwzU/image_thumb%5B44%5D.png?imgmax=800" width="399" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;After all the work that have been done we are now set to browse the cube according using the hierarchies that we have created according to our business needs. &lt;/p&gt;  &lt;p&gt;Below is a screenshot of the cube being browsed using the custom hierarchy that was created.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_eSBtF1cAQjQ/SVazeucECWI/AAAAAAAAASk/lTGb5cuJNK8/s1600-h/image%5B81%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="341" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SVazfldH-WI/AAAAAAAAASo/xCBuw5-NjY8/image_thumb%5B48%5D.png?imgmax=800" width="557" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If a user now decides to add another hierarchy to the BI solution browsing the cube will look similar to the screenshot below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_eSBtF1cAQjQ/SVazgfFi9fI/AAAAAAAAASs/f94jFZBqfSc/s1600-h/image%5B85%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="274" alt="image" src="http://lh4.ggpht.com/_eSBtF1cAQjQ/SVazg8HKOjI/AAAAAAAAASw/L496i6qqZRQ/image_thumb%5B50%5D.png?imgmax=800" width="557" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;I am sure that everyone can agree that the ability to allow users to create hierarchies as per their business requirements is a big advantage in any BI solution. &lt;/p&gt;  &lt;p&gt;It must be noted that this must be used sparingly as it will have a performance impact on the cube used in the solution. This can be partly offset by using the correct processing strategies but the use of an intermediate fact table does come at a cost. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-5341914525403340706?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/5341914525403340706/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=5341914525403340706&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/5341914525403340706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/5341914525403340706'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2008/12/allowing-users-to-create-their-own.html' title='Allowing users to create their own hierarchies in a cube'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_eSBtF1cAQjQ/SVazN3J_EXI/AAAAAAAAARE/2-ouRUaDRvM/s72-c/image_thumb%5B14%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-3628255698579992945</id><published>2008-09-14T19:10:00.000+01:00</published><updated>2008-09-14T20:16:33.183+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WMI'/><category scheme='http://www.blogger.com/atom/ns#' term='WQL'/><category scheme='http://www.blogger.com/atom/ns#' term='VBscript'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Getting your drive fragmentation percentage programmatically</title><content type='html'>&lt;p&gt;Recently a colleague of my asked me if there is a way to get the fragmentation percentage of a drive programmatically. My first thought was to do this in SSIS but my colleague wanted to get the information using a TSQL script on any version of SQL Server and this prompted me to look for other means of accomplishing this.&lt;/p&gt;  &lt;p&gt;The easiest way to get this done was via a visual basic script. I found a very helpful section at Microsoft Script Center that provides you with a very useful guide on how to write a script to accomplish this exact task (&lt;a title="http://www.microsoft.com/technet/scriptcenter/topics/win2003/defrag.mspx#EKEAC" href="http://www.microsoft.com/technet/scriptcenter/topics/win2003/defrag.mspx#EKEAC"&gt;http://www.microsoft.com/technet/scriptcenter/topics/win2003/defrag.mspx#EKEAC&lt;/a&gt;).&lt;/p&gt;  &lt;p&gt;Since the script provided at the above location returns all the information that can be returned from the Win32_DefragAnalysis method of the Win32_Volume WMI class I have decided to strip this down into the following script.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#808080"&gt;strComputer = &amp;quot;.&amp;quot;        &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;Set&lt;/font&gt; &lt;font color="#808080"&gt;objWMIService = GetObject(&amp;quot;winmgmts:\\&amp;quot; &amp;amp; strComputer &amp;amp; &amp;quot;\root\cimv2&amp;quot;)&lt;/font&gt; &lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff"&gt;Set &lt;/font&gt;&lt;font color="#808080"&gt;colVolumes = objWMIService.ExecQuery(&amp;quot;SELECT * FROM Win32_Volume WHERE DriveType = 3&amp;quot;)&lt;/font&gt; &lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff"&gt;For Each&lt;/font&gt; &lt;font color="#808080"&gt;objVolume&lt;/font&gt; &lt;font color="#0000ff"&gt;in&lt;/font&gt; &lt;font color="#808080"&gt;colVolumes        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;errResult = objVolume.DefragAnalysis(blnRecommended, objReport)        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;If&lt;/font&gt; &lt;font color="#808080"&gt;errResult = 0 Then        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo &amp;quot;Volume Name: &amp;quot; &amp;amp; objVolume.Name &amp;amp; &amp;quot;; Total fragmentation: &amp;quot; &amp;amp; _         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objReport.TotalPercentFragmentation &amp;amp; &amp;quot;%&amp;quot;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo         &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Else&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;Wscript.Echo objVolume.Name &amp;amp; &amp;quot; could not be analyzed.&amp;quot; &amp;amp; _        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot; Error number &amp;quot; &amp;amp; errResult &amp;amp; &amp;quot; occurred.&amp;quot;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo         &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;End If&lt;/font&gt;       &lt;br /&gt;&lt;font color="#0000ff"&gt;Next&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font color="#000000"&gt;This small script will loop through all the local drives available and it will return the name and the total fragmentation percentage of the drive. (By using the DriveType property of the Win32_Volume WMI Class in the WHERE clause we filter our results to that of the local drives only. By specifying only the local drives we ensure that we will not receive any errors for the optical drives attached to the system.)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000000"&gt;If we change the &lt;font color="#808080"&gt;strComputer&lt;/font&gt; variable's value to that of a remote machine the query will return the fragmentation information of the remote machine.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000000"&gt;The next step will be to save the above script to a file on your drive. You can use notepad to save it. Make sure that you save it with an extension of .vbs otherwise you will not be able to execute the script with the windows script engine.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000000"&gt;&lt;em&gt;It is very important to note that the DefragAnalysis and Defrag methods of the Win32_Volume class are only available in Windows Server 2003 and newer editions of windows. It is not available in Windows Server 2000 or Windows XP.&lt;/em&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;Executing your script from SQL Server&lt;/h3&gt;  &lt;p&gt;The next step will be to execute our script from SQL Server. Before you do this you need to ensure that you are capable of executing the xp_cmdshell extended stored procedure. Use the Books Online of your particular version of SQL Server to find the steps needed to enable the use of xp_cmdshell.&lt;/p&gt;  &lt;p&gt;The following TSQL will execute the script that I saved as scptGetDriveAnalysis.vbs in the Temp folder of my C: drive.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#0000ff"&gt;exec &lt;/font&gt;master.dbo.&lt;font color="#800000"&gt;xp_cmdshell&lt;/font&gt; &lt;font color="#ff0000"&gt;'cscript C:\Temp\scptGetDriveAnalysis.vbs'&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The result should be similar to the screenshot below.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/twist43/SM1VRQQWWOI/AAAAAAAAAO4/5O-Uj01A5uc/SQLResult%5B3%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="179" alt="SQLResult" src="http://lh4.ggpht.com/twist43/SM1WnBJGYnI/AAAAAAAAAO8/fFDo6FXARxw/SQLResult_thumb%5B1%5D.png" width="319" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You can see that I only have two local hard drives on my machine (C:\ and E:\) and the total fragmentation percentage for each is listed next to it.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Now if you would like to use this information to determine which drive you need to defrag you might want to changes the script to look similar to this.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#808080"&gt;strComputer = &amp;quot;.&amp;quot;        &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;Set&lt;/font&gt; &lt;font color="#808080"&gt;objWMIService = GetObject(&amp;quot;winmgmts:\\&amp;quot; &amp;amp; strComputer &amp;amp; &amp;quot;\root\cimv2&amp;quot;)&lt;/font&gt; &lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff"&gt;Set &lt;/font&gt;&lt;font color="#808080"&gt;colVolumes = objWMIService.ExecQuery(&amp;quot;SELECT * FROM Win32_Volume WHERE DriveType = 3&amp;quot;)&lt;/font&gt; &lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff"&gt;For Each&lt;/font&gt; &lt;font color="#808080"&gt;objVolume&lt;/font&gt; &lt;font color="#0000ff"&gt;in&lt;/font&gt; &lt;font color="#808080"&gt;colVolumes        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;errResult = objVolume.DefragAnalysis(blnRecommended, objReport)        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;If&lt;/font&gt; &lt;font color="#808080"&gt;errResult = 0 Then        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo &amp;quot;Drive: &amp;quot; &amp;amp; objVolume.Name &amp;amp; &amp;quot;;&amp;quot; &amp;amp; _         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; objReport.TotalPercentFragmentation &amp;amp; _&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo         &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Else&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;Wscript.Echo objVolume.Name &amp;amp; &amp;quot; could not be analyzed.&amp;quot; &amp;amp; _        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot; Error number &amp;quot; &amp;amp; errResult &amp;amp; &amp;quot; occurred.&amp;quot;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo         &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;End If&lt;/font&gt;       &lt;br /&gt;&lt;font color="#0000ff"&gt;Next&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;You will see that I have removed most of the text description in front of the values that will be displayed. This will allow us to get the values into a table much easier. Have a look at the script below that creates a table and inserts the values into it.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#00ff80"&gt;&lt;font color="#008040"&gt;--Create the table that will contain the values for future use&lt;/font&gt;         &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;CREATE TABLE&lt;/font&gt; dbo.DefragAnalysis(Date &lt;font color="#0000ff"&gt;DATETIME&lt;/font&gt;,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Drive &lt;font color="#0000ff"&gt;VARCHAR&lt;/font&gt;(10),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FragmentationPerc &lt;font color="#0000ff"&gt;FLOAT        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ) &lt;/p&gt;    &lt;p&gt;&lt;font color="#008040"&gt;--Declare a table variable for temporary use&lt;/font&gt;       &lt;br /&gt;&lt;font color="#0000ff"&gt;DECLARE&lt;/font&gt; @TempTable &lt;font color="#0000ff"&gt;TABLE&lt;/font&gt; (TxtLine &lt;font color="#0000ff"&gt;VARCHAR&lt;/font&gt;(80)) &lt;/p&gt;    &lt;p&gt;&lt;font color="#008040"&gt;--Insert the results of the script into the table variable&lt;/font&gt;       &lt;br /&gt;&lt;font color="#0000ff"&gt;INSERT&lt;/font&gt; @TempTable       &lt;br /&gt;&lt;font color="#0000ff"&gt;exec&lt;/font&gt; (&lt;font color="#ff0000"&gt;'exec master.dbo.xp_cmdshell ''cscript C:\Temp\scptGetDriveAnalysis.vbs'''&lt;/font&gt;) &lt;/p&gt;    &lt;p&gt;&lt;font color="#008040"&gt;--Delete all the unwanted information from the table variable&lt;/font&gt;       &lt;br /&gt;&lt;font color="#0000ff"&gt;DELETE FROM&lt;/font&gt; @TempTable &lt;font color="#0000ff"&gt;WHERE&lt;/font&gt; TxtLine &lt;font color="#808080"&gt;NOT LIKE&lt;/font&gt;&lt;font color="#ff0000"&gt; '%Drive%'&lt;/font&gt; &lt;font color="#808080"&gt;OR&lt;/font&gt; TxtLine &lt;font color="#808080"&gt;IS NULL&lt;/font&gt; &lt;/p&gt;    &lt;p&gt;&lt;font color="#008040"&gt;--Insert the data into the table&lt;/font&gt;       &lt;br /&gt;&lt;font color="#0000ff"&gt;INSERT INTO&lt;/font&gt; dbo.DefragAnalysis (Date,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Drive,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FragmentationPerc       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )       &lt;br /&gt;&lt;font color="#0000ff"&gt;SELECT&lt;/font&gt; &lt;font color="#ff00ff"&gt;Cast&lt;/font&gt;(&lt;font color="#ff00ff"&gt;Floor&lt;/font&gt;(&lt;font color="#ff00ff"&gt;Cast&lt;/font&gt;(&lt;font color="#ff00ff"&gt;Getdate&lt;/font&gt;()&lt;font color="#0000ff"&gt;AS&lt;/font&gt; &lt;font color="#0000ff"&gt;Float&lt;/font&gt;)) &lt;font color="#0000ff"&gt;AS DateTime&lt;/font&gt;) &lt;font color="#0000ff"&gt;AS&lt;/font&gt; Date,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#ff00ff"&gt;SUBSTRING&lt;/font&gt;(TxtLine,8,&lt;font color="#ff00ff"&gt;CHARINDEX&lt;/font&gt;(&lt;font color="#ff0000"&gt;';'&lt;/font&gt;,TxtLine) -8) &lt;font color="#0000ff"&gt;AS&lt;/font&gt; Drive,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#ff00ff"&gt;SUBSTRING&lt;/font&gt;(TxtLine,&lt;font color="#ff00ff"&gt;CHARINDEX&lt;/font&gt;(&lt;font color="#ff0000"&gt;';'&lt;/font&gt;,TxtLine) +1,&lt;font color="#ff00ff"&gt;LEN&lt;/font&gt;(TxtLine)) &lt;font color="#0000ff"&gt;AS&lt;/font&gt; FragmentationPerc       &lt;br /&gt;&lt;font color="#0000ff"&gt;FROM&lt;/font&gt; @TempTable&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If we query the dbo.DefragAnalysis table our results are as follows.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/twist43/SM1aJsFjV3I/AAAAAAAAAPI/lPSPcIsSpfo/TableQueryResult%5B1%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="91" alt="TableQueryResult" src="http://lh4.ggpht.com/twist43/SM1WuSTlxJI/AAAAAAAAAPM/YU9jkE8k5AA/TableQueryResult_thumb.png" width="319" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h3&gt;Taking it one step further&lt;/h3&gt;  &lt;p&gt;After all this work to get the fragmentation percentage of a drive it would be very disheartening if we could not defrag the drives that have a fragmentation percentage above our maintenance threshold.&lt;/p&gt;  &lt;p&gt;Luckily we are able to do this and you can use the script below to do exactly that. &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#808080"&gt;strComputer = &amp;quot;.&amp;quot;        &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;Set&lt;/font&gt; &lt;font color="#808080"&gt;objWMIService = GetObject(&amp;quot;winmgmts:\\&amp;quot; &amp;amp; strComputer &amp;amp; &amp;quot;\root\cimv2&amp;quot;)&lt;/font&gt; &lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff"&gt;Set &lt;/font&gt;&lt;font color="#808080"&gt;colVolumes = objWMIService.ExecQuery _        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;Select * from Win32_Volume Where Name = 'C:\\'&amp;quot;) &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Set &lt;/font&gt;&lt;font color="#808080"&gt;colProcesses = objWMIService.ExecQuery _        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;Select * from Win32_Process Where Name = ' Dfrgntfs.exe'&amp;quot;) &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;If&lt;/font&gt; &lt;font color="#808080"&gt;colProcesses.Count = 0&lt;/font&gt; &lt;font color="#0000ff"&gt;Then&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;&amp;#160; For Each&lt;/font&gt; &lt;font color="#808080"&gt;objVolume&lt;/font&gt; &lt;font color="#0000ff"&gt;in&lt;/font&gt; &lt;font color="#808080"&gt;colVolumes &lt;/font&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;Wscript.Echo &amp;quot;Please wait while drive &amp;quot; &amp;amp; objVolume.Name &amp;amp; &amp;quot; is defragged.&amp;quot;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; errResult = objVolume.Defrag() &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;If&lt;/font&gt; &lt;font color="#808080"&gt;errResult = 0 &lt;/font&gt;&lt;font color="#0000ff"&gt;Then&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;Wscript.Echo &amp;quot;Drive &amp;quot; &amp;amp; objVolume.Name &amp;amp; &amp;quot; successfully defragged.&amp;quot;        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Else&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;Wscript.Echo &amp;quot;Drive &amp;quot; &amp;amp; objVolume.Name &amp;amp; &amp;quot; could not be defragged.&amp;quot;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo &amp;quot;Error number &amp;quot; &amp;amp; errResult &amp;amp; &amp;quot; occurred.&amp;quot;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Err.Clear         &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;End If        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Next &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160;&amp;#160; Else        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;&amp;#160; Wscript.Echo &amp;quot; Dfrgntfs.exe is running.&amp;quot;        &lt;br /&gt;&lt;/font&gt;&amp;#160; &lt;font color="#0000ff"&gt;&amp;#160; End If&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The above script will first check to see if an instance of defrag is already running before it starts to defrag the relevant drive.&lt;/p&gt;  &lt;p&gt;You can modify the script by changing &amp;quot;C:\&amp;quot; to the drive that you would like to defrag. We could create a script for each drive of our system and execute the script for a particular drive based on the fragmentation percentage stored in our DefragAnalysis table from within a stored procedure or script.&lt;/p&gt;  &lt;p&gt;Alternatively we could move the logic to defrag a drive above a certain fragmentation percentage into our script instead of having it in a stored procedure or SQL Script. The following script will defrag all drives with a total fragmentation percentage above 15%.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#808080"&gt;strComputer = &amp;quot;.&amp;quot;        &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;Set&lt;/font&gt; &lt;font color="#808080"&gt;objWMIService = GetObject(&amp;quot;winmgmts:\\&amp;quot; &amp;amp; strComputer &amp;amp; &amp;quot;\root\cimv2&amp;quot;) &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff"&gt;Set&lt;/font&gt; &lt;font color="#808080"&gt;colVolumes = objWMIService.ExecQuery(&amp;quot;SELECT * FROM Win32_Volume WHERE DriveType = 3&amp;quot;)        &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;Set&lt;/font&gt; &lt;font color="#808080"&gt;colProcesses = objWMIService.ExecQuery(&amp;quot;Select * from Win32_Process Where Name = ' Dfrgntfs.exe'&amp;quot;) &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff"&gt;For Each&lt;/font&gt; &lt;font color="#808080"&gt;objVolume&lt;/font&gt; &lt;font color="#0000ff"&gt;in&lt;/font&gt; &lt;font color="#808080"&gt;colVolumes&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;errResult = objVolume.DefragAnalysis(blnRecommended, objReport)        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;If&lt;/font&gt; &lt;font color="#808080"&gt;errResult = 0&lt;/font&gt; &lt;font color="#0000ff"&gt;Then&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;&amp;#160; If&lt;/font&gt; &lt;font color="#808080"&gt;colProcesses.Count = 0&lt;/font&gt; &lt;font color="#0000ff"&gt;AND&lt;/font&gt; &lt;font color="#808080"&gt;objReport.TotalPercentFragmentation &amp;gt; &lt;/font&gt;&lt;font color="#ff0000"&gt;15&lt;/font&gt; &lt;font color="#0000ff"&gt;Then        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;&amp;#160;&amp;#160; Wscript.Echo &amp;quot;Please wait while drive &amp;quot; &amp;amp; objVolume.Name &amp;amp; &amp;quot; is defragged.&amp;quot;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; errDefragResult = objVolume.Defrag() &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;If&lt;/font&gt;&lt;font color="#808080"&gt; errDefragResult = 0&lt;/font&gt; &lt;font color="#0000ff"&gt;Then&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;Wscript.Echo &amp;quot;Drive &amp;quot; &amp;amp; objVolume.Name &amp;amp; &amp;quot; successfully defragged.&amp;quot;        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Else&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;Wscript.Echo &amp;quot;Drive &amp;quot; &amp;amp; objVolume.Name &amp;amp; &amp;quot; could not be defragged.&amp;quot;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo &amp;quot;Error number &amp;quot; &amp;amp; errResult &amp;amp; &amp;quot; occurred.&amp;quot;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Err.Clear         &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; End If&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;ElseIf &lt;/font&gt;&lt;font color="#808080"&gt;colProcesses.Count = 0&lt;/font&gt;&lt;font color="#0000ff"&gt; AND&lt;/font&gt; &lt;font color="#808080"&gt;objReport.TotalPercentFragmentation &amp;lt; &lt;/font&gt;&lt;font color="#ff0000"&gt;15&lt;/font&gt; &lt;font color="#0000ff"&gt;Then        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;Wscript.Echo &amp;quot;Drive &amp;quot; &amp;amp; objVolume.Name &amp;amp; &amp;quot; does not need to be defragged.&amp;quot;        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;&amp;#160;&amp;#160; Else&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;&amp;#160; Wscript.Echo &amp;quot;Drive &amp;quot; &amp;amp; objVolume.Name &amp;amp; &amp;quot; could not be defragged.&amp;quot;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo &amp;quot;Error number &amp;quot; &amp;amp; errResult &amp;amp; &amp;quot; occurred.&amp;quot;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Err.Clear         &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;Else&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;Wscript.Echo objVolume.Name &amp;amp; &amp;quot; could not be analyzed.&amp;quot; &amp;amp; _        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot; Error number &amp;quot; &amp;amp; errResult &amp;amp; &amp;quot; occurred.&amp;quot;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Wscript.Echo         &lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;#160;&amp;#160;&amp;#160; End If        &lt;br /&gt;Next&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;As mentioned earlier in this post, we can change the value of the &lt;font color="#808080"&gt;strComputer &lt;/font&gt;variable to that of a remote machine and in doing so defrag the drives of our remote machine programmatically.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-3628255698579992945?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/3628255698579992945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=3628255698579992945&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/3628255698579992945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/3628255698579992945'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2008/09/getting-your-drive-fragmentation.html' title='Getting your drive fragmentation percentage programmatically'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/twist43/SM1WnBJGYnI/AAAAAAAAAO8/fFDo6FXARxw/s72-c/SQLResult_thumb%5B1%5D.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-8668499121948152563</id><published>2008-08-05T20:29:00.000+01:00</published><updated>2008-09-10T20:29:52.678+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><title type='text'>SSIS package for SQL Server Maintenance</title><content type='html'>&lt;p&gt;Just a quick post regarding SSIS package for SQL Server Maintenance. Few people actually know that you don't always have to open up the Business Intelligence Development Studio to design SSIS packages. A good example of this is designing your SSIS Maintenance Package from the SQL Server Management Studio.&lt;/p&gt;  &lt;p&gt;Have a look at the below screenshot. You will see that you can design your maintenance routines by right clicking on Maintenance Plans under the Maintenance section in SQL Server Management Studio and selecting New Maintenance Plan.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1pDX_d6G3NWnlRbrOyFEbSq5qu27lqDGv9NIvAJv4GJxWYe6nIU1XLX4GOM9iFEZ34gW2BXuhsCk8?PARTNER=WRITER"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="388" alt="Maintenance Plan" src="http://pimfqq.bay.livefilestore.com/y1pkZ4ojBLbdPAr_X6RV2FmyuLw-luXajH2rdRAD_ASrUN9txR1PvAKIWLsIP4af5N9iCXsydO5cCaMbUVR4809fg?PARTNER=WRITER" width="619" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You will be prompted to supply a name for your maintenance plan after which you will see a screen that looks very much like the control flow in BIDS.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1p3LE5cEIvsAqj3eMdciBjo5mLHueI28FeBOTuIF-rJ4GpTVwaFBjAfpn0Jx_yFZKojWz5ek7MRBPqPqYCLqOWWg?PARTNER=WRITER"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="388" alt="Maintenance Plan SSIS Tasks" src="http://pimfqq.bay.livefilestore.com/y1p02hOZbypRPsjJCpoFPRQthtf2di2Z0EIn3RqcJQPuYSPtMO88Vq9f3Ufkvw49ospNP4jDL2Jp3lLEdnICSI-_Q?PARTNER=WRITER" width="619" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;From here you can design your maintenance plan which is an SSIS package that will be stored in the MSDB database. Once you connect to your Integration Services Engine in SQL Server Management Studio you will find the maintenance plan package saved under the Store Packages in the MSDB subsection.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1pCpRWXdcaIlNmCw4N04W2A422Ert3b6VRaCiKJAYawRpmy3DdToDYzuRxS2MDhVvEPSGLAizV-CeSinqAv-wa2Q?PARTNER=WRITER"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="388" alt="Maintenance Plan SSIS Package" src="http://pimfqq.bay.livefilestore.com/y1p-AbQXXNfFpXRcf6R9LRoWe_wPBJWQi_raC5ARqC4sfaJqcgd4UN-7NcmQ2nMH8OiA7HW0JskDNRNmaDjyaNz0w?PARTNER=WRITER" width="619" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-8668499121948152563?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/8668499121948152563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=8668499121948152563&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8668499121948152563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/8668499121948152563'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2008/08/ssis-package-for-sql-server-maintenance.html' title='SSIS package for SQL Server Maintenance'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-1606592155357647858</id><published>2008-08-01T05:39:00.001+01:00</published><updated>2008-09-17T19:40:26.928+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><title type='text'>Integration Services 2008 - Data Profiling Task</title><content type='html'>&lt;p&gt;I have recently been playing with SQL Server 2008 RC0 and have been creating some demos for presentation purposes and would like to share with you a couple of really cool new features.&lt;/p&gt;  &lt;p&gt;The release to market of SQL Server 2008 is fast becoming one of the most anticipated events on my calendar. With new features such as the Data Profiling Task in SSIS 2008 how can it not be?&lt;/p&gt;  &lt;h3&gt;Getting a good look at source data&lt;/h3&gt;  &lt;p&gt;I am sure that anyone that have been involved in any kind of ETL knows the pain of bad data. Each developer normally has his or her own way of analysing the source data whether it's a third party tool or internal process. In SQL Server 2008 Integration Services Microsoft has provided us with a nice and nifty task call the Data Profiling Task.&lt;/p&gt;  &lt;p&gt;The Data Profiling Task allows you to create a set of profiles for tables or views. The source database has to be SQL 2000 or later and an ADO.NET connection manager is used to provide access to the tables or views.&lt;/p&gt;  &lt;h3&gt;A quick introduction&lt;/h3&gt;  &lt;p&gt;Let's look at creating a quick profile of a table with this new task.&lt;/p&gt;  &lt;p&gt;As I have mentioned previously you need to set up a ADO.NET connection manager to you source database. From the below screenshot you will see that I have established a connection to the Adventure Works 2008 database. (you can get it on CodePlex if you don't already have it)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1pAxJC8f2kkcom5Cog3i4lQZx3U7qKj0BRnWwta0cuKPwyGWOc33pQA9mVgGhBnajFu1sVgJSW1yU?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="ADONET Connection Manager" src="http://byfiles.storage.msn.com/y1pydg9GfCWXMCFqpWkzxBcex0bbdFJhKCdhrlpgydIVuwc9HCke1AgdtdCktLd5djYz5MoEVR-YM4?PARTNER=WRITER" width="575" border="0" height="395" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now that we have our connection manager the next step is to add a Data Profiling Task to our control flow. Yes the task resides in the control flow and not the data flow.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1pPS06ePUobgP688HreudDKY2CAX7XG-eZcQGInCQi6TyaScbW1526N-d98eHiWHXW4RUXPcaETGHAtzB9sAvuCg?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="DataProfilingTask" src="http://byfiles.storage.msn.com/y1peYvL85G7zJV2tqG-_7mobUYWuX0H_yzHVzn6DxWvAlNyBm84YM-Ge8LaxtfQ9B9Zewyf0O1SY34?PARTNER=WRITER" width="575" border="0" height="435" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;So now that we have our Data Profiling Task added to the control flow we need to configure it in order to create our data profile.&lt;/p&gt;  &lt;p&gt;On the general section of the Data Profiling Task Editor we specify how we want the results to be saved. You have two options one being an XML file and the other being a variable. We will use the XML file as we will use the Data Profiling Viewer at the end to look at the profiling data that the task creates.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pFu_zHB6zIcrLZoUcIh00bh-EW9vH60lzi9BQkNVLCAsEtENGy9Q4u7Qo14T4waXBdm93itNYPl4?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="DataProfilingTask_General" src="http://byfiles.storage.msn.com/y1pWBERhXswKWqxfYsX7IHhgHRE6iTnhqoM1hfiKJQcdhnIfv7pH8-EmXvhH8ZYMRxBE5OYTSVOzFc?PARTNER=WRITER" width="419" border="0" height="400" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;On the Profile Requests section we have the ability to manually specify which profiles we want to create and on which columns. Instead of doing an in depth blog post this post is aimed at a brief introduction to this task. We will click on the "Quick Profile" button at the bottom of the General section. This allows us to quickly setup a number of profiles for a specific table or view and is generally a good start if you want to quickly set up profiling for a specific source.&lt;/p&gt;  &lt;p&gt;When you click on the "Quick Profile" button the Single Table Quick Profile Form window is launched. Here you will be able to select the different profiles that you would like to create. Keep in mind that this is for a single table. If you want to use multiple tables as you would for certain profiles you need to use the Profile Request section to set up the profiles manually.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pq-prb9rEyfW_s_Hf1VyM4vyYrkfywIRqoNmcHu3z4i-NNKMnHNDLu0XpzBXnCya2Z6lv3o-leM8?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="Single Table Quick Profile Form" src="http://byfiles.storage.msn.com/y1pHuQzm1FHEVUe9ciPxhOfhZhno-8xmqBHMHmFZa_GvoZ3RCfUJDCzM_k4e9CZPi32l_wAmbOIMtY?PARTNER=WRITER" width="419" border="0" height="353" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In the above screenshot you will see that we specify the ADO.NET connection manager that we created earlier. We then choose the table on which we want to perform the analysis. I have chosen the Product table in the Production schema. &lt;/p&gt;  &lt;p&gt;Next we choose the different profiles that we would like to create on the table. (When you use the Quick Profile the profiles that you compute will be done on all the columns in the table where the column supports the profile. For example the Column Patter Profile can only be computed on columns of a text data type (varchar, nvarchar etc.) thus it will not be created for numeric column.)&lt;/p&gt;  &lt;p&gt;Here is an extract from Books Online of SQL Server RC0 with the definitions and some detail regarding the different profiles:&lt;/p&gt;  &lt;table width="765" border="1" cellpadding="2" cellspacing="0"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="176"&gt;         &lt;p dir="ltr" style="margin-right: 0px;"&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="587"&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="177"&gt;Column Null Ratio Profile&lt;/td&gt;        &lt;td valign="top" width="587"&gt;         &lt;p&gt;Compute a Column Null Ratio Profile. &lt;/p&gt;          &lt;p&gt;The Column Null Ratio Profile reports the percentage of null values in the selected column. This profile can help you identify problems in your data such as an unexpectedly high ratio of null values in a column. For example, you profile a Zip Code/Postal Code column and discover an unacceptably high percentage of missing codes.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="178"&gt;Column Statistics Profile&lt;/td&gt;        &lt;td valign="top" width="587"&gt;         &lt;p&gt;Select this option to compute a Column Statistics Profile using the default settings for all applicable columns in the selected table or view. &lt;/p&gt;          &lt;p&gt;The Column Statistics Profile reports statistics such as minimum, maximum, average, and standard deviation for numeric columns, and minimum and maximum for datetime columns. This profile can help you identify problems in your data, such as dates that are not valid. For example, you profile a column of historical dates and discover a maximum date that is in the future.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="179"&gt;Column Value Distribution Profile&lt;/td&gt;        &lt;td valign="top" width="587"&gt;         &lt;p&gt;Compute a Column Value Distribution Profile. &lt;/p&gt;          &lt;p&gt;The Column Value Distribution Profile reports all the distinct values in the selected column and the percentage of rows in the table that each value represents. This profile can also report values that represent more than a specified percentage in the table. This profile can help you identify problems in your data such as an incorrect number of distinct values in a column. For example, you profile a column that contains states in the United States and discover more than 50 distinct values.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="180"&gt;Column Length Distribution Profile&lt;/td&gt;        &lt;td valign="top" width="587"&gt;         &lt;p&gt;Compute a Column Length Distribution profile by using the default settings for all applicable columns in the selected table or view. &lt;/p&gt;          &lt;p&gt;This profile reports all the distinct lengths of string values in the selected column and the percentage of rows in the table that each length represents. This profile can help you identify problems in your data, such as values that are not valid. For more information about the settings for this profile, see Column Length Distribution Profile Request Options (Data Profiling Task).&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="180"&gt;Column Pattern Profile&lt;/td&gt;        &lt;td valign="top" width="587"&gt;         &lt;p&gt;Compute a Column Pattern Profile. &lt;/p&gt;          &lt;p&gt;The Column Pattern Profile reports a set of regular expressions that cover the specified percentage of values in a string column. This profile can help you identify problems in your data, such as strings that are not valid strings. This profile can also suggest regular expressions that can be used in the future to validate new values. For example, a pattern profile of a Zip Code/Postal Code column might produce the regular expressions: \d{5}-\d{4}, \d{5}, and \d{9}. If you see other regular expressions, your data likely contains values that are not valid or in an incorrect format.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="180"&gt;Candidate Key Profile&lt;/td&gt;        &lt;td valign="top" width="587"&gt;         &lt;p&gt;Compute a Candidate Key Profile. &lt;/p&gt;          &lt;p&gt;This profile This profile reports whether a column or set of columns is a key, or an approximate key, for the selected table. This profile can also help you identify problems in your data, such as duplicate values in a potential key column.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="180"&gt;   for up to N Column keys&lt;/td&gt;        &lt;td valign="top" width="587"&gt;Select the maximum number of columns to test in possible combinations as a key for the table or view. The default value is 1. The maximum value is 1000. For example, selecting 3 tests one-column, two-column, and three-column key combinations.&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="180"&gt;Functional Dependency Profile&lt;/td&gt;        &lt;td valign="top" width="587"&gt;         &lt;p&gt;Compute a Functional Dependency Profile. &lt;/p&gt;          &lt;p&gt;The Functional Dependency Profile reports the extent to which the values in one column (the dependent column) depend on the values in another column or set of columns (the determinant column). This profile can also help you identify problems in your data, such as values that are not valid. For example, you profile the dependency between a column of United States Zip Codes and a column of states in the United States. The same Zip Code should always have the same state, but the profile discovers violations of this dependency.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="180"&gt;   for up to N Columns as         &lt;br /&gt;   the determiner&lt;/td&gt;        &lt;td valign="top" width="587"&gt;         &lt;p&gt;Select the maximum number of columns to test in possible combinations as the determinant columns. The default value is 1. The maximum value is 1000. For example, selecting 2 tests combinations in which either single columns or two-column combinations are the determinant columns for another (dependent) column.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="180"&gt;         &lt;p&gt;Value Inclusion Profile&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="587"&gt;         &lt;p&gt;Compute a Value Inclusion Profile. &lt;/p&gt;          &lt;p&gt;The Value Inclusion Profile computes the overlap in the values between two columns or sets of columns. This profile can also determine whether a column or set of columns is appropriate to serve as a foreign key between the selected tables. This profile can also help you identify problems in your data such as values that are not valid. For example, you profile the ProductID column of a Sales table and discover that the column contains values that are not found in the ProductID column of the Products table.&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;It is important to note that Value Inclusion Profile Type is not available for the Single Table Quick Profile Form.&lt;/p&gt;  &lt;p&gt;I am very sure that by only looking at the information in the above table that this feature will add a great deal of value to any ETL project.&lt;/p&gt;  &lt;p&gt;Next we click on the "OK" button. This will take us to the Profile Requests section of the Data Profile Task Editor. Here you will see that we now have the profiles we ticked in the Single Table Quick Form created in this section. Below is a screenshot of Profile Requests section.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pg8VRJAYq_ywW7EkoXXS-gMu0NWGn1sHMZmK9ojgwU7IVHrzrXMvsA6qLx1SVkQva2qVY2LKrjCs?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="Profile Requests" src="http://byfiles.storage.msn.com/y1pTFrU5ZLqIHdZLv98_eyizTDQ8J4s5GjPD45DTU6hnhohO00V4zoya8OY4s5Yx4DkrHyqT6WSFdg?PARTNER=WRITER" width="519" border="0" height="536" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In the screenshot I have selected the Null Ratio Profile Request. You will notice that in the Request Properties section we have the all the column in our table selected for the Columns property. When you setup the Profiles manually you will specify these details for each and every profile you create. You will see that it will thus be possible to create a profile consisting of different profiles request for different tables and views, even using different ADO.NET Connection Managers all using one Data Profiling Task. &lt;/p&gt;  &lt;p&gt;Next we click on "OK" which completes out setup of the Data Profiling Task. We then run the package to create our output file.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1ppq7VBxWkI4LFJSjzMIVEQknoQF5Vwj1dAu65IVOerBK6Qu3fezl0SagKHCdGJJKY-QvbZbR-ucF3AMV8BI_3Jg?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="image" src="http://byfiles.storage.msn.com/y1poa8KMN_70VkPKNwHtoUvZTfOCelRHz6oosYi16gRHVC_wIrov6xn2vld9U9y8GXlmXca9FAPSOA?PARTNER=WRITER" width="519" border="0" height="326" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h3&gt;Viewing the output file&lt;/h3&gt;  &lt;p&gt;So now we have created our output file but what is next? We have to view the data of course. If you open up the file with notepad or Internet Explorer you will see that it is in XML format. This allows all sort of other capabilities that I will touch on later.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1p-NiFp4OQXZTWJ_w7Nz5HTEMi0PzNCuZGPfqkNFlFRXgvh36hXT_1k7-4M7tgudOu2NuwrSJrFKr23_kNTJfjxQ?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="Output File in Internet Explorer" src="http://byfiles.storage.msn.com/y1pEHjICpbXj11Ts5fqUppOCQ9Qaa_GuMlkbO79yPHhd_kwY9JMtN45hoq6HqQHdeOikatHIl2EJxk?PARTNER=WRITER" width="519" border="0" height="317" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Luckily we do not need to view the output file in Internet Explorer. We have a utility specifically designed to view the output files of the data profiling task. The utility is the Data Profile Viewer and you can locate it under the Integration Services folder of the Microsoft SQL Server 2008 folder of the start menu.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1pOGBZ_0Z8eNFNxJbkLUQHjRQKkSSEYFjobEcrNxGBLjqumzuuSp-bR38yFHCp5ca1GRq7TJThFjSbT448Vd2ukw?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="Navigate Data Profile Viewer" src="http://byfiles.storage.msn.com/y1pRbTlAC9zhcYzDcddmAjpKoqAbcO_LFIhdFoGfLnWQzW9HeaEqQFkB-1Ph-vqz9grgSWFL0a4rhI?PARTNER=WRITER" width="519" border="0" height="326" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Once we have launched the Data Profile Viewer you will be greeted with the screen in the below screenshot.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1p40b8YhvK3WjoSUM4BO-sxOai6DuJo9pySk1LmmpzR2sz9jx4mLq1x7fp653Y_ZigCMKUJW1bBbbBSydsSa5yww?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="Data Profile Viewer" src="http://byfiles.storage.msn.com/y1pHjBtgERlGtphKHmC7cVHn_vrnwe4ClGoZPEzac32j_HkWp_O7nOT_uELMQ7iS8vCPOIRQobD_GY?PARTNER=WRITER" width="519" border="0" height="326" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now we need to open the file that we created with our SSIS package. Click on the "Open" button in the top left corner and navigate to the output file. Once you have loaded the file you will see the following in your Data Profile Viewer.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pmBYzdfNHLrSmnqrPi9npYJnG4rVqiltck6whJEjq1rX9MoBKvsOQdp9Kcfh3oGetr2LQXAHtWSU?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="Data Profile Viewer With Output File" src="http://pimfqq.bay.livefilestore.com/y1pmfhOLUg22NV5cs3HWV_HNi3H6xprQG1QHQ5rlmLZ7fd4HSz3Zo0MNQEotk9gQ-cl27gpVAEss3epZAdQ-1bbIg?PARTNER=WRITER" width="628" border="0" height="394" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;All we now need to do is to click on the different profiles that we have requested to start and analyse our data. Let's click on the Candidate Key Profile.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1pC7frxc-pMN_Zc9NSFx9XvFA9GuDmq8Spgs1irxZmQaD8YypXTDuLhDcds_szWk7vZ88-vwfAkc2KuJnrGIIp3g?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="Candidate Profile" src="http://pimfqq.bay.livefilestore.com/y1plX-DMTf3GRCnu0NTxf6a18Gr4yi-LnvLyGr3dqUKtcDideOOVQ45JfFdJLtj57TlCdgIh4-M2gMsj8iNnUJhLQ?PARTNER=WRITER" width="628" border="0" height="384" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In the screenshot you can see that there are three fields with a Key Strength of 100% that could serve as a primary key on the table. Next click on the Column Length Distribution Profile. After you have selected the Length Distribution Profile click on the Color column.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1pLDE8-DibwqlwevAcDTJs75ndkfLUx2T5CCQ1GFUr45F2A-bCnZCano0fqk0v1seGLeCz-stqw-wRbBqSuO56iw?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="Column Length Distribution Profile" src="http://pimfqq.bay.livefilestore.com/y1p02UUaDRcT56uXCEGwfXaxVe8pRaTxWwiwSAUUDOngkXkmm_Yda7h6U3SEvR76VzcuZZ0AN-M3OFeCN2oXdKbIg?PARTNER=WRITER" width="628" border="0" height="394" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This profile provides us with the maximum and minimum lengths of the specific columns in our table. This is definitely very valuable if you want to get your field lengths as narrow as possible. You also have the Length Distribution window that shows you the percentage of rows that make up the different lengths of values found in the column.&lt;/p&gt;  &lt;p&gt;The last profile I want to have a look at is the Column Null Ratio Profile.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1p9G7cTQXOwpCQuZkybmRyDcZtC8HRHHhfffUA8HgdmM2LTejK_sYbTCU826XR-AERHO2RNmOtsxjMg3px6Bjy6Q?PARTNER=WRITER"&gt;&lt;img style="border-width: 0px;" alt="image" src="http://pimfqq.bay.livefilestore.com/y1pBFKdQHBlgNZz6avvFdneWWda26fdPT65TfTHGzaVHTnhnLhDAcxuJyn9oCQU9_QgZ_uivjgmsv8UO7nA_AO0xA?PARTNER=WRITER" width="628" border="0" height="384" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This profile shows you the null count per column and also gives you the null percentage. From the above screenshot we can see that in the Color column we have 248 null values and they make up 49.2063% of the total values in the column.&lt;/p&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;I am sure that you will agree with me when I say that the Data Profiling capabilities is definitely going to add a great deal of value to SQL Server 2008.&lt;/p&gt;  &lt;p&gt;One thing that I think definitely will be used a lot is the ability to consume the XML output form a Data Profiling Task using a script task or XML Task and base decisions upon the data.This will for example allow you to notify an administrator when you find anomalies in the data before loading the data into you data warehouse.&lt;/p&gt;  &lt;p&gt;We do however have some limitations one being that we cannot develop additional profiles as we need them, however I am sure that the profiles that come with the task will already provide a great deal of functionality.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8754068738496607590-1606592155357647858?l=businessintelligencechronicles.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://businessintelligencechronicles.blogspot.com/feeds/1606592155357647858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8754068738496607590&amp;postID=1606592155357647858&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1606592155357647858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8754068738496607590/posts/default/1606592155357647858'/><link rel='alternate' type='text/html' href='http://businessintelligencechronicles.blogspot.com/2008/08/integration-services-2008-data.html' title='Integration Services 2008 - Data Profiling Task'/><author><name>Christo Olivier</name><uri>http://www.blogger.com/profile/10027544063761249933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_eSBtF1cAQjQ/SMfqbajfueI/AAAAAAAAAGw/L2a_YiM5D4Q/S220/Christo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8754068738496607590.post-6975353233347315604</id><published>2008-07-27T06:05:00.000+01:00</published><updated>2008-09-15T06:05:56.307+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Business Intelligence'/><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><title type='text'>Non delimited text files and the script component as source</title><content type='html'>&lt;p&gt;I am sure that many people have been faced with files or sources of data for which no standard source component exists in SSIS. One of these types is bound to be a non delimited text files. I have decided to show an example of how to use the Script Component in the data flow to bring the information in these files into the data flow. &lt;/p&gt;  &lt;h3&gt;The source files&lt;/h3&gt;  &lt;p&gt;Let's first look at the file that I have created for this exercise. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1pguIAp-e3VV1jnmu5XrVKPEPBcMRQmHD65E6VS4Vz5Fx7uyeNbsaMQdmnUVFVnUDXfpAPu2hAdP1nakFjI_nm0A?PARTNER=WRITER"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="437" alt="NonDelimitedFile" src="http://pimfqq.bay.livefilestore.com/y1pSUnefzffu2BYIeb3B9VLxpdJbLQs1mOiQvlQIzVapGefLmLKdVJUbls3rmmNOmVvhZXBeBk76CzcNXZrKisVKw?PARTNER=WRITER" width="725" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;First we need to note that we have two distinctly different types of records in the file (This is indicated with the green circles in the above screen shot). We have record Type A and record Type B. Each one of these types have a certain layout and we need to bring both types into the same staging table in our database. The structures of the types are as follows. &lt;/p&gt;  &lt;h4&gt;Record Type A&lt;/h4&gt;  &lt;p&gt;Record Type A consists of four columns, Type, FirstName, LastName and Education. The lengths of these fields are as follows: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Type : 1 &lt;/li&gt;    &lt;li&gt;FirstName: 30 &lt;/li&gt;    &lt;li&gt;LastName: 30 &lt;/li&gt;    &lt;li&gt;Education: 30 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Record Type A thus has a total length of 91 characters. &lt;/p&gt;  &lt;h4&gt;Record Type B&lt;/h4&gt;  &lt;p&gt;Record Type B consists of 5 columns, Type, FirstName, LastName, Education and PhoneNumber. The lengths of these fields are as follows: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Type : 1 &lt;/li&gt;    &lt;li&gt;FirstName: 20 &lt;/li&gt;    &lt;li&gt;LastName: 20 &lt;/li&gt;    &lt;li&gt;Education: 20 &lt;/li&gt;    &lt;li&gt;PhoneNumber: 20 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Record Type B has a total length of 81 characters. &lt;/p&gt;  &lt;h3&gt;Loading the file&lt;/h3&gt;  &lt;p&gt;We can see from the above layout of the file and the two records that it will not be possible to load the text file with one of the standard source components that we have in SSIS. This is where the Script Component comes into play. However before we get to work on the script that we need to bring our data into our data flow we need to add a Data Flow Task to our package as well as a Flat File Connection Manager. (I am sure everyone knows how to add a Data Flow Task so I will not be showing this in our example.) &lt;/p&gt;  &lt;p&gt;Let's start by looking at the connection manager. &lt;/p&gt;  &lt;h4&gt;Connection Manager&lt;/h4&gt;  &lt;p&gt;The connection manager is a normal flat file connection manager. For this example we need it to point at the source file which I have named &amp;quot;Customers.txt&amp;quot; &lt;/p&gt;  &lt;p&gt;Below is a screenshot of the Connection manager. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1phDn63iq0X85R4ahFsgI_RL3SoMP40dOcYPQSwPG9lJXK2lsT3S9VzHGbY_iI-x9gnoM9LOMUuqk?PARTNER=WRITER"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="479" alt="Connection Manager" src="http://byfiles.storage.msn.com/y1ppi5w6o5bLPWAVJ4d6mIvxDbZW5oARzn0s_LIYpHUCPHhhecGYhFzkc0ot2jNYOVjL2HJaCP_kRg?PARTNER=WRITER" width="532" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Don't worry about the format of the file. We will use the connection manager in our script later on. &lt;/p&gt;  &lt;h4&gt;Script Component&lt;/h4&gt;  &lt;p&gt;Next we add our script component to the Data Flow of our package. &lt;/p&gt;  &lt;p&gt;The script component can be used as a Source, Transformation or Destination. It adds a level of flexibility to SSIS that is invaluable. In this example we will be using the Script Component as a Source. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1pX_asnuXG1SshkeJKmORO06JUFzSVR5_UNCuPcQMErPFcomQkLwnCqxVeyV3cDg_g1apQh3eZN5iR-UWg2H_Gvw?PARTNER=WRITER"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="462" alt="Dataflow" src="http://pimfqq.bay.livefilestore.com/y1pTeNfcrJ4wPhmv-rdBx_d-yI7Fbdm5bn7FX5HIK9UXQnPmAQCNRklPtIZxfgtv1tjIZfo79Lq5JiiMS-fqwaZ_w?PARTNER=WRITER" width="772" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Once we have added the script component and specified that we want to use it as a Source we need to add the columns that we want to use in the Data Flow. We want to add the following columns for this example: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;FirstName &lt;/li&gt;    &lt;li&gt;LastName &lt;/li&gt;    &lt;li&gt;Education &lt;/li&gt;    &lt;li&gt;PhoneNo &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;To add the columns you need to double click on the Script Component that we have just added to our Data Flow. This will open the Script Transformation Editor. Under Inputs and outputs rename Output 0 to OutputText, expand OutputText and click on Output Columns. This is where we add the above mentioned columns. Begin to add the above columns by clicking on the Add Column button. &lt;/p&gt;  &lt;p&gt;All the columns should have a data type of string and we can make the Length 30 for all columns except the PhoneNo, this columns length can be 20. (We use the maximum lengths of the columns as we have it in our definition of the Record Types) &lt;/p&gt;  &lt;p&gt;The result of our efforts is displayed in the screenshot below. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pWC_pEfavqFBCF6CuHmP2hojguuOzZhQViV7s4KlF3Va0_uzlKDY1oEXcc6bkR0dwu60escYlJQU?PARTNER=WRITER"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="459" alt="Script Transformation Editor Input Output" src="http://byfiles.storage.msn.com/y1plR3Lj7qWlpVB9nEXIFpqxjSIE2zNbDmLZxpE_8MrjCVfWArdU1XfFybx7sJusG2H_63Uuodr4u4?PARTNER=WRITER" width="532" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The next step is to add the connection manager, which we created earlier on, to the Connection Managers properties of the script component. Simply provide the name that you wish to use to refer to the connection manager in the script under the Name column and then select the desired connection manager under the Connection Manager column. Below is a screenshot of the connection manager after it has been added. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pT448ov_FIEWZccJSke_FC6AJqFbzcxW4Ux6h3tpD5rV3UiohLCEACFXbfuFcHKDtS-yR5bEWADo?PARTNER=WRITER"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="459" alt="Script Transformation Editor Connection Manager" src="http://byfiles.storage.msn.com/y1pDI3ptlG2paWnFvGxMaD4LSQdwxTUlW1PLAHJr0WOhKlEz7IqcP6D168lsgydH_EK92GgDDyHdGM?PARTNER=WRITER" width="532" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Next we need to write the script that we are going to use in brining the data into the Data Flow. Click on the Script option in the left hand pane. This will open up the Script Properties. Click on the Design Script button to open Microsoft Visual Studio for Application. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pOx_FHOEuHamaa1W2EkqEjsixZGXcgkx-Ps0FUv-88idHm5wmMca9iUEhu7WXePzu8RU6Ng8CIaA?PARTNER=WRITER"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="459" alt="Script Transformation Editor Script" src="http://byfiles.storage.msn.com/y1pXJfZ2Q9h0-Xi7IiedqdIV8lDRSdQMIex5e62lJty5Vl6L_W0ffN7yooTeDJRzQlFX_MmcNLl3Jk?PARTNER=WRITER" width="532" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Let's look at the script that we need in order to get our data from the &amp;quot;Customer.txt&amp;quot; file into the Data Flow. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://pimfqq.bay.livefilestore.com/y1p5ceSL7FmqbhunoiOXQZf_c53JRPAW9Cvx-eDqRahyR5iR61NUEcY971dsT24C3B7SSGS8ygKdhglyfY7KnHGEg?PARTNER=WRITER"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="410" alt="Script Part 1" src="http://pimfqq.bay.livefilestore.com/y1piRFqkA7TRh1y8YRmzNd6Y8JgB8-8Znd3F_k5ewCQTBJAQO3fj9NxE2rgc3H0KXzIKYYNMIRDasK9PaH8QtP7Mw?PARTNER=WRITER" width="772" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The first important part is the fact that we reference the System.IO namespace in order to make life a little bit easier. &lt;/p&gt;  &lt;h5&gt;RecordA Subroutine&lt;/h5&gt;  &lt;p&gt;Next we create a subroutine that we use to populate the values of our output columns if the record is a Type A record. The subroutine firstly adds a new row to the OutputText Buffer. (Remember that we renamed
