﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Steven Feuerstein's Blog</title>
    <description>&lt;table cellspacing="1" cellpadding="1"&gt;
        &lt;tr&gt;
            &lt;td valign="top"&gt;&lt;img height="183" alt="" width="139" src="/Portals/0/Blog/blog-steven-feuerstein.png" /&gt;&lt;/td&gt;
            &lt;td valign="top"&gt;Steven Feuerstein is considered one of the world's leading experts on the Oracle PL/SQL language, having written ten books on PL/SQL (all published by O'Reilly Media, including Oracle PL/SQL Programming. Steven has been developing software since 1980, spent five years with Oracle (1987-1992) and has served as PL/SQL Evangelist for Quest Software since January 2001. He is also an Oracle ACE Director. He writes regularly for Oracle Magazine, which named him the PL/SQL Developer of the Year in both 2002 and 2006.
            &lt;p&gt;&amp;#160;Steven's blog provides advice and code that you can put to immediate use in your world of programming.&amp;#160;&lt;/p&gt;
            &lt;p&gt;&lt;font color="#003366" size="3"&gt;&lt;strong&gt;Recent postings on his  PL/SQL Obsession:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
&lt;/table&gt;</description>
    <link>http://www.toadworld.com/BLOGS/tabid/67/BlogId/13/Default.aspx</link>
    <language>en-US</language>
    <managingEditor>Steven Feuerstein</managingEditor>
    <webMaster>webmaster@toadworld.com</webMaster>
    <pubDate>Fri, 19 Mar 2010 14:55:09 GMT</pubDate>
    <lastBuildDate>Fri, 19 Mar 2010 14:55:09 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>Blog RSS Generator Version 3.2.0.15477</generator>
    <item>
      <title>Functions should return data only through the RETURN clause</title>
      <description>&lt;div&gt;You will find below an excerpt from my latest publication: the 2&lt;sup&gt;nd&lt;/sup&gt; edition of &lt;em&gt;&lt;u&gt;&lt;a href="http://www.oreilly.com/catalog/9780596514105/ "&gt;Oracle PL/SQL Best Practices&lt;/a&gt;&lt;/u&gt;&lt;/em&gt;.  This edition is a complete rewrite of the 1&lt;sup&gt;st&lt;/sup&gt; edition. I decided that since software is still, for the most part, written by humans, I would create a cast of characters who write the software I reference and critique in this book.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt;They work for a company named My Flimsy Excuse, Inc (MFE) and their web site is &lt;u&gt;&lt;font color="#0000ff"&gt;&lt;a href="http://myflimsyexcuse.com"&gt;myflimsyexcuse.com&lt;/a&gt;&lt;/font&gt;&lt;/u&gt;. The mission statement of My Flimsy Excuse is simple and powerful:&lt;/font&gt;&lt;/div&gt;
&lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt;
&lt;div&gt;&lt;font color="#008080" size="2"&gt;Provide a wide array of excuses (flimsy and otherwise) to people in need of a way to explain away questionable behavior.&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font size="2"&gt;The MFE founders love technology and don't want to have any flimsy excuses for failure, so they have chosen Oracle as their database technology. They have several different development teams working on various aspects of the web-deployed business plan. The team, which has graciously volunteered to share their experiences with my readers, is made up of the following individuals:&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt; &lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;Sunita&lt;/font&gt;&lt;/div&gt;
&lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;The team leader, a very smart woman with a fast, razor-sharp mind. She is always busy, always constructive, and somewhat intimidating. She was a programmer in years past, mostly trained in Fortran and then some C+. She isn't sure if that makes her a better manager or a bigger danger to the team, but she still likes to get her hands "dirty," now and then, writing code. &lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font size="2"&gt;&lt;font color="#008000"&gt;Delaware &lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;A classic anarchistic, anti-standards, big ego kind of programmer. He has a hard time learning from anyone else, and writes code that is hard to understand....but he is very productive and very bright. If you need a job done overnight (literally), Delaware is the guy to do it. He claims to read up on all the latest features of PL/SQL, but he generally programs in a rut – relying on techniques learned years past in Oracle7. He keeps his thinning hair neatly trimmed, with just a hint of a comb-over, and favors three-piece suits from the Men's Wearhouse. &lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;Lizbeth &lt;/font&gt;&lt;/div&gt;
&lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;The anchor of the team. She used to write in Cobol and is continually shocked at the lack of strong process in the PL/SQL world. She can't understand why programmers today make fun of the Cobol programmers of the past. Didn't they write the software that made the first phase of the Information Revolution a broad success? Lizbeth is methodical and careful, but not, on the whole, the best problem solver—she too easily falls into the trap of seeing things only from her own perspective. &lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;Jasper&lt;/font&gt;&lt;/div&gt;
&lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;The junior member of the team. He is new to PL/SQL and new to MFE. Jasper is eager to learn from anyone and everyone and has nice thick skin, but he is not very creative (not ready to take risks in his code). He always wears jeans, preferably of the distressed variety, complemented by polo shirts with the logos of animals on them. Lizbeth thinks of him as the son she never had, and Delaware treats him like the mascot of the team.&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;And here is my recommended best practice and explanation for this first blog entry of the new year:&lt;/div&gt;
&lt;div&gt;&lt;hr /&gt;
&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;em&gt;&lt;font size="3"&gt;&lt;font size="4"&gt;Functions should return data only through the RETURN clause.&lt;/font&gt;&lt;/font&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;em&gt;&lt;font size="3"&gt; &lt;/font&gt;&lt;/em&gt;&lt;/strong&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font size="3"&gt;Problem: Jasper returns data in a very confusing manner.&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;strong&gt;&lt;font size="3"&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;/font&gt;&lt;/strong&gt;
&lt;div&gt;&lt;font size="2"&gt;Jasper needs a program to retrieve several pieces of information about an excuse: the title, the author and the word count. In just a few moments he builds the following function:&lt;/font&gt;&lt;/div&gt;
&lt;font size="2"&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;/font&gt;
&lt;div&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;/div&gt;
&lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt;
&lt;pre&gt;FUNCTION excuse_title (&lt;br /&gt;   excuse_id_in IN mfe_excuse.isbn%TYPE&lt;br /&gt; , author_out OUT mfe_excuse.author%TYPE&lt;br /&gt; , word_count_out OUT mfe_excuse.word_count%TYPE)&lt;br /&gt;RETURN mfe_excuse.title%TYPE&lt;br /&gt;IS BEGIN &lt;br /&gt;   ... implementation unimportant! ... &lt;br /&gt;END excuse_title;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;div&gt; &lt;font size="2"&gt;And then he puts this function to use as follows:&lt;/font&gt;&lt;/div&gt;
&lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt;
&lt;pre&gt;PROCEDURE process_excuse (excuse_id_in IN mfe_excuse.isbn%TYPE)&lt;br /&gt;IS&lt;br /&gt; l_title mfe_excuse.title%TYPE;&lt;br /&gt; l_author mfe_excuse.author%TYPE;&lt;br /&gt; l_word_count mfe_excuse.word_count%TYPE;&lt;br /&gt;BEGIN&lt;br /&gt;   l_title := excuse_title (l_id, l_author, l_word_count);&lt;br /&gt;   ...&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font size="2"&gt;Jasper is proud that he took the time to put this retrieval logic into its own program. Now it can be used in many places in the application. He shows everyone excuse_title at the weekly code review session. Imagine his dismay when Delaware snorts:&lt;/font&gt;&lt;/div&gt;
&lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt;
&lt;div&gt;&lt;font color="#008080" size="2"&gt;Humph. Well, Jasper, it's absolutely peachy keen that you wrote a reusable function. But that is not a program I would ever want to use. The name says you are giving me a title, and you are, but then you are also passing back all that other stuff. It's self-contradictory &lt;em&gt;and&lt;/em&gt; I have to declare a bunch of individual variables to use the darned thing!&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font size="2"&gt;Jasper pouts; he was so looking forward to a pat or two on the back. Sunita gives Delaware a dirty look and shakes her head. "Jasper," she says, drawing his attention away from Delaware's gloomy outlook, "hiding the lookup was an excellent move. You just need to take a step or two further, and make sure there are no mixed messages. Let's redesign excuse_title together."&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font size="3"&gt;Solution: Return multiple values through a single, composite structure or with a procedure.&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font size="3"&gt; &lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt;Here are the steps that Sunita takes to revamp the lookup function and make it more useful:&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;/div&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;font size="2"&gt;&lt;em&gt;&lt;font color="#ff0000"&gt;Make sure the name of the program reflects what it does:&lt;/font&gt;&lt;/em&gt;&lt;font color="#000080"&gt; In this case, the program doesn't return just the title; it returns several pieces of information about an excuse. Let's call it the "excuse_info" function.&lt;/font&gt;&lt;/font&gt; &lt;/li&gt;
    &lt;li&gt;&lt;font size="2"&gt;&lt;em&gt;&lt;font color="#ff0000"&gt;Pass everything in the RETURN clause:&lt;/font&gt;&lt;/em&gt;&lt;font color="#000080"&gt; Rather than returning one value through the RETURN clause and another through the parameter list, let's pass everything back in the RETURN clause, using a composite structure—in this case, a record.&lt;/font&gt;&lt;/font&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;font size="2"&gt;Here, then, is the new header of the program:&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;pre&gt;FUNCTION excuse_info (id_in IN mfe_excuse.id%TYPE)&lt;br /&gt;   RETURN mfe_excuse%ROWTYPE&lt;br /&gt;And here is the revised usage of this function:&lt;br /&gt;PROCEDURE process_excuse (excuse_id_in IN mfe_excuse.isbn%TYPE)&lt;br /&gt;IS&lt;br /&gt;   l_excuse mfe_excuse%ROWTYPE;&lt;br /&gt;BEGIN&lt;br /&gt;   l_excuse := excuse_info (l_id);&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font size="2"&gt;Now the code is leaner and cleaner. Everything that is returned by the function is deposited into a single record. And if you are concerned about returning all the data in a table's row, when you need only a small subset of its columns, you can always create your own user-defined record, as shown here:&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;/div&gt;
&lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt;
&lt;pre&gt;PACKAGE excuse_pkg&lt;br /&gt;IS&lt;br /&gt;   TYPE key_info IS RECORD (&lt;br /&gt;      title mfe_excuse.title%TYPE&lt;br /&gt;    , author mfe_excuse.author%TYPE&lt;br /&gt;    , word_count mfe_excuse.word_count%TYPE&lt;br /&gt;   );&lt;br /&gt; &lt;br /&gt;   FUNCTION excuse_info (id_in IN mfe_excuse.id%TYPE)&lt;br /&gt;      RETURN key_info;&lt;br /&gt;END excuse_pkg;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font size="2"&gt;To sum up: the whole point of a function is to return a value (whether it’s a single, scalar value or a composite, such as a record or a collection). If you also return data back through the parameter list with OUT or IN OUT arguments, the purpose and usage of the function will be obscured. &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt;If you need to return multiple pieces of information, take one of the following approaches: &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;Return a record or collection of values &lt;/font&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;Make sure to publish the structure of your record or collection (the TYPE statement) in a package specification so that developers can understand and use the function more easily. &lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;Break up a single function into multiple functions, all returning scalar values&lt;/font&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;With this approach, you can call the functions from within SQL statements. &lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;Change a function into a procedure&lt;/font&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;Unless you need to call a function to return this information, just change it to a procedure returning multiple pieces of information through the OUT arguments in the parameter list&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;font size="2"&gt;If you follow these guidelines, your subprograms will be more likely to be used and reused, because they will be defined in ways that make them easy to understand and apply in your own code. &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size="2"&gt;Your function may also then be callable from within a SQL statement, which encourages even wider use of this program. Note, though, that there are restrictions on function calls from SQL. You may not call a function with an OUT argument from within SQL, You also may not call a function that returns a record (the datatypes of all parameters must be SQL-compatible). &lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;</description>
      <link>http://www.toadworld.com/BLOGS/tabid/67/EntryID/166/Default.aspx</link>
      <author>Steven Feuerstein</author>
      <comments>http://www.toadworld.com/BLOGS/tabid/67/EntryID/166/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.toadworld.com/Default.aspx?tabid=67&amp;EntryID=166</guid>
      <pubDate>Mon, 07 Jan 2008 21:46:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.toadworld.com/DesktopModules/Blog/Trackback.aspx?id=166</trackback:ping>
    </item>
  </channel>
</rss>