<?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 tags 'SQL', 'Database Programming', and 'SQL Server'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=SQL,Database+Programming,SQL+Server&amp;orTags=0</link><description>Search results matching tags 'SQL', 'Database Programming', and 'SQL Server'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Defensive database programming: eliminating IF statements.</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/11/27/defensive-database-programming-if-statement-vs-where-clause.aspx</link><pubDate>Thu, 27 Nov 2008 23:27:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:10149</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>&lt;p class="MsoNormal"&gt;The following pattern is quite common in database
programming:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;IF EXISTS(some query) BEGIN&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;DO SOMETHING;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;END&lt;/p&gt;

&lt;p class="MsoNormal"&gt;When such code runs in high concurrency situations, it may
not work as expected. I will provide a repro when such logic fails 40% of the
time. The following script provides a test table and attempts to implement
optimistic locking using rowversion columns:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;TABLE&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoINTs&lt;span style="color:gray;"&gt;(&lt;/span&gt;ID &lt;span style="color:blue;"&gt;INT&lt;/span&gt; &lt;span style="color:gray;"&gt;NOT&lt;/span&gt; &lt;span style="color:gray;"&gt;NULL,&lt;/span&gt; i1 &lt;span style="color:blue;"&gt;INT&lt;/span&gt; &lt;span style="color:gray;"&gt;NOT&lt;/span&gt; &lt;span style="color:gray;"&gt;NULL,&lt;/span&gt; i2 &lt;span style="color:blue;"&gt;INT&lt;/span&gt; &lt;span style="color:gray;"&gt;NOT&lt;/span&gt; &lt;span style="color:gray;"&gt;NULL,&lt;/span&gt; version &lt;span style="color:blue;"&gt;ROWVERSION&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;NOCOUNT&lt;/span&gt; &lt;span style="color:blue;"&gt;ON&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @i &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @i&lt;span style="color:gray;"&gt;=&lt;/span&gt;0&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;WHILE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @i&lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt;1000000 &lt;span style="color:blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;INTO&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoINTs&lt;span style="color:gray;"&gt;(&lt;/span&gt;ID&lt;span style="color:gray;"&gt;,&lt;/span&gt; i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; i2&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;@i&lt;span style="color:gray;"&gt;,&lt;/span&gt;0&lt;span style="color:gray;"&gt;,&lt;/span&gt;0&lt;span style="color:gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @i &lt;span style="color:gray;"&gt;=&lt;/span&gt; @i&lt;span style="color:gray;"&gt;+&lt;/span&gt;1&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;END&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';color:blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;UNIQUE&lt;/span&gt; &lt;span style="color:blue;"&gt;INDEX&lt;/span&gt;
UNQ_TwoInts_ID &lt;span style="color:blue;"&gt;ON&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoInts&lt;span style="color:gray;"&gt;(&lt;/span&gt;ID&lt;span style="color:gray;"&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';color:gray;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;PROCEDURE&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;UpdateTwoINTs&lt;span style="color:gray;"&gt;(&lt;/span&gt;@ID &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i1 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version &lt;span style="color:blue;"&gt;ROWVERSION&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;AS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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:blue;"&gt;NOCOUNT&lt;/span&gt;
&lt;span style="color:blue;"&gt;ON&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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:blue;"&gt;TRANSACTION&lt;/span&gt;
&lt;span style="color:blue;"&gt;ISOLATION&lt;/span&gt; &lt;span style="color:blue;"&gt;LEVEL&lt;/span&gt;
&lt;span style="color:blue;"&gt;READ&lt;/span&gt; COMMITTED&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;DECLARE&lt;/span&gt; @ret &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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:blue;"&gt;TRANSACTION&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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;EXISTS(&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoINTs &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;@ID &lt;span style="color:gray;"&gt;AND&lt;/span&gt; version &lt;span style="color:gray;"&gt;=&lt;/span&gt; @version&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;UPDATE&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoINTs &lt;span style="color:blue;"&gt;SET&lt;/span&gt; i1&lt;span style="color:gray;"&gt;=&lt;/span&gt;@i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; i2&lt;span style="color:gray;"&gt;=&lt;/span&gt;@i2 &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;@ID &lt;span style="color:gray;"&gt;AND&lt;/span&gt; version &lt;span style="color:gray;"&gt;=&lt;/span&gt; @version&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @ret&lt;span style="color:gray;"&gt;=&lt;/span&gt;0&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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:blue;"&gt;ELSE&lt;/span&gt;
&lt;span style="color:blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @ret&lt;span style="color:gray;"&gt;=&lt;/span&gt;1&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;COMMIT&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;RETURN&lt;/span&gt; @ret&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;END&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';"&gt;GO&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;A naïve test not involving high concurrency succeeds all
right. You can run a naïve test yourself. In one tab, run the following code,
which mimics a user who read a row and modified column i1 in 10 seconds:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @i1 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version &lt;span style="color:blue;"&gt;ROWVERSION&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @count &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @ret &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @i1&lt;span style="color:gray;"&gt;=&lt;/span&gt;i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2&lt;span style="color:gray;"&gt;=&lt;/span&gt;i2&lt;span style="color:gray;"&gt;+&lt;/span&gt;1&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version&lt;span style="color:gray;"&gt;=&lt;/span&gt;version &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoInts &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;5&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;WAITFOR&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; DELAY &lt;span style="color:red;"&gt;'00:00:10'&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;EXEC&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @ret&lt;span style="color:gray;"&gt;=&lt;/span&gt;dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;UpdateTwoINTs 5&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @ret &lt;span style="color:blue;"&gt;AS&lt;/span&gt; ret&lt;span style="color:gray;"&gt;,&lt;/span&gt; i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; i2 &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoInts &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;5&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Immediately start another script, which mimics a user who
modified another column, i2, also after 10 seconds of delay:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @i1 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version &lt;span style="color:blue;"&gt;ROWVERSION&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @count &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @ret &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @i1&lt;span style="color:gray;"&gt;=&lt;/span&gt;i1&lt;span style="color:gray;"&gt;+&lt;/span&gt;1&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2&lt;span style="color:gray;"&gt;=&lt;/span&gt;i2&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version&lt;span style="color:gray;"&gt;=&lt;/span&gt;version &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoInts &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;5&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;WAITFOR&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; DELAY &lt;span style="color:red;"&gt;'00:00:10'&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;EXEC&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @ret&lt;span style="color:gray;"&gt;=&lt;/span&gt;dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;UpdateTwoINTs 5&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @ret &lt;span style="color:blue;"&gt;AS&lt;/span&gt; ret&lt;span style="color:gray;"&gt;,&lt;/span&gt; i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; i2 &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoInts &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;5&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Note that only one of two updates succeeded, which is
expected – the procedure detected a rowversion mismatch and did not overwrite
the first update. However, a more realistic test on my laptop fails 40% of the
time. First of all, some cleanup:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';color:blue;"&gt;UPDATE&lt;/span&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';"&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoINTs &lt;span style="color:blue;"&gt;SET&lt;/span&gt; i1&lt;span style="color:gray;"&gt;=&lt;/span&gt;0&lt;span style="color:gray;"&gt;,&lt;/span&gt; i2&lt;span style="color:gray;"&gt;=&lt;/span&gt;0 &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;5;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Here is the script to
run in one tab:&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @i1 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version &lt;span style="color:blue;"&gt;ROWVERSION&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @count &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @ret &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @count &lt;span style="color:gray;"&gt;=&lt;/span&gt; 0&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;WHILE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @count&lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt;100000 &lt;span style="color:blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; @i1&lt;span style="color:gray;"&gt;=&lt;/span&gt;i1&lt;span style="color:gray;"&gt;+&lt;/span&gt;1&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2&lt;span style="color:gray;"&gt;=&lt;/span&gt;i2&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version&lt;span style="color:gray;"&gt;=&lt;/span&gt;version &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoInts &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;5&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;EXEC&lt;/span&gt; @ret&lt;span style="color:gray;"&gt;=&lt;/span&gt;dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;UpdateTwoINTs 5&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @count &lt;span style="color:gray;"&gt;=&lt;/span&gt; @count &lt;span style="color:gray;"&gt;+&lt;/span&gt; 1 &lt;span style="color:gray;"&gt;-&lt;/span&gt; @ret&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';color:blue;"&gt;END&lt;/span&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Here is the script to run in another tab:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @i1 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version &lt;span style="color:blue;"&gt;ROWVERSION&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @count &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @ret &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SET&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @count &lt;span style="color:gray;"&gt;=&lt;/span&gt; 0&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;WHILE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; @count&lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt;100000 &lt;span style="color:blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; @i1&lt;span style="color:gray;"&gt;=&lt;/span&gt;i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2&lt;span style="color:gray;"&gt;=&lt;/span&gt;i2&lt;span style="color:gray;"&gt;+&lt;/span&gt;1&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version&lt;span style="color:gray;"&gt;=&lt;/span&gt;version &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoInts &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;5&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;EXEC&lt;/span&gt; @ret&lt;span style="color:gray;"&gt;=&lt;/span&gt;dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;UpdateTwoINTs 5&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @count &lt;span style="color:gray;"&gt;=&lt;/span&gt; @count &lt;span style="color:gray;"&gt;+&lt;/span&gt; 1 &lt;span style="color:gray;"&gt;-&lt;/span&gt; @ret&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';color:blue;"&gt;END&lt;/span&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;If no updates were
lost, I would expect the values in both i1 and i2 to be 100000. Unfortunately,
this is not the case:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; i2 &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoINTs&amp;nbsp;&lt;span&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;5&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;57871&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;54473&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;As you have seen, more than 40% updates were lost. There are
several ways to fix the problem. Of course, you can just up the isolation level
to REPEATABLE READ or even to SERIALIZABLE. Unfortunately, under higher
isolation levels code like this is very prone to deadlocks. You can alter the
stored procedure, rerun the loops, and see for yourself. There is a much
simpler and more robust way to implement optimistic locking. Let me clean up the
data first and improve the procedure:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';color:blue;"&gt;UPDATE&lt;/span&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';"&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoINTs &lt;span style="color:blue;"&gt;SET&lt;/span&gt; i1&lt;span style="color:gray;"&gt;=&lt;/span&gt;0&lt;span style="color:gray;"&gt;,&lt;/span&gt; i2&lt;span style="color:gray;"&gt;=&lt;/span&gt;0 &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;5;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;ALTER&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;PROCEDURE&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;UpdateTwoINTs&lt;span style="color:gray;"&gt;(&lt;/span&gt;@ID &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i1 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @i2 &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; @version &lt;span style="color:blue;"&gt;ROWVERSION&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;AS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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:blue;"&gt;NOCOUNT&lt;/span&gt;
&lt;span style="color:blue;"&gt;ON&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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:blue;"&gt;TRANSACTION&lt;/span&gt;
&lt;span style="color:blue;"&gt;ISOLATION&lt;/span&gt; &lt;span style="color:blue;"&gt;LEVEL&lt;/span&gt;
&lt;span style="color:blue;"&gt;READ&lt;/span&gt; COMMITTED&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;DECLARE&lt;/span&gt; @ret &lt;span style="color:blue;"&gt;INT&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;UPDATE&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoINTs &lt;span style="color:blue;"&gt;SET&lt;/span&gt; i1&lt;span style="color:gray;"&gt;=&lt;/span&gt;@i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; i2&lt;span style="color:gray;"&gt;=&lt;/span&gt;@i2 &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;@ID &lt;span style="color:gray;"&gt;AND&lt;/span&gt; version &lt;span style="color:gray;"&gt;=&lt;/span&gt; @version&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;SET&lt;/span&gt; @ret&lt;span style="color:gray;"&gt;=&lt;/span&gt; 1 &lt;span style="color:gray;"&gt;-&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;@@ROWCOUNT&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;RETURN&lt;/span&gt; @ret&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';color:blue;"&gt;END&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;When you rerun those two scripts with loops from 1 to 100000
again, you can see that this time not a single update was lost:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; i1&lt;span style="color:gray;"&gt;,&lt;/span&gt; i2 &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TwoINTs&amp;nbsp;&lt;span style="color:blue;"&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; ID&lt;span style="color:gray;"&gt;=&lt;/span&gt;5&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;100000&lt;span&gt;&amp;nbsp; &lt;/span&gt;100000&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Note that you did not get any deadlocks at all. &lt;/p&gt;

&lt;p class="MsoNormal"&gt;As you have seen, the following pattern is very prone to
errors in high concurrency OLTP environments:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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;EXISTS(&lt;/span&gt;&lt;span style="color:blue;"&gt;SELECT&lt;/span&gt; 1 &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;SomeTable &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; &amp;lt;Some
Conditions&amp;gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;DO Something;&lt;span style="color:gray;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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:blue;"&gt;ELSE&lt;/span&gt;
&lt;span style="color:blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;DO Something else&lt;span style="color:gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&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;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;If you use this pattern in your procedures and expect to run
them in high concurrency OLTP environments, you need to properly stress test
your procedures. While it is OK to just run scripts from SSMS tabs to
demonstrate the problem, as I did in this post, I think that in real life there are more convenient ways
to stress test. For instance, I was describing a C# test harness &lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.simple-talk.com/sql/t-sql-programming/close-those-loopholes-stress-test-those-stored-procedures/"&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This post continues my series on defensive database programming. &lt;/p&gt;&lt;p&gt;The next post is:&lt;/p&gt;&lt;p&gt;&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/12/08/defensive-database-programming-fun-with-update.aspx"&gt;Defensive
database programming: fun with UPDATE.&lt;/a&gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Here are the previous posts&amp;nbsp; from the series:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/11/19/defensive-database-programming-fun-with-changing-column-widths.aspx"&gt;Defensive database programming: fun with changing column widths.&lt;/a&gt;

&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/11/15/avoid-mixing-old-and-new-styles-of-error-handling.aspx"&gt;Avoid mixing old and new styles of error handling.&lt;/a&gt;

&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/11/08/defensive-database-programming-adding-escape-clauses.aspx"&gt;Defensive database programming: adding ESCAPE clauses.&lt;/a&gt;

&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/10/25/defensive-database-programming-qualifying-column-names.aspx"&gt;Defensive database programming: qualifying column names.&lt;/a&gt;

&lt;a href="http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/10/21/defensive-database-programming-rewriting-queries-with-not-in.aspx"&gt;Defensive database programming: rewriting queries with NOT IN().&lt;/a&gt;



&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;</description></item><item><title>Performance of inserts and IGNORE_DUP_KEY</title><link>http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/07/30/performance-of-inserts-and-ignore-dup-key.aspx</link><pubDate>Thu, 31 Jul 2008 02:39:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:8134</guid><dc:creator>Alexander Kuznetsov</dc:creator><description>

&lt;p class="MsoNormal"&gt;&lt;br&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;If your data has a small percentage of duplicates, then IGNORE_DUP_KEY
may speed up your inserts. For larger amounts of duplicates, IGNORE_DUP_KEY may
slow them down significantly. I set up two tables, stripping down all the
irrelevant details, as follows:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;TABLE&lt;/span&gt; t1&lt;span style="color:gray;"&gt;(&lt;/span&gt;n &lt;span style="color:blue;"&gt;INT&lt;/span&gt; &lt;span style="color:gray;"&gt;NOT&lt;/span&gt; &lt;span style="color:gray;"&gt;NULL&lt;/span&gt; &lt;span style="color:blue;"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:blue;"&gt;KEY&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;TABLE&lt;/span&gt; [dbo]&lt;span style="color:gray;"&gt;.&lt;/span&gt;[t2]&lt;span style="color:gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[n] [int] &lt;span style="color:gray;"&gt;NOT&lt;/span&gt; &lt;span style="color:gray;"&gt;NULL,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;PRIMARY&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;KEY&lt;/span&gt; &lt;span style="color:blue;"&gt;CLUSTERED&lt;/span&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[n] &lt;span style="color:blue;"&gt;ASC&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:gray;"&gt;)&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;WITH&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:gray;"&gt;(&lt;/span&gt;IGNORE_DUP_KEY &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:blue;"&gt;ON&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;ON&lt;/span&gt; [PRIMARY]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:gray;"&gt;)&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;ON&lt;/span&gt; [PRIMARY]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;line-height:115%;font-family:'Courier New';"&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;If the incoming data had no duplicates, the performance of both
inserts was consistently the same:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; t1&lt;span style="color:gray;"&gt;(&lt;/span&gt;n&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; t2&lt;span style="color:gray;"&gt;(&lt;/span&gt;n&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;(Note that dbo. Numbers has 1 million rows.) &lt;span&gt;&amp;nbsp;&lt;/span&gt;Of course, I always truncated both tables
between my tests.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;If the incoming data had 1% of duplicates, the insert with IGNORE_DUP_KEY
consistently performed approximately 5% faster:&lt;/p&gt;&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; t1&lt;span style="color:gray;"&gt;(&lt;/span&gt;n&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;DISTINCT&lt;/span&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;UNION&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:gray;"&gt;ALL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; n &lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt;10000&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:gray;"&gt;)&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; t&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; t2&lt;span style="color:gray;"&gt;(&lt;/span&gt;n&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;UNION&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:gray;"&gt;ALL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; n &lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt;10000&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;On the other hand, if the incoming data had 100% of
duplicates, the insert with IGNORE_DUP_KEY consistently performed at least 300%
slower, both for a large set of 2 million rows:&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; t1&lt;span style="color:gray;"&gt;(&lt;/span&gt;n&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;DISTINCT&lt;/span&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;UNION&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:gray;"&gt;ALL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:gray;"&gt;)&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; t&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; t2&lt;span style="color:gray;"&gt;(&lt;/span&gt;n&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;UNION&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:gray;"&gt;ALL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;As well as for a smaller set of 200K rows:&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; t1&lt;span style="color:gray;"&gt;(&lt;/span&gt;n&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;DISTINCT&lt;/span&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; n&lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt;100000&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;UNION&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:gray;"&gt;ALL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; n&lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt;100000&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:gray;"&gt;)&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; t&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;INSERT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; t2&lt;span style="color:gray;"&gt;(&lt;/span&gt;n&lt;span style="color:gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; n&lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt;100000&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;UNION&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; &lt;span style="color:gray;"&gt;ALL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="margin-bottom:0.0001pt;line-height:normal;"&gt;&lt;span style="font-size:10pt;font-family:'Courier New';color:blue;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:10pt;font-family:'Courier New';"&gt; n &lt;span style="color:blue;"&gt;FROM&lt;/span&gt; dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;Numbers &lt;span style="color:blue;"&gt;WHERE&lt;/span&gt; n&lt;span style="color:gray;"&gt;&amp;lt;&lt;/span&gt;100000&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;Overall, I decided not to use IGNORE_DUP_KEY in my
particular case. I decided that small savings for a small amount of duplicates
do not justify the risk of a huge performance drop for larger amounts of
duplicate data.&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;</description></item></channel></rss>