<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Being Cellfish : SQL</title><link>http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx</link><description>Tags: SQL</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>How to prevent the use of "SELECT *"</title><link>http://blogs.msdn.com/cellfish/archive/2009/11/08/how-to-prevent-the-use-of-select.aspx</link><pubDate>Sun, 08 Nov 2009 16:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9918066</guid><dc:creator>cellfish</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/9918066.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=9918066</wfw:commentRss><description>One &lt;A href="http://blogs.msdn.com/cellfish/archive/2009/08/12/20-tips-to-write-a-good-stored-procedure-is-really-just-12.aspx" mce_href="http://blogs.msdn.com/cellfish/archive/2009/08/12/20-tips-to-write-a-good-stored-procedure-is-really-just-12.aspx"&gt;good tip for writing good SQL&lt;/A&gt; code is to always select the columns you need and never just select everything. Well &lt;A href="http://www.sqlservercentral.com/articles/SELECT+*/68324/" target=_blank mce_href="http://www.sqlservercentral.com/articles/SELECT+*/68324/"&gt;here&lt;/A&gt; is a description on how to actually prevent &lt;EM&gt;SELECT *&lt;/EM&gt; queries (you need to complete a free registration to see the article). The basic idea is to add a dummy column to all your tables and then limit the access to this column using &lt;A href="http://msdn.microsoft.com/en-us/library/ms173724.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/ms173724.aspx"&gt;DENY SELECT ON OBJECT&lt;/A&gt; for that column. Personally I think this is maybe taking it a little bit too far but desperate times calls for desperate measures, right...&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9918066" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>SQL programming mistake #12</title><link>http://blogs.msdn.com/cellfish/archive/2009/09/27/sql-programming-mistake-12.aspx</link><pubDate>Mon, 28 Sep 2009 01:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9900071</guid><dc:creator>cellfish</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/9900071.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=9900071</wfw:commentRss><description>&lt;P&gt;I would like to add another thing to &lt;A href="http://blogs.msdn.com/cellfish/archive/2009/09/13/sql-programming-mistakes.aspx" mce_href="http://blogs.msdn.com/cellfish/archive/2009/09/13/sql-programming-mistakes.aspx"&gt;my previous list&lt;/A&gt;. And that is the mistake of not properly understanding how to use correctly create the WHERE clause. I came to think about this when I read &lt;A href="http://www.sql-server-pro.com/sql-where-clause-optimization.html" target=_blank mce_href="http://www.sql-server-pro.com/sql-where-clause-optimization.html"&gt;this&lt;/A&gt; which also includes a few good tips on how to rewrite your query to work more efficient.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9900071" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>SQL programming mistakes</title><link>http://blogs.msdn.com/cellfish/archive/2009/09/13/sql-programming-mistakes.aspx</link><pubDate>Mon, 14 Sep 2009 07:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9894802</guid><dc:creator>cellfish</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/9894802.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=9894802</wfw:commentRss><description>&lt;P&gt;I recently read &lt;A href="http://www.simple-talk.com/sql/t-sql-programming/ten-common-sql-programming-mistakes/" target=_blank mce_href="http://www.simple-talk.com/sql/t-sql-programming/ten-common-sql-programming-mistakes/"&gt;this comprehensive list with ten common mistakes&lt;/A&gt; done when writing SQL. And I'd like to add number eleven to that list: &lt;EM&gt;using dynamic queries in stored procedures&lt;/EM&gt;. Especially in projects with a lot of stored procedures for parts (or all) of the business logic there is often a few stored procedures with which builds an SQL query in a string and then executes it. These tend to be very difficult to understand and frankly are often only there just in order to return exactly what is needed. Personally I prefer a more naive way to solve queries that just have to be dynamic. There are three things you can do depending on exactly what makes the query complex. Either you can create a single query that returns everything you possibly need and then filter the data afterward. Or you can get what you need in a number of smaller queries. The last alternative I tend to avoid is to move the creation of the SQL out of the stored procedure and keep it as parameterized as possible.&lt;/P&gt;
&lt;P&gt;All in all, in my experience the use of dynamic queries is usually not needed at all. Only with a bad database design may they really be needed,in which case you need to work around it as I described above. But the best way to avoid it is to make sure the design of the database supports the kinds of queries you need to do instead of relying on dynamic queries.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9894802" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>20 tips to write a good stored procedure (is really just 12)</title><link>http://blogs.msdn.com/cellfish/archive/2009/08/12/20-tips-to-write-a-good-stored-procedure-is-really-just-12.aspx</link><pubDate>Wed, 12 Aug 2009 18:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9863859</guid><dc:creator>cellfish</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/9863859.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=9863859</wfw:commentRss><description>&lt;P&gt;A few days ago there was an article with &lt;A href="http://www.sqlservercentral.com/articles/Performance+Tuning/67427/" target=_blank mce_href="http://www.sqlservercentral.com/articles/Performance+Tuning/67427/"&gt;20 tips to write a good stored procedure&lt;/A&gt;&amp;nbsp;(requires free registration to read). The problem is that there are really only&amp;nbsp;12 good tips (and 4 bad and 4 neither good or bad). So let me go over the tips one by one and comment on them:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;EM&gt;Capital letters for keywords and proper indentation&lt;/EM&gt;. With todays code editors with syntax high lighting I don't see why you want to high light keywords with capital letters. The code editor will do that for you. And suggesting proper indentation is not really a tip to write a good stored procedure. It's common (&lt;A href="https://blogs.msdn.com/cellfish/archive/2008/06/12/readable-sql.aspx" mce_href="http://blogs.msdn.com/cellfish/archive/2008/06/12/readable-sql.aspx"&gt;coding&lt;/A&gt;) sense! So I don't think this one counts...&amp;nbsp;&lt;STRONG&gt;Score&lt;/STRONG&gt; (good-not really-bad advice IMHO): &lt;STRONG&gt;0-1-0&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Use SQL-92 syntax for joins&lt;/EM&gt;. If MS SQL server drops support for the old syntax this is good advice. &lt;STRONG&gt;Score: 1-1-0&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Use as few variables as possible&lt;/EM&gt;. The article mentions cache utilization as an argument. Sounds like premature optimization to me. I'd say use as many variables as makes sense to make the code most readable. If that turns out to be a problem, then you optimize. So in general I found this advice to be bad. &lt;STRONG&gt;Score: 1-1-1&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Minimize usage of dynamic queries&lt;/EM&gt;. Kudos to the article to pointing out how to minimize the bad of dynamic queries and I guess technically &lt;EM&gt;minimizing&lt;/EM&gt; could mean &lt;EM&gt;zero&lt;/EM&gt; but that is really the only good advice; don't use dynamic queries. So once again a bad, or at least misleading advice IMHO. &lt;STRONG&gt;Score: 1-1-2&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Use fully qualified names&lt;/EM&gt;. If you don't do this you might end up with some weird behavior so this is a good advice. &lt;STRONG&gt;Score: 2-1-2&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Set NOCOUNT on&lt;/EM&gt;. Good advice: &lt;STRONG&gt;Score: 3-1-2&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Don't use sp_ prefix&lt;/EM&gt;. &lt;STRONG&gt;Score: 4-1-2&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;KEEPFIXED PLAN&lt;/EM&gt;. Learn from &lt;A href="http://technet.microsoft.com/en-us/library/cc966425.aspx" target=_blank mce_href="http://technet.microsoft.com/en-us/library/cc966425.aspx"&gt;this article&lt;/A&gt; and use it correctly. Hard to argue with "learn something and use it right". &lt;STRONG&gt;Score: 5-1-2&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Use select instead of set&lt;/EM&gt;. Once again performance is mentioned as a motivator. However the potential bad side effects of using select rather than set are more important in my opinion. The problem with select is that the variable might not be set if a query returns no rows and the set gives you an error if the select returns more than one row. Read more about it &lt;A href="http://blog.sqlauthority.com/2007/04/27/sql-server-select-vs-set-performance-comparison/" target=_blank mce_href="http://blog.sqlauthority.com/2007/04/27/sql-server-select-vs-set-performance-comparison/"&gt;here&lt;/A&gt;. I'd definitely prefer set over select. &lt;STRONG&gt;Score: 5-1-3&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Compare the right thing in the where clause&lt;/EM&gt;. This advice just confuses me. The article talks about what operators are the fastest and then refers to &lt;A href="http://msdn.microsoft.com/en-us/library/ms190276.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/ms190276.aspx"&gt;this page talking about preference&lt;/A&gt;. Even though the article is confusing on this point the basic idea is correct. For example using IN is generally faster than NOT IN. So I'll call this one a draw. &lt;STRONG&gt;Score: 5-2-3&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Avoid OR in WHERE clause&lt;/EM&gt;. This is good advise for good performance. &lt;STRONG&gt;Score: 6-2-3&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Use CAST over Convert&lt;/EM&gt;. CAST is SQL92 standard. Convert is not. &lt;STRONG&gt;Score: 7-2-3&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Avoid distinct and order by&lt;/EM&gt;. Once again this is common sense. Don't do things you don't need... &lt;STRONG&gt;Score: 7-3-3&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Avoid cursors&lt;/EM&gt;. This falls into the same category as dynamic queries to me. The only good advice is don't use cursors. &lt;STRONG&gt;Score: 7-3-4&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Select only the columns you need&lt;/EM&gt;. Common sense! &lt;STRONG&gt;Score: 7-4-4&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Sub queries vs joins&lt;/EM&gt;. Article lists a few good rule of thumbs. I think you should use whatever is most readable. &lt;STRONG&gt;Score: 8-4-4&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Create table vs select into&lt;/EM&gt;. Article points out important differences. &lt;STRONG&gt;Score: 9-4-4&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Use variables instead of temporary tables&lt;/EM&gt;. &lt;STRONG&gt;Score: 10-4-4&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Use proper indexes&lt;/EM&gt;. &lt;STRONG&gt;Score: 11-4-4&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;Use profiler&lt;/EM&gt;. Many tips in the article suggest you do things to improve performance. But I think doing so before you know you have a problem is a waste of time and resources. So this advice is actually one of the best advices in the article. &lt;STRONG&gt;Score: 12-4-4&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9863859" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Instead of triggers</title><link>http://blogs.msdn.com/cellfish/archive/2009/07/08/instead-of-triggers.aspx</link><pubDate>Thu, 09 Jul 2009 08:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9825722</guid><dc:creator>cellfish</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/9825722.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=9825722</wfw:commentRss><description>&lt;P&gt;I've never been a big fan of triggers in a database since the existence of triggers is easily overlooked. I've also seen the use of triggers in situations where they where used to &lt;EM&gt;fix&lt;/EM&gt; a bad database design. Specifically trigger were used to enforce constraints on other tables. I've also seen triggers used to move data to another table to keep history of records. I think that use is debatable since a stored procedure can be used to do that and the application should use the stored procedure and not do delete and updates directly. So in this case the trigger was used to protect the system from developers not following the application design. This should not really be needed but...&lt;/P&gt;
&lt;P&gt;Anyway, since I've not been working with triggers for quite a while I've never really thought about the options available but today I saw &lt;A href="http://www.sqlservercentral.com/articles/Video/67321/" target=_blank mce_href="http://www.sqlservercentral.com/articles/Video/67321/"&gt;this video&lt;/A&gt; (requires free registration) which covers &lt;A href="http://msdn.microsoft.com/en-us/magazine/cc164032.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/magazine/cc164032.aspx"&gt;instead of triggers&lt;/A&gt;. I think it's a nice feature which simplifies the implementation of &lt;EM&gt;protect-from-developers&lt;/EM&gt; type triggers since you can basically redefine a delete to not do an delete at all and vice versa (if you have the urge to delete data instead of updating it).&lt;/P&gt;
&lt;P&gt;But in my opinion triggers is not the best way to handle things in your application. Use a stored procedure since a trigger easily is forgotten but a used stored procedure is not. Also it is easier to follow the flow in a stored procedure over trigger execution. And if you have a nice stored procedure everybody should use but your developer keep screwing things up by using inserts, updates and deletes directly in the database then I would consider adding a trigger preventing direct use. This can be hard since the stored procedure it self will cause the trigger to execute but in my experience the stored procedure typically updates only one record at the time so an easy way to try to find developer "abuse" is to prevent updates of more than one row at the time. That has been enough for me so far.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Preemptive comment response:&lt;/EM&gt;&lt;/STRONG&gt; &lt;EM&gt;I know instead of triggers is nothing new and has been available for some time but I've just not been interested in triggers for the last 9 years so please forgive me...&lt;/EM&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9825722" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Random SQL</title><link>http://blogs.msdn.com/cellfish/archive/2009/06/09/random-sql.aspx</link><pubDate>Wed, 10 Jun 2009 08:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9723381</guid><dc:creator>cellfish</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/9723381.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=9723381</wfw:commentRss><description>&lt;P&gt;I must say that I have never used the random functionality in SQL more than once in my life and that was not for work, it was in a hobby project. Never the less, I find &lt;A href="http://www.sqlservercentral.com/articles/Random+Numbers/66718/" target=_blank mce_href="http://www.sqlservercentral.com/articles/Random+Numbers/66718/"&gt;this article&lt;/A&gt; (free registration required) on how the RAND function works and is seeded quite interesting.&lt;/P&gt;
&lt;P&gt;A summary of the article: You want a random number for each row in a result to do some kind of filtering. The problem is that the RAND function by default uses date/time to seed the random so in a query you don't really get any different random numbers. So you need a nifty way to seed the random for each row. The article proposes: &lt;FONT face=Courier&gt;RAND(Checksum(Newid()))&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The use of &lt;EM&gt;Newid&lt;/EM&gt; in the link above might however not be practical for performance reasons. If you want to try some other ways to produce random you can find more alternatives &lt;A href="http://msdn.microsoft.com/en-us/library/aa175776(SQL.80).aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/aa175776(SQL.80).aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9723381" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>SQL Unit Testing</title><link>http://blogs.msdn.com/cellfish/archive/2009/05/04/sql-unit-testing.aspx</link><pubDate>Tue, 05 May 2009 06:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9587392</guid><dc:creator>cellfish</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/9587392.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=9587392</wfw:commentRss><description>&lt;P&gt;Thought it was time to combine my old favorite subject (SQL) with a new interest (TDD). So how do you test drive your SQL? I think the first answer is &lt;EM&gt;you don't&lt;/EM&gt;. The database is typically something you want to fake anyway since setting up and accessing the database is to slow when you want rapid feedback. Nowadays when things like NHibernate are popular I think most people don't write much SQL anyway so there is no need to test drive the creation of SQL queries or stored procedures. But there was a time when many applications kept a lot of logic in the stored procedures and in those systems it might make some sense. Also we have the fact that the database needs to be created some way. Why not test drive the database schema?&lt;/P&gt;
&lt;P&gt;So even though this might not be the hottest topic on the block, what alternatives do we have? First of all we have &lt;A href="http://sqlunit.sourceforge.net/" target=_blank mce_href="http://sqlunit.sourceforge.net/"&gt;SQLUnit&lt;/A&gt;. This project does not seem to have been updated for several years. Guess that is because we don't put all application logic in stored procedures any more. But it is at least an attempt to create a unit test framework for SQL. But why use the same language for the tests as the implementation? Some people think this is OK but I think there is also a danger in doing so. Switching languages typically makes you do small stupid mistakes you don't do if you stick to one language. But sometimes it might still be worth it. For example I'd much rather use any .Net based unit test framework over SQLUnit and an example of how that looks can be found &lt;A href="http://www.sqlservercentral.com/articles/System+Development+Life+Cycle/66133/" target=_blank mce_href="http://www.sqlservercentral.com/articles/System+Development+Life+Cycle/66133/"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Then there is of course the option of not using any framework at all. Creating your own framework may be the most efficient way of doing things and&amp;nbsp;an example of database creation in a test driven manner without any fancy frameworks&amp;nbsp;can be found &lt;A href="http://www.sqlservercentral.com/articles/Testing/66553/" target=_blank mce_href="http://www.sqlservercentral.com/articles/Testing/66553/"&gt;here&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9587392" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/TDD/default.aspx">TDD</category><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Becoming a good programmer takes time</title><link>http://blogs.msdn.com/cellfish/archive/2009/03/30/becoming-a-good-programmer-takes-time.aspx</link><pubDate>Tue, 31 Mar 2009 07:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9521411</guid><dc:creator>cellfish</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/9521411.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=9521411</wfw:commentRss><description>&lt;P&gt;By now you've hopefully heard about &lt;A href="http://elegantcode.com/2009/01/11/ethics-in-software-development-craftsmanship-over-crap/" target=_blank mce_href="http://elegantcode.com/2009/01/11/ethics-in-software-development-craftsmanship-over-crap/"&gt;craftsmanship over crap&lt;/A&gt; and the other day I heard about a research report where they concluded that university students majoring in engineering have problems translating theory into practice (&lt;A href="http://www2.unt.se/pages/1,1826,MC=77-AV_ID=887110,00.html" target=_blank mce_href="http://www2.unt.se/pages/1,1826,MC=77-AV_ID=887110,00.html"&gt;article in Swedish&lt;/A&gt;). Education is not the key to becoming a good programmer. It is a catalyst that will help you get better faster. But it will always take time to become a good developer. But to become a great developer you must never stop learning. So why am I talking about this? Well, it's because &lt;A href="http://www.mssqltips.com/tip.asp?tip=1711" target=_blank mce_href="http://www.mssqltips.com/tip.asp?tip=1711"&gt;something I read&lt;/A&gt; that made me real sad: &lt;/P&gt;
&lt;P align=center&gt;"&lt;EM&gt;Benefits: [...] Through less lines of code you can get more done.&lt;/EM&gt;"&lt;/P&gt;
&lt;P&gt;And this is not the only example from the DBA world I've seen. First of all the statement is false. Through less lines of code you get the same work done. But less is not more. Just reducing the number of code lines&amp;nbsp;for the sake of reducing lines generally result in code more difficult to understand and&amp;nbsp;maintain.&amp;nbsp;For some reason being a DBA and being a developer seams like a rare&amp;nbsp;combination. I've worked with a few DBAs that worked like developers mainly because they were developers that had an interest in databases and then turned into DBAs. And what do I mean with "working as a developer"? Being lazy, i.e. automating as much as possible and making sure they can reuse stuff without duplicating code. Maybe even having a number of automated tests. And having at least basic understanding of what makes code easy to understand and easy to maintain.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9521411" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/Agile/default.aspx">Agile</category><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category><category domain="http://blogs.msdn.com/cellfish/archive/tags/Development/default.aspx">Development</category></item><item><title>Joining with previous and/or next row</title><link>http://blogs.msdn.com/cellfish/archive/2009/01/23/joining-with-previous-and-or-next-row.aspx</link><pubDate>Fri, 23 Jan 2009 12:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9372305</guid><dc:creator>cellfish</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/9372305.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=9372305</wfw:commentRss><description>&lt;P&gt;Sometimes in my career I've had to create SQL queries that uses data from the previous and/or next row in the result. That is, something I wont on row &lt;EM&gt;X&lt;/EM&gt; depends on row &lt;EM&gt;X&lt;/EM&gt;-1 or &lt;EM&gt;X&lt;/EM&gt;+1 in the result. Most of the time I have not done this in the SQL query itself but rather in worked on the result but a few times I just had to do it in SQL. This leads to a construction with sub-selects so the resulting query is both hard to read and understand and it is slow due to a large number of sub-selects.&lt;/P&gt;
&lt;P&gt;This morning I read a &lt;A class="" href="http://www.sqlservercentral.com/articles/T-SQL/62159/" target=_blank mce_href="http://www.sqlservercentral.com/articles/T-SQL/62159/"&gt;short article describing the use of row_number method introduced in SQL Server 2005&lt;/A&gt;. Worth reading if you need to solve similar problem since it removes the need for sub-selects. At least the same amount of sub-selects. To read the article you have to register with the site but it is free and you don't get spammed.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9372305" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Testdriven Database development</title><link>http://blogs.msdn.com/cellfish/archive/2008/10/29/testdriven-database-development.aspx</link><pubDate>Wed, 29 Oct 2008 13:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9022021</guid><dc:creator>cellfish</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/9022021.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=9022021</wfw:commentRss><description>&lt;P&gt;I recently found this interesting article on &lt;A class="" href="http://www.sqlservercentral.com/articles/TSQLUnit/64357/" target=_blank mce_href="http://www.sqlservercentral.com/articles/TSQLUnit/64357/"&gt;TDD when using T-SQL&lt;/A&gt;. It describes how a new unit test framework form T-SQL, called &lt;A class="" href="http://tsqlunit.sourceforge.net/" target=_blank mce_href="http://tsqlunit.sourceforge.net/"&gt;tsqlunit&lt;/A&gt;, works. Even though it feels like the framework lacks a lot of the fancy asserts and that is probably because of limitations in T-SQL I still welcome it as a new addition in the family of unit test frameworks. Definitely something I'll use next time I have to do T-SQL work.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9022021" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/TDD/default.aspx">TDD</category><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Be suspicious to DAL frameworks</title><link>http://blogs.msdn.com/cellfish/archive/2008/07/16/be-suspicious-to-dal-frameworks.aspx</link><pubDate>Wed, 16 Jul 2008 23:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8740081</guid><dc:creator>cellfish</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/8740081.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=8740081</wfw:commentRss><description>&lt;P&gt;I've always been suspicious to SQL queries that are automagically generated by some framework. And when I read &lt;A class="" title="Lengthy SQL Server Queries Will Consume Your CPU" href="http://www.mssqltips.com/tip.asp?tip=1500" target=_blank mce_href="http://www.mssqltips.com/tip.asp?tip=1500"&gt;this article on lengthy SQL queries&lt;/A&gt; it certainly was another gallon of gasoline on the fire. Sure premature optimization is the root of all evil and all that but there is also another important rule in software development; Don't do obviously stupid things. If you want to use a framework for data access, which is very common for productivity reasons, be sure to design your software so it is easy to replace the generic framework with something specific.&lt;/P&gt;
&lt;P&gt;If you on the other hand end up with really large queries when you write the queries your self (I'm a &lt;EM&gt;stored procedure&lt;/EM&gt; guy so&amp;nbsp;I have a hard time even&amp;nbsp;making up what kind of SQL query would end up being that large), but it is obvious what the solution is - Stored procedure.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8740081" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Readable SQL</title><link>http://blogs.msdn.com/cellfish/archive/2008/06/12/readable-sql.aspx</link><pubDate>Thu, 12 Jun 2008 09:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8590349</guid><dc:creator>cellfish</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/8590349.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=8590349</wfw:commentRss><description>&lt;P&gt;I read this article on &lt;A class="" href="http://www.simple-talk.com/sql/t-sql-programming/sql-code-layout-and-beautification/" target=_blank mce_href="http://www.simple-talk.com/sql/t-sql-programming/sql-code-layout-and-beautification/"&gt;SQL Code Layout and Beautification&lt;/A&gt; and can only agree with the author that other people's SQL often is hard to understand because I'm so used to how I write my SQL statements. One of the links is to an &lt;A class="" title="Instant SQL Formatter" href="http://www.wangz.net/cgi-bin/pp/gsqlparser/sqlpp/sqlformat.tpl" target=_blank mce_href="http://www.wangz.net/cgi-bin/pp/gsqlparser/sqlpp/sqlformat.tpl"&gt;on-line tool&lt;/A&gt; formatting your SQL according to a number of rules. I was happy to find that my way of writing SQL was supported:&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;SELECT a,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;b,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;c AS d&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;FROM x,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;y,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;z AS w&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;WHERE a = 2&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND b IN (3,4,7)&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Arial"&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-FAMILY: Arial"&gt;And another example:&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Arial"&gt;&lt;/P&gt;
&lt;P style="FONT-SIZE: 9pt; MARGIN: 0in"&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;SELECT obj.run,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;obj.camcol,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;STR(obj.field,3) AS field,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;STR(obj.rowc,6,1) AS rowc,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;STR(obj.colc,6,1) AS colc,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;STR(dbo.FOBJ(obj.objid),4) AS id,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;STR(obj.psfmag_g - 0 * obj.extinction_g,6,3) AS g,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;STR(obj.psfmag_r - 0 * obj.extinction_r,6,3) AS r,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;STR(obj.psfmag_i - 0 * obj.extinction_i,6,3) AS i,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;STR(obj.psfmag_z - 0 * obj.extinction_z,6,3) AS z,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;STR(60 * distance,3,1) AS d,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;dbo.FFIELD(neighborobjid) AS nfield,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;STR(dbo.FOBJ(neighborobjid),4) AS nid,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;'new' AS 'new'&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;FROM (SELECT obj.objid,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;run,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;camcol,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;field,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;rowc,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;colc,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;psfmag_u,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;extinction_u,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;psfmag_g,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;extinction_g,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;psfmag_r,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;extinction_r,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;psfmag_i,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;extinction_i,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;psfmag_z,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;extinction_z,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;nn.neighborobjid,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;nn.distance&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;FROM photoobj AS obj&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;JOIN neighbors AS nn&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ON obj.objid = nn.objid&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WHERE 60 * nn.distance BETWEEN 0 AND 15&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND nn.mode = 1&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND nn.neighbormode = 1&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND run = 756&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND camcol = 5&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND obj.TYPE = 6&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND (obj.flags &amp;amp; 0x40006) = 0&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND nchild = 0&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND obj.psfmag_i &amp;lt; 20&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND (g - r BETWEEN 0.3 AND 1.1&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND r - i BETWEEN -0.1 AND 0.6)) AS obj&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;JOIN photoobj AS nobj&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ON nobj.objid = obj.neighborobjid&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WHERE nobj.run = obj.run&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND (ABS(obj.psfmag_g - nobj.psfmag_g) &amp;lt; 0.5&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;OR ABS(obj.psfmag_r - nobj.psfmag_r) &amp;lt; 0.5&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;OR ABS(obj.psfmag_i - nobj.psfmag_i) &amp;lt; 0.5)&lt;BR&gt;ORDER BY obj.run,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;obj.camcol,&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;obj.field&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Arial"&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8590349" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>SQL crosswords</title><link>http://blogs.msdn.com/cellfish/archive/2008/05/29/sql-crosswords.aspx</link><pubDate>Thu, 29 May 2008 11:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8557443</guid><dc:creator>cellfish</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/8557443.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=8557443</wfw:commentRss><description>&lt;P&gt;I don't know what's worse; making &lt;A class="" title="SQL Crosswords" href="http://www.sqlservercentral.com/articles/crossword/" target=_blank mce_href="http://www.sqlservercentral.com/articles/crossword/"&gt;crosswords with only SQL related questions&lt;/A&gt;&amp;nbsp;(requires free registration to access)&amp;nbsp;or actually trying to solve the same. This is one of many thing that currently puzzles me. One other thing that also scares me is that I get annoyed when I cannot solve these crosswords right away...&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8557443" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Stored Procedures and data sharing</title><link>http://blogs.msdn.com/cellfish/archive/2008/05/15/stored-procedures-and-data-sharing.aspx</link><pubDate>Thu, 15 May 2008 15:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8507828</guid><dc:creator>cellfish</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/8507828.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=8507828</wfw:commentRss><description>&lt;P&gt;In my career I've worked with stored procedures in a way I think many people never do. For example I've worked on projects where both the data access and the business logic have been placed in the database in the form of stored procedures. Not quite your standard three-tier solution but it works quite well when the people with all the business knowledge also knows a lot about databases and SQL but less about anything else. Obviously this involves a lot of data being passed around between stored procedures.&lt;/P&gt;
&lt;P&gt;This means that I've seen a few different ways to pass data around and I'm sad I didn't find &lt;A class="" title="How to Share Data Between Stored Procedures" href="http://www.sommarskog.se/share_data.html" target=_blank mce_href="http://www.sommarskog.se/share_data.html"&gt;this page&lt;/A&gt; earlier. Sommerskog's description of the pros and cons with different approaches would definitely have saved be some time. Over the years I've tried output parameters, cursors, tables, user defined functions and the table data type. And as usual the latest technology is not the best for all situations but may simplify things that was cumbersome to accomplish before.&lt;/P&gt;
&lt;P&gt;And some times the simplest solution is the most brilliant.&amp;nbsp;A common problem I've faced is that I have one SP (stored procedure) returning some data as a select statement. Later on I want to reuse that SP in several other SPs. Previously I've been using functions or temporary tables to do this which both have their disadvantages, rewriting the original SP being one. But with the &lt;EM&gt;insert-exec&lt;/EM&gt; pattern I can reuse the SP right away. I'm embarrassed I didn't think of that before. Let's say it is so obvious you don't think about it. In the same way you forget to look for your glasses on your nose. It's no silver bullet and it wouldn't have solved all my problems but it is yet another tool to use.&lt;/P&gt;
&lt;P&gt;So if you're working with databases you should definitely take a closer look at what &lt;A class="" title="How to Share Data Between Stored Procedures" href="http://www.sommarskog.se/share_data.html" target=_blank mce_href="http://www.sommarskog.se/share_data.html"&gt;Sommerskog is writing&lt;/A&gt; because knowing things like that will definitely make your life easier. And there is no point in learning it the hard way by your self.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8507828" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item><item><title>UPSERT in SQL server 2008</title><link>http://blogs.msdn.com/cellfish/archive/2008/04/29/upsert-in-sql-server-2008.aspx</link><pubDate>Tue, 29 Apr 2008 09:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8436611</guid><dc:creator>cellfish</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/cellfish/comments/8436611.aspx</comments><wfw:commentRss>http://blogs.msdn.com/cellfish/commentrss.aspx?PostID=8436611</wfw:commentRss><description>I recently read this &lt;A class="" href="http://www.databasejournal.com/features/mssql/article.php/3739131" target=_blank mce_href="http://www.databasejournal.com/features/mssql/article.php/3739131"&gt;article on&amp;nbsp;upsert functionality&amp;nbsp;in SQL server 2008&lt;/A&gt;. I thought that the SQL server team finally had come to theri senses and added functionality similar to &lt;A class="" href="http://dev.mysql.com/doc/refman/6.0/en/replace.html" target=_blank mce_href="http://dev.mysql.com/doc/refman/6.0/en/replace.html"&gt;replace in MySQL&lt;/A&gt;, something that have been available in MySQL for ages. But no. The article describes a way to use the new merge command in order to perform an "upsert". 
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;An upsert is an operation where rows in the database are updated if they exists and inserted if they don't. This has been available as a replace statement in MySQL for quite some time. At first glance the merge seems much more cumbersome to use than the replace, but don't be fooled by this. One problem I've had with the &lt;EM&gt;replace&lt;/EM&gt; command is knowing exactly what rows will be updated and which will be added. Especially when updating things that are part of&amp;nbsp;a multi-column&amp;nbsp;primary key. The merge however is really more clear in what it actually does and you have full control of what you update and what you insert.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8436611" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/cellfish/archive/tags/SQL/default.aspx">SQL</category></item></channel></rss>