<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   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/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Software Voices - Database development</title>
    <link>http://www.softwarevoices.com/</link>
    <description>Perspectives from commercial developers of consumer software</description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.0 - http://www.s9y.org/</generator>
    <pubDate>Fri, 26 May 2006 03:22:37 GMT</pubDate>

    <image>
        <url>http://www.softwarevoices.com/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Software Voices - Database development - Perspectives from commercial developers of consumer software</title>
        <link>http://www.softwarevoices.com/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>Book Review:  Joe Celko's Trees and Hierarchies</title>
    <link>http://www.softwarevoices.com/archives/39-Book-Review-Joe-Celkos-Trees-and-Hierarchies.html</link>
            <category>Database development</category>
    
    <comments>http://www.softwarevoices.com/archives/39-Book-Review-Joe-Celkos-Trees-and-Hierarchies.html#comments</comments>
    <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=39</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=2.0&amp;type=comments&amp;cid=39</wfw:commentRss>
    

    <author>nospam@example.com (Glenn Crowe)</author>
    <content:encoded>
    This is a book review of Joe Celko&#039;s book titled &quot;Joe Celko&#039;s Trees and Hierarchies in SQL for Smarties&quot;  ISBN: 1558609202&lt;br /&gt;
&lt;br /&gt;
Should you read this book?  This, it seems to me, is the point a book review must inevitably resolve.  Ill go ahead and kill the suspense by saying &quot;&lt;b&gt;yes&lt;/b&gt;.&quot;  If you are involved with the development of SQL systems at any level and wish to read some productive material you can safely turn to this book.  This isnt a perfect book by any means.  It disappoints in some key ways.  However, I am hard pressed to find fault enough to justify not recommending the book.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;The Good News&lt;/h3&gt; &lt;br /&gt;&lt;a href=&quot;http://www.softwarevoices.com/archives/39-Book-Review-Joe-Celkos-Trees-and-Hierarchies.html#extended&quot;&gt;Continue reading &quot;Book Review:  Joe Celko&#039;s Trees and Hierarchies&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Thu, 25 May 2006 22:22:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/39-guid.html</guid>
    <category>binary trees</category>
<category>book review</category>
<category>joe celko</category>
<category>sql</category>
<category>trees and hierarchies in sql for smarties</category>

</item>
<item>
    <title>Counting nodes in a tree:  A bottom-up approach</title>
    <link>http://www.softwarevoices.com/archives/32-Counting-nodes-in-a-tree-A-bottom-up-approach.html</link>
            <category>Database development</category>
    
    <comments>http://www.softwarevoices.com/archives/32-Counting-nodes-in-a-tree-A-bottom-up-approach.html#comments</comments>
    <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=32</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=2.0&amp;type=comments&amp;cid=32</wfw:commentRss>
    

    <author>nospam@example.com (Glenn Crowe)</author>
    <content:encoded>
    A popular interview question for SQL Developers goes something like the following:  Given an employee table where ManagerID is an attribute of the Employee record, write a stored procedure which counts the total number of employees which report to the passed employee.&lt;br /&gt;
&lt;br /&gt;
For clarity I will point out that the organization is a tree where each employee represents a node.&lt;br /&gt;
&lt;br /&gt;
There is a simple answer which you should probably stick to in the context of an interview.  A top down approach (without the sproc wrapper) would look like this:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Create table #tEmployeeTree &lt;br /&gt;
( EmployeeID int, ManagerID int, PassNumber int )&lt;br /&gt;
&lt;br /&gt;
Declare @Pass int, @RowCount int, @EmpIDParam int&lt;br /&gt;
Select  @Pass = 1, @RowCount = 0, @EmpIDParam = 12&lt;br /&gt;
Insert #tEmployeeTree ( EmployeeID, ManagerID, PassNumber )&lt;br /&gt;
Select EmployeeID, ManagerID, @Pass &lt;br /&gt;
  from HumanResources.Employee a&lt;br /&gt;
 where  ManagerID = @EmpIDParam&lt;br /&gt;
&lt;br /&gt;
Select @RowCount = @@RowCount, @Pass = @Pass + 1&lt;br /&gt;
&lt;br /&gt;
While ( @RowCount != 0 )&lt;br /&gt;
begin&lt;br /&gt;
&lt;br /&gt;
    Insert #tEmployeeTree &lt;br /&gt;
    ( EmployeeID, ManagerID, PassNumber )&lt;br /&gt;
    Select&lt;br /&gt;
          b.EmployeeID&lt;br /&gt;
         ,b.ManagerID&lt;br /&gt;
         ,@Pass&lt;br /&gt;
      from  #tEmployeeTree a&lt;br /&gt;
       join HumanResources.Employee b on a.EmployeeID = b.ManagerID&lt;br /&gt;
     where a.PassNumber = @Pass -1&lt;br /&gt;
&lt;br /&gt;
    Select @RowCount = @@RowCount, @Pass = @Pass + 1&lt;br /&gt;
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;At this point you can be confident that the number of records in the #tEmployeeTree table represents the correct answer.&lt;br /&gt;
&lt;br /&gt;
Now, there is an embellishment to this question which can lead to some interesting discussion.  An executive would like to know which of his or her direct subordinates has the most number of employees in their organization.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.softwarevoices.com/archives/32-Counting-nodes-in-a-tree-A-bottom-up-approach.html#extended&quot;&gt;Continue reading &quot;Counting nodes in a tree:  A bottom-up approach&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Tue, 25 Apr 2006 23:43:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/32-guid.html</guid>
    <category>graph</category>
<category>hierarchy</category>
<category>sql</category>
<category>sql2005</category>
<category>stored procedures</category>
<category>transact sql</category>
<category>tree</category>

</item>
<item>
    <title>Passing n parameters to a Stored Procedure in a single call</title>
    <link>http://www.softwarevoices.com/archives/27-Passing-n-parameters-to-a-Stored-Procedure-in-a-single-call.html</link>
            <category>Database development</category>
    
    <comments>http://www.softwarevoices.com/archives/27-Passing-n-parameters-to-a-Stored-Procedure-in-a-single-call.html#comments</comments>
    <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=27</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=2.0&amp;type=comments&amp;cid=27</wfw:commentRss>
    

    <author>nospam@example.com (Glenn Crowe)</author>
    <content:encoded>
    Application developers have long lamented the seemingly delinquent support for passing an unbounded number of parameters to a SQL Server stored procedure.  Such support has always existed, but the mechanism has never been entirely intuitive.&lt;br /&gt;
&lt;br /&gt;
Observe a stored procedure defined thusly:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;Create proc sp_AsManyAsYouLike as&lt;br /&gt;
set nocount on Select myInt * 1000 from #tempParam&lt;br /&gt;
go&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Now I bring all of my Perl programming skills to bear:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;$cmd-&gt;{ActiveConnection} = $conn;&lt;br /&gt;
$cmd-&gt;{CommandType} = 1;&lt;br /&gt;
$cmd-&gt;{CommandText} = &quot;set nocount on Create table #tempParam (MyInt int)\n&quot;;&lt;br /&gt;
$cmd-&gt;{CommandText} = $cmd-&gt;{CommandText} . &quot;Insert #tempParam Select 1\n&quot;;&lt;br /&gt;
$cmd-&gt;{CommandText} = $cmd-&gt;{CommandText} . &quot;Insert #tempParam Select 2\n&quot;;&lt;br /&gt;
$cmd-&gt;{CommandText} = $cmd-&gt;{CommandText} . &quot;Exec sp_AsManyAsYouLike&quot;;&lt;br /&gt;
&lt;br /&gt;
$WScript-&gt;Echo($cmd-&gt;CommandText . &quot;\n&quot;);&lt;br /&gt;
    &lt;br /&gt;
$RS = $cmd-&gt;Execute();&lt;br /&gt;
&lt;br /&gt;
while(!$RS-&gt;EOF){&lt;br /&gt;
$WScript-&gt;Echo($RS-&gt;Fields(0)-&gt;value);&lt;br /&gt;
$RS-&gt;MoveNext;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Which yeilds the following:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;set nocount on Create table #tempParam (MyInt int)&lt;br /&gt;
Insert #tempParam Select 1&lt;br /&gt;
Insert #tempParam Select 2&lt;br /&gt;
Exec sp_AsManyAsYouLike&lt;br /&gt;
&lt;br /&gt;
1000&lt;br /&gt;
2000&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
My example above is simplistic, but you can extend this model to pass all sorts of complex structures to a stored procedure.  I don&#039;t offer this solution as a brilliant design.  It is merely more palatable, and more flexible, than parsing strings with Transact SQL.   
    </content:encoded>

    <pubDate>Wed, 01 Mar 2006 00:03:00 -0600</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/27-guid.html</guid>
    <category>ado</category>
<category>database</category>
<category>parameters</category>
<category>perl</category>
<category>sql</category>
<category>sql2005</category>
<category>sql2k</category>
<category>stored procedures</category>
<category>transact sql</category>
<category>variable parameters</category>

</item>
<item>
    <title>Code Review:  OUTPUT parameters and transactions</title>
    <link>http://www.softwarevoices.com/archives/26-Code-Review-OUTPUT-parameters-and-transactions.html</link>
            <category>Database development</category>
    
    <comments>http://www.softwarevoices.com/archives/26-Code-Review-OUTPUT-parameters-and-transactions.html#comments</comments>
    <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=26</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=2.0&amp;type=comments&amp;cid=26</wfw:commentRss>
    

    <author>nospam@example.com (Glenn Crowe)</author>
    <content:encoded>
    File this one away for the next time you code review a SQL Server stored procedure.  Those OUTPUT parameters arent bound to your transactions in any way.&lt;br /&gt;
&lt;br /&gt;
Observe:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Create proc sp_OutputMyIdent (@myOutputIdent int output)&lt;br /&gt;
as&lt;br /&gt;
set nocount on&lt;br /&gt;
Begin transaction &lt;br /&gt;
    Insert myIdentTable Select &#039;foo&#039;&lt;br /&gt;
    Select @myOutputIdent = @@Identity&lt;br /&gt;
&lt;b&gt;rollback transaction&lt;/b&gt;&lt;br /&gt;
go&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Now a little ADO from JScript:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
myCommand.CommandText = &quot;sp_OutputMyIdent&quot;;&lt;br /&gt;
myCommand.CommandType = adCmdStoredProc;&lt;br /&gt;
myCommand.ActiveConnection = myConnection;        &lt;br /&gt;
myCommand.Parameters(&quot;@myOutputIdent&quot;) = 0;        &lt;br /&gt;
WScript.Echo(&quot;Before:  &quot; + myCommand.Parameters(&quot;@myOutputIdent&quot;));&lt;br /&gt;
myCommand.Execute();        &lt;br /&gt;
WScript.Echo(&quot;After:  &quot; + myCommand.Parameters(&quot;@myOutputIdent&quot;));&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Which yields the following:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Before:  0&lt;br /&gt;
&lt;b&gt;After:  1&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Errors dont alter this behavior at all.  Any reasonably competent scripting programmer can trap and then disregard your error.&lt;br /&gt;
&lt;br /&gt;
Observe:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Create proc sp_OutputMyIdent (@myOutputIdent int output)&lt;br /&gt;
as&lt;br /&gt;
set nocount on&lt;br /&gt;
Begin transaction &lt;br /&gt;
    Insert myIdentTable Select &#039;foo&#039;&lt;br /&gt;
    Select @myLocalVar = @@Identity&lt;br /&gt;
    &lt;b&gt;RaisError ( N&#039;Uh Oh!&#039;, 16, 1 )&lt;/b&gt;&lt;br /&gt;
rollback transaction &lt;br /&gt;
go&lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
myCommand.CommandText = &quot;sp_OutputMyIdent&quot;;&lt;br /&gt;
myCommand.CommandType = adCmdStoredProc;&lt;br /&gt;
myCommand.ActiveConnection = myConnection;        &lt;br /&gt;
myCommand.Parameters(&quot;@myOutputIdent&quot;) = 0;        &lt;br /&gt;
WScript.Echo(&quot;Before:  &quot; + myCommand.Parameters(&quot;@myOutputIdent&quot;));&lt;br /&gt;
myCommand.Execute();&lt;br /&gt;
}&lt;br /&gt;
catch(e){ WScript.Echo(e.description) }&lt;br /&gt;
WScript.Echo(&quot;After: &quot; + myCommand.Parameters(&quot;@myOutputIdent&quot;));&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Which yields the following:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Before:  0&lt;br /&gt;
Uh Oh!&lt;br /&gt;
&lt;b&gt;After:  2&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
The best thing to do is to keep your progress private until you know you are done:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Create proc sp_OutputMyIdent (@myOutputIdent int output)&lt;br /&gt;
as&lt;br /&gt;
set nocount on&lt;br /&gt;
Declare @myLocalVar int&lt;br /&gt;
Begin transaction &lt;br /&gt;
    Insert myIdentTable Select &#039;foo&#039;&lt;br /&gt;
    Select @myLocalVar = @@Identity&lt;br /&gt;
    RaisError ( N&#039;Uh Oh!&#039;, 16, 1 )&lt;br /&gt;
&lt;b&gt;commit transaction &lt;/b&gt;&lt;br /&gt;
Select &lt;b&gt;@myOutputIdent &lt;/b&gt;= @myLocalVar&lt;br /&gt;
go&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 
    </content:encoded>

    <pubDate>Thu, 16 Feb 2006 23:47:03 -0600</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/26-guid.html</guid>
    <category>database</category>
<category>output parameters</category>
<category>sql</category>
<category>sql2005</category>
<category>sql2k</category>
<category>stored procedures</category>

</item>
<item>
    <title>Set XACT_Abort ON:  Not quite the Panacea we thought it would be</title>
    <link>http://www.softwarevoices.com/archives/25-Set-XACT_Abort-ON-Not-quite-the-Panacea-we-thought-it-would-be.html</link>
            <category>Database development</category>
    
    <comments>http://www.softwarevoices.com/archives/25-Set-XACT_Abort-ON-Not-quite-the-Panacea-we-thought-it-would-be.html#comments</comments>
    <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=25</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=2.0&amp;type=comments&amp;cid=25</wfw:commentRss>
    

    <author>nospam@example.com (Glenn Crowe)</author>
    <content:encoded>
    So, you have stumbled across this SET option?  Lemme guess.  You&#039;ve had some problems with locking or poor performance.  Perhaps you just discovered some conditional logic in your stored procedures whereby BEGIN TRANSACTION, &lt;i&gt;some error&lt;/i&gt; and COMMIT TRANSACTION don&#039;t flow quite the way you thought they would.  What are your options?  If you think XACT_ABORT is your salvation, read on.&lt;br /&gt;
&lt;br /&gt;
At first glance, XACT_ABORT ON (it defaults to OFF) seems like the right answer:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;It seems plausible.  As soon as an error is encountered, roll back that transaction!  Release those locks!  Abort!  Who better to implement this than the DBMS itself?&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;It&#039;s surgical.  One call to sp_configure and all users will pick it up when they next create a connection.  But wait, you only have a few users and they are all currently caching hundreds of connections on who knows how many web servers.  Time for Plan B:  alter all the sproc definitions to SET XACT_ABORT ON right at the top of the procedure definition.  It&#039;s easy to script, and takes effect instantly.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;
Here is where I am going to go ahead and let you know that the XACT_ABORT setting is a little, well, misunderstood.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;It doesn&#039;t always abort the transaction.&lt;/h3&gt;&lt;br /&gt;
Observe:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Set XACT_ABORT On&lt;br /&gt;
Begin Transaction&lt;br /&gt;
RaisError ( N&#039;Uh Oh!&#039;, 16, 1 )&lt;br /&gt;
If @@Error &lt;&gt; 0 &lt;br /&gt;
begin print &#039;My rollback&#039; rollback transaction end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
This yields the following:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Msg 50000, Level 16, State 1, Line 3&lt;br /&gt;
Uh Oh!&lt;br /&gt;
My rollback&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
As you can see, the transaction wasn&#039;t aborted at all.  SQL Server seems to deem this scenario unworthy of the XACT_ABORT ON treatment.  This is somewhat forgivable.  After all, we hadn&#039;t changed any state or locked any resources.  But it&#039;s only somewhat forgivable.  If we didn&#039;t know the behavior and this was a business logic test that we were safely handling, we might not think it necessary to properly code the commit or rollback.  But that&#039;s not the whole story.  Let&#039;s actually do something transactional and see what we get.&lt;br /&gt;
&lt;br /&gt;
Observe:&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Set XACT_ABORT On&lt;br /&gt;
Begin Transaction&lt;br /&gt;
update dbo.TestXACT1 set mySmallInt = 0 where myInt = 1&lt;br /&gt;
print @@TranCount&lt;br /&gt;
RaisError ( N&#039;Uh Oh!&#039;, 16, 1 )&lt;br /&gt;
If @@Error &lt;&gt; 0 &lt;br /&gt;
begin print @@TranCount print &#039;My rollback&#039; rollback transaction end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
This yields the following:&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
(1 row(s) affected)&lt;br /&gt;
1&lt;br /&gt;
Msg 50000, Level 16, State 1, Line 5&lt;br /&gt;
Uh Oh!&lt;br /&gt;
1&lt;br /&gt;
My rollback&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Oh dear.  What does this mean?  We were transacting.  There was an @@Error.  But no transaction rollback occurred.&lt;br /&gt;&lt;br /&gt;
&lt;h3&gt;It does so much more than just rollback the transaction.&lt;/h3&gt;&lt;br /&gt;
Lets go ahead and invoke a case where we can rest assured SQL Server will actually roll something back.&lt;br /&gt;
&lt;br /&gt;
Observe:&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Set XACT_ABORT On&lt;br /&gt;
Begin Transaction&lt;br /&gt;
update dbo.TestXACT1 set mySmallInt = 32768 -- clearly not small&lt;br /&gt;
 where myInt = 1&lt;br /&gt;
print @@TranCount&lt;br /&gt;
If @@Error &lt;&gt; 0 &lt;br /&gt;
begin &lt;br /&gt;
    Print &#039;Couldn&#039;&#039;t update that myInt 1&#039; &lt;br /&gt;
    RaisError ( N&#039;Oh this is bad!  Alert the troops!&#039;, 16, 1 ) with log &lt;br /&gt;
    rollback transaction&lt;br /&gt;
end&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
This yields the following:&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Msg 220, Level 16, State 1, Line 3&lt;br /&gt;
Arithmetic overflow error for data type smallint, value = 32768.&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
I can assure you that the transaction is indeed gone.  Terminated.  Aborted.  But then so is your code.  It isn&#039;t just the transaction that this setting aborts.  It&#039;s the entire batch.  Wait, batch?  As in???&lt;br /&gt;
&lt;br /&gt;
Observe:&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Create procedure sp_TestXACT1 as &lt;br /&gt;
update dbo.TestXACT1 set mySmallInt = 32768 -- clearly not small&lt;br /&gt;
where myInt = 1&lt;br /&gt;
return -1&lt;br /&gt;
go&lt;br /&gt;
&lt;br /&gt;
Set XACT_ABORT On&lt;br /&gt;
Begin Transaction&lt;br /&gt;
Declare @RetCode int&lt;br /&gt;
update dbo.TestXACT1 set mySmallInt = 0 &lt;br /&gt;
 where myInt = 1&lt;br /&gt;
print @@TranCount&lt;br /&gt;
Exec @RetCode = sp_TestXACT1&lt;br /&gt;
print @RetCode&lt;br /&gt;
If @RetCode &lt;&gt; 0 &lt;br /&gt;
begin &lt;br /&gt;
    RaisError ( N&#039;Badness happened when I called sp_TestXACT1!!&#039;, 16, 1 ) with log &lt;br /&gt;
    rollback transaction&lt;br /&gt;
end&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
This yields the following:&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
(1 row(s) affected)&lt;br /&gt;
1&lt;br /&gt;
Msg 220, Level 16, State 1, Procedure sp_TestXACT1, Line 3&lt;br /&gt;
Arithmetic overflow error for data type smallint, value = 32768.&lt;br /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
So yeah, the whole batch.  From somewhere deep within the stack of sprocs which called other sprocs which called even more sprocs came the one line of code which ended consideration of all other lines of code.  The XACT was ABORTed and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
So where does this leave us?  In my mind XACT_ABORT has limited applications.  Certainly spend some time looking over your code before you decide what is best for your situation.  Robust error handling has always been hard, no matter what language you code.  These are your transactions and you are far better equipped to deal with them than your vendor. &lt;br /&gt;
&lt;br /&gt;
I tested the code above on SQL 2005.  There is new TRY,CATCH functionality available which could change the arguments, but I haven&#039;t had time to review.&lt;br /&gt;
 
    </content:encoded>

    <pubDate>Tue, 07 Feb 2006 01:40:00 -0600</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/25-guid.html</guid>
    <category>database</category>
<category>sql2005</category>
<category>sql2k</category>
<category>stored procedures</category>

</item>
<item>
    <title>SQL Server sps without XACT_ABORT on considered harmful</title>
    <link>http://www.softwarevoices.com/archives/4-SQL-Server-sps-without-XACT_ABORT-on-considered-harmful.html</link>
            <category>Database development</category>
    
    <comments>http://www.softwarevoices.com/archives/4-SQL-Server-sps-without-XACT_ABORT-on-considered-harmful.html#comments</comments>
    <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=4</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=2.0&amp;type=comments&amp;cid=4</wfw:commentRss>
    

    <author>nospam@example.com (Craig Ogg)</author>
    <content:encoded>
    &lt;b&gt;UPDATE:&lt;/b&gt; 1/31/2006 - &lt;i&gt;This is not an issue if you are using the connection pooling built into MDAC v2.6 or later (see Glenn&#039;s comments on this post for details - Thanks Glenn!). This is still something you should be aware of if you are using your own connection pooling.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
When you have a multi-step transaction in your stored procedures you are alway careful to check @@error and rollback if there is a problem.  You think you&#039;re safe, and then one day disaster strikes:  somehow random transactions were rolled back after they appeared to be commited (and after your application server returned the success results to client).  The only clue you have is some database timeouts in your application server logs.  What happened?&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.softwarevoices.com/archives/4-SQL-Server-sps-without-XACT_ABORT-on-considered-harmful.html#extended&quot;&gt;Continue reading &quot;SQL Server sps without XACT_ABORT on considered harmful&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Fri, 07 Oct 2005 09:30:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/4-guid.html</guid>
    <category>database</category>
<category>sql2k</category>
<category>stored procedures</category>

</item>

</channel>
</rss>