<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.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>Search results matching tag 'Defensive programming'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=Defensive+programming&amp;orTags=0</link><description>Search results matching tag 'Defensive programming'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>The client code that handles timeouts</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2013/01/10/the-client-code-that-handles-timeouts.aspx</link><pubDate>Thu, 10 Jan 2013 21:05:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:47107</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>&lt;p&gt;After timeouts we need to make sure that active transactions, if any, are rolled back. All timeout handling must be done on the client. This post provides the implementation and unit tests.&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Implementation&lt;/b&gt;&lt;/u&gt; &lt;/p&gt;&lt;p&gt;The following class extends SqlCommand and rolls back active transactions after timeouts:&lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;public static class &lt;/span&gt;&lt;span style="color:black;"&gt;SqlCommandExtentions&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;public static void &lt;/span&gt;&lt;span style="color:black;"&gt;ExecuteNonQueryWithErrorHandling&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;this &lt;/span&gt;&lt;span style="color:black;"&gt;SqlCommand command&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;try&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;command.ExecuteNonQuery&lt;/span&gt;&lt;span style="color:gray;"&gt;();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;catch &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SqlException e&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HandleSqlException&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;command&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;e&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;throw&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;public static &lt;/span&gt;&lt;span style="color:black;"&gt;SqlDataReader ExecuteReaderWithErrorHandling&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;this &lt;/span&gt;&lt;span style="color:black;"&gt;SqlCommand command&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;try&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;return &lt;/span&gt;&lt;span style="color:black;"&gt;command.ExecuteReader&lt;/span&gt;&lt;span style="color:gray;"&gt;();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;catch &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SqlException e&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HandleSqlException&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;command&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;e&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;throw&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;private static void &lt;/span&gt;&lt;span style="color:black;"&gt;HandleSqlException&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SqlCommand command&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;SqlException e&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;const int &lt;/span&gt;&lt;span style="color:black;"&gt;timeoutCode &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;if &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;e.Number &lt;/span&gt;&lt;span style="color:gray;"&gt;!= &lt;/span&gt;&lt;span style="color:black;"&gt;timeoutCode&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;var rollbackCommand &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;command.Connection.CreateCommand&lt;/span&gt;&lt;span style="color:gray;"&gt;();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;rollbackCommand.CommandText &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:darkred;"&gt;"IF @@TRANCOUNT &amp;gt; 0 BEGIN ; ROLLBACK ;&amp;nbsp;&amp;nbsp;END ;"&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;rollbackCommand.CommandType &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;CommandType.Text&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;rollbackCommand.CommandTimeout &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;0&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;rollbackCommand.ExecuteNonQueryWithErrorHandling&lt;/span&gt;&lt;span style="color:gray;"&gt;();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/code&gt;
                &amp;nbsp;&amp;nbsp;
              &lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Testing&lt;/b&gt;&lt;/u&gt; &lt;/p&gt;&lt;p&gt;We need to unit test the two methods. For each one, we need to test the following four cases:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Command succeeds&amp;nbsp;&lt;/li&gt;&lt;li&gt;Command blows up with some other error, which must not be caught by our handling&lt;/li&gt;&lt;li&gt;Command times out, active transaction&lt;/li&gt;&lt;li&gt;Command times out, no active transaction&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The following tests cover these four cases for ExecuteReader. The other four tests are very similar, so there is no need to post them.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;code style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Test]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;public void &lt;/span&gt;&lt;span style="color:black;"&gt;ExecuteReaderWithErrorHandling_WorksOnSuccess&lt;/span&gt;&lt;span style="color:gray;"&gt;()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;using &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;var dr &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;ExecuteReaderWithErrorHandling&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;sqlConn&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:darkred;"&gt;"SELECT 1 AS n"&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert.IsTrue&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;dr.Read&lt;/span&gt;&lt;span style="color:gray;"&gt;());&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;Assert.AreEqual&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;dr.GetInt32&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;0&lt;/span&gt;&lt;span style="color:gray;"&gt;));&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Test]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;public void &lt;/span&gt;&lt;span style="color:black;"&gt;ExecuteReaderWithErrorHandling_HandlesTimeout_ActiveTransaction&lt;/span&gt;&lt;span style="color:gray;"&gt;()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;try&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ExecuteReaderWithErrorHandling&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;sqlConn&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:darkred;"&gt;"EXEC dbo.IWillTimeOut"&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;timeoutInSeconds: 1&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;Assert.Fail&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:darkred;"&gt;"Must throw exception"&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;catch&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SqlException e&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert.AreEqual&lt;/span&gt;&lt;span style="color:gray;"&gt;(-&lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;e.Number&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;VerifyNoOpenTransaction&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;sqlConn&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Test]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;public void &lt;/span&gt;&lt;span style="color:black;"&gt;ExecuteReaderWithErrorHandling_HandlesTimeout&lt;/span&gt;&lt;/code&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;_NoActiveTransaction&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;try&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ExecuteReaderWithErrorHandling&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;sqlConn&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:darkred;"&gt;"EXEC dbo.IWillTimeOutWithoutTransaction"&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;timeoutInSeconds: 1&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;Assert.Fail&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:darkred;"&gt;"Must throw exception"&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;catch &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SqlException e&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert.AreEqual&lt;/span&gt;&lt;span style="color:gray;"&gt;(-&lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;e.Number&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;VerifyNoOpenTransaction&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;sqlConn&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Test]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;public void &lt;/span&gt;&lt;span style="color:black;"&gt;ExecuteReaderWithErrorHandling_ThrowsOtherExceptions&lt;/span&gt;&lt;span style="color:gray;"&gt;()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;try&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ExecuteReaderWithErrorHandling&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;sqlConn&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:darkred;"&gt;"EXEC dbo.IThrowError8134"&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;Assert.Fail&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:darkred;"&gt;"Must throw exception"&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;catch &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SqlException e&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert.AreEqual&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;8134&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;e.Number&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;VerifyNoOpenTransaction&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;sqlConn&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;These unit tests utilize a few database objects:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;code style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;CREATE FUNCTION &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.IWillCompleteInNSeconds &lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:#434343;"&gt;@NumSeconds &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;RETURNS INT&lt;br&gt;AS &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BEGIN &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;DECLARE &lt;/span&gt;&lt;span style="color:#434343;"&gt;@StartTime &lt;/span&gt;&lt;span style="color:blue;"&gt;DATETIME &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Toggle &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@StartTime &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:magenta;"&gt;GETDATE&lt;/span&gt;&lt;span style="color:gray;"&gt;() ,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Toggle &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;1 &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;WHILE &lt;/span&gt;&lt;span style="color:magenta;"&gt;DATEDIFF&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SECOND&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:#434343;"&gt;@StartTime&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:magenta;"&gt;GETDATE&lt;/span&gt;&lt;span style="color:gray;"&gt;()) &amp;lt; &lt;/span&gt;&lt;span style="color:#434343;"&gt;@NumSeconds &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;BEGIN &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span style="color:#434343;"&gt;@Toggle &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;1 &lt;/span&gt;&lt;span style="color:gray;"&gt;- &lt;/span&gt;&lt;span style="color:#434343;"&gt;@Toggle &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;END &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;RETURN &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;END &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;CREATE PROCEDURE &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.IWillTimeOut&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;br&gt;&amp;nbsp;&amp;nbsp;BEGIN &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;BEGIN TRANSACTION &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.IWillCompleteInNSeconds&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:black;"&gt;5 &lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;SomeNumber &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;COMMIT &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;END &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;CREATE PROCEDURE &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.IWillTimeOutWithoutTransaction&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;br&gt;&amp;nbsp;&amp;nbsp;BEGIN &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;WAITFOR &lt;/span&gt;&lt;span style="color:black;"&gt;DELAY &lt;/span&gt;&lt;span style="color:red;"&gt;'00:00:05' &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;END &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;CREATE PROCEDURE &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.IThrowError8134&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;AS&lt;br&gt;BEGIN &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET XACT_ABORT ON &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;DECLARE &lt;/span&gt;&lt;span style="color:#434343;"&gt;@i &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:#434343;"&gt;@i &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;/&lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;1 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;n&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;END &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;
                &amp;nbsp;
              &lt;/p&gt;</description></item><item><title>Yet another use of OUTER APPLY in defensive programming</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2012/06/06/yet-another-use-of-outer-apply-in-defensive-programming.aspx</link><pubDate>Wed, 06 Jun 2012 21:58:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43779</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>
&lt;p&gt;When a SELECT is used to populate variables from a subquery, it fails to change them if the subquery returns nothing - and that can lead to subtle bugs. We shall use OUTER APPLY to eliminate this problem. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;b&gt;Prerequisites&lt;/b&gt;&lt;/u&gt; &lt;br&gt;&lt;/p&gt;
&lt;p&gt;All we need is the following mock function that imitates a subquery:&lt;/p&gt;
&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;CREATE FUNCTION &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.BoxById &lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span&gt;@BoxId &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;RETURNS TABLE&lt;br&gt;AS RETURN&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta;"&gt;CAST&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS INT&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;[Length] &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta;"&gt;CAST&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;2 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS INT&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;[Width] &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta;"&gt;CAST&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;3 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS INT&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;[Height]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;@BoxId &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;) ;&lt;/span&gt;&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;Let us assume that this subquery is slow and we do not want to run it more than absolutely necessary. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;b&gt;Short recap on SET vs. SELECT&lt;/b&gt;&lt;/u&gt; &lt;br&gt;&lt;/p&gt;
&lt;p&gt;The following approach uses SET to populate variables:&lt;/p&gt;
&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;DECLARE &lt;/span&gt;&lt;span style="color:#434343;"&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@BoxId &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;0&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span style="color:#434343;"&gt;@BoxId &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;1 &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span style="color:#434343;"&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;[Length]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.BoxById&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:#434343;"&gt;@BoxId&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;) ;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span style="color:#434343;"&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;[Width]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.BoxById&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:#434343;"&gt;@BoxId&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) ;&lt;/span&gt;&lt;/code&gt; &lt;br&gt;&lt;/p&gt;
&lt;p&gt;This script will always change the values of variables, even when the subquery returns nothing, which is good. However, it runs a possibly slow/expensive subquery twice. Also it duplicates code. We want to avoid both these disadvantages.&lt;/p&gt;
&lt;p&gt;The following script uses SELECT, it has no duplication, and it runs the subquery only once:&lt;/p&gt;
&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;DECLARE &lt;/span&gt;&lt;span&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;@BoxId &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;0&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span&gt;@BoxId &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;1 &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;[Length] &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;[Width]&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.BoxById&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span&gt;@BoxId&lt;/span&gt;&lt;span style="color:gray;"&gt;) ;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;[Length] &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;[Width] &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This code looks cleaner and performs better, but it has the following problem: if the subquery returns nothing, the variables are not changed. You can change @BoxId from 1 to any other number, rerun the script, and see for yourself.&lt;/p&gt;
&lt;p&gt;When the variables are not changed by an assignment, that can lead to subtle bugs,&amp;nbsp; &lt;br&gt;&lt;/p&gt;&lt;p&gt; &lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/23/when-you-process-your-rows-one-by-one-avoid-infinite-loops.aspx"&gt;like this one.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;To avoid this vulnerability, we can use OUTER APPLY, as follows:&lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;DECLARE &lt;/span&gt;&lt;span style="color:#434343;"&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@BoxId &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;0 &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;0&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span style="color:#434343;"&gt;@BoxId &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2 &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;[Length] &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;[Width]&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;1 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;PlaceHolder&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;AlwaysOneRow&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;OUTER &lt;/span&gt;&lt;span style="color:black;"&gt;APPLY dbo.BoxById&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:#434343;"&gt;@BoxId&lt;/span&gt;&lt;span style="color:gray;"&gt;) ;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Length &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;[Length] &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@Width &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;[Width] &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt; &lt;br&gt;&lt;/p&gt;As a result, we still have no duplication, run an expensive subquery only once, and also always change the variables, making the code less vulnerable to bugs.</description></item><item><title>&amp;quot;Trusted&amp;quot; Foreign Keys Allow Orphans, Reject Valid Child Rows</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2011/10/17/trusted-foreign-keys-allow-orphans-reject-valid-child-rows.aspx</link><pubDate>Mon, 17 Oct 2011 17:15:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:39107</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>&lt;p&gt;In SQL 2008 R2, MERGE does not implement foreign keys properly. I will show both false negatives (valid rows are rejected) and false positives - orphan rows that are allowed to save.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;b&gt;False Negatives&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The following tables implement a very common type/subtype pattern:&lt;/p&gt;
&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Vehicles&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;ID &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;NOT NULL, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;[Type] &lt;/span&gt;&lt;span style="color:blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;5&lt;/span&gt;&lt;span style="color:gray;"&gt;) NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;Vehicles_PK &lt;/span&gt;&lt;span style="color:blue;"&gt;PRIMARY KEY&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID&lt;/span&gt;&lt;span style="color:gray;"&gt;),&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;Vehicles_UNQ_ID_Type &lt;/span&gt;&lt;span style="color:blue;"&gt;UNIQUE&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[Type]&lt;/span&gt;&lt;span style="color:gray;"&gt;),&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;Vehicles_CHK_ValidTypes &lt;/span&gt;&lt;span style="color:blue;"&gt;CHECK&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;[Type] &lt;/span&gt;&lt;span style="color:blue;"&gt;IN &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'Car'&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Truck'&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;br&gt;);&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Cars&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;NOT NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;[Type] &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:magenta;"&gt;CAST&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:red;"&gt;'Car' &lt;/span&gt;&lt;span style="color:blue;"&gt;AS VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;5&lt;/span&gt;&lt;span style="color:gray;"&gt;)) &lt;/span&gt;&lt;span style="color:black;"&gt;PERSISTED&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;OtherData &lt;/span&gt;&lt;span style="color:blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;10&lt;/span&gt;&lt;span style="color:gray;"&gt;) NULL,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;Cars_PK &lt;/span&gt;&lt;span style="color:blue;"&gt;PRIMARY KEY&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID&lt;/span&gt;&lt;span style="color:gray;"&gt;),&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;Cars_FK_Vehicles &lt;/span&gt;&lt;span style="color:blue;"&gt;FOREIGN KEY&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[Type]&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;REFERENCES &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Vehicles&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[Type]&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;);&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;-- adding parent rows&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Vehicles&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[Type]&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Car'&lt;/span&gt;&lt;span style="color:gray;"&gt;),&lt;br&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Truck'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;
                The following INSERT succeeds:&lt;/p&gt;
&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Cars&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;OtherData&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Some Data'&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;DELETE FROM &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Cars&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;MERGE should be able to add the same row, but it fails:&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &lt;code style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;MERGE dbo.Cars &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;TargetTable&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;USING &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;1 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;ID &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:red;"&gt;'Some Data' &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;OtherData&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;SourceData&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;ON&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;SourceData.ID &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;TargetTable.ID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color:gray;"&gt;NOT &lt;/span&gt;&lt;span style="color:black;"&gt;MATCHED &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;THEN INSERT &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;OtherData&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SourceData.ID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;SourceData.OtherData&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Msg 547&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:blue;"&gt;LEVEL &lt;/span&gt;&lt;span style="color:black;"&gt;16&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;State 0&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;Line 1&lt;br&gt;The MERGE statement conflicted &lt;/span&gt;&lt;span style="color:blue;"&gt;WITH &lt;/span&gt;&lt;span style="color:black;"&gt;the &lt;/span&gt;&lt;span style="color:blue;"&gt;FOREIGN KEY CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;"Cars_FK_Vehicles" The conflict occurred &lt;/span&gt;&lt;span style="color:blue;"&gt;IN DATABASE &lt;/span&gt;&lt;span style="color:black;"&gt;"Test" &lt;/span&gt;&lt;span style="color:blue;"&gt;TABLE &lt;/span&gt;&lt;span style="color:black;"&gt;"dbo.Vehicles"&lt;br&gt;The statement has been terminated.&lt;br&gt;&lt;/span&gt;&lt;/code&gt;
              &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;b&gt;False Positives&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Martin Smith has posted this repro on stackoverflow, in response to my scenario described above. This script successfully adds an orphan row into dbo.Cars table:&lt;/p&gt;
&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;ALTER TABLE &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Vehicles&lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;DROP CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;Vehicles_CHK_ValidTypes &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT INTO &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Vehicles&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;[Type]&lt;/span&gt;&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;&lt;span style="color:black;"&gt;3&lt;/span&gt;&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;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;MERGE dbo.Cars &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;TargetTable&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;USING &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;3 &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;ID &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:red;"&gt;'Some Data' &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;OtherData&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;/span&gt;&lt;span style="color:black;"&gt;SourceData&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;ON&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;SourceData.ID &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;TargetTable.ID&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;WHEN &lt;/span&gt;&lt;span style="color:gray;"&gt;NOT &lt;/span&gt;&lt;span style="color:black;"&gt;MATCHED &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;THEN INSERT &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;ID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;OtherData&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SourceData.ID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;SourceData.OtherData&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;-- the FK constraint is enabled and trusted&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;is_disabled&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:black;"&gt;is_not_trusted &lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;sys.foreign_keys &lt;br&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE &lt;/span&gt;&lt;span style="color:black;"&gt;name &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:red;"&gt;'Cars_FK_Vehicles'&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;-- yet we have an orphan row&lt;br&gt;&lt;/span&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;&lt;span style="color:black;"&gt;dbo.Cars&lt;br&gt;&lt;/span&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;&lt;span style="color:black;"&gt;dbo.Vehicles&lt;br&gt;GO&lt;br&gt;&lt;br&gt;is_disabled is_not_trusted&lt;br&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;----------- --------------&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1 row&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;s&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:black;"&gt;affected&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;ID&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;TYPE&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;OtherData&lt;br&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;----------- ----- ----------&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Car&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;SOME &lt;/span&gt;&lt;span style="color:black;"&gt;Data&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1 row&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;s&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:black;"&gt;affected&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;ID&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;TYPE&lt;br&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;----------- -----&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Car&lt;br&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Truck&lt;br&gt;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;u&gt;&lt;b&gt;Conclusion&amp;nbsp; &lt;/b&gt;&lt;/u&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;In Ch 7 of my book "Defensive Database Programming", I wrote the following statement.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;"As long as a constraint is trusted, then we know for sure that all our data complies with the rules that it dictates." &lt;/p&gt;
&lt;p&gt;At the time I was writing that, I believed that was true. Unfortunately, as we have just seen, I was wrong - we can bypass trusted foreign key constraints in SQL 2008 R2. &lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;P.S.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;&lt;p&gt;I have just learned that there is another scenario to bypass a foreign key. Google up this: "Parameterized DELETE and MERGE Allow Foreign Key Constraint Violations".&lt;/p&gt;&lt;p&gt;Another very important thing that I have just learned that this Connect item did not get urgent priority. Quoting directly from Connect: "Since this is not a common scenario or use case i.e., doing DDL changes 
and DML in the same transaction &lt;u&gt;&lt;b&gt;we don't see this as a big issue&lt;/b&gt;&lt;/u&gt;".&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;</description></item><item><title>Reads involving UDFs under READ_COMMITTED_SNAPSHOT may seem inconsistent.</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2011/08/02/reads-involving-udfs-under-read-committed-snapshot-may-seem-inconsistent.aspx</link><pubDate>Wed, 03 Aug 2011 01:33:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:37448</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>&lt;p&gt;When a select uses scalar or multi-statement UDFs under READ_COMMITTED_SNAPSHOT, we might not get consistent results as of the time our select began - I will provide simple repro scripts.&lt;/p&gt;&lt;p&gt;At the time of this writing MSDN clearly states the following: "Read committed isolation using row versioning provides statement-level read consistency". However, if our select invokes scalar or multi-statement UDFs, &lt;i&gt;&lt;u&gt;this consistency is ensured per a statement in the body of the UDF, not per the whole statement that invokes the UDF(s)&lt;/u&gt;&lt;/i&gt;. &lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Prerequisites&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;&lt;p&gt;Before we run the repro scripts, we need the following setup:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;ALTER DATABASE &lt;/span&gt;&lt;span style="color:black;"&gt;MyTest &lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span style="color:black;"&gt;READ_COMMITTED_SNAPSHOT &lt;/span&gt;&lt;span style="color:blue;"&gt;ON &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;USE &lt;/span&gt;&lt;span style="color:black;"&gt;MyTest &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;CREATE TABLE &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;MessageID &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;NOT NULL&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;CONSTRAINT &lt;/span&gt;&lt;span style="color:black;"&gt;PK_Messages &lt;/span&gt;&lt;span style="color:blue;"&gt;PRIMARY KEY &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;50&lt;/span&gt;&lt;span style="color:gray;"&gt;) NOT NULL&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;) ;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT&amp;nbsp;&amp;nbsp;INTO &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:black;"&gt;MessageID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Hello world' &lt;/span&gt;&lt;span style="color:gray;"&gt;) ;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Getting inconsistent results from a multi-statement UDF&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;&lt;p&gt;First, we need to create this UDF:&lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;CREATE FUNCTION &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.AllMessagesTwice &lt;/span&gt;&lt;span style="color:gray;"&gt;( )&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;RETURNS &lt;/span&gt;&lt;span style="color:#434343;"&gt;@ret &lt;/span&gt;&lt;span style="color:blue;"&gt;TABLE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:blue;"&gt;VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;50&lt;/span&gt;&lt;span style="color:gray;"&gt;) NOT NULL ,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;SelectedAt DATETIME2&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;5&lt;/span&gt;&lt;span style="color:gray;"&gt;) NOT NULL&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BEGIN &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@ret&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;SelectedAt&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta;"&gt;GETDATE&lt;/span&gt;&lt;span style="color:gray;"&gt;()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;DECLARE &lt;/span&gt;&lt;span style="color:#434343;"&gt;@d &lt;/span&gt;&lt;span style="color:black;"&gt;DATETIME2&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;5&lt;/span&gt;&lt;span style="color:gray;"&gt;), &lt;/span&gt;&lt;span style="color:#434343;"&gt;@i &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span style="color:#434343;"&gt;@d &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:magenta;"&gt;DATEADD&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SECOND&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;30&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:magenta;"&gt;GETDATE&lt;/span&gt;&lt;span style="color:gray;"&gt;()) ;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;WHILE &lt;/span&gt;&lt;span style="color:magenta;"&gt;GETDATE&lt;/span&gt;&lt;span style="color:gray;"&gt;() &amp;lt; &lt;/span&gt;&lt;span style="color:#434343;"&gt;@d &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;BEGIN &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span style="color:#434343;"&gt;@i &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;END &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;INSERT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@ret&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;SelectedAt&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta;"&gt;GETDATE&lt;/span&gt;&lt;span style="color:gray;"&gt;()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;RETURN &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;END &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Next, let us open a tab and cut and paste the following script, but not run it yet: &lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SET TRANSACTION ISOLATION LEVEL READ COMMITTED &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&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;&lt;span style="color:black;"&gt;dbo.AllMessagesTwice &lt;/span&gt;&lt;span style="color:gray;"&gt;( )&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;DELETE FROM &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages &lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE &lt;/span&gt;&lt;span style="color:black;"&gt;MessageId &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2 &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;In another tab, cut and paste  the following script, but not run it either:&lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;INSERT&amp;nbsp;&amp;nbsp;INTO &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:black;"&gt;MessageID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Hi there' &lt;/span&gt;&lt;span style="color:gray;"&gt;) ;&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Run the select script in the first tab - it takes 30 seconds to complete. Immediately return to the second tab and insert the 'Hi there' message.&lt;/p&gt;&lt;p&gt;When the select in the first tab completes, we shall clearly see the 'Hi there' message, which definitle was inserted after the select began, as well as the timestamp that shows when the row was selected, 30 seconds after the beginning of the statement:&lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;Hello world 2011&lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;08&lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;02 20&lt;/span&gt;&lt;span style="color:gray;"&gt;:&lt;/span&gt;&lt;span style="color:black;"&gt;56&lt;/span&gt;&lt;span style="color:gray;"&gt;:&lt;/span&gt;&lt;span style="color:black;"&gt;44.70000&lt;br&gt;Hello world 2011&lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;08&lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;02 20&lt;/span&gt;&lt;span style="color:gray;"&gt;:&lt;/span&gt;&lt;span style="color:black;"&gt;57&lt;/span&gt;&lt;span style="color:gray;"&gt;:&lt;/span&gt;&lt;span style="color:black;"&gt;14.74000&lt;br&gt;Hi there&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2011&lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;08&lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;02 20&lt;/span&gt;&lt;span style="color:gray;"&gt;:&lt;/span&gt;&lt;span style="color:black;"&gt;57&lt;/span&gt;&lt;span style="color:gray;"&gt;:&lt;/span&gt;&lt;span style="color:black;"&gt;14.74000&lt;/span&gt;&lt;/code&gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;i&gt;As we have seen, a multi-statement UDF can return data that was committed after the time when the select using the UDF began.&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Getting inconsistent results from a scalar UDF&lt;/b&gt;&lt;/u&gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;Here is the scalar UDF we shall be using:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;CREATE FUNCTION &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.MessageWithLastId &lt;/span&gt;&lt;span style="color:gray;"&gt;( )&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;RETURNS VARCHAR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;50&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;AS &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BEGIN &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;DECLARE &lt;/span&gt;&lt;span style="color:#434343;"&gt;@d &lt;/span&gt;&lt;span style="color:black;"&gt;DATETIME2&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;5&lt;/span&gt;&lt;span style="color:gray;"&gt;) ,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#434343;"&gt;@i &lt;/span&gt;&lt;span style="color:blue;"&gt;INT &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span style="color:#434343;"&gt;@d &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:magenta;"&gt;DATEADD&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;SECOND&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;30&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:magenta;"&gt;GETDATE&lt;/span&gt;&lt;span style="color:gray;"&gt;()) ;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;WHILE &lt;/span&gt;&lt;span style="color:magenta;"&gt;GETDATE&lt;/span&gt;&lt;span style="color:gray;"&gt;() &amp;lt; &lt;/span&gt;&lt;span style="color:#434343;"&gt;@d &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;BEGIN &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET &lt;/span&gt;&lt;span style="color:#434343;"&gt;@i &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;1 &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;END &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;RETURN &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT TOP&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;ORDER BY &lt;/span&gt;&lt;span style="color:black;"&gt;MessageID &lt;/span&gt;&lt;span style="color:blue;"&gt;DESC&lt;/span&gt;&lt;span style="color:gray;"&gt;) ;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;END &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;When we have created the scalar UDF, let us cut, paste, and run the following script:&lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SET TRANSACTION ISOLATION LEVEL READ COMMITTED &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;DELETE FROM &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages &lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE &lt;/span&gt;&lt;span style="color:black;"&gt;MessageId &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2 &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;PRINT &lt;/span&gt;&lt;span style="color:red;"&gt;'Data as of the beginning of the dbo.MessageWithLastId ( ) below'&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:blue;"&gt;FROM &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;ORDER BY &lt;/span&gt;&lt;span style="color:black;"&gt;MessageID &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;PRINT &lt;/span&gt;&lt;span style="color:red;"&gt;'Data returned by dbo.MessageWithLastId ( )'&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.MessageWithLastId &lt;/span&gt;&lt;span style="color:gray;"&gt;( ) ;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;DELETE FROM &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages &lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE &lt;/span&gt;&lt;span style="color:black;"&gt;MessageId &lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;&lt;span style="color:black;"&gt;2 &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;In the second tab we need to immediately run the following, we have 30 seconds to do so:&lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;INSERT&amp;nbsp;&amp;nbsp;INTO &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Messages&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:black;"&gt;MessageID&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;MessageBody &lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;VALUES&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;( &lt;/span&gt;&lt;span style="color:black;"&gt;2&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'Hi there' &lt;/span&gt;&lt;span style="color:gray;"&gt;) ;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;When the select in the first tab completes, we shall see that the scalar UDF returned the value that was not in the table when the select has started:&lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:black;"&gt;Data &lt;/span&gt;&lt;span style="color:blue;"&gt;AS OF &lt;/span&gt;&lt;span style="color:black;"&gt;the beginning &lt;/span&gt;&lt;span style="color:blue;"&gt;OF &lt;/span&gt;&lt;span style="color:black;"&gt;the dbo.MessageWithLastId &lt;/span&gt;&lt;span style="color:gray;"&gt;( ) &lt;/span&gt;&lt;span style="color:black;"&gt;below&lt;br&gt;MessageBody&lt;br&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;--------------------------------------------------&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Hello world&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;1 row&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;s&lt;/span&gt;&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:black;"&gt;affected&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Data returned &lt;/span&gt;&lt;span style="color:blue;"&gt;BY &lt;/span&gt;&lt;span style="color:black;"&gt;dbo.MessageWithLastId &lt;/span&gt;&lt;span style="color:gray;"&gt;( )&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;--------------------------------------------------&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;Hi there&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;i&gt;As we have seen, a scalar UDF can read data that was committed after the time when the select using the UDF began.&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Snapshot isolation guarantees consistency&lt;/b&gt;&lt;/u&gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;We can rerun both previous examples under snapshot isolation. All we need to do is add the following line immediately before the select that invokes our UDF:&lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SET TRANSACTION ISOLATION LEVEL &lt;/span&gt;&lt;span style="color:black;"&gt;SNAPSHOT &lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;In both cases we shall see that &lt;i&gt;&lt;u&gt;under snapshot isolation our selects return consistent data as of the time the select started.&lt;/u&gt;&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/u&gt; &lt;/p&gt;&lt;p&gt;As we have seen, if we are using scalar or multi-statement UDFs, and we need statement level consistency, we need to use snapshot isolation - READ_COMMITTED_SNAPSHOT may fail to provide the consistency we need. &lt;/p&gt;&lt;p&gt;Naturally, inline UDFs are esentially macroes - they are flattened into the select they are invoked from. As such, &lt;u&gt;&lt;i&gt;READ_COMMITTED_SNAPSHOT does provide statement level consistency as long as we are only using inline UDFs&lt;/i&gt;&lt;/u&gt;, and do not use scalar and multi-statement ones.&lt;br&gt;&lt;/p&gt;&lt;p&gt;I would like to thank Erland Sommarskog, whose feedback inspired this post - I am posting this content with his permission. &lt;br&gt;&lt;/p&gt;</description></item><item><title>Math with Months Is Not Commutative</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2010/11/29/math-with-months-is-not-commutative.aspx</link><pubDate>Mon, 29 Nov 2010 22:58:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:31138</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>&lt;p&gt;In other words, if we add a month, then subtract a month, we might not get back to the date we started from. For example:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta;"&gt;DATEADD&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;MONTH&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:magenta;"&gt;DATEADD&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;MONTH&lt;/span&gt;&lt;span style="color:gray;"&gt;, -&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'20100330'&lt;/span&gt;&lt;span style="color:gray;"&gt;)) ,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta;"&gt;DATEADD&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;MONTH&lt;/span&gt;&lt;span style="color:gray;"&gt;, -&lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:magenta;"&gt;DATEADD&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;MONTH&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:black;"&gt;1&lt;/span&gt;&lt;span style="color:gray;"&gt;, &lt;/span&gt;&lt;span style="color:red;"&gt;'20100330'&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;2010&lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;03&lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;28 00&lt;/span&gt;&lt;span style="color:gray;"&gt;:&lt;/span&gt;&lt;span style="color:black;"&gt;00&lt;/span&gt;&lt;span style="color:gray;"&gt;:&lt;/span&gt;&lt;span style="color:black;"&gt;00.000&lt;br&gt;2010&lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;03&lt;/span&gt;&lt;span style="color:gray;"&gt;-&lt;/span&gt;&lt;span style="color:black;"&gt;30 00&lt;/span&gt;&lt;span style="color:gray;"&gt;:&lt;/span&gt;&lt;span style="color:black;"&gt;00&lt;/span&gt;&lt;span style="color:gray;"&gt;:&lt;/span&gt;&lt;span style="color:black;"&gt;00.000&lt;/span&gt;&lt;/code&gt;&amp;nbsp;
                &lt;br&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;If our code assumes otherwise, it has a bug.&lt;br&gt;&lt;/p&gt;</description></item><item><title>Additional links for my presentation on defensive database programming.</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2010/09/19/additional-links-for-my-presentation-on-defensive-database-programming.aspx</link><pubDate>Sun, 19 Sep 2010 18:29:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:28859</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>
&lt;p&gt;Yesterday I delivered a session named "Develop T-SQL defensively" at East Iowa SQL Saturday. Thanks to those who attended,
 and many thanks to Michelle Ufford, Chris Leonard, &lt;span style="font-family:arial,sans-serif;font-size:13px;border-collapse:collapse;"&gt;Ed Leighton-Dick, and other volunteers,&lt;/span&gt; who organized the event.&lt;/p&gt;

&lt;p&gt;Here are the links with more information and more repro 
scripts, more or less in the order following the order of the 
presentation.&lt;/p&gt;


&lt;a href="http://www.simple-talk.com/sql/t-sql-programming/basic-defensive-database-programming-techniques/"&gt;Basic Defensive Database Programming Techniques&lt;/a&gt;

&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/03/08/summarizing-previous-posts-about-defensive-database-programming.aspx"&gt;Summarizing previous posts about defensive database programming&lt;/a&gt;

Happy programming!</description></item><item><title>Repro scripts and more info for my presentation on concurrency</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2010/09/19/repro-scripts-and-more-info-for-my-presentation-on-concurrency.aspx</link><pubDate>Sun, 19 Sep 2010 18:10:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:28858</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>&lt;p&gt;Yesterday I delivered a session named "Developing T-SQL to survive concurrency" at East Iowa SQL Saturday. Thanks to everyone who attended, and thanks to Michelle Ufford, Chris Leonard, &lt;span style="font-family:arial,sans-serif;font-size:13px;border-collapse:collapse;"&gt;Ed Leighton-Dick, and other volunteers,&lt;/span&gt;  who organized the event.&lt;/p&gt;

&lt;p&gt;As promised, here are the links with more information and more repro scripts, more or less in the order following the order of the presentation.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/10/selects-under-read-committed-and-repeatable-read-may-return-incorrect-results.aspx"&gt;Selects under READ COMMITTED and REPEATABLE READ may return incorrect results. &lt;/a&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx"&gt;Reproducing deadlocks involving only one table  &lt;/a&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx"&gt;Reproducing deadlocks involving only one table  &lt;/a&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2010/01/08/retrying-after-deadlocks-leads-to-lost-updates.aspx"&gt;Retrying after deadlocks leads to lost updates&lt;/a&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2010/01/12/t-sql-tuesday-002-patterns-that-do-not-work-as-expected.aspx"&gt;Patterns that do not work as expected.&lt;/a&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;a href="http://www.simple-talk.com/sql/t-sql-programming/developing-modifications-that-survive-concurrency/"&gt;Developing Modifications that Survive Concurrency&lt;/a&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;

And, finally, Erland Sommarskog's article

&lt;a href="http://www.sommarskog.se/arrays-in-sql-2005.html"&gt;Arrays and lists in SQL&lt;/a&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item><item><title>Speaking at SQL Saturday #50 in Iowa City, IA, and the recent disturbance in the Force.</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2010/08/29/speaking-at-sql-saturday-50-in-iowa-city-ia-and-the-recent-disturbance-in-the-force.aspx</link><pubDate>Sun, 29 Aug 2010 15:29:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:28398</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>
&lt;p&gt;In a few weeks I will be meeting a lot of old friends and new folks &lt;a href="http://www.sqlsaturday.com/50/schedule.aspx"&gt;at SQL Saturday #50 in Iowa City&lt;/a&gt;. I'll do two presentations: on &lt;a href="http://www.amazon.com/Defensive-Database-Programming-SQL-Server/dp/190643445X"&gt;defensive database programming&lt;/a&gt; and on coding for high concurrency. &lt;/p&gt;
&lt;p&gt;I really like this whole SQL Saturday thing. For me it is much better to allocate a Saturday for training and networking close to where I live, than to travel and not work for several business days. I would like to thank Steve Jones, Andy Warren, and Brian Knight who got this whole thing up and running.&lt;/p&gt;
&lt;p&gt;Recently there was a disturbance in the Force. Quite a few people got really disappointed that Steve Jones was rejected for PASS board. Here is my take at it.&lt;/p&gt;
&lt;p&gt;I really appreciate Steve's contributions to the community. I like, attend, and speak at SQL Saturdays. Also I regularly visit sqlserevercentral.com. To show how much I appreciate this great site, I will begin contributing to it - I will be regularly submitting articles to it. I hope they will be accepted and published. I don't have anything else to say on this issue.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item><item><title>My book is complete, many thanks to Hugo, Tony, and many others!</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2010/06/18/my-book-is-complete-many-thanks-to-hugo-tony-and-many-others.aspx</link><pubDate>Fri, 18 Jun 2010 19:22:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:26267</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>&lt;p&gt;&lt;a href="http://www.amazon.com/Defensive-Database-Programming-SQL-Server/dp/1906434492/ref=cm_cr_pr_product_top"&gt;My book is finished.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A couple years ago I googled up "Defensive Database Programming", and came up with nothing. Naturally, I started filling up the void. Although the book is complete, I am planning to continue my research; I would appreciate any other defensive scenarios to discuss and describe.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Many thanks to my longtime friend &lt;a href="http://sqlblog.com/controlpanel/blogs/sqlblog.com/blogs/hugo_kornelis/"&gt;Hugo Kornelis&lt;/a&gt;. I was very lucky that he agreed to review my book; he went very much beyond just reviewing it - his multiple excellent suggestions were invaluable.&lt;/p&gt;
&lt;p&gt;Thanks to the &lt;a href="http://www.simple-talk.com/community/blogs/tony_davis/default.aspx"&gt;brilliant editor Tony Davis&lt;/a&gt;, who patiently guided me all the way through. &lt;/p&gt;
&lt;p&gt;Maybe we should do it again some time. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;Also thanks to everyone who commented on my blog posts, helping me to crystallize and clarify the ideas, around which I eventually wrote my book.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item><item><title>Yet another example of defensive query optimization</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2010/02/18/yet-another-example-of-defensive-query-optimiziation.aspx</link><pubDate>Thu, 18 Feb 2010 20:11:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:22452</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>&lt;p&gt;My second take at the same problem I blogged about yesterday:&lt;/p&gt;
&lt;p&gt;To optimize a query, we frequently have to explicitly tell optimizer
some information which it does not realize by itself. Short term, this
works, but long term we run the risk that what we are telling to the
optimizer may be no longer relevant. In the previous post, &lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2010/02/17/optimizing-a-query-then-documenting-assumptions-in-a-unit-test.aspx"&gt;Optimizing a query, then documenting assumptions in a unit test&lt;/a&gt; , we defined the problem and used a unit test to document an assumption. Read the previous post before proceeding.&lt;br&gt;&lt;/p&gt;
&lt;p&gt;In this post we shall eliminate the assumption altogether, and our code will be safer and easier to maintain. Instead of hardcoding the maximum duration of an event, we shall read it from the same table. To make sure that we read it efficiently, we shall use an index on a computed column:&lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;ALTER&amp;nbsp;TABLE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Events&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;ADD&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;EventDurationInMinutes&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;AS&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta;"&gt;DATEDIFF&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;MINUTE&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:black;"&gt;StartedAt&lt;/span&gt;&lt;span style="color:gray;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;EndedAt&lt;/span&gt;&lt;span style="color:gray;"&gt;)&amp;nbsp;;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br&gt;&lt;/span&gt;&lt;span style="color:black;"&gt;GO
&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;CREATE&amp;nbsp;INDEX&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;Events_EventDurationInMinutes&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;ON&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Events&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;EventDurationInMinutes&lt;/span&gt;&lt;span style="color:gray;"&gt;)&amp;nbsp;;
&lt;br&gt;&lt;/span&gt;&lt;/code&gt;&amp;nbsp;                &lt;br&gt;&lt;/p&gt;&lt;p&gt;This index allows to retrieve maximum duration efficiently, as shown in the following procedure:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;ALTER&amp;nbsp;PROCEDURE&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.SelectRunningEventsForTime&amp;nbsp;&lt;/span&gt;&lt;span&gt;@AsOfTime&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;DATETIME
&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;AS&amp;nbsp;
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BEGIN&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;;
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;DECLARE&amp;nbsp;&lt;/span&gt;&lt;span&gt;@MaxEventDurationInMinutes&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;INT&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;,
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;@EarliestPossibleStart&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;DATETIME&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;;
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET&amp;nbsp;&lt;/span&gt;&lt;span&gt;@MaxEventDurationInMinutes&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;(&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;EventDurationInMinutes&lt;/span&gt;&lt;span style="color:gray;"&gt;)&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;1
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;&lt;span style="color:blue;"&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Events
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;&lt;span style="color:gray;"&gt;)&amp;nbsp;;&amp;nbsp;&amp;nbsp;
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SET&amp;nbsp;&lt;/span&gt;&lt;span&gt;@EarliestPossibleStart&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:magenta;"&gt;DATEADD&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:black;"&gt;MINUTE&lt;/span&gt;&lt;span style="color:gray;"&gt;,
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;&lt;span&gt;@MaxEventDurationInMinutes&lt;/span&gt;&lt;span style="color:gray;"&gt;,
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;&lt;span&gt;@AsOfTime&lt;/span&gt;&lt;span style="color:gray;"&gt;)&amp;nbsp;;
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;EventID&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;,
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;StartedAt&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;,
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;EndedAt
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.Events
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;@AsOfTime&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;BETWEEN&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;StartedAt&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;AND&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;EndedAt
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;AND&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;StartedAt&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;gt;=&amp;nbsp;&lt;/span&gt;&lt;span&gt;@EarliestPossibleStart&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;;
&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;END&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;                &amp;nbsp;
              &lt;/p&gt;&lt;p&gt;Let us run this procedure: &lt;/p&gt;&lt;p&gt;&lt;code style="font-size:12px;"&gt;&lt;span style="color:blue;"&gt;SET&amp;nbsp;STATISTICS&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;IO&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;ON&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;;
&lt;br&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;EXEC&amp;nbsp;&lt;/span&gt;&lt;span style="color:black;"&gt;dbo.SelectRunningEventsForTime&amp;nbsp;&lt;/span&gt;&lt;span&gt;@AsOfTime&amp;nbsp;&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color:red;"&gt;'20100223&amp;nbsp;01:38:08'&amp;nbsp;&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Selecting the maximum duration uses 3 reads, it is a simple index seek &lt;br&gt;&lt;/p&gt;&lt;p&gt;Table 'Events'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.&lt;br&gt;(snip)&lt;/p&gt;&lt;p&gt;&amp;nbsp;Reading the rows takes just a few more reads.&lt;br&gt;&lt;/p&gt;&lt;p&gt;Table 'Events'. Scan count 1, logical reads 6, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/u&gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;We have added an index on a computed column, and changed the stored procedure, so that it does not use any hardcoded constants. As such, the procedure is safer. Quite likely this improved stored procedure will require less maintenance.&lt;br&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item></channel></rss>