<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Boyan Penev on Microsoft BI &#187; T-SQL</title>
	<atom:link href="http://www.bp-msbi.com/category/40-tsql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bp-msbi.com</link>
	<description>A practical blog about Microsoft BI tools, techniques and practices written by a developer for other fellow developers.</description>
	<lastBuildDate>Sun, 29 Jan 2012 03:23:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Number of Weekdays Between Two Dates</title>
		<link>http://www.bp-msbi.com/2010/08/number-of-weekdays-between-two-dates/</link>
		<comments>http://www.bp-msbi.com/2010/08/number-of-weekdays-between-two-dates/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 04:43:04 +0000</pubDate>
		<dc:creator>Boyan Penev</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[dates]]></category>
		<category><![CDATA[weekdays]]></category>

		<guid isPermaLink="false">http://www.bp-msbi.com/?p=113</guid>
		<description><![CDATA[There was an old post here describing some T-SQL code for finding the number of weekdays between two dates, which I wrote. It was working fine, so if you have implemented it you have not done anything wrong. However, Jeff Moden from SQL Server Central has written a post a while ago about this same [...]]]></description>
			<content:encoded><![CDATA[<p>There was an old post here describing some T-SQL code for finding the number of weekdays between two dates, which I wrote. It was working fine, so if you have implemented it you have not done anything wrong. However, Jeff Moden from SQL Server Central has written a post a while ago about this same problem and his implementation is a bit cleaner, and thus I would consider it better than mine. So, here is the link:</p>
<p><a href="http://www.sqlservercentral.com/articles/Advanced+Querying/calculatingworkdays/1660/">http://www.sqlservercentral.com/articles/Advanced+Querying/calculatingworkdays/1660/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bp-msbi.com/2010/08/number-of-weekdays-between-two-dates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Do Business Analysts make good dimensional modellers??</title>
		<link>http://www.bp-msbi.com/2010/05/do-business-analysts-make-good-dimensional-modellers/</link>
		<comments>http://www.bp-msbi.com/2010/05/do-business-analysts-make-good-dimensional-modellers/#comments</comments>
		<pubDate>Wed, 26 May 2010 08:04:07 +0000</pubDate>
		<dc:creator>Boyan Penev</dc:creator>
				<category><![CDATA[SSAS]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[dimensional modelling]]></category>
		<category><![CDATA[dimensions]]></category>

		<guid isPermaLink="false">http://www.bp-msbi.com/?p=82</guid>
		<description><![CDATA[Recently I had the (dis)pleasure of working with Business Analysts, who also thought that they are good in dimensional modelling. so, I had to implement BI solutions (including cubes) on top of their database design. I will show an example (about 95% the same as the actual design), where the idea of letting BAs go [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">Recently I had the (dis)pleasure of working with Business Analysts, who also thought that they are good in dimensional modelling. so, I had to implement BI solutions (including cubes) on top of their database design. I will show an example (about 95% the same as the actual design), where the idea of letting BAs go into dev territory does not yield the best results:</p>
<p style="text-align: left;"> <img class="aligncenter size-full wp-image-84" title="Bad Design" src="http://www.bp-msbi.com/wp-content/uploads/2010/05/bad_design_2.gif" alt="" width="623" height="483" /></p>
<p style="text-align: left;">This &#8220;dimensional model&#8221; was created by an experienced BA. Some &#8220;features&#8221; are missing here:<br />
1. The fact table had EffectiveFrom and EffectiveTo dates<br />
2. The relationships between some Dim Tables were 1-1 ?!<br />
3. The Time dim (the only one properly implemented on its own &#8211; on the bottom of my example) had columns like: DateTimeName nvarchar(100), DateTimeKey nvarchar(100), YearName nvarchar(100), etc..<br />
4. The Some Tables on the top had nothing to do with the rest (in fact a colleague of mine reckons they are there to fill in the white space on the top of the A3 printout)</p>
<p style="text-align: left;">Another design, which is better, but still pretty bad showed up after my training on Dimensional Modelling (1hr to go through EVERYTHING, including M2M relationships, Parent-Child hierarchies, Type 2 dimensions, etc):</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-83" title="Bad Design" src="http://www.bp-msbi.com/wp-content/uploads/2010/05/bad_design.gif" alt="" width="578" height="400" /></p>
<p>Obviously, the designer (a developer actually) did grasp some concepts. However, my explanation of a star schema must have been not too clear..</p>
<p>Hope that you had some fun with these two diagrams..and I am sure many developers get in a similar situation, especially when someone else designs their databases. But two points:</p>
<p>1. Ask the BAs to analyse the business and their requirements &#8211; not to design the database<br />
2. 1 hour of training on dimensional modelling will not make you an expert</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bp-msbi.com/2010/05/do-business-analysts-make-good-dimensional-modellers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Star-Join Optimisation &#8211; Prerequisites</title>
		<link>http://www.bp-msbi.com/2010/05/star-join-optimisation-prerequisites/</link>
		<comments>http://www.bp-msbi.com/2010/05/star-join-optimisation-prerequisites/#comments</comments>
		<pubDate>Thu, 06 May 2010 04:29:29 +0000</pubDate>
		<dc:creator>Boyan Penev</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[star join]]></category>

		<guid isPermaLink="false">http://www.bp-msbi.com/?p=77</guid>
		<description><![CDATA[A colleague of mine asked recently: Do we need to have foreign keys between our fact tables and dim tables in order to take advantage of the new SQL Server 2008 star-join optimisation. I decided to ask the question at the MSDN Forums. Just now I got a reply and I thought it may be [...]]]></description>
			<content:encoded><![CDATA[<p>A colleague of mine asked recently: <strong>Do we need to have foreign keys between our fact tables and dim tables in order to take advantage of the new SQL Server 2008 star-join optimisation</strong>. I decided to ask the question at the MSDN Forums. Just now I got a reply and I thought it may be good to share with everyone:</p>
<blockquote><p><strong>Charles Wang &#8211; MSFT<br />
</strong><br />
To use star join, indexes are required on tables. FK constraints are not necessary, but it is recommended that you have FK constraints defined since without it SQL Server must depend on heuristics to detect star schema query patterns. There are some restrictions for heuristics to determine a start join query. And it may not pick up a correct start join query plan under some cases. You can find the detailed information in the section &#8220;Star Join Heuristics&#8221; of this article, <a href="http://technet.microsoft.com/en-us/magazine/2008.04.dwperformance.aspx" target="_blank">Data Warehouse Query Performance</a>. The following is an extraction of the content:</p>
<p>Many physical designs for data warehouses follow the star schema but do not completely specify the relationships between the fact and dimension tables, as mentioned earlier for foreign key constraints, for instance. Without the foreign key constraints explicitly specified, SQL Server must depend on heuristics to detect star schema query patterns. The following heuristics are applied to detect star join query patterns</p>
<p>1. The largest of the tables participating in the n-ary join is considered the fact table. There are additional restrictions on the minimum size of the fact table. For instance, if even the largest table is not beyond a specific size, the n-ary join is not considered a star join.</p>
<p>2.All join conditions of the binary joins in a star join query have to be single column equality predicates. The joins have to be inner joins. While this might sound restrictive, it covers the vast majority of joins between the fact table and dimension tables on the surrogate key in typical star schemas. If a join has a more complex join condition that doesn&#8217;t fit the pattern described above, the join is excluded from the star join. A five-way join, for example, can lead to a three-way star join (with two additional joins later on), if two of the joins have more complex join predicates.</p></blockquote>
<p>There we go &#8211; so we need indexes, while FK constraints would be good to have but not necessary. I also wrote to the CSS SQL Server Team, so if they come back with more information, I will update this post.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bp-msbi.com/2010/05/star-join-optimisation-prerequisites/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Server DBMS Top 1 Wish List</title>
		<link>http://www.bp-msbi.com/2009/12/sql-server-dbms-top-1-wish-list/</link>
		<comments>http://www.bp-msbi.com/2009/12/sql-server-dbms-top-1-wish-list/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 03:23:00 +0000</pubDate>
		<dc:creator>Boyan Penev</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[source control]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://www.bp-msbi.com/2009/12/sql-server-dbms-top-1-wish-list/</guid>
		<description><![CDATA[As an addition to Teo Lachev&#8217;s Top 10 Wishlists (SSAS and SSRS), I would like to contribute only 1 item to a possible SQL Server DBMS wishlist: 1. Source Control. Not SourceSafe source control, but rather an automated version out-of-the-box, not relying on developers to check in/out. Rather, it should track the changes to the [...]]]></description>
			<content:encoded><![CDATA[<p>As an addition to <a href="http://prologika.com/CS/blogs/">Teo Lachev&#8217;s Top 10 Wishlists </a>(SSAS and SSRS), I would like to contribute only 1 item to a possible SQL Server DBMS wishlist:</p>
<p>1. Source Control.</p>
<p>Not SourceSafe source control, but rather an automated version out-of-the-box, not relying on developers to check in/out. Rather, it should track the changes to the code as they are made, and a full version history should be available directly in the DBMS. It should not be too hard. After all, there is a nice database available, which can store code with its version numbers just like anything else.</p>
<p>This would make a lot of developers&#8217; lives a bit less frustrating.</p>
<p>OK, a SQL code &#8220;beautifier&#8221; would also be nice, but it is not all that important&#8230;</p>
<p><a href="https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=518835" class="broken_link">Vote on Connect</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bp-msbi.com/2009/12/sql-server-dbms-top-1-wish-list/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Changes in SQL Server 2008 sysadmin group</title>
		<link>http://www.bp-msbi.com/2008/12/changes-in-sql-server-2008-sysadmin/</link>
		<comments>http://www.bp-msbi.com/2008/12/changes-in-sql-server-2008-sysadmin/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 10:46:00 +0000</pubDate>
		<dc:creator>Boyan Penev</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[SQL Server 2008]]></category>

		<guid isPermaLink="false">http://www.bp-msbi.com/2008/12/changes-in-sql-server-2008-sysadmin-group/</guid>
		<description><![CDATA[There are some noteworthy changes in the way SQL Server 2008 handles security; apart from the single major improvement &#8211; the replacement of the Surface Area Configuration tool by Policy-Based Management. One thing that surprised me today was that even though I was a Domain Admin and a member of the local Administrators group, SQL [...]]]></description>
			<content:encoded><![CDATA[<p>There are some noteworthy changes in the way SQL Server 2008 handles security; apart from the single major improvement &#8211; the replacement of the Surface Area Configuration tool by Policy-Based Management.</p>
<p>One thing that surprised me today was that even though I was a Domain Admin and a member of the local Administrators group, SQL Server 2008 refused to let me log in. A login had to be explicitly created so I could access the instance. After some research, I found out that in SQL Server 2008 the local Windows administrators do not get mapped to the sysadmin role. Therefore, it is possible to get locked out of a server instance if there are no sysadmins on it. This is a feature, which separates more clearly SQL Server admins and Windows admins.</p>
<p>A further note on this topic. I would have not lost a small SQL Server war on a Dev environment recently if we were using SQL Server 2008 instead of SQL Server 2005. Now, being a Domain Admin does not necessarily win the battle for SQL Server permissions.</p>
<p>There is a TechNet page describing <a href="http://technet.microsoft.com/en-us/library/cc280562.aspx">SQL Server 2008 Security Changes</a> for further reference.</p>
<p>And another one, helping in case all <a href="http://technet.microsoft.com/en-us/library/dd207004.aspx">system administrators are locked out</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bp-msbi.com/2008/12/changes-in-sql-server-2008-sysadmin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spreading Non-Transactional Data Along Time</title>
		<link>http://www.bp-msbi.com/2008/12/spreading-non-transactional-data-along/</link>
		<comments>http://www.bp-msbi.com/2008/12/spreading-non-transactional-data-along/#comments</comments>
		<pubDate>Mon, 08 Dec 2008 12:18:00 +0000</pubDate>
		<dc:creator>Boyan Penev</dc:creator>
				<category><![CDATA[SSAS]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[dimensions]]></category>
		<category><![CDATA[planning]]></category>

		<guid isPermaLink="false">http://www.bp-msbi.com/2008/12/spreading-non-transactional-data-along-time/</guid>
		<description><![CDATA[In some cases we need to be able to analyse non-transactional data for discrete periods along a time dimension. An example of such a case is a collection of invoices, which have start and end dates for a period, but are not otherwise connected to a time axis. We may have such invoices with these [...]]]></description>
			<content:encoded><![CDATA[<p>In some cases we need to be able to analyse non-transactional data for discrete periods along a time dimension. An example of such a case is a collection of invoices, which have start and end dates for a period, but are not otherwise connected to a time axis. We may have such invoices with these properties:</p>
<blockquote><p>Invoice Id<br />
Start Date<br />
End Date<br />
Amount</p></blockquote>
<p>One of the invoices may be:</p>
<blockquote><p>Invoice Id: 34821432<br />
Start Date: 2008-10-15<br />
End Date: 2009-03-14<br />
Amount: 15,000.00</p></blockquote>
<p>and another one:</p>
<blockquote><p>Invoice Id: 34934221<br />
Start Date: 2008-12-01<br />
End Date: 2009-05-30<br />
Amount: 6,500.00</p></blockquote>
<p>If the company we are building this for is daily deducting a fee for its services (e.g. funds management, software maintenance, etc.), we may have to be able to spread the amount in smaller periods, like months or days and then aggregate the smaller amounts along a time dimension.</p>
<p>To do this we have to first store the data in a relational table and then write some SQL to do the trick for us.</p>
<p>First, we should create a table valued function which returns all the dates at a specified granularity, such as days, from the Start to the End dates and the count of all the periods in between (in our case is is a count of days):</p>
<blockquote><p>CREATE FUNCTION udf_Create_Daily_Date_Spread<br />
(   <br />
      @Start_Date datetime<br />
    , @End_Date datetime<br />
)<br />
RETURNS @Daily_Spread TABLE (<br />
      Date_Id datetime<br />
    , Count_Of_Days int<br />
)<br />
AS<br />
BEGIN<br />
    DECLARE @Count int<br />
    SET @Count = 0</p>
<p>    IF @Start_Date &gt;= @End_Date<br />
        RETURN</p>
<p>    WHILE @Start_Date &lt;= @End_Date<br />
    BEGIN<br />
        INSERT INTO @Daily_Spread(Date_Id)<br />
        SELECT @Start_Date</p>
<p>        SET @Start_Date = DATEADD(d, 1,@Start_Date)<br />
        SET @Count = @Count + 1<br />
    END</p>
<p>    UPDATE @Daily_Spread<br />
    SET   Count_Of_Days = @Count</p>
<p>    RETURN<br />
END</p></blockquote>
<p>After having created these functions, we can use the CROSS APPLY statement to create the even spread:</p>
<blockquote><p>SELECT             Invoice_Id<br />
                        ,Start_Date<br />
                        ,End_Date<br />
                        ,cdds.Date_Id<br />
                        ,Amount/cdds.Count_Of_Days<br />
FROM Invoice_Source inv<br />
CROSS APPLY udf_Create_Daily_Date_Spread(inv.Start_Date, inv.End_Date) cdds</p></blockquote>
<p>After running the sample data through this code, we will get an even spread for both invoices and we will be able to attach a time dimension to them.</p>
<p>Even though the data size may explode after such a manipulation, Analysis Services provides an excellent way of handling even the largest sets of data. If storage is a problem, we can always choose to break down our data in less periods &#8211; instead of days, weeks or months.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bp-msbi.com/2008/12/spreading-non-transactional-data-along/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ordering Dimensions: Recursion vs Loops in T-SQL</title>
		<link>http://www.bp-msbi.com/2008/11/ordering-dimensions-recursion-vs-loops/</link>
		<comments>http://www.bp-msbi.com/2008/11/ordering-dimensions-recursion-vs-loops/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 00:25:00 +0000</pubDate>
		<dc:creator>Boyan Penev</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[recursion vs loops]]></category>
		<category><![CDATA[stored procedures]]></category>

		<guid isPermaLink="false">http://www.bp-msbi.com/2008/11/ordering-dimensions-recursion-vs-loops-in-t-sql/</guid>
		<description><![CDATA[Recently I had to build a function, which returned dimension members from a parent-child relational table. I needed to be able to order the members hierarchically and I decided to use a recursive CTE call. Usually, we have a parent-child dimension table with structure similar to this: Dim_Business Business_Skey int Parent_Business_Skey int   with a root [...]]]></description>
			<content:encoded><![CDATA[<div>Recently I had to build a function, which returned dimension members from a parent-child relational table. I <span id="SPELLING_ERROR_0" class="blsp-spelling-corrected">needed</span> to be able to order the members hierarchically and I decided to use a recursive <span id="SPELLING_ERROR_1" class="blsp-spelling-error">CTE</span> call.</div>
<div>Usually, we have a parent-child dimension table with structure similar to this:</div>
<blockquote>
<div><span class="Apple-style-span" style="font-weight: bold;">Dim_Business</span><span class="Apple-style-span" style="font-weight: bold;"><br />
</span></div>
<div><span class="Apple-style-span" style="font-weight: bold;">Business_<span id="SPELLING_ERROR_2" class="blsp-spelling-error">Skey</span> int</span></div>
<div><span class="Apple-style-span" style="font-weight: bold;">Parent_Business_<span id="SPELLING_ERROR_3" class="blsp-spelling-error">Skey</span> int<br />
</span></div>
</blockquote>
<div> </div>
<div>with a root node with <span id="SPELLING_ERROR_4" class="blsp-spelling-error">Skey</span> of -3 and Parent_Business_<span id="SPELLING_ERROR_5" class="blsp-spelling-error">Skey</span> of -3.</div>
<div>Let&#8217;s assume we have a hierarchy like this:</div>
<blockquote>
<div><span class="Apple-style-span" style="color: #000066;">All (Id = -3, P_ID = -3)</span></div>
<div><span class="Apple-style-span" style="color: #000066;">-GLOBAL (Id = 1, P_ID = -3)</span></div>
<div><span class="Apple-style-span" style="color: #000066;">&#8211;Europe (Id = 2, P_ID = 1)</span></div>
<div><span class="Apple-style-span" style="color: #000066;">&#8212;UK (Id = 3, P_ID = 2)</span></div>
<div><span class="Apple-style-span" style="color: #000066;">&#8212;France (Id = 4, P_ID = 2)</span></div>
<div><span class="Apple-style-span" style="color: #000066;">&#8212;Spain (Id = 5, P_ID = 2)</span></div>
<div><span class="Apple-style-span" style="color: #000066;">&#8211;North America (Id = 6, P_ID = 1)</span></div>
<div><span class="Apple-style-span" style="color: #000066;">&#8212;USA (Id = 7, P_ID = 6)</span></div>
<div><span class="Apple-style-span" style="color: #000066;">&#8212;Canada (Id = 8, P_ID = 6)</span></div>
<div><span class="Apple-style-span" style="color: #000066;">&#8212;Mexico (Id = 9, P_ID = 6)<br />
</span></div>
</blockquote>
<div> </div>
<div>If we do something like:</div>
<blockquote>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SELECT Business_<span id="SPELLING_ERROR_6" class="blsp-spelling-error">Skey</span></span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">FROM Dim_Business</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">ORDER BY Parent_Business_<span id="SPELLING_ERROR_7" class="blsp-spelling-error">Skey</span> <span id="SPELLING_ERROR_8" class="blsp-spelling-error">ASC</span>, Business_<span id="SPELLING_ERROR_9" class="blsp-spelling-error">Skey</span> <span id="SPELLING_ERROR_10" class="blsp-spelling-error">ASC<br />
</span></span></span></div>
</blockquote>
<div> </div>
<div>We will get:</div>
<blockquote>
<div>-3 (All)</div>
<div>1 (GLOBAL)</div>
<div>2 (Europe)</div>
<div>6 (North America)</div>
<div>3 (UK)</div>
<div>4 (France)</div>
<div>5 (Spain)</div>
<div>7 (USA)</div>
<div>8 (Canada)</div>
<div>9 (Mexico)</div>
</blockquote>
<div>Obviously, this hierarchy is incorrect, because we want to see the leaf nodes under their respective parents.</div>
<div>We can recursively create order, which concatenates the parent ids:</div>
<blockquote>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">WITH b_<span id="SPELLING_ERROR_11" class="blsp-spelling-error">ord</span>(bid, <span id="SPELLING_ERROR_12" class="blsp-spelling-error">bord</span>)</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">AS</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">(</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SELECT</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> Business_<span id="SPELLING_ERROR_13" class="blsp-spelling-error">Skey</span> AS bid</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">, CONVERT(<span id="SPELLING_ERROR_14" class="blsp-spelling-error">nvarchar</span>(1000), Business_<span id="SPELLING_ERROR_15" class="blsp-spelling-error">Skey</span>) AS <span id="SPELLING_ERROR_16" class="blsp-spelling-error">bord</span></span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">FROM Dim_Business</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">WHERE Business_<span id="SPELLING_ERROR_17" class="blsp-spelling-error">Skey</span> = -3</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"><br />
</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">UNION ALL</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"><br />
</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SELECT</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> Business_<span id="SPELLING_ERROR_18" class="blsp-spelling-error">Skey</span> AS bid</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">, CONVERT(<span id="SPELLING_ERROR_19" class="blsp-spelling-error">nvarchar</span>(1000), <span id="SPELLING_ERROR_20" class="blsp-spelling-error">bord</span> + &#8216;|&#8217; + CONVERT(<span id="SPELLING_ERROR_21" class="blsp-spelling-error">nvarchar</span>, Business_<span id="SPELLING_ERROR_22" class="blsp-spelling-error">Skey</span>))</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">FROM Dim_Business db</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">INNER JOIN b_<span id="SPELLING_ERROR_23" class="blsp-spelling-error">ord</span> <span id="SPELLING_ERROR_24" class="blsp-spelling-error">bo</span></span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">ON db.Parent_Business_<span id="SPELLING_ERROR_25" class="blsp-spelling-error">Skey</span> = <span id="SPELLING_ERROR_26" class="blsp-spelling-error">bo</span>.bid</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">WHERE db.Business_<span id="SPELLING_ERROR_27" class="blsp-spelling-error">Skey</span> &lt;&gt; <span id="SPELLING_ERROR_28" class="blsp-spelling-error">bo</span>.bid</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">)</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SELECT *</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">FROM b_<span id="SPELLING_ERROR_29" class="blsp-spelling-error">ord</span></span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">ORDER BY <span id="SPELLING_ERROR_30" class="blsp-spelling-error">bord</span> <span id="SPELLING_ERROR_31" class="blsp-spelling-error">ASC<br />
</span></span></span></div>
</blockquote>
<div> </div>
<div>The result of the <span id="SPELLING_ERROR_32" class="blsp-spelling-error">CTE </span>query is:</div>
<blockquote>
<div>-3 -3 (All)</div>
<div>1 -3|1 (GLOBAL)</div>
<div>2 -3|1|2 (Europe)</div>
<div>3 -3|1|2|3 (UK)</div>
<div>4 -3|1|2|4 (France)</div>
<div>5 -3|1|2|5 (Spain)</div>
<div>6 -3|1|6 (North America)</div>
<div>7 -3|1|6|7 (USA)</div>
<div>8 -3|1|6|8 (Canada)</div>
<div>9 -3|1|6|9 (Mexico)</div>
</blockquote>
<div> </div>
<div>and the order is correct.</div>
<div> </div>
<div>Because the code needed to go in a function, invoked by a number of stored procedures, .NET application and various reports, I needed the code to be quick and </div>
<div>light. As some dimensions had a large number of members (50000+), which could grow with time, the code needed to implemented in a careful way. So, I decided </div>
<div>to compare the recursive <span id="SPELLING_ERROR_33" class="blsp-spelling-error">CTE</span> function to a WHILE loop and a temporary table implementation:</div>
<blockquote>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">DECLARE @c int</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">DECLARE @<span id="SPELLING_ERROR_34" class="blsp-spelling-error">num</span>_of_nodes int</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"><br />
</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SET @<span id="SPELLING_ERROR_35" class="blsp-spelling-error">num</span>_of_nodes = (SELECT  COUNT(*) FROM Dim_Business)</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"><br />
</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">CREATE TABLE #order(</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> <span id="SPELLING_ERROR_36" class="blsp-spelling-error">skey</span> int</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">, <span id="SPELLING_ERROR_37" class="blsp-spelling-error">ord</span> <span id="SPELLING_ERROR_38" class="blsp-spelling-error">nvarchar</span>(1000)</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">, <span id="SPELLING_ERROR_39" class="blsp-spelling-error">lvl</span> int</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">)</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"><br />
</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">INSERT INTO #order</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SELECT</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> Business_<span id="SPELLING_ERROR_40" class="blsp-spelling-error">Skey</span></span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">, CONVERT(<span id="SPELLING_ERROR_41" class="blsp-spelling-error">nvarchar</span>(1000), Business_<span id="SPELLING_ERROR_42" class="blsp-spelling-error">Skey</span>)</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">, 1</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">FROM Dim_Business</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">WHERE Business_<span id="SPELLING_ERROR_43" class="blsp-spelling-error">Skey</span> = -3</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"><br />
</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SET @c = 2</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"><br />
</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">WHILE @c &gt; 0</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">BEGIN</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">INSERT INTO #order</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SELECT</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> Business_<span id="SPELLING_ERROR_44" class="blsp-spelling-error">Skey</span></span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">, CONVERT(<span id="SPELLING_ERROR_45" class="blsp-spelling-error">nvarchar</span>(1000), <span id="SPELLING_ERROR_46" class="blsp-spelling-error">ord</span> + &#8216;|&#8217; + CONVERT(<span id="SPELLING_ERROR_47" class="blsp-spelling-error">nvarchar</span>, Business_<span id="SPELLING_ERROR_48" class="blsp-spelling-error">Skey</span>))</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">, @c</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">FROM Dim_Business db</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">INNER JOIN #order o</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">ON db.Parent_Business_<span id="SPELLING_ERROR_49" class="blsp-spelling-error">Skey</span> = o.<span id="SPELLING_ERROR_50" class="blsp-spelling-error">skey</span></span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">AND o.<span id="SPELLING_ERROR_51" class="blsp-spelling-error">lvl</span> = @c &#8211; 1</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">WHERE db.Business_<span id="SPELLING_ERROR_52" class="blsp-spelling-error">Skey</span> &lt;&gt; o.<span id="SPELLING_ERROR_53" class="blsp-spelling-error">skey</span></span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"><br />
</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SET @c = @c + 1</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">IF (SELECT COUNT(*) FROM #order) = @num_of_nodes</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SET @c = 0</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">END</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"><br />
</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">SELECT</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> skey AS bid</span></span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"> </span></span></span><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">, ord AS bord</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">FROM #order</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">ORDER BY ord ASC</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';"><br />
</span></span></div>
<div><span class="Apple-style-span" style="color: #993300;"><span class="Apple-style-span" style="font-family: 'courier new';">DROP TABLE #order<br />
</span></span></div>
</blockquote>
<div> </div>
<div>After comparing the results in Client Statistics and the IO reads, the 1st recursive query performs more than 20% worse than the WHILE loop query. It also trails the non-recursive query in the count of logical reads,read-ahead reads and scan counts.</div>
<div>It seems like in SQL Server 2005 calling WITH recursively does not work as good as coding set-based operations through WHILE loops.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bp-msbi.com/2008/11/ordering-dimensions-recursion-vs-loops/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fun with T-SQL</title>
		<link>http://www.bp-msbi.com/2008/11/fun-with-t-sql/</link>
		<comments>http://www.bp-msbi.com/2008/11/fun-with-t-sql/#comments</comments>
		<pubDate>Sat, 15 Nov 2008 02:22:00 +0000</pubDate>
		<dc:creator>Boyan Penev</dc:creator>
				<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://www.bp-msbi.com/2008/11/fun-with-t-sql/</guid>
		<description><![CDATA[As a tribute to some fairly restrictive .NET design I once fell victim to, I wrote this piece of code: Use [Database] Select [Select] From [From] Where [Where] = &#8216;Where&#8217; And [nvarchar(50)] = &#8216;nvarchar(50)&#8217; And [int] = 1 The CREATE and INSERT statements for the above command:   CREATE TABLE [dbo].[From](  [Id] [int] NOT NULL, [...]]]></description>
			<content:encoded><![CDATA[<p>As a tribute to some fairly restrictive .NET design I once fell victim to, I wrote this piece of code:</p>
<div>
<blockquote>
<div><span style="color: #993300;">Use [Database]</span></div>
<div><span class="Apple-style-span" style="color: #993300;">Select [Select]</span></div>
<div><span class="Apple-style-span" style="color: #993300;">From [From]</span></div>
<div><span class="Apple-style-span" style="color: #993300;">Where [Where] = &#8216;Where&#8217;</span></div>
<div><span class="Apple-style-span" style="color: #993300;">And [nvarchar(50)] = &#8216;nvarchar(50)&#8217;</span></div>
<div><span class="Apple-style-span" style="color: #993300;">And [int] = 1</span></div>
</blockquote>
<div>The CREATE and INSERT statements for the above command:</div>
<div> </div>
<div>
<blockquote>
<div><span class="Apple-style-span" style="color: #993300;">CREATE TABLE [dbo].[From](</span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"> </span></span><span class="Apple-style-span" style="color: #993300;">[Id] [int] NOT NULL,</span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"> </span></span><span class="Apple-style-span" style="color: #993300;">[Where] [nvarchar](50) NOT NULL,</span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"> </span></span><span class="Apple-style-span" style="color: #993300;">[On] [nvarchar](50) NOT NULL,</span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"> </span></span><span class="Apple-style-span" style="color: #993300;">[Select] [nvarchar](50) NOT NULL,</span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"> </span></span><span class="Apple-style-span" style="color: #993300;">[From] [nvarchar](50) NOT NULL,</span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="color: #993300;"> </span></span><span class="Apple-style-span" style="color: #993300;">[int] [int] NOT NULL,</span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"> </span><span class="Apple-style-span" style="color: #993300;">[nvarchar(50)] [nvarchar](50) NOT NULL</span></div>
<div><span class="Apple-style-span" style="color: #993300;">)</span></div>
<div><span class="Apple-style-span" style="color: #993300;"><br />
</span></div>
<div>
<div><span class="Apple-style-span" style="color: #993300;">INSERT INTO [From] (  [Id]</span></div>
<div><span class="Apple-style-span" style="color: #993300;">, [Where]</span></div>
<div><span class="Apple-style-span" style="color: #993300;">, [On]</span></div>
<div><span class="Apple-style-span" style="color: #993300;">, [Select]</span></div>
<div><span class="Apple-style-span" style="color: #993300;">, [From]</span></div>
<div><span class="Apple-style-span" style="color: #993300;">, [int]</span></div>
<div><span class="Apple-style-span" style="color: #993300;">, [nvarchar(50)])</span></div>
</div>
<div><span class="Apple-style-span" style="color: #993300;">SELECT 1, &#8216;Where&#8217;, &#8216;On&#8217;, &#8216;:-)&#8217;, &#8216;From&#8217;, 1, &#8216;nvarchar(50)&#8217;</span></div>
</blockquote>
<p>Enjoy!</p>
<div><span class="Apple-style-span" style="color: #993300;"> </span> </div>
<div> </div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bp-msbi.com/2008/11/fun-with-t-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EXECUTE AS someone else &#8211; impersonation in stored procedures</title>
		<link>http://www.bp-msbi.com/2008/11/recently-i-had-to-implement-stored/</link>
		<comments>http://www.bp-msbi.com/2008/11/recently-i-had-to-implement-stored/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 00:55:00 +0000</pubDate>
		<dc:creator>Boyan Penev</dc:creator>
				<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[stored procedures]]></category>

		<guid isPermaLink="false">http://www.bp-msbi.com/2008/11/execute-as-someone-else-impersonation-in-stored-procedures/</guid>
		<description><![CDATA[Recently, I had to implement a stored procedure, which is executed under a service account context. It had to be invoked by an Informatica workflow and its purpose was to clean a cache database table and to update all statistics on a database through invoking the sp_updatestats. As the Informatica user did not have enough [...]]]></description>
			<content:encoded><![CDATA[<div>Recently, I had to implement a stored procedure, which is executed under a service account context. It had to be invoked by an Informatica workflow and its purpose was to clean a cache database table and to update all statistics on a database through invoking the sp_updatestats. As the Informatica user did not have enough permissions to perform these tasks, I had to use the EXECUTE AS in the stored procedure. The EXECUTE AS statement can also effectively be used to limit the execution scope through allowing limited permissions to the user account executing the stored procedure:</div>
<blockquote>
<div>CREATE PROCEDURE [dbo].[usp_Update_Statistics] </div>
<div>WITH EXECUTE AS <span class="Apple-style-span" style="font-style: italic;">user</span></div>
<div>AS</div>
<div>BEGIN</div>
<div><span class="Apple-tab-span" style="white-space: pre;"> </span><span class="Apple-style-span" style="font-style: italic;">clear cache</span></div>
<div><span class="Apple-tab-span" style="white-space: pre;"> </span>EXEC sp_UpdateStats</div>
<div>END</div>
</blockquote>
<div>Immediately I encountered various problems with the execution of the stored procedure. After some research it turned out that a few preconditions need to be satisfied before we can execute it:</div>
<blockquote>
<div>1. TRUSTWORTHY setting on the database needs to be turned on:</div>
<div>     ALTER DATABASE <span class="Apple-style-span" style="font-style: italic;">database</span> SET TRUSTWORTHY ON;</div>
<div>2. The owner of both the context database and the master database must be the same. To set this property we need to:</div>
<div><span class="Apple-tab-span" style="white-space: pre;">   </span>2.1 Find who is the owner of master:</div>
<div><span class="Apple-tab-span" style="white-space: pre;">           </span>exec sp_helpdb</div>
<div><span class="Apple-tab-span" style="white-space: pre;">   </span>2.2 Set the context database owner to the same owner:</div>
<div><span class="Apple-tab-span" style="white-space: pre;">           </span>ALTER AUTHORIZATION ON DATABASE::<span class="Apple-style-span" style="font-style: italic;">database </span>TO <span class="Apple-style-span" style="font-style: italic;">user</span></div>
<div>3. The account under which we EXECUTE AS needs to be a database/server principal. The database and server principals can be found in the <span class="Apple-style-span" style="font-weight: bold;">sys.database_principals</span> and the <span class="Apple-style-span" style="font-weight: bold;">sys.server_principals</span> tables.</div>
<div>4. The account needs to be granted impersonate permissions:</div>
<div>     GRANT IMPERSONATE ON USER::<span class="Apple-style-span" style="font-style: italic;">user in EXECUTE AS</span> TO <span class="Apple-style-span" style="font-style: italic;">user executing the sproc</span></div>
<div>5. If a server login is specified (instead of a database user), it needs to be mapped to a database user.</div>
</blockquote>
<div>Also, if SQL Server is running under a local account/service it is not possible to use the EXECUTE AS statement.</div>
<div>The same statement can be used to execute SQL Server Agent jobs under different context &#8211; something particularly useful when trying to run them through Integration Services.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bp-msbi.com/2008/11/recently-i-had-to-implement-stored/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

