<?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 'stored procedures' and 'return'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=stored+procedures,return&amp;orTags=0</link><description>Search results matching tags 'stored procedures' and 'return'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Bad habits to kick : using SELECT or RETURN instead of OUTPUT</title><link>http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-using-select-or-return-instead-of-output.aspx</link><pubDate>Fri, 09 Oct 2009 20:01:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:17475</guid><dc:creator>AaronBertrand</dc:creator><description>&lt;p&gt;&lt;i&gt;In my &lt;a href="http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-using-dashes-and-spaces-in-entity-names.aspx" title="http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-using-dashes-and-spaces-in-entity-names.aspx" target="_blank"&gt;last post in this series&lt;/a&gt;,
I
covered the use of "bad" characters in entity names, such as spaces
or dashes.&amp;nbsp; In this post I will talk about using RETURN and OUTPUT inappropriately.&lt;br&gt;&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;i&gt;&lt;/i&gt;Jamie Thomson touched on part of this pet peeve in response to one of the other posts in this series.&amp;nbsp; So let me ask, do you see anything wrong with this procedure?&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;table cellpadding="0" cellspacing="0" bgcolor="#eeeeee"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;-moz-background-clip:border;-moz-background-origin:padding;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font color="blue"&gt;CREATE&amp;nbsp;PROCEDURE&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;dbo.foo&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;AS&lt;br&gt;BEGIN&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SET NOCOUNT ON&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;DECLARE&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;&lt;br&gt;      @hr&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;,&lt;br&gt;      &lt;/font&gt;&lt;font color="#434343"&gt;@rc&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;EXEC&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@hr = &lt;/font&gt;&lt;font color="blue"&gt;&lt;/font&gt;&lt;font color="black"&gt;dbo.&lt;/font&gt;&lt;font color="darkred"&gt;sp_columns&amp;nbsp;&lt;/font&gt;&lt;font color="red"&gt;'dbo.bar'&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;SELECT&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@rc = &lt;/font&gt;&lt;font color="blue"&gt;&lt;/font&gt;&lt;font color="magenta"&gt;@@ROWCOUNT&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;SELECT &lt;/font&gt;&lt;font color="black"&gt;hr = &lt;/font&gt;&lt;font color="#434343"&gt;@hr&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;RETURN&amp;nbsp;&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="#434343"&gt;@rc&lt;/font&gt;&lt;font color="gray"&gt;);&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;END&lt;br&gt;GO&lt;/font&gt;&lt;font color="black"&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/blockquote&gt;

&lt;p&gt;The title of this post kind of gives it away, but I thought it would fun to ask anyway.&amp;nbsp; Here is what I see wrong: &lt;br&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms189499.aspx" title="http://msdn.microsoft.com/en-us/library/ms189499.aspx" target="_blank"&gt;SELECT&lt;/a&gt; should be used for returning resultsets, not scalars.&amp;nbsp; This procedure uses a SELECT statement to return a single value to the client.&amp;nbsp; This is inefficient because most applications will have to prepare additional objects (typically referred to as "recordsets") and other support in order to consume the result.&amp;nbsp; While it is certainly valid syntax to use SELECT to return scalar values, this does not need to be common in production code.&amp;nbsp; This is the kind of thing that can make it slightly harder for high-end applications to scale.&lt;br&gt;&lt;br&gt;While not definitive proof that this is bad, and while I use SELECT for multiple variable assignment, IIRC the standard does not allow SELECT without FROM.&amp;nbsp; And in the &lt;a href="http://msdn.microsoft.com/en-us/library/ms187731.aspx" title="http://msdn.microsoft.com/en-us/library/ms187731.aspx" target="_blank"&gt;26 SELECT examples in Books Online&lt;/a&gt;, not one of them references scalars, at least at the time of writing.&lt;br&gt;&lt;br&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms174998.aspx" title="http://msdn.microsoft.com/en-us/library/ms174998.aspx" target="_blank"&gt;RETURN&lt;/a&gt; is for exiting the procedure, and is intended for returning error / status codes, not data.&amp;nbsp; Do not use this to send back to the caller the latest IDENTITY value generated or the row count from an operation.&amp;nbsp; Note that you are restricted to using integer-based data anyway, since you cannot change the data type of the value passed back by RETURN().&amp;nbsp; For more information, see the topic "&lt;a href="http://msdn.microsoft.com/en-us/library/ms190778.aspx" title="http://msdn.microsoft.com/en-us/library/ms190778.aspx" target="_blank"&gt;Returning Data by Using a Return Code&lt;/a&gt;" in Books Online.&lt;br&gt;&lt;br&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms191422.aspx" title="http://msdn.microsoft.com/en-us/library/ms191422.aspx" target="_blank"&gt;OUTPUT&lt;/a&gt; is designed for returning scalar values (oh, and &lt;a href="http://msdn.microsoft.com/en-us/library/ms175498.aspx" title="http://msdn.microsoft.com/en-us/library/ms175498.aspx" target="_blank"&gt;cursors&lt;/a&gt;, but who does that?).&amp;nbsp; In the example above, we are sending two scalar values back to the caller (though, in fact, one should be a RETURN value), yet we are not using an OUTPUT parameter at all!&amp;nbsp; For more information, see the topic "&lt;a href="http://msdn.microsoft.com/en-us/library/ms187004.aspx" title="http://msdn.microsoft.com/en-us/library/ms187004.aspx" target="_blank"&gt;Returning Data by Using OUTPUT Parameters&lt;/a&gt;" in Books Online.&amp;nbsp; As an aside, I suggest always using the full word OUTPUT; you may be tempted to just type OUT but personally I find this lazy shorthand that could prove troublesome later - for example, if you have to search your codebase for all uses of OUTPUT parameters.&lt;br&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Yes, using OUTPUT makes it a little more complex to develop and debug stored procedures, since you have to declare your output parameters up front.&amp;nbsp; I am not against using SELECT for scalars while developing.&amp;nbsp; But there is no reason to deploy them that way.&amp;nbsp; You can even use a @debug parameter to switch the methodology depending on the scenario, e.g.: &lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;table cellpadding="0" cellspacing="0" bgcolor="#eeeeee"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;-moz-background-clip:border;-moz-background-origin:padding;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font color="blue"&gt;CREATE PROCEDURE &lt;/font&gt;&lt;font color="black"&gt;dbo.foo&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@debug &lt;/font&gt;&lt;font&gt;&lt;font color="blue"&gt; BIT&lt;/font&gt;&lt;/font&gt;&lt;font color="black"&gt; = &lt;/font&gt;&lt;font color="black"&gt;0&lt;/font&gt;&lt;font color="gray"&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@rc&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;    INT &lt;/font&gt;&lt;font color="black"&gt;= &lt;/font&gt;&lt;font color="gray"&gt;NULL&lt;/font&gt;&lt;font color="blue"&gt; OUTPUT&lt;/font&gt;&lt;font color="gray"&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;AS&lt;br&gt;BEGIN&lt;br&gt;&amp;nbsp;&amp;nbsp;SET NOCOUNT&lt;/font&gt;&lt;font color="black"&gt; &lt;/font&gt;&lt;font color="blue"&gt;ON&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;DECLARE&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@hr&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;EXEC&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@hr = &lt;/font&gt;&lt;font color="black"&gt;dbo.&lt;/font&gt;&lt;font color="darkred"&gt;sp_columns&amp;nbsp;&lt;/font&gt;&lt;font color="red"&gt;'dbo.bar'&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;SET&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@rc = &lt;/font&gt;&lt;font color="blue"&gt;&lt;/font&gt;&lt;font color="magenta"&gt;@@ROWCOUNT&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;IF&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@debug = &lt;/font&gt;&lt;font color="blue"&gt;&lt;/font&gt;&lt;font color="black"&gt;1&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;  BEGIN&lt;br&gt;      SELECT&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;hr =&lt;/font&gt;&lt;font color="blue"&gt; &lt;/font&gt;&lt;font color="#434343"&gt;@hr&lt;/font&gt;&lt;font color="gray"&gt;,&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;rc = &lt;/font&gt;&lt;font color="blue"&gt;&lt;/font&gt;&lt;font color="#434343"&gt;@rc&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;END&lt;br&gt;&lt;br&gt;  RETURN&amp;nbsp;&lt;/font&gt;&lt;font color="gray"&gt;(&lt;/font&gt;&lt;font color="#434343"&gt;@hr&lt;/font&gt;&lt;font color="gray"&gt;);&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;END&lt;br&gt;GO&lt;/font&gt;&lt;font color="black"&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/blockquote&gt;



&lt;p&gt;Now you can call this stored procedure with or without specifying the OUTPUT parameter up front.&amp;nbsp; (I use this @debug technique for a lot of debugging elements, including cases where using the flag can change the plan - in the normal case this doesn't really hurt anything because the production plan is the one that is in the cache 99.99% of the time.) &lt;br&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;table cellpadding="0" cellspacing="0" bgcolor="#eeeeee"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style="padding:10px 20px;-moz-background-clip:border;-moz-background-origin:padding;font-size:12px;font-family:consolas,lucida console,courier new,courier;-moz-background-inline-policy:continuous;"&gt;&lt;font color="green"&gt;--&amp;nbsp;debug&amp;nbsp;mode:&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;&lt;br&gt;EXEC&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;dbo.foo&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@debug = &lt;/font&gt;&lt;font color="black"&gt;1&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="green"&gt;--&amp;nbsp;normal&amp;nbsp;operation:&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;DECLARE&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;&lt;br&gt;  @rc&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;,&lt;br&gt;  &lt;/font&gt;&lt;font color="#434343"&gt;@hr&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;INT&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;EXEC&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@hr = &lt;/font&gt;&lt;font color="blue"&gt;&lt;/font&gt;&lt;font color="black"&gt;dbo.foo&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@rc = &lt;/font&gt;&lt;font color="blue"&gt;&lt;/font&gt;&lt;font color="#434343"&gt;@rc&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;OUTPUT&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;&lt;br&gt;PRINT&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@hr&lt;/font&gt;&lt;font color="gray"&gt;;&lt;br&gt;&lt;/font&gt;&lt;font color="blue"&gt;PRINT&amp;nbsp;&lt;/font&gt;&lt;font color="#434343"&gt;@rc&lt;/font&gt;&lt;font color="gray"&gt;;&lt;/font&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/blockquote&gt;

You'll notice that I laced the above commentary with several links to Books Online topics.&amp;nbsp; I highly recommend becoming very familiar with when and where you should use RETURN, OUTPUT and SELECT to return data from a stored procedure.

&lt;p&gt;&lt;i&gt;I am working on a series of "Bad habits to kick" articles, in an
effort to motivate people to drop some of the things that I hate to see
when I inherit code.&amp;nbsp; Up next: &lt;a href="http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/10/bad-habits-to-kick-using-select-omitting-the-column-list.aspx" title="http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/10/bad-habits-to-kick-using-select-omitting-the-column-list.aspx" target="_blank"&gt;using SELECT * / omitting the column list&lt;/a&gt;.&lt;/i&gt;&amp;nbsp; &lt;br&gt;&lt;/p&gt;</description></item></channel></rss>