<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>SQL Server Planet</title>
	
	<link>http://sqlserverplanet.com</link>
	<description>SQL Articles &amp; Tips from the field</description>
	<lastBuildDate>Mon, 13 May 2013 20:32:15 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/SqlServerPlanet" /><feedburner:info uri="sqlserverplanet" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Top 3 SQL Errors That Will Leave Your Users Stranded</title>
		<link>http://feedproxy.google.com/~r/SqlServerPlanet/~3/hO_oJZrvwOY/top-3-sql-errors-that-will-leave-your-users-stranded</link>
		<comments>http://sqlserverplanet.com/tsql/top-3-sql-errors-that-will-leave-your-users-stranded#comments</comments>
		<pubDate>Thu, 21 Feb 2013 19:00:34 +0000</pubDate>
		<dc:creator>Derek Dieter</dc:creator>
				<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://sqlserverplanet.com/?p=3456</guid>
		<description><![CDATA[Over the years I&#8217;ve ran across certain situations that cause errors in SQL that error out the calling application if they are not correctly trapped. As unsuspecting as these can be, you end up learning your lesson when you get a call late at night that a web page is erroring out. Then to follow you get a deep sinking feeling in your gut while you think, &#8220;Why didn&#8217;t I think of that?&#8221;. In some of these cases I&#8217;ve often wondered why SQL doesn&#8217;t simply return a NULL or an invalid result. And often I wish there was an option that could set that because while it&#8217;s true that all errors should be handled, in truth they are not. Hopefully this list can save you a bit of heartache. divide by zero string or binary data would be truncated Invalid length parameter passed to the LEFT or SUBSTRING function These three errors are very common and all of them at one time or another have bit me in the pants &#8211; most of the time after deploying code and even worse, hours/days/months after deploying the code. Not only that, they can occur on an intermittent basis which is always fun to troubleshoot. Divide by Zero This innocent division operation turns ugly when your divisor hits the dead even zero. This is because of the rules of math. You simply cannot divide by zero. Reproducing this issue is simple enough. &#160; &#160; SELECT 8 / 0 The workaround is to make [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://sqlserverplanet.com/wp-content/uploads/2013/02/windows_errors.jpg"><img style="margin: 8px;" src="http://sqlserverplanet.com/wp-content/uploads/2013/02/windows_errors-300x225.jpg" alt="windows_errors" width="300" height="225" class="alignleft size-medium wp-image-3468" /></a>Over the years I&#8217;ve ran across certain situations that cause errors in SQL that error out the calling application if they are not correctly trapped.  As unsuspecting as these can be, you end up learning your lesson when you get a call late at night that a web page is erroring out.  Then to follow you get a deep sinking feeling in your gut while you think, &#8220;Why didn&#8217;t I think of that?&#8221;.  </p>
<p>In some of these cases I&#8217;ve often wondered why SQL doesn&#8217;t simply return a NULL or an invalid result.  And often I wish there was an option that could set that because while it&#8217;s true that all errors should be handled, in truth they are not.  </p>
<p>Hopefully this list can save you a bit of heartache. </p>
<ul>
<li>divide by zero</li>
<li>string or binary data would be truncated</li>
<li>Invalid length parameter passed to the LEFT or SUBSTRING function</li>
</ul>
<p>These three errors are very common and all of them at one time or another have bit me in the pants &#8211; most of the time after deploying code and even worse, hours/days/months after deploying the code.  Not only that, they can occur on an intermittent basis which is always fun to troubleshoot.</p>
<h4>Divide by Zero</h4>
<p>This innocent division operation turns ugly when your divisor hits the dead even zero.  This is because of the rules of math.  You simply cannot divide by zero.  Reproducing this issue is simple enough.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #cc66cc;">8</span> <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">0</span></div></div>
<div class="block style05">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico14.gif" alt="" class="ico" />
						<div class="text-holder">
							Divide by zero error encountered.
						</div>
					</div>
<p>The workaround is to make the divisor NULL, which then returns a NULL</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #cc66cc;">8</span> <span style="color: #66cc66;">/</span> <span style="color: #993333; font-weight: bold;">NULL</span></div></div>
<p>Why does it error out instead of returning NULL?  While I&#8217;m not sure I&#8217;d imagine if paychecks were being calculated it&#8217;d be better to have the code error out so someone would catch it than have your &#8220;Pay Amount&#8221; equal NULL.  Though this is the case there are times in the past I wish it did return a NULL.  Luckily there is a workaround.  <a href="http://sqlserverplanet.com/tsql/overcome-divide-by-zero-using-nullif">Overcome Divide by Zero Using NULLIF</a></p>
<h4>String or Binary Data Would be Truncated</h4>
<p>Ah yes, the dreaded string or binary data would be truncated error.  Even if you have been coding for a month or so I&#8217;m sure you&#8217;ve run into this one.  When this error crops up in a SQL statement that has a large SELECT list, you have to painstakingly comment out half of the columns (in b-tree fashion) to end up narrowing down which column is causing this error.  </p>
<p>In the majority of cases when I&#8217;ve come across this error, it&#8217;s because a predefined table did not have a datatype large enough to accommodate the unsuspecting data.  This can very simply be reproduced using the following example.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">DECLARE</span> @target <span style="color: #993333; font-weight: bold;">TABLE</span><br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; mybin varbinary<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; mystring <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> @target <span style="color: #66cc66;">&#40;</span>mybin<span style="color: #66cc66;">,</span> mystring<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span><br />
&nbsp; &nbsp; &nbsp;mybin &nbsp;&nbsp; &nbsp; <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">512</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>mystring &nbsp; <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'hiu'</span></div></div>
<p>Gives us:<br />
<div class="block style05">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico14.gif" alt="" class="ico" />
						<div class="text-holder">
							String or binary data would be truncated.
						</div>
					</div></p>
<p>In this particular case, maybe we didn&#8217;t know what size the data would be before we inserted it.  If that&#8217;s the case we can select..into a temp table instead.  <a href="http://sqlserverplanet.com/troubleshooting/string-or-binary-data-would-be-truncated">More info here</a>.</p>
<h4>Invalid length parameter passed to the LEFT or SUBSTRING function</h4>
<p>Ah yes.  Once again we have a doozy.  You&#8217;ve created your complex string parsing function only to find out you didn&#8217;t account for the string not being there (At least that&#8217;s where I run into this the most).</p>
<p>To reproduce this error we can do</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">LEFT</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'hello'</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>Of course it makes sense we cannot return the negative one character from the string, and I sometimes wonder why it doesn&#8217;t return a NULL.  But there&#8217;s probably a reason that I don&#8217;t know about.</p>
<p>For simplicity, the above example doesn&#8217;t reproduce the exact error mentioned.  To reproduce that error, we can do the following:</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">DECLARE</span> @MyString <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'no slash here'</span><br />
<br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">SUBSTRING</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">LEFT</span><span style="color: #66cc66;">&#40;</span>@MyString<span style="color: #66cc66;">,</span>CHARINDEX<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/'</span><span style="color: #66cc66;">,</span> @MyString <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>Then to fix, we can implement the CASE statement:</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">DECLARE</span> @MyString <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'no slash here'</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">SUBSTRING</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">LEFT</span><span style="color: #66cc66;">&#40;</span>@MyString<span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">CASE</span> <span style="color: #993333; font-weight: bold;">WHEN</span> CHARINDEX<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/'</span><span style="color: #66cc66;">,</span> @MyString <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">THEN</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">ELSE</span> CHARINDEX<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/'</span><span style="color: #66cc66;">,</span> @MyString <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">END</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>So remember if you can, when running into these scenarios, make sure to account for the errors that can happen.</p>
<img src="http://feeds.feedburner.com/~r/SqlServerPlanet/~4/hO_oJZrvwOY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverplanet.com/tsql/top-3-sql-errors-that-will-leave-your-users-stranded/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://sqlserverplanet.com/tsql/top-3-sql-errors-that-will-leave-your-users-stranded</feedburner:origLink></item>
		<item>
		<title>SQL Server Database Optimization Guide</title>
		<link>http://feedproxy.google.com/~r/SqlServerPlanet/~3/bHyI8a4U_tk/sql-server-optimization-guide</link>
		<comments>http://sqlserverplanet.com/optimization/sql-server-optimization-guide#comments</comments>
		<pubDate>Wed, 06 Feb 2013 09:15:53 +0000</pubDate>
		<dc:creator>Derek Dieter</dc:creator>
				<category><![CDATA[Featured Articles]]></category>
		<category><![CDATA[Optimization]]></category>

		<guid isPermaLink="false">http://sqlserverplanet.com/?p=3386</guid>
		<description><![CDATA[In the troubleshooting guide we went over the different physical bottlenecks that can cause SQL Server slowness and showed how to identify them. In this guide, we&#8217;ll drill down one step deeper to help identify the actual settings or queries that are contributing to the bottleneck. By relieving these bottlenecks we will start to see our batch requests / sec increase. While it may seem you will be able to go through this article once, what is more likely is that you will need to continue to iterate through some of these principles multiple times. This is because many times when one bottleneck is relieved, another is revealed. One thing we will not cover much in this article is architecture. Unfortunately this is a much more complex subject. Suffice it to say, either you have it or you don&#8217;t. I can&#8217;t so much give architecture principles in an optimization guide, but it is probably the single most important factor in determining throughput in a system. Without a good foundation you can only build a house so large. With that said, there are still luckily plenty of optimization techniques we can employ. Missing Indexes The biggest way to be a hero in your organization is to create the missing indexes. This task is simple ever since the introduction of DMV&#8217;s. When an index is missing it contributes directly to IO usage, and the higher the IO typically means higher CPU. Each time the SQL Server service is restarted the system tables [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://sqlserverplanet.com/wp-content/uploads/2013/02/fast_database.jpg"><img src="http://sqlserverplanet.com/wp-content/uploads/2013/02/fast_database.jpg" alt="fast_database" width="188" height="220" class="alignleft size-full wp-image-3421" /></a>In the <a href="http://sqlserverplanet.com/troubleshooting/sql-server-slowness" title="Troubleshooting SQL Server Slowness">troubleshooting guide</a> we went over the different physical bottlenecks that can cause SQL Server slowness and showed how to identify them. In this guide, we&#8217;ll drill down one step deeper to help identify the actual settings or queries that are contributing to the bottleneck.  By relieving these bottlenecks we will start to see our <a href="http://sqlserverplanet.com/dba/understanding-batch-requests-sec" title="Understanding Batch Requests / sec">batch requests / sec</a> increase.  While it may seem you will be able to go through this article once, what is more likely is that you will need to continue to iterate through some of these principles multiple times.  This is because many times when one bottleneck is relieved, another is revealed.  </p>
<p>One thing we will not cover much in this article is architecture.  Unfortunately this is a much more complex subject.  Suffice it to say, either you have it or you don&#8217;t.  I can&#8217;t so much give architecture principles in an optimization guide, but it is probably the single most important factor in determining throughput in a system.  Without a good foundation you can only build a house so large.  With that said, there are still luckily plenty of optimization techniques we can employ.</p>
<h4>Missing Indexes</h4>
<p>The biggest way to be a hero in your organization is to create the missing indexes. This task is simple ever since the introduction of DMV&#8217;s. When an index is missing it contributes directly to IO usage, and the higher the IO typically means higher CPU. Each time the SQL Server service is restarted the system tables begin getting populated and missing index information is collected. Needless to say, the longer the SQL Server service has been running, the more accurate this information will be. Once an index is determined as missing, the number of times it could have been used is counted. Fortunately we are able to query this data to help determine what which new indexes will have the most positive impact.</p>
<p><a title="Missing Indexes DMV" href="http://sqlserverplanet.com/dmvs/missing-indexes-dmv">This query</a> will show the missing indexes sorted by most impactful first. Implementing the top 10 typically has an enormous impact on a system that is not very optimized.</p>
<div class="block style04">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico9.gif" alt="" class="ico" />
						<div class="text-holder">Many times the indexes shown in the DMV above can be combined into a single index</div>
					</div>
<h4>High IO Queries</h4>
<p>After taking care of the indexes, we can begin to focus on the high IO queries. There are two different categories high IO queries fall into.</p>
<ol>
<li>High Average IO</li>
<li>High Cumulative IO</li>
</ol>
<p>The difference between these two is that a high average IO query will (hopefully) be run infrequently but when it does run, it uses an enormous amount of resources. This is typical behavior we see in reports or job related processes.</p>
<p>The High Cumulative IO procedure will typically be a procedure that is executed a lot. While the average amount of IO per execution is low when it is added up throughout the day we find it can also consume an enormous amount of resources.</p>
<p>The same DMV is used to determine both these types of <a title="Find Queries Using Most Memory (IO)" href="http://sqlserverplanet.com/dmvs/find-queries-taking-most-memory">High IO queries</a>. The only difference is that we are sorting the results by average IO vs cumulative IO. The first two queries in the above link show how to find these. Once these are found you can begin to figure out what is causing the biggest issue <a title="How to Optimize a Stored Procedure using the Execution Plan" href="http://sqlserverplanet.com/optimization/how-to-optimize-a-stored-procedure-using-the-execution-plan">using the execution plan</a>. Also reference <a title="How to Write Optimized Stored Procedures" href="http://sqlserverplanet.com/optimization/how-to-optimize-stored-procedures">How to Write Optimized Stored Procedures</a>.</p>
<h4>High CPU Queries</h4>
<p>If your biggest bottleneck is CPU, I actually consider this to be the best bottleneck you can have.  You will know if your CPU is bottlnecked because you are able to hit (95%+) usage.  If this is the case, then you need to tackle the queries that take higher CPU rather than higher IO first.  First of course, make sure this is being caused by SQLServer.exe and not some other process.  With that out of the way, we can run yet another DMV.  This DMV is basically the same one we ran for the IO, however we are sorting by worker time instead.  The same &#8220;average vs cumulative&#8221; case comes into play with the CPU queries just like the IO queries.  We need to focus on both the intensive &#8220;job&#8221; type queries AND the &#8220;operational&#8221; queries that utilize a lot of CPU cumulatively.  This DMV will show you both.</p>
<p><a href="http://sqlserverplanet.com/dmvs/find-queries-taking-most-cpu-processor" title="Find Queries Taking Most CPU (Processor)">Find Queries using the most CPU</a></p>
<div class="block style04">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico9.gif" alt="" class="ico" />
						<div class="text-holder">Don&#8217;t be surprised if after lowering the CPU usage, a disk bottleneck appears.  The system is so interrelated you often times will go back and forth between the two.</div>
					</div>
<h4>Most Executed Queries</h4>
<p>One of the least recognized optimization techniques focuses on the most executed queries.  Often times in systems you will find that many procedures will depend on one particular query or procedure.  If this single query can be sped up, then the entire system would see a big increase in throughput.  A gross example of this was one system I worked on that had a calculated column defined as a <a href="http://sqlserverplanet.com/optimization/user-defined-functions-and-performance" title="User Defined Functions and Performance">user defined function</a>.  While architecturally this is a big mistake, after optimizing this function this system that previously hit max batch requests/sec of 400, now hit over 3500.  Suffice it to say my yearly salary could have been justified with that one fix.  To find the most executed queries run the following DMV:</p>
<p><a href="http://sqlserverplanet.com/dmvs/find-most-executed-queries" title="Find Most Executed Queries">Find Most Executed Queries</a></p>
<div class="block style02">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico11.gif" alt="" class="ico" />
						<div class="text-holder">When modifying sensitive procedures for performance, make sure to not only test them in staging, but also find a way to do a test in production.  Execution plans may differ between environments.</div>
					</div>
<h4>Keep an Eye on Your Server</h4>
<p>While it&#8217;s possible management may think you&#8217;re wasting time, it is very important to keep an eye on your server to become familiar with the processes that are running.  If you do not do this you won&#8217;t be able to recognize new &#038; slow processes.  By watching the server you can discover blocking, adhoc queries run by users, increases in connection count, queries run at a certain time of day.  There are so many positive discoveries that can come about by watching your server I can&#8217;t begin to mention them all here.  There are two tools I can recommend to manually watch your server.</p>
<ul>
<li><a href="http://sqlserverplanet.com/dba/a-better-sp_who2-using-dmvs-sp_who3" title="A Better sp_who2 using DMVs (sp_who3)">sp_who3</a> &#8211; created by me</li>
<li><a href="http://sqlblog.com/files/folders/release/default.aspx">Who is Active</a> &#8211; created by <a href="http://sqlblog.com/blogs/adam_machanic/">Adam Machanic</a></li>
</ul>
<h4>Parallelism</h4>
<p>One of the least understood and improperly configured settings in SQL Server has to be <a href="http://sqlserverplanet.com/optimization/what-is-parallelism" title="What is Parallelism?">parallelism</a>.  My take on parallelism for a customer facing OLTP system, is that any user initiated process should not qualify for parallelism.  Long story short is the risk is not worth the reward.  Parallelism is basically a multi-threaded call for a single query.  If the cost threshold is too low, then you will get everything under the sun qualifying for parallelism.  </p>
<p>You can read more about it here: <a href="http://sqlserverplanet.com/optimization/what-is-parallelism" title="What is Parallelism?">What is parallelism</a>.<br />
Configuring it here: <a href="http://sqlserverplanet.com/dba/configuring-parallelism" title="Configuring Parallelism">Configuring parallelism</a>.<br />
This will help you <a href="http://sqlserverplanet.com/dmvs/find-most-blocked-queries" title="Find Most Blocked Queries">find queries qualifying for parallelism</a>.<br />
This can help you <a href="http://sqlserverplanet.com/optimization/maxdop-query-hint" title="MAXDOP Query Hint">control a single query</a>.</p>
<h4>Blocking</h4>
<p>Blocking can also be a hindrance to throughput.  Blocking occurs because the default isolation level for SQL Server is read-committed.  This basically means that while a record is being updated it is locked so that it cannot be read until the update is complete.  At least that is one example.  Most of the time blocking is a symptom of missing or non optimal indexes.  With improper indexes, scans occur.  When scans occur too many records are touched and locked.  To help get around blocking you need to add indexes or <a href="http://sqlserverplanet.com/optimization/set-transaction-isolation-level" title="SET TRANSACTION ISOLATION LEVEL">change the default isolation level</a> for your procedure.  To discover the blocker you can run <a href="http://sqlserverplanet.com/dba/blocking-processes-lead-blocker" title="Blocking Processes (lead blocker)">finding the lead blocker</a>.  Run this to <a href="http://sqlserverplanet.com/dmvs/find-most-blocked-queries" title="Find Most Blocked Queries">find the queries that are most blocked</a>.</p>
<p>I hope this helps.  Additional resources you could use would be the <a href="http://sqlserverplanet.com/troubleshooting/sql-server-slowness" title="Troubleshooting SQL Server Slowness">troubleshooting guide</a> and <a href="http://sqlserverplanet.com/optimization/how-to-optimize-stored-procedures" title="How to Write Optimized Stored Procedures">how to write optimized stored procedures</a>.</p>
<img src="http://feeds.feedburner.com/~r/SqlServerPlanet/~4/bHyI8a4U_tk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverplanet.com/optimization/sql-server-optimization-guide/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverplanet.com/optimization/sql-server-optimization-guide</feedburner:origLink></item>
		<item>
		<title>Comparing EXISTS vs LEFT JOIN WHERE NOT NULL</title>
		<link>http://feedproxy.google.com/~r/SqlServerPlanet/~3/pFFk2pXVbGs/comparing-exists-vs-left-join-where-not-null</link>
		<comments>http://sqlserverplanet.com/tsql/comparing-exists-vs-left-join-where-not-null#comments</comments>
		<pubDate>Wed, 26 Dec 2012 20:50:34 +0000</pubDate>
		<dc:creator>Derek Dieter</dc:creator>
				<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://sqlserverplanet.com/?p=3064</guid>
		<description><![CDATA[Two of the most common ways to check for the existence of records is to use a WHERE EXISTS or to perform a LEFT JOIN WHERE values are NOT NULL. My personal choice is usually to use the EXISTS method where possible. Call me a prude, but I think just by virtue of EXISTS being the keyword for this method, it&#8217;s a safer and more optimization friendly method. If someone asked me how to check for existence I would tell them to use exists. However I do think there are many more considerations that need to be outlined before making a final decision. Let&#8217;s look at examples of the two methods to illustrate: -- using EXISTS to check for existence SELECT P.ProductID FROM Production.Product p WHERE EXISTS &#40; &#160; &#160; SELECT 1 &#160; &#160; FROM Sales.SalesOrderDetail sod &#160; &#160; WHERE sod.ProductID = p.ProductID &#41; -- Using LEFT JOIN to check for existence GO SELECT DISTINCT P.ProductID FROM Production.Product p LEFT JOIN Sales.SalesOrderDetail sod &#160; &#160; ON sod.ProductID = p.ProductID WHERE sod.SalesOrderDetailID IS NOT NULL Since these examples are straightforward, the optimizer realizes the end result we are looking for and gives us the same execution plan for both. However we don&#8217;t always want to rely on the optimizer&#8217;s brains. This is because as the execution plan gets more complex (by adding additional tables), it&#8217;s less likely to make good suggestions. This brings up a separate point. Anatomy of LEFT JOIN WHERE NOT NULL While there is a chance both methods [...]]]></description>
				<content:encoded><![CDATA[<p>Two of the most common ways to check for the existence of records is to use a WHERE EXISTS or to perform a LEFT JOIN WHERE values are NOT NULL.  My personal choice is usually to use the EXISTS method where possible.  Call me a prude, but I think just by virtue of EXISTS being the keyword for this method, it&#8217;s a safer and more optimization friendly method.  If someone asked me how to check for existence I would tell them to use exists.  However I do think there are many more considerations that need to be outlined before making a final decision.</p>
<p>Let&#8217;s look at examples of the two methods to illustrate:</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- using EXISTS to check for existence</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> P<span style="color: #66cc66;">.</span>ProductID<br />
<span style="color: #993333; font-weight: bold;">FROM</span> Production<span style="color: #66cc66;">.</span>Product p<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">EXISTS</span><br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #cc66cc;">1</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> Sales<span style="color: #66cc66;">.</span>SalesOrderDetail sod<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> sod<span style="color: #66cc66;">.</span>ProductID <span style="color: #66cc66;">=</span> p<span style="color: #66cc66;">.</span>ProductID<br />
<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- Using LEFT JOIN to check for existence</span><br />
<span style="color: #993333; font-weight: bold;">GO</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">DISTINCT</span> P<span style="color: #66cc66;">.</span>ProductID<br />
<span style="color: #993333; font-weight: bold;">FROM</span> Production<span style="color: #66cc66;">.</span>Product p<br />
<span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> Sales<span style="color: #66cc66;">.</span>SalesOrderDetail sod<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ON</span> sod<span style="color: #66cc66;">.</span>ProductID <span style="color: #66cc66;">=</span> p<span style="color: #66cc66;">.</span>ProductID<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> sod<span style="color: #66cc66;">.</span>SalesOrderDetailID <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span></div></div>
<p>Since these examples are straightforward, the optimizer realizes the end result we are looking for and gives us the same execution plan for both.  </p>
<p><a href="http://sqlserverplanet.com/wp-content/uploads/2012/12/exists_execution_plan.png"><img src="http://sqlserverplanet.com/wp-content/uploads/2012/12/exists_execution_plan.png" alt="" title="exists_execution_plan" width="803" height="239" class="aligncenter size-full wp-image-3068" /></a></p>
<p>However we don&#8217;t always want to rely on the optimizer&#8217;s brains.  This is because as the execution plan gets more complex (by adding additional tables), it&#8217;s less likely to make good suggestions.  This brings up a separate point.  </p>
<div class="block style04">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico9.gif" alt="" class="ico" />
						<div class="text-holder">When possible it&#8217;s better to keep queries small. If needed we can insert results to intermediate temp tables then use temp tables for additional joins</div>
					</div>
<h4>Anatomy of LEFT JOIN WHERE NOT NULL</h4>
<p>While there is a chance both methods can take the same execution path, it&#8217;s not always likely.  When the optimizer sees tables being joined together (as in LEFT JOIN) it anticipates that columns will also need to be returned from these tables.  To help facilitate this, it will often create a worktable to help with the join.  This worktable is an intermediate step to help with further joins.  This worktable may be a good choice in some cases we have to keep in mind it contributes to increased IO because it&#8217;s writing to TempDB.  This is where EXISTS may present a better option.  </p>
<h4>Anatomy of Exists</h4>
<p>When the optimizer sees an EXISTS, it does not anticipate a join of two different tables &#8211; so it will often not create a worktable.  The reason for this is because the very nature of EXISTS is to return a true or false, therefore, it only needs to use the EXISTS table as a filter.  Now this does not mean that EXISTS will always outperform the LEFT JOIN method.  The times I&#8217;ve seen the LEFT JOIN NOT NULL method beat EXISTS have usually been when too many exists were used in a single statement.  This makes sense from a logical standpoint because at a certain threshold a worktable provides the benefit of an intermediary step, rather than having a single complex filter. </p>
<p>The other benefit of EXISTS is that it may not need to scan the entire table in order to return it&#8217;s result.  Let&#8217;s say we are looking for the existence of 1 product in our SalesOrderDetail table.  In the best case scenario, this product could be in the first row.  If it is, we only need to find the single case where it does exist in order to be finished with our query.  Even if the product is listed thousands of time in our table, we only need the first instance.  This is not true with the LEFT JOIN WHERE NOT NULL.  In this case, we are telling the optimizer to return us back all the joined records.  Thankfully it is sometimes smart enough to know that&#8217;s not what we really want.</p>
<h4>Checking for No Existence (Anti Join)</h4>
<p>This gets a bit trickier.  If we do a NOT EXISTS, then do you think it&#8217;s still true that we need to find the first instance of a product to be finished with our query? Nope, we literally need to touch EVERY row in order to find the rows to return.  This is sometimes where I find LEFT JOIN WHERE NULL a better option.  This can often be a more efficient query so you&#8217;ll have to test it out on your own.</p>
<p>If both operations need to touch all the rows anyway, why use LEFT JOIN WHERE NULL instead of NOT EXISTS?  Well, I&#8217;m going to give two reasons and you&#8217;ll have to take my word for one of them if you don&#8217;t already agree.  </p>
<ol>
<li>As the query grows in complexity, NOT EXISTS can end up confusing the optimizer.  You&#8217;ll have to take my word for that because I don&#8217;t have an example.</li>
<li>Since you are checking every row in this table, we may as well join it because we might need a column from it later.</li>
</ol>
<p>If you need a column with an EXISTS table you&#8217;ll end up needing to rewrite the query or add the same table being referenced in the exists as a JOIN against the outer table.  One negative to note, is that if the two tables are not 1-1 then you will end up having to do a DISTINCT.  That does suck, but if you can keep your result set small, it still may be worth it.</p>
<p>Here&#8217;s an example:</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> p<span style="color: #66cc66;">.</span>ProductID<br />
<span style="color: #993333; font-weight: bold;">FROM</span> Production<span style="color: #66cc66;">.</span>Product p<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">EXISTS</span><br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #cc66cc;">1</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> Sales<span style="color: #66cc66;">.</span>SalesOrderDetail sod<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> sod<span style="color: #66cc66;">.</span>ProductID <span style="color: #66cc66;">=</span> p<span style="color: #66cc66;">.</span>ProductID<br />
<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #993333; font-weight: bold;">GO</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">DISTINCT</span> p<span style="color: #66cc66;">.</span>ProductID<br />
<span style="color: #993333; font-weight: bold;">FROM</span> Production<span style="color: #66cc66;">.</span>Product p<br />
<span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> Sales<span style="color: #66cc66;">.</span>SalesOrderDetail sod<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ON</span> sod<span style="color: #66cc66;">.</span>ProductID <span style="color: #66cc66;">=</span> p<span style="color: #66cc66;">.</span>ProductID<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> sod<span style="color: #66cc66;">.</span>SalesOrderDetailID <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NULL</span></div></div>
<p>So here we are hitting plenty of data pages regardless of the method.  Only when the plans get more complex have I seen issues occur.</p>
<h4>Alternate Methods</h4>
<p>There are alternate methods of performing these operations.  The first is to use IN or NOT IN.  In my experience, these are exactly the same (execution wise) as the EXISTS.  The difference is using <a href="http://sqlserverplanet.com/tsql/using-not-in-with-null-values">NOT IN with NULL values</a> can yield some unexpected results.  The other option is to use the SET based EXCEPT.  This can be tricky however because it functions as an ANTI UNION.  Both the result sets in each operation need to match, which is not always ideal. </p>
<h4>Conclusion</h4>
<p>The conclusion really is not black or white.  You will have to test for yourself which is quicker for your own scenario.  Since there are many factors including table size, relationship, carnality, result set size, I would suggest you investigate the pros and cons of each.  It is generally true however that when checking for mere existence, exists is faster.  And when performing an anti-join, the LEFT JOIN method can be safer.</p>
<img src="http://feeds.feedburner.com/~r/SqlServerPlanet/~4/pFFk2pXVbGs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverplanet.com/tsql/comparing-exists-vs-left-join-where-not-null/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverplanet.com/tsql/comparing-exists-vs-left-join-where-not-null</feedburner:origLink></item>
		<item>
		<title>Yet Another Temp Tables Vs Table Variables Article</title>
		<link>http://feedproxy.google.com/~r/SqlServerPlanet/~3/szPuDYeblqk/yet-another-temp-tables-vs-table-variables-article</link>
		<comments>http://sqlserverplanet.com/tsql/yet-another-temp-tables-vs-table-variables-article#comments</comments>
		<pubDate>Sun, 09 Dec 2012 09:30:11 +0000</pubDate>
		<dc:creator>Derek Dieter</dc:creator>
				<category><![CDATA[Featured Articles]]></category>
		<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://sqlserverplanet.com/?p=2911</guid>
		<description><![CDATA[The debate whether to use temp tables or table variables is an old debate that goes back since they were first introduced. The real answer to knowing the difference lies in what is going on under the hood and correlating those specifics to your situation. In this article we&#8217;ll touch on (hopefully all) the differences between the two. #Temp tables are just regular SQL tables that are defined and stored in TempDB. The only difference between them and a permanent table is they are not allowed to have foreign keys. You can view the temp tables currently defined via SSMS by going to TempDB and Expanding Temp Tables. Let&#8217;s look at a matrix of specific differences then we&#8217;ll touch on a few of the key differences below. Item #Temp Tables @Table Variables Can participate in a transaction Writes to Log File Writes only to memory (not disk) Can Qualify for Parallelism Allows creation of statistics Does not affect recompilation Allows nonclustered indexes Allows clustered indexes Can perform SELECT INTO Can access in nested stored procedures Can define globally Can use in user defined functions Can insert from EXEC Allows TRUNCATE Allows ALTER TABLE Scope #Temp tables can be either #locally defined (within the scope of the session) or ##globally defined (within a database). When they are locally defined, the table can be used by whatever is executed within that session (or SPID). In other words, if you define a #temp table in procedure A, then procedure A calls procedure B, [...]]]></description>
				<content:encoded><![CDATA[<p>The debate whether to use temp tables or table variables is an old debate that goes back since they were first introduced.  The real answer to knowing the difference lies in what is going on under the hood and correlating those specifics to your situation.  In this article we&#8217;ll touch on (hopefully all) the differences between the two.</p>
<div class="block style04">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico9.gif" alt="" class="ico" />
						<div class="text-holder">The rest of this article will preface the word #temp tables by using the pound sign (#) and preface @table variables using the &#8220;at&#8221; (@) symbol</div>
					</div>
<p>#Temp tables are just regular SQL tables that are defined and stored in TempDB.  The only difference between them and a permanent table is they are not allowed to have foreign keys.  You can view the temp tables currently defined via SSMS by going to TempDB and Expanding Temp Tables.</p>
<p>Let&#8217;s look at a matrix of specific differences then we&#8217;ll touch on a few of the key differences below.</p>
<table border="1" class="center">
<tbody>
<thead>
<tr>
<th class="bold"><strong>Item</strong></th>
<th class="bold"><strong>#Temp Tables</strong></th>
<th class="bold"><strong>@Table Variables</strong></th>
</tr>
</thead>
<tr>
<td>Can participate in a transaction</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Writes to Log File</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Writes only to memory (not disk)</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Can Qualify for Parallelism</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Allows creation of statistics</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Does not affect recompilation</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Allows nonclustered indexes</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Allows clustered indexes</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><a href="http://sqlserverplanet.com/tsql/create-index-on-table-variable" title="Create Index on Table Variable"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/yellow_caution_trans.png" alt="" class="ico" /></a></td>
</tr>
<tr>
<td>Can perform <a href="http://sqlserverplanet.com/tsql/sql-server-select-into" title="SQL Server SELECT INTO">SELECT INTO</a></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Can access in nested stored procedures</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Can define globally</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Can use in user defined functions</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td><a href="http://sqlserverplanet.com/tsql/insert-stored-procedure-results-into-table" title="Insert Stored Procedure Results Into Table">Can insert from EXEC</a></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Allows TRUNCATE</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
</tr>
<tr>
<td>Allows ALTER TABLE</td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/green_check_trans.png" alt="" class="ico" /></td>
<td class="center"><img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/red_x_trans.png" alt="" class="ico" /></td>
</tr>
</tbody>
</table>
<h4>Scope</h4>
<p>#Temp tables can be either #locally defined (within the scope of the session) or ##globally defined (within a database).  When they are locally defined, the table can be used by whatever is executed within that session (or SPID).  In other words, if you define a #temp table in procedure A, then procedure A calls procedure B, procedure B will also be able to access that same temp table.  This of course needs to happen within the same SPID.  Once the session is terminated, the #temp tables assigned to that session are automatically deallocated.  </p>
<p>Globally defined ##temp tables are defined by using the pound sign twice ## then the temp table name.  As the name indicates, they are available to   Global ##temp tables are deallocated when the originating session terminates and all locks have been released.</p>
<p>@Table variables on the other hand, can only be defined locally yet their scope is limited to the procedure or batch they are called within.  They cannot be referenced by other procedures from within the same session.</p>
<h4>SELECT INTO.. Capability</h4>
<p>This advantage the #temp table has over the @table variable is not often spoken about, but in my experience it&#8217;s a big one.  Let me paint a picture of the first scenario.  Let&#8217;s say you need to create a @table variable to accept the filtered results of one of your permanent tables, your Employees table.  You end up creating 10 procedures and in each of them you explicitly define the columns to match the data types of the Employee table.  Well, all is going fine, then one day HR says they need the firstname field to accept 50 characters instead of 25.  Even worse, a new developer on your team doesn&#8217;t know that you have the firstname fields explicitly defined in @table variables and he goes ahead and changes firstname column to 50 characters in Employees.  Now, all of your table variables are throwing errors because the long firstnames won&#8217;t fit.  This is where the advantage of the #temp table comes in.  Since you can capture your results using SELECT..INTO, the datatypes are determined at runtime.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- Example of SELECT..INTO</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> TOP <span style="color: #cc66cc;">10</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span><br />
<span style="color: #993333; font-weight: bold;">INTO</span> #sod<br />
<span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">&#91;</span>Sales<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderDetail<span style="color: #66cc66;">&#93;</span></div></div>
<h4>Performance</h4>
<p>In my experience of taking an average of all queries that have used #temp tables vs @table variables, the temp tables have come out on top.  The reason is that the query optimizer will sometimes generate poor plans for @table vars.  This can mostly be seen when there is a lot of data.  For this reason a general rule of thumb I&#8217;ve seen many places in the SQL community is.  If there are less than 1000 rows, use a @table var, otherwise use a #temp table.  While that may be a good rule of thumb, it certainly doesn&#8217;t apply to every situation.  I have also seen some very strange scanning happen on @table variables.  The biggest point I can make is that @table variables are more likely to cause unpredictable execution plans when compared to the plans generated for #temp tables.  #Temp tables on the other hand, <a href="http://sqlserverplanet.com/optimization/temp-table-recompiles" title="Temp Table Recompiles">will cause more recompilation</a>.</p>
<h4>@Table Variables Do Not Write to Disk &#8211; Myth</h4>
<p>There&#8217;s a common misconception that @table variables do not write to disk.  I can dispel that myth with the following example.  Below, we will watch the physical disk performance object using the counter &#8220;Disk Writes/sec&#8221;.  By watching this object, we can be sure that the results of this graph represent actual writes to disk.  This is not memory IO, this counter can only represent actual disk writes.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">/********************************************<br />
* &nbsp; TEST 1: @Table Variable insertion<br />
*********************************************/</span><br />
<span style="color: #993333; font-weight: bold;">DECLARE</span> &nbsp;@SalesOrderDetail <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span>&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#93;</span><br />
<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> @SalesOrderDetail<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span>&nbsp; &nbsp; <br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> TOP <span style="color: #cc66cc;">10</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">&#91;</span>Sales<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderDetail<span style="color: #66cc66;">&#93;</span><br />
<br />
<span style="color: #993333; font-weight: bold;">DELETE</span> @SalesOrderDetail<br />
<br />
<span style="color: #993333; font-weight: bold;">GO</span> <span style="color: #cc66cc;">10000</span>&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">-- loop the above batch 10k times</span><br />
<br />
<span style="color: #808080; font-style: italic;">/********************************************<br />
* &nbsp; TEST 2: #temp table insertion<br />
*********************************************/</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> TOP <span style="color: #cc66cc;">10</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">INTO</span> #sod<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">&#91;</span>Sales<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderDetail<span style="color: #66cc66;">&#93;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> #sod<br />
<br />
<span style="color: #993333; font-weight: bold;">GO</span> <span style="color: #cc66cc;">10000</span>&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">-- loop the above batch 10k times</span></div></div>
<p>This example used the AdventuresWorks2012 database.  The graph below shows the disk writes for both executions. Both executions took 10 seconds to execute, and they both wrote to disk the same amount.  This also dispels the myth that @table vars only write to disk if the threshold goes over a certain number of records.</p>
<p><a href="http://stage.sqlserverplanet.com/wp-content/uploads/2012/12/table_var_vs_temp_table.png"><img src="http://stage.sqlserverplanet.com/wp-content/uploads/2012/12/table_var_vs_temp_table.png" alt="" title="table_var_vs_temp_table" width="465" height="317" class="aligncenter size-full wp-image-2954" /></a></p>
<p>Itzik Ben Gan also gives an example of how @table vars write to disk in chapter 2 of his book <a href="http://www.amazon.com/gp/product/0735626022/ref=as_li_tf_tl?ie=UTF8&#038;camp=1789&#038;creative=9325&#038;creativeASIN=0735626022&#038;linkCode=as2&#038;tag=sqlserverplanet-20">TSQL-Programming</a>.</p>
<h4>Parallelism</h4>
<p>The example below shows @table vars not qualifying for parallelism.  This fact helps the argument that @table vars are better suited for small amounts of data.  While parallelism is typically a symptom of a poorly written query, overall it provides a performance gain and definitely has good uses in large data transfers.  This is another +1 for the #temp table.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">/********************************************<br />
* &nbsp; TEST 1: @Table Variable Parallelism<br />
*********************************************/</span><br />
<span style="color: #993333; font-weight: bold;">DECLARE</span> &nbsp;@SalesOrderDetail <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span>&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#93;</span><br />
<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> @SalesOrderDetail<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span>&nbsp; &nbsp; <br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span><br />
&nbsp; &nbsp; sod<span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; sod<span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">&#91;</span>Sales<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderDetail<span style="color: #66cc66;">&#93;</span> sod<br />
<span style="color: #993333; font-weight: bold;">CROSS</span> <span style="color: #993333; font-weight: bold;">JOIN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> top <span style="color: #cc66cc;">50</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">&#91;</span>Sales<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderHeader<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> t<br />
<span style="color: #993333; font-weight: bold;">OPTION</span> <span style="color: #66cc66;">&#40;</span>MAXDOP <span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span><br />
<br />
<br />
<span style="color: #993333; font-weight: bold;">GO</span> <br />
<br />
<span style="color: #808080; font-style: italic;">/********************************************<br />
* &nbsp; TEST 2: #Temp Table Parallelism<br />
*********************************************/</span><br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> &nbsp;#SalesOrderDetail &nbsp;<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span>&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#93;</span><br />
<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> #SalesOrderDetail<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span>&nbsp; &nbsp; <br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <br />
&nbsp; &nbsp; sod<span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderID<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; sod<span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderDetailID<span style="color: #66cc66;">&#93;</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">&#91;</span>Sales<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderDetail<span style="color: #66cc66;">&#93;</span> sod<br />
<span style="color: #993333; font-weight: bold;">CROSS</span> <span style="color: #993333; font-weight: bold;">JOIN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> top <span style="color: #cc66cc;">50</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">&#91;</span>Sales<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>SalesOrderHeader<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> t<br />
<span style="color: #993333; font-weight: bold;">OPTION</span> <span style="color: #66cc66;">&#40;</span>MAXDOP <span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>And here&#8217;s the execution plan:</p>
<p><a href="http://stage.sqlserverplanet.com/wp-content/uploads/2012/12/table_var_vs_temp_table_parallelism.png"><img src="http://stage.sqlserverplanet.com/wp-content/uploads/2012/12/table_var_vs_temp_table_parallelism-300x157.png" alt="" title="table_var_vs_temp_table_parallelism" width="300" height="157" class="aligncenter size-medium wp-image-2955" /></a></p>
<h4>Recompilation</h4>
<p>This is a definite advantage for the @table var.  When coding for sub second throughput, you can definitely be hindered by recompilation that occurs because the dataset size that was used to initially compile the statement has now changed enough to warrant a recompile.  There is a full article I wrote on this subject already that walks you through an <a href="http://sqlserverplanet.com/optimization/temp-table-recompiles" title="Temp Table Recompiles">example of the recompilation</a>.</p>
<h4>Summary</h4>
<p>Hopefully this provides enough information to make a decision on what to use.  Long story short, when you know you&#8217;re dealing with small result sets and you know your source data definitions are not going to change then use @table vars.  Otherwise I would go with #temp tables.</p>
<img src="http://feeds.feedburner.com/~r/SqlServerPlanet/~4/szPuDYeblqk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverplanet.com/tsql/yet-another-temp-tables-vs-table-variables-article/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://sqlserverplanet.com/tsql/yet-another-temp-tables-vs-table-variables-article</feedburner:origLink></item>
		<item>
		<title>The Difference Between UNION and UNION ALL</title>
		<link>http://feedproxy.google.com/~r/SqlServerPlanet/~3/4U7C1VI18ew/the-difference-between-union-and-union-all</link>
		<comments>http://sqlserverplanet.com/tsql/the-difference-between-union-and-union-all#comments</comments>
		<pubDate>Tue, 04 Dec 2012 22:25:01 +0000</pubDate>
		<dc:creator>Derek Dieter</dc:creator>
				<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://sqlserverplanet.com/?p=2903</guid>
		<description><![CDATA[If you&#8217;re like me, after using UNION for many years you may have stumbled upon the UNION ALL and thought, what the heck is the difference? Well it&#8217;s pretty simple. UNION performs a distinct and gives you the unique results for all UNION&#8217;ed queries, whereas UNION ALL does not perform a distinct and gives you all rows regardless of whether they are duplicate. The performance difference is that UNION ALL can be much faster since distinct is an expensive operation. Here is a simple example detailing the difference. We&#8217;ll populate a single temp table with one record, then we&#8217;ll do both a UNION, and a UNION ALL to see the results. -- create the table and populate sample data SELECT &#160; &#160; &#160; name = 'derek' &#160; &#160; &#160;,detail = 'this is record 1' INTO #faba -- perform the UNION on the same table SELECT * FROM #faba UNION SELECT * FROM #faba -- perform the UNION ALL on the same table SELECT * FROM #faba UNION ALL SELECT * FROM #faba From the results we see below, the UNION only returns one record. The execution plans are identical except for the distinct operation being performed as the last operation before output. From this example we see how much utilization distinct is consuming relational to the other operations. (It&#8217;s a lot, however this is a rather simple operation) Long story short, if you know you&#8217;re two separate result sets contain distinct values, it&#8217;s best to use UNION ALL. If for [...]]]></description>
				<content:encoded><![CDATA[<p>If you&#8217;re like me, after using UNION for many years you may have stumbled upon the UNION ALL and thought, what the heck is the difference?  Well it&#8217;s pretty simple.  UNION performs a distinct and gives you the unique results for all UNION&#8217;ed queries, whereas UNION ALL does not perform a distinct and gives you all rows regardless of whether they are duplicate.  The performance difference is that UNION ALL can be much faster since distinct is an expensive operation.</p>
<p>Here is a simple example detailing the difference.  We&#8217;ll populate a single temp table with one record, then we&#8217;ll do both a UNION, and a UNION ALL to see the results.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- create the table and populate sample data</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <br />
&nbsp; &nbsp; &nbsp; name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'derek'</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">,</span>detail <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'this is record 1'</span><br />
<span style="color: #993333; font-weight: bold;">INTO</span> #faba<br />
<br />
<span style="color: #808080; font-style: italic;">-- perform the UNION on the same table</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> #faba<br />
<span style="color: #993333; font-weight: bold;">UNION</span> <br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> #faba<br />
<br />
<span style="color: #808080; font-style: italic;">-- perform the UNION ALL on the same table</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> #faba<br />
<span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">ALL</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> #faba</div></div>
<p>From the results we see below, the UNION only returns one record.</p>
<div id="attachment_2904" class="wp-caption aligncenter" style="width: 238px"><a href="http://sqlserverplanet.com/wp-content/uploads/2012/12/union_vs_union_all.png"><img src="http://sqlserverplanet.com/wp-content/uploads/2012/12/union_vs_union_all.png" alt="" title="union_vs_union_all" width="228" height="201" class="size-full wp-image-2904" /></a><p class="wp-caption-text">UNION returning distinct values</p></div>
<div id="attachment_2905" class="wp-caption aligncenter" style="width: 248px"><a href="http://sqlserverplanet.com/wp-content/uploads/2012/12/UNION_VS_UNION_ALL_UA.png"><img src="http://sqlserverplanet.com/wp-content/uploads/2012/12/UNION_VS_UNION_ALL_UA.png" alt="" title="UNION_VS_UNION_ALL_UA" width="238" height="226" class="size-full wp-image-2905" /></a><p class="wp-caption-text">UNION ALL returning all values</p></div>
<p>The execution plans are identical except for the distinct operation being performed as the last operation before output.  From this example we see how much utilization distinct is consuming relational to the other operations.  (It&#8217;s a lot, however this is a rather simple operation)</p>
<div id="attachment_2906" class="wp-caption aligncenter" style="width: 590px"><a href="http://sqlserverplanet.com/wp-content/uploads/2012/12/union_execution_plan.png"><img src="http://sqlserverplanet.com/wp-content/uploads/2012/12/union_execution_plan.png" alt="" title="union_execution_plan" width="580" height="255" class="size-full wp-image-2906" /></a><p class="wp-caption-text">UNION&#8217;s execution plan performs an additional DISTINCT</p></div>
<div id="attachment_2907" class="wp-caption aligncenter" style="width: 526px"><a href="http://sqlserverplanet.com/wp-content/uploads/2012/12/Union_all_execution_plan.png"><img src="http://sqlserverplanet.com/wp-content/uploads/2012/12/Union_all_execution_plan.png" alt="" title="Union_all_execution_plan" width="516" height="254" class="size-full wp-image-2907" /></a><p class="wp-caption-text">Just a simple concatenation</p></div>
<p>Long story short, if you know you&#8217;re two separate result sets contain distinct values, it&#8217;s best to use UNION ALL.  If for some reason you can&#8217;t guarantee the uniqueness, only then use UNION. </p>
<img src="http://feeds.feedburner.com/~r/SqlServerPlanet/~4/4U7C1VI18ew" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverplanet.com/tsql/the-difference-between-union-and-union-all/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverplanet.com/tsql/the-difference-between-union-and-union-all</feedburner:origLink></item>
		<item>
		<title>Using WITH (NOLOCK)</title>
		<link>http://feedproxy.google.com/~r/SqlServerPlanet/~3/sAQzC6CpYv8/using-with-nolock</link>
		<comments>http://sqlserverplanet.com/tsql/using-with-nolock#comments</comments>
		<pubDate>Fri, 30 Nov 2012 06:56:30 +0000</pubDate>
		<dc:creator>Derek Dieter</dc:creator>
				<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://sqlserverplanet.com/?p=2891</guid>
		<description><![CDATA[The WITH (nolock) hint is an explicit command directed at a specific table or view used to set the transaction isolation level against the table or tables within a view for a query. Once issued, locks will not be used against the data within the table. The advantage to this is there is no chance a deadlock will occur against any other queries running against the table. The other indirect advantage is that less memory will be used in order to hold locks against that data. Example: SELECT &#160; &#160; first_name, &#160; &#160; last_name, FROM dbo.person p WITH &#40;NOLOCK&#41; JOIN dbo.employee e WITH &#40;NOLOCK&#41; &#160; &#160; ON e.person_id = p.person_id WHERE p.person_id = 1; The nolock setting above is explicit for the table it is being set against. To set the value globally for the scope of the connection, see SET TRANSACTION ISOLATION LEVEL Advantages: Deadlocks will not occur against other queries running against the same data Less memory is utilized due to the lack of row, page, or range level locking Typically allows for much higher concurrency due to lower footprint Disadvantages: Uncommitted data can be read leading to dirty reads Explicit hints against a table are generally bad practice Usage In most places I have worked, with (nolock) has been a generally accepted practice in the specific areas of the system that are not sensitive to data being slightly out of sync. It is important to know where things could go wrong though. The biggest red flag I [...]]]></description>
				<content:encoded><![CDATA[<p>The WITH (nolock) hint is an explicit command directed at a specific table or view used to set the <a href="http://sqlserverplanet.com/optimization/set-transaction-isolation-level" title="SET TRANSACTION ISOLATION LEVEL">transaction isolation level</a> against the table or tables within a view for a query.  Once issued, locks will not be used against the data within the table.  The advantage to this is there is no chance a deadlock will occur against any other queries running against the table.  The other indirect advantage is that less memory will be used in order to hold locks against that data.</p>
<h3>Example:</h3>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <br />
&nbsp; &nbsp; first_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; last_name<span style="color: #66cc66;">,</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> dbo<span style="color: #66cc66;">.</span>person p <span style="color: #993333; font-weight: bold;">WITH</span> <span style="color: #66cc66;">&#40;</span>NOLOCK<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">JOIN</span> dbo<span style="color: #66cc66;">.</span>employee e <span style="color: #993333; font-weight: bold;">WITH</span> <span style="color: #66cc66;">&#40;</span>NOLOCK<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ON</span> e<span style="color: #66cc66;">.</span>person_id <span style="color: #66cc66;">=</span> p<span style="color: #66cc66;">.</span>person_id<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> p<span style="color: #66cc66;">.</span>person_id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;</div></div>
<p>The nolock setting above is explicit for the table it is being set against.  To set the value globally for the scope of the connection, see <a href="http://sqlserverplanet.com/optimization/set-transaction-isolation-level" title="SET TRANSACTION ISOLATION LEVEL">SET TRANSACTION ISOLATION LEVEL</a></p>
<div class="block style04">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico9.gif" alt="" class="ico" />
						<div class="text-holder">While the &#8220;WITH&#8221; keyword may not be necessary in current versions of SQL Server, its use is strongly recommended for future version compatibility</div>
					</div>
<h3>Advantages:</h3>
<ul>
<li><a href="http://sqlserverplanet.com/optimization/understanding-sql-server-deadlocks" title="Understanding Deadlocks">Deadlocks</a> will not occur against other queries running against the same data</li>
<li>Less memory is utilized due to the lack of row, page, or range level locking</li>
<li>Typically allows for much higher concurrency due to lower footprint</li>
</ul>
<h3>Disadvantages:</h3>
<ul>
<li>Uncommitted data can be read leading to dirty reads</li>
<li>Explicit hints against a table are generally bad practice</li>
</ul>
<h3>Usage</h3>
<p>In most places I have worked, with (nolock) has been a generally accepted practice in the specific areas of the system that are not sensitive to data being slightly out of sync.  It is important to know where things could go wrong though.  The biggest red flag I can think of for not using NOLOCK would be a system that uses explicit transactions (BEGIN TRAN ..END TRAN) or heavy use of triggers.  Multiple statements executed within a transaction experience a time delay of their INSERT / UPDATE / DELETE operations however the changes are committed at once upon the COMMIT.  Statements that query the changed data using the READ COMMITTED isolation level will be blocked from seeing these changes until commit, whereas READ UNCOMMITTED (NOLOCK) will see the changes immediately irregardless of when the commit occurs.  The assumption here is that if your system uses explicit transactions or relies on triggers heavily, it may be plausible to assume nolock is not a good idea.  </p>
<div class="block style05">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico14.gif" alt="" class="ico" />
						<div class="text-holder">
							Do not use WITH (NOLOCK) without fully understanding the ramifications of a dirty read
						</div>
					</div>
<h3>Example of a Dirty Read</h3>
<p>The following example will open a transaction in order to update the first_name column in our global temp table: ##my_name</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">IF</span> OBJECT_ID<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'tempdb..##my_name'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><br />
<span style="color: #993333; font-weight: bold;">BEGIN</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> ##my_name;<br />
<span style="color: #993333; font-weight: bold;">END</span>;<br />
<br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> ##my_name<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; id <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; first_name <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#41;</span>;<br />
<br />
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> ##my_name <span style="color: #66cc66;">&#40;</span>id<span style="color: #66cc66;">,</span> first_name<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'dexter'</span><span style="color: #66cc66;">&#41;</span>;<br />
<br />
<span style="color: #993333; font-weight: bold;">BEGIN</span> TRAN<br />
<br />
<span style="color: #993333; font-weight: bold;">UPDATE</span> ##my_name<br />
<span style="color: #993333; font-weight: bold;">SET</span> first_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'derek'</span><br />
<span style="color: #993333; font-weight: bold;">WHERE</span> id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;</div></div>
<p>Here we have left a transaction open on ##my_name so that row is exclusively locked and cannot be read by any transaction using isolation level read committed or higher.</p>
<p>Open a new connection and execute the following queries:</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> ##my_name <span style="color: #993333; font-weight: bold;">WITH</span> <span style="color: #66cc66;">&#40;</span>NOLOCK<span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> ##my_name;</div></div>
<p>Here you will see the first query will show the updated value &#8216;derek&#8217;, whereas the query without the nolock will hang waiting for the transaction to release.  The data that has been successfully read is considered dirty data.  This is because there may be other tables that need to be updated which relate to the &#8216;derek&#8217; record (id=1) in order to show a consistent view of all data related to &#8216;derek&#8217;.</p>
<p>Finally let&#8217;s commit our transaction within our original window and you&#8217;ll see that you are now able to query the data without using (nolock).</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">COMMIT TRAN<br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> ##my_name;</div></div>
<img src="http://feeds.feedburner.com/~r/SqlServerPlanet/~4/sAQzC6CpYv8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverplanet.com/tsql/using-with-nolock/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverplanet.com/tsql/using-with-nolock</feedburner:origLink></item>
		<item>
		<title>Detecting Row Level Changes Using HASHBYTES</title>
		<link>http://feedproxy.google.com/~r/SqlServerPlanet/~3/tgLpKzncLdk/detecting-row-level-changes</link>
		<comments>http://sqlserverplanet.com/data-warehouse/detecting-row-level-changes#comments</comments>
		<pubDate>Sat, 17 Nov 2012 00:02:47 +0000</pubDate>
		<dc:creator>Derek Dieter</dc:creator>
				<category><![CDATA[Data Warehouse]]></category>

		<guid isPermaLink="false">http://sqlserverplanet.com/?p=2862</guid>
		<description><![CDATA[A common situation in a data warehouse is the requirement to detect changes in data in order to track what rows need to be imported. The traditional method of comparing the values of each field is performance intensive. Luckily there are other methods to quickly track the changes that involve creating hashes (or a fingerprint) of a particular data row. In using this method, if we want to synchronize two separate tables, we can simply join on the primary key and only compare this fingerprint column in order to determine what has changed. There are two major methods I&#8217;ve used to create a row valued hash key. The first is by using the CHECKSUM function. The other is to use the HASHBYTES function. Both of these function return back a single value representing a hash, however their parameters differ. With CHECKSUM you can pass in a list of columns to evaluate and it returns an integer value. Whereas HASHBYTES requires a single parameter to be passed in and returns back a 16-bit binary value. The trick to forcing HASHBYTES into accepting multiple column values is to use the FOR XML function which will generate a single value to pass in. The obvious difference between the two functions is the size and datatype of the hash being returned. To make a long story short, there are rare occasions (that I have witnessed more than once) where passing in different column values into CHECKSUM will return back the exact same value. Granted [...]]]></description>
				<content:encoded><![CDATA[<p>A common situation in a data warehouse is the requirement to detect changes in data in order to track what rows need to be imported.  The traditional method of comparing the values of each field is performance intensive.  Luckily there are other methods to quickly track the changes that involve creating hashes (or a fingerprint) of a particular data row.  In using this method, if we want to synchronize two separate tables, we can simply join on the primary key and only compare this fingerprint column in order to determine what has changed.</p>
<p>There are two major methods I&#8217;ve used to create a row valued hash key.  The first is by using the CHECKSUM function.  The other is to use the HASHBYTES function.  Both of these function return back a single value representing a hash, however their parameters differ.  With CHECKSUM you can pass in a list of columns to evaluate and it returns an integer value.  Whereas HASHBYTES requires a single parameter to be passed in and returns back a 16-bit binary value.  The trick to forcing HASHBYTES into accepting multiple column values is to use the FOR XML function which will generate a single value to pass in.  The obvious difference between the two functions is the size and datatype of the hash being returned.  To make a long story short, there are rare occasions (that I have witnessed more than once) where passing in different column values into CHECKSUM will return back the exact same value.  Granted this is maybe 2 times for a billion rows, but it has happened.  The chances of this happening with HASHBYTES is extremely rare.</p>
<div class="block style04">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico9.gif" alt="" class="ico" />
						<div class="text-holder">When columns are added or removed from an existing hasbytes function, it is important to to regenerate all stored hash values for source and target tables.  Otherwise all records will be duplicated on import.</div>
					</div>
<p>So, for this example we will use HASHBYTES.  I don&#8217;t plan to use CHECKSUM anymore, however if space is an option I won&#8217;t rule it out.</p>
<p>For this example we will perform a one-way synchronization of the employee_table to the employee_sync_table by joining their primary keys and comparing the hash.  We&#8217;ll put a trigger on the employee table to automatically update or insert the hash for the employee values.  </p>
<p>Let&#8217;s start by creating the DDL for our example tables.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- source table</span><br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> employee_table<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; employee_id <span style="color: #993333; font-weight: bold;">INT</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; first_name <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; last_name <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; row_value varbinary<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8000</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">GO</span><br />
<span style="color: #808080; font-style: italic;">-- trigger to calculate row_value</span><br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TRIGGER</span> row_value_trigger <span style="color: #993333; font-weight: bold;">ON</span> employee_table<br />
<span style="color: #993333; font-weight: bold;">FOR</span> <span style="color: #993333; font-weight: bold;">UPDATE</span><span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">AS</span> &nbsp;<br />
<span style="color: #993333; font-weight: bold;">UPDATE</span> employee_table<br />
<span style="color: #993333; font-weight: bold;">SET</span> row_value <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> hashbytes<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'md5'</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> first_name<span style="color: #66cc66;">,</span> last_name <span style="color: #993333; font-weight: bold;">FOR</span> xml raw<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">GO</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- target table</span><br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> employee_sync_table<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; employee_sync_table_id <span style="color: #993333; font-weight: bold;">INT</span> <span style="color: #993333; font-weight: bold;">IDENTITY</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; employee_id <span style="color: #993333; font-weight: bold;">INT</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; first_name <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; last_name <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; row_value varbinary<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8000</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; datetime_updated datetime<br />
<span style="color: #66cc66;">&#41;</span></div></div>
<p>Our trigger will fire on insert or update and modify the row_value accordingly.  Now let&#8217;s insert some values into the employee_table to see the results</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> employee_table<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; employee_id<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; first_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; last_name<br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <br />
&nbsp; &nbsp; &nbsp;employee_id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>first_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Chris'</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>last_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Johnson'</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span><br />
&nbsp; &nbsp; &nbsp;employee_id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">2</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>first_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Jack'</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>last_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Sullivan'</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span><br />
&nbsp; &nbsp; &nbsp;employee_id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">3</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>first_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Terri'</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>last_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Duffy'</span><br />
<br />
<span style="color: #993333; font-weight: bold;">GO</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- let's also insert these rows into our sync table</span><br />
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> employee_sync_table<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; employee_id<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; first_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; last_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; row_value<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; datetime_updated<br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span><br />
&nbsp; &nbsp; employee_id<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; first_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; last_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; row_value<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; datetime_updated <span style="color: #66cc66;">=</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> employee_table et<br />
<br />
<br />
<span style="color: #808080; font-style: italic;">-- view the results</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> employee_table</div></div>
<div id="attachment_2863" class="wp-caption aligncenter" style="width: 310px"><a href="http://sqlserverplanet.com/wp-content/uploads/2012/11/hashbytes_value.gif" class="ad lightbox"><img src="http://sqlserverplanet.com/wp-content/uploads/2012/11/hashbytes_value-300x72.gif" alt="" title="hashbytes_value" width="300" height="72" class="size-medium wp-image-2863" /></a><p class="wp-caption-text">row_value is the result of HASHBYTES</p></div>
<p>Now we&#8217;ll simulate an employee name change and run our update process to capture changes.  Also below is an insert process to capture any inserts that may have happened.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- simulate employee name change</span><br />
<span style="color: #993333; font-weight: bold;">UPDATE</span> employee_table<br />
<span style="color: #993333; font-weight: bold;">SET</span> last_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Buffy'</span><br />
<span style="color: #993333; font-weight: bold;">WHERE</span> employee_id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">3</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- update rows that have changed</span><br />
<span style="color: #993333; font-weight: bold;">UPDATE</span> eht<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SET</span> first_name&nbsp; <span style="color: #66cc66;">=</span> et<span style="color: #66cc66;">.</span>first_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; last_name &nbsp; <span style="color: #66cc66;">=</span> et<span style="color: #66cc66;">.</span>last_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; row_value &nbsp; <span style="color: #66cc66;">=</span> et<span style="color: #66cc66;">.</span>row_value<br />
<span style="color: #993333; font-weight: bold;">FROM</span> employee_sync_table eht<br />
<span style="color: #993333; font-weight: bold;">JOIN</span> employee_table et<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ON</span> et<span style="color: #66cc66;">.</span>employee_id <span style="color: #66cc66;">=</span> eht<span style="color: #66cc66;">.</span>employee_id<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> eht<span style="color: #66cc66;">.</span>row_value !<span style="color: #66cc66;">=</span> et<span style="color: #66cc66;">.</span>row_value<br />
<br />
<span style="color: #808080; font-style: italic;">-- insert rows that have been added</span><br />
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> employee_sync_table<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; employee_id<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; first_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; last_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; row_value<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; datetime_updated<br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span><br />
&nbsp; &nbsp; employee_id<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; first_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; last_name<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; row_value<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; datetime_updated <span style="color: #66cc66;">=</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> employee_table et<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">EXISTS</span><br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #cc66cc;">1</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> employee_sync_table eht<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> eht<span style="color: #66cc66;">.</span>employee_id <span style="color: #66cc66;">=</span> et<span style="color: #66cc66;">.</span>employee_id<br />
<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- finally, check our results</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> employee_sync_table</div></div>
<p>There, now we see the name Duffy, has been changed to Buffy in our target sync table.</p>
<img src="http://feeds.feedburner.com/~r/SqlServerPlanet/~4/tgLpKzncLdk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverplanet.com/data-warehouse/detecting-row-level-changes/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://sqlserverplanet.com/data-warehouse/detecting-row-level-changes</feedburner:origLink></item>
		<item>
		<title>How to Order Numeric Values in a Varchar Field</title>
		<link>http://feedproxy.google.com/~r/SqlServerPlanet/~3/s0zCQzwcU5o/how-to-order-numeric-values-in-a-varchar-field</link>
		<comments>http://sqlserverplanet.com/tsql/how-to-order-numeric-values-in-a-varchar-field#comments</comments>
		<pubDate>Fri, 02 Nov 2012 06:00:57 +0000</pubDate>
		<dc:creator>Derek Dieter</dc:creator>
				<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://sqlserverplanet.com/?p=2695</guid>
		<description><![CDATA[If you have ever tried to order numerical values in a varchar field you&#8217;ll know that the sort doesn&#8217;t occur numerically as it would if the datatype were numeric. In other words, the values of 1 and 10 will be sorted together because they both start with a leading 1. To overcome this, we have to cast the values as numeric. But this raises another issue. Since it&#8217;s a varchar field we cannot ensure that the values are all numeric which means we additionally have to take into account characters. Let&#8217;s start by creating a sample table and populating some values: CREATE TABLE #varchar_field &#40; &#160; &#160; ID INT IDENTITY&#40;1,1&#41;, &#160; &#160; mixed_field VARCHAR&#40;100&#41;, &#41; INSERT INTO #varchar_field &#40;mixed_field&#41; SELECT '1' UNION ALL SELECT '4.9' UNION ALL SELECT '10' UNION ALL SELECT '50' UNION ALL SELECT '6' UNION ALL SELECT 'a' UNION ALL SELECT 'z' UNION ALL SELECT 'A' Now let&#8217;s run a simple sort so we can see the default behavior. SELECT * FROM #varchar_field ORDER BY mixed_field Here we see everything is only sorted by it&#8217;s leading character, not taking into consideration the value of the numbers. Now let&#8217;s execute a revised version of this order by. SELECT * FROM #varchar_field ORDER BY &#160; &#160; CASE &#160; &#160; &#160; &#160; WHEN ISNUMERIC&#40;mixed_field&#41; = 1 THEN CAST&#40;mixed_field AS FLOAT&#41; &#160; &#160; &#160; &#160; WHEN ISNUMERIC&#40;LEFT&#40;mixed_field,1&#41;&#41; = 0 THEN ASCII&#40;LEFT&#40;LOWER&#40;mixed_field&#41;,1&#41;&#41; &#160; &#160; &#160; &#160; ELSE 2147483647 &#160; &#160; END Here we check to see if the field is numeric first. [...]]]></description>
				<content:encoded><![CDATA[<p>If you have ever tried to order numerical values in a varchar field you&#8217;ll know that the sort doesn&#8217;t occur numerically as it would if the datatype were numeric. In other words, the values of 1 and 10 will be sorted together because they both start with a leading 1. To overcome this, we have to cast the values as numeric. But this raises another issue. Since it&#8217;s a varchar field we cannot ensure that the values are all numeric which means we additionally have to take into account characters.</p>
<p>Let&#8217;s start by creating a sample table and populating some values:</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> #varchar_field <br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; ID <span style="color: #993333; font-weight: bold;">INT</span> <span style="color: #993333; font-weight: bold;">IDENTITY</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; mixed_field <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> #varchar_field <span style="color: #66cc66;">&#40;</span>mixed_field<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'1'</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">ALL</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'4.9'</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">ALL</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'10'</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">ALL</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'50'</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">ALL</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'6'</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">ALL</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'a'</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">ALL</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'z'</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span> <span style="color: #993333; font-weight: bold;">ALL</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">'A'</span></div></div>
<p>Now let&#8217;s run a simple sort so we can see the default behavior.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> #varchar_field<br />
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> mixed_field</div></div>
<p><a href="http://sqlserverplanet.com/wp-content/uploads/2012/11/order_sort_default.png"><img src="http://sqlserverplanet.com/wp-content/uploads/2012/11/order_sort_default.png" alt="" title="order_sort_default" width="264" height="288" class="alignnone size-full wp-image-2696" /></a><br />
Here we see everything is only sorted by it&#8217;s leading character, not taking into consideration the value of the numbers.</p>
<p>Now let&#8217;s execute a revised version of this order by.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> #varchar_field<br />
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> <br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">CASE</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHEN</span> ISNUMERIC<span style="color: #66cc66;">&#40;</span>mixed_field<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">THEN</span> <span style="color: #993333; font-weight: bold;">CAST</span><span style="color: #66cc66;">&#40;</span>mixed_field <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #993333; font-weight: bold;">FLOAT</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHEN</span> ISNUMERIC<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">LEFT</span><span style="color: #66cc66;">&#40;</span>mixed_field<span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">THEN</span> ASCII<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">LEFT</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">LOWER</span><span style="color: #66cc66;">&#40;</span>mixed_field<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ELSE</span> <span style="color: #cc66cc;">2147483647</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">END</span></div></div>
<p>Here we check to see if the field is numeric first.  If it is, we cast it to float to deal with potential decimals.  If it&#8217;s not numeric we simply take the ASCII value of the leading character and sort by that.  This allows us to also sort the alpha characters within the field.</p>
<p>Here is the new result:<br />
<a href="http://sqlserverplanet.com/wp-content/uploads/2012/11/order_sort_fixed.png"><img src="http://sqlserverplanet.com/wp-content/uploads/2012/11/order_sort_fixed.png" alt="" title="order_sort_fixed" width="160" height="203" class="alignnone size-full wp-image-2697" /></a></p>
<p>If the value turns out to be not caught we use the maximum value for an integer.</p>
<img src="http://feeds.feedburner.com/~r/SqlServerPlanet/~4/s0zCQzwcU5o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverplanet.com/tsql/how-to-order-numeric-values-in-a-varchar-field/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://sqlserverplanet.com/tsql/how-to-order-numeric-values-in-a-varchar-field</feedburner:origLink></item>
		<item>
		<title>Creating Hot Swap Tables to Hide Complex Logic</title>
		<link>http://feedproxy.google.com/~r/SqlServerPlanet/~3/Xzx1lXPPcSw/creating-hot-swap-tables-to-hide-complex-logic</link>
		<comments>http://sqlserverplanet.com/design/creating-hot-swap-tables-to-hide-complex-logic#comments</comments>
		<pubDate>Sat, 13 Oct 2012 07:29:48 +0000</pubDate>
		<dc:creator>Derek Dieter</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Optimization]]></category>

		<guid isPermaLink="false">http://sqlserverplanet.com/?p=2459</guid>
		<description><![CDATA[Highly concurrent systems that feed off normalized data stores typically require a middle layer of logic to serve the front-end needs. More often than not, this middle layer of logic is stored in the same stored procedures that the web layer accesses. While sometimes this may be the right place for simple logic, for more complex calculations and joins it is simply not efficient. The answer in these cases is to create a new meta layer of data that pre-joins data and rolls up necessary aggregations. To paint a better picture &#8211; in an ideal database each procedure that feeds the front-end would house a simple select statement from a single table. We know in real life this is not always possible, however we should think in these terms with every web proc we write. The reason is simple &#8211; complex logic is both IO and CPU intensive. We have no control over the web traffic, but we do have control over what logic we use to serve the web. Often times it is better to run jobs in the background that perform complicated logic on behalf of the web procs and dump the results into static tables. This methodology basically creates a denormalized meta layer of data on top of the normalized data. The argument against this is that the data will not truly be real-time. However you need to ask yourself what&#8217;s more important, &#8220;real-time&#8221; data that is 5-10 times slower or preaggregated data that is potentially seconds [...]]]></description>
				<content:encoded><![CDATA[<p>Highly concurrent systems that feed off normalized data stores typically require a middle layer of logic to serve the front-end needs.  More often than not, this middle layer of logic is stored in the same stored procedures that the web layer accesses.  While sometimes this may be the right place for simple logic, for more complex calculations and joins it is simply not efficient.  The answer in these cases is to create a new meta layer of data that pre-joins data and rolls up necessary aggregations.</p>
<p>To paint a better picture &#8211; in an ideal database each procedure that feeds the front-end would house a simple select statement from a single table.  We know in real life this is not always possible, however we should think in these terms with every web proc we write.  The reason is simple &#8211; complex logic is both IO and CPU intensive.  We have no control over the web traffic, but we do have control over what logic we use to serve the web.  Often times it is better to run jobs in the background that perform complicated logic on behalf of the web procs and dump the results into static tables.</p>
<p>This methodology basically creates a denormalized meta layer of data on top of the normalized data.  The argument against this is that the data will not truly be real-time.  However you need to ask yourself what&#8217;s more important, &#8220;real-time&#8221; data that is 5-10 times slower or preaggregated data that is potentially seconds old?</p>
<p>This leads us to the technique of Creating a Hot Swap table.  You can use the AdventureWorks database for this example.  Let&#8217;s start:</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">/*******************************************************************<br />
* &nbsp; logic for rollup table<br />
*******************************************************************/</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <br />
&nbsp; &nbsp; &nbsp;product_id &nbsp; &nbsp; <span style="color: #66cc66;">=</span> p<span style="color: #66cc66;">.</span>ProductID<br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>product_name &nbsp; <span style="color: #66cc66;">=</span> p<span style="color: #66cc66;">.</span>Name<br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>standard_cost&nbsp; <span style="color: #66cc66;">=</span> p<span style="color: #66cc66;">.</span>StandardCost<br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>sales_count&nbsp; &nbsp; <span style="color: #66cc66;">=</span> sales<span style="color: #66cc66;">.</span>sales_count<br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>rating_count &nbsp; <span style="color: #66cc66;">=</span> rating<span style="color: #66cc66;">.</span>rating_count<br />
&nbsp; &nbsp; <span style="color: #66cc66;">,</span>rating_avg &nbsp; &nbsp; <span style="color: #66cc66;">=</span> rating<span style="color: #66cc66;">.</span>avg_rating<br />
<span style="color: #993333; font-weight: bold;">INTO</span> dbo<span style="color: #66cc66;">.</span>product_rollup_load<br />
<span style="color: #993333; font-weight: bold;">FROM</span> Production<span style="color: #66cc66;">.</span>Product p<br />
<span style="color: #993333; font-weight: bold;">CROSS</span> APPLY<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; sales_count <span style="color: #66cc66;">=</span> <span style="color: #993333; font-weight: bold;">COUNT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> sales<span style="color: #66cc66;">.</span>SalesOrderDetail sod<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> sod<span style="color: #66cc66;">.</span>productid <span style="color: #66cc66;">=</span> p<span style="color: #66cc66;">.</span>ProductID<br />
<span style="color: #66cc66;">&#41;</span> sales<br />
<span style="color: #993333; font-weight: bold;">OUTER</span> APPLY<br />
<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;avg_rating &nbsp; &nbsp; <span style="color: #66cc66;">=</span> ISNULL<span style="color: #66cc66;">&#40;</span>AVG<span style="color: #66cc66;">&#40;</span>pr<span style="color: #66cc66;">.</span>Rating<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">,</span>rating_count &nbsp; <span style="color: #66cc66;">=</span> <span style="color: #993333; font-weight: bold;">COUNT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> Production<span style="color: #66cc66;">.</span>ProductReview pr<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> pr<span style="color: #66cc66;">.</span>ProductID <span style="color: #66cc66;">=</span> p<span style="color: #66cc66;">.</span>ProductID<br />
<span style="color: #66cc66;">&#41;</span> rating<br />
<br />
<span style="color: #808080; font-style: italic;">/*******************************************************************<br />
* &nbsp; apply indexes to the rollup table <br />
*******************************************************************/</span><br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">INDEX</span> IX_product_rollup_1 <span style="color: #993333; font-weight: bold;">ON</span> product_rollup_load <span style="color: #66cc66;">&#40;</span>product_id<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">/*******************************************************************<br />
* &nbsp; rename <br />
*******************************************************************/</span><br />
<span style="color: #993333; font-weight: bold;">BEGIN</span> <span style="color: #993333; font-weight: bold;">TRANSACTION</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">EXEC</span> sp_rename <span style="color: #ff0000;">'product_rollup'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'product_rollup_temp'</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">EXEC</span> sp_rename <span style="color: #ff0000;">'product_rollup_load'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'product_rollup'</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> dbo<span style="color: #66cc66;">.</span>product_rollup_temp<br />
COMMIT <span style="color: #993333; font-weight: bold;">TRANSACTION</span></div></div>
<p>Here we see the complex logic is being loaded into a permanent temporary table (not a mistake) &#8220;product_rollup_load&#8221;.  This is not the table the web procs will query, it&#8217;s just used to house the data prior to creating our necessary indexes.  We create our indexes then within a transaction rename the table the front-end procedures use to an old name, then hot swap the new table to the actual production table.  Many Props go out to Tim Collins for turning me on to this technique.</p>
<p>Now, instead of the web procs needing complex logic, a simple SELECT will work just fine.  Make sure to test this in your environment.  I have seen this used in highly concurrent systems and it works well.  It should be noted the other option is to use partitioned tables instead of the rename trick, however we have not run into enough problems using this technique to force that discovery.</p>
<img src="http://feeds.feedburner.com/~r/SqlServerPlanet/~4/Xzx1lXPPcSw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverplanet.com/design/creating-hot-swap-tables-to-hide-complex-logic/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverplanet.com/design/creating-hot-swap-tables-to-hide-complex-logic</feedburner:origLink></item>
		<item>
		<title>Substring Between Two Characters</title>
		<link>http://feedproxy.google.com/~r/SqlServerPlanet/~3/HuUU73heM2s/substring-between-two-characters</link>
		<comments>http://sqlserverplanet.com/tsql/substring-between-two-characters#comments</comments>
		<pubDate>Tue, 09 Oct 2012 07:06:58 +0000</pubDate>
		<dc:creator>Derek Dieter</dc:creator>
				<category><![CDATA[TSQL]]></category>

		<guid isPermaLink="false">http://sqlserverplanet.com/?p=2455</guid>
		<description><![CDATA[Though SQL may not be the most elegant language for string handling, it does perform most functions and in a set based manner. The SQL substring function basically has the same syntax as found in other languages. In this example we will take the common scenario of extracting a string from between two fixed characters. In our example we&#8217;ll start with a domain name that contains the subdomain. We will extract only the top level domain from the results. Keep in mind for the purposes of this example all the URLs listed in the table need to have a subdomain. Setup the Data Let&#8217;s begin by creating a new table named URLs and insert some data. IF EXISTS &#40;SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID&#40;N'dbo.URLs'&#41; AND OBJECTPROPERTY&#40;id, N'IsUserTable'&#41; = 1&#41; --DROP TABLE dbo.URLs CREATE TABLE dbo.URLs&#40; url nvarchar&#40;1024&#41; NULL &#41; INSERT dbo.URLs &#40;url&#41; VALUES &#40;N'www.litwareinc.com/'&#41; GO INSERT dbo.URLs &#40;url&#41; VALUES &#40;N'www.treyresearch.net/'&#41; GO INSERT dbo.URLs &#40;url&#41; VALUES &#40;N'www.adatum.com/'&#41; GO INSERT dbo.URLs &#40;url&#41; VALUES &#40;N'www.northwindtraders.com/'&#41; GO INSERT dbo.URLs &#40;url&#41; VALUES &#40;N'www.wideworldimporters.com/'&#41; GO INSERT dbo.URLs &#40;url&#41; VALUES &#40;N'www.proseware.com/'&#41; Now that we have the data setup let&#8217;s start with the extraction. For the substring function, the first parameter is the string we want to parse from, the next parameter is the starting position to be extracted and the last parameter is the number of characters to extract. DECLARE @first_char nvarchar&#40;10&#41; DECLARE @second_char nvarchar&#40;10&#41; SET @first_char = '.'; SET @second_char = '/'; SELECT SUBSTRING &#40; -- column url -- start position ,CHARINDEX&#40;@first_char, url , [...]]]></description>
				<content:encoded><![CDATA[<p>Though SQL may not be the most elegant language for string handling, it does perform most functions and in a set based manner. The <a href="http://sqlserverplanet.com/tsql/sql-server-substring">SQL substring function</a> basically has the same syntax as found in other languages. In this example we will take the common scenario of extracting a string from between two fixed characters.</p>
<div class="block style05">
						<img src="http://sqlserverplanet.com/wp-content/themes/sqlserverplanet/images/ico14.gif" alt="" class="ico" />
						<div class="text-holder">
							Use caution when using the substring function.  Invalid parameters (negative numbers) will cause errors
						</div>
					</div>
<p>In our example we&#8217;ll start with a domain name that contains the subdomain. We will extract only the top level domain from the results. Keep in mind for the purposes of this example all the URLs listed in the table need to have a subdomain.</p>
<h4>Setup the Data</h4>
<p>Let&#8217;s begin by creating a new table named URLs and insert some data.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> dbo<span style="color: #66cc66;">.</span>sysobjects <span style="color: #993333; font-weight: bold;">WHERE</span> id <span style="color: #66cc66;">=</span> OBJECT_ID<span style="color: #66cc66;">&#40;</span>N<span style="color: #ff0000;">'dbo.URLs'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AND</span> OBJECTPROPERTY<span style="color: #66cc66;">&#40;</span>id<span style="color: #66cc66;">,</span> N<span style="color: #ff0000;">'IsUserTable'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #808080; font-style: italic;">--DROP TABLE dbo.URLs</span><br />
<br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> dbo<span style="color: #66cc66;">.</span>URLs<span style="color: #66cc66;">&#40;</span><br />
url nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1024</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NULL</span><br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">INSERT</span> dbo<span style="color: #66cc66;">.</span>URLs <span style="color: #66cc66;">&#40;</span>url<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>N<span style="color: #ff0000;">'www.litwareinc.com/'</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">GO</span><br />
<span style="color: #993333; font-weight: bold;">INSERT</span> dbo<span style="color: #66cc66;">.</span>URLs <span style="color: #66cc66;">&#40;</span>url<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>N<span style="color: #ff0000;">'www.treyresearch.net/'</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">GO</span><br />
<span style="color: #993333; font-weight: bold;">INSERT</span> dbo<span style="color: #66cc66;">.</span>URLs <span style="color: #66cc66;">&#40;</span>url<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>N<span style="color: #ff0000;">'www.adatum.com/'</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">GO</span><br />
<span style="color: #993333; font-weight: bold;">INSERT</span> dbo<span style="color: #66cc66;">.</span>URLs <span style="color: #66cc66;">&#40;</span>url<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>N<span style="color: #ff0000;">'www.northwindtraders.com/'</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">GO</span><br />
<span style="color: #993333; font-weight: bold;">INSERT</span> dbo<span style="color: #66cc66;">.</span>URLs <span style="color: #66cc66;">&#40;</span>url<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>N<span style="color: #ff0000;">'www.wideworldimporters.com/'</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">GO</span><br />
<span style="color: #993333; font-weight: bold;">INSERT</span> dbo<span style="color: #66cc66;">.</span>URLs <span style="color: #66cc66;">&#40;</span>url<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>N<span style="color: #ff0000;">'www.proseware.com/'</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>Now that we have the data setup let&#8217;s start with the extraction. For the substring function, the first parameter is the string we want to parse from, the next parameter is the starting position to be extracted and the last parameter is the number of characters to extract.</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">DECLARE</span> @first_char nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">DECLARE</span> @second_char nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #993333; font-weight: bold;">SET</span> @first_char <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'.'</span>;<br />
<span style="color: #993333; font-weight: bold;">SET</span> @second_char <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'/'</span>;<br />
<br />
<span style="color: #993333; font-weight: bold;">SELECT</span><br />
<span style="color: #993333; font-weight: bold;">SUBSTRING</span><br />
<span style="color: #66cc66;">&#40;</span><br />
<span style="color: #808080; font-style: italic;">-- column</span><br />
url<br />
<span style="color: #808080; font-style: italic;">-- start position</span><br />
<span style="color: #66cc66;">,</span>CHARINDEX<span style="color: #66cc66;">&#40;</span>@first_char<span style="color: #66cc66;">,</span> url <span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><br />
<span style="color: #808080; font-style: italic;">-- length</span><br />
<span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">CASE</span><br />
<span style="color: #993333; font-weight: bold;">WHEN</span> <span style="color: #66cc66;">&#40;</span>CHARINDEX<span style="color: #66cc66;">&#40;</span>@second_char<span style="color: #66cc66;">,</span> url <span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> CHARINDEX<span style="color: #66cc66;">&#40;</span>@first_char<span style="color: #66cc66;">,</span> url<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">0</span><br />
<span style="color: #993333; font-weight: bold;">THEN</span> CHARINDEX<span style="color: #66cc66;">&#40;</span>@second_char<span style="color: #66cc66;">,</span> url<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> CHARINDEX<span style="color: #66cc66;">&#40;</span>@first_char<span style="color: #66cc66;">,</span> url<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span><br />
<span style="color: #993333; font-weight: bold;">ELSE</span> <span style="color: #cc66cc;">0</span><br />
<span style="color: #993333; font-weight: bold;">END</span><br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> dbo<span style="color: #66cc66;">.</span>URLs u</div></div>
<p>From here we see that the thir parameter is the most difficult to understand. What we are doing is subtracting a single character&#8217;s length from the number of characters to extract. This is because we do not want to include the @second_char in our string. What we have to do however is use a case statement to determine if the @second_char exists. If it does not, then we end up subtracting 1 from 0, leaving us with -1 for the 3rd parameter which is invalid.</p>
<p>And the result:</p>
<p>litwareinc.com<br />
treyresearch.net<br />
adatum.com<br />
northwindtraders.com<br />
wideworldimporters.com<br />
proseware.com</p>
<p>If we want to return just the domain name without the .com or .net, we need to alter this a bit:</p>
<div class="codecolorer-container sql default block style01" style="overflow:auto;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">DECLARE</span> @first_char nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">SET</span> @first_char <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'.'</span>;<br />
<br />
<span style="color: #993333; font-weight: bold;">SELECT</span><br />
<span style="color: #993333; font-weight: bold;">SUBSTRING</span><br />
<span style="color: #66cc66;">&#40;</span><br />
<span style="color: #808080; font-style: italic;">-- column</span><br />
url<br />
<span style="color: #808080; font-style: italic;">-- start position</span><br />
<span style="color: #66cc66;">,</span>CHARINDEX<span style="color: #66cc66;">&#40;</span>@first_char<span style="color: #66cc66;">,</span> url <span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span><br />
<span style="color: #808080; font-style: italic;">-- length</span><br />
<span style="color: #66cc66;">,</span>LEN<span style="color: #66cc66;">&#40;</span>url<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> CHARINDEX<span style="color: #66cc66;">&#40;</span>@first_char<span style="color: #66cc66;">,</span> url<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> CHARINDEX<span style="color: #66cc66;">&#40;</span>@first_char<span style="color: #66cc66;">,</span> REVERSE<span style="color: #66cc66;">&#40;</span>url<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> dbo<span style="color: #66cc66;">.</span>URLs u</div></div>
<p>And the result for this:</p>
<p>litwareinc<br />
treyresearch<br />
adatum<br />
northwindtraders<br />
wideworldimporters<br />
proseware</p>
<img src="http://feeds.feedburner.com/~r/SqlServerPlanet/~4/HuUU73heM2s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://sqlserverplanet.com/tsql/substring-between-two-characters/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://sqlserverplanet.com/tsql/substring-between-two-characters</feedburner:origLink></item>
	</channel>
</rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using apc
Object Caching 1966/1986 objects using apc

 Served from: sqlserverplanet.com @ 2013-05-13 20:36:38 by W3 Total Cache -->
