• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Guru: Arranging Query Logic in DB2 for i Routines

    January 7, 2019 Michael Sansoterra

    Hey, Mike:

    We use a stored procedure to return the result set to Java and display the results to a screen. I would like to make this stored procedure put the result set into a temporary table and then do some processing on the temporary table. Is this possible and if so how can I achieve this? Thanks.

    Your dilemma is understandable: stored procedure result sets are great when data needs to be returned to a client. However, once generated, the result set cannot be joined, sorted, or stored in a temporary table. Thankfully, a user-defined table function (UDTF) allows a developer to perform additional operations on a query result set.

    The easiest way to accomplish this goal is to move the logic of your query from the stored procedure into a user-defined table function. Thereafter, to prevent duplicate query code, the stored procedure can be refactored to use the UDTF to build the result set for your Java program. The UDTF will provide a way to store the result set in a temporary table.

    Let’s look at a simple example. Say the below code is your stored procedure that receives a customer ID and returns a result set of customer orders (using IBM i 7.3 but it should work on earlier versions):

    CREATE OR REPLACE PROCEDURE GetOrders (@CustomerId IN INT)
    LANGUAGE SQL
    RESULT SETS 1
    NO EXTERNAL ACTION
    BEGIN
    
     DECLARE SalesOrders CURSOR FOR 
      SELECT SalesOrderId,CustomerId,
             OrderDate,ShipDate,SubTotal
        FROM SalesOrderHeader
       WHERE CustomerId=@CustomerId
    ORDER BY SalesOrderId;
    
    OPEN SalesOrders;
    
    SET RESULT SETS CURSOR SalesOrders;
    
    END;
    

    The procedure can be invoked as follows:

    CALL GetOrders (11091);
    

    The SELECT statement to build the result set contains the important logic and can be incorporated in an SQL UDTF as follows:

    CREATE OR REPLACE FUNCTION GetOrders (
    @CustomerID INT)
    RETURNS TABLE (
    SalesOrderId INT,
    CustomerId   INT,
    OrderDate    DATE,
    ShipDate     DATE,
    SUBTOTAL     DEC(19,4))
    LANGUAGE SQL
    NO EXTERNAL ACTION
    DISALLOW PARALLEL
    SET OPTION COMMIT=*NONE,USRPRF=*OWNER,DATFMT=*ISO
        RETURN
            SELECT SalesOrderId,CustomerId,
                   OrderDate,ShipDate,SubTotal
              FROM SalesOrderHeader
             WHERE CustomerId=@CustomerId
          ORDER BY SalesOrderId;
    

    Notice the SELECT statement is the same in both routines. The UDTF can be invoked as shown here and will return the same result set as the stored procedure:

    SELECT * FROM TABLE(GetOrders (11091)) Orders
    

    Now you can also create a temporary table using the function and the CREATE TABLE AS statement:

    CREATE TABLE TEMP_ORDERS AS (
    SELECT * FROM TABLE(GetOrders (11091)) Orders
    )
    WITH DATA;
    

    Just a quick word of warning, be careful about using an ORDER BY in a UDTF as it will often be ignored/overridden by a host query.

    Unless IBM changed it recently, the CREATE TABLE AS statement doesn’t support substitution parameters, so passing the customer number may require the use of EXECUTE IMMEDIATE. Here is a cheapskate example of how to do this using SQL:

    BEGIN
    
    DECLARE @SQL VARCHAR(1000);
    DECLARE @CUSTOMER_ID INT DEFAULT 11091;
    
    SET @SQL=
    'CREATE TABLE TEMP_ORDERS AS 
    (SELECT * FROM TABLE(GetOrders (' || VARCHAR(@CUSTOMER_ID) || ')) Orders) 
    WITH DATA';
    
    EXECUTE IMMEDIATE @SQL;
    
    END;
    

    Another approach to this problem that isn’t as messy as EXECUTE IMMEDIATE is to use a global variable to store the customer ID, since you can pass that variable into the function.

    Back to the task at hand, to minimize the duplication of logic and queries, you can replace the original SELECT statement in the stored procedure with a reference to the table function:

    CREATE OR REPLACE PROCEDURE GetOrders (@CustomerId IN INT)
    LANGUAGE SQL
    RESULT SETS 1
    NO EXTERNAL ACTION
    BEGIN
    
    DECLARE SalesOrders CURSOR FOR 
     SELECT Orders.*
       FROM TABLE(GetOrders(@CustomerID)) ORDERS;
    
    
    OPEN SalesOrders;
    
    SET RESULT SETS CURSOR SalesOrders;
    
    END;
    

    This technique is beneficial when code reuse is desired. However, code reuse is often harmful to performance so, depending on your situation, you may not want to adopt this approach. At the very least, a table function wrapper is going to impose some overhead on the stored procedure. But if your UDTF logic is simple and your IBM i is at i 7.2 TR4 or later, then DB2 may do you a favor and run your UDTF “inline” which should minimize the performance tax of using a UDTF.

    If for some reason your stored procedure is complicated enough so that you can’t reasonably move the code that builds the result set into a UDTF, then it is possible to build an external UDTF that wraps the stored procedure result set. The UDTF invokes the stored procedure (the opposite of what I showed above), captures and returns the result set, which allows a developer to further manipulate the data using DML. In a future tip, I will demonstrate how to create a Java UDTF wrapper to do this.

    A general design principle to take away is this: a UDTF is more versatile than a stored procedure for building result sets that may require further operations. If the performance tax is not too high and code reuse is desirable, code your result set queries in UDTFs. This specific advice only applies to building result sets; UDTFs should not necessarily be used to replace your view or materialized query table definitions!

    RELATED STORY

    Inline Table Functions In DB2 For i

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags: Tags: 400guru, DB2, FHG, Four Hundred Guru, IBM i, Java, SQL, UDTF, user-defined table function

    Sponsored by
    WorksRight Software

    Do you need area code information?
    Do you need ZIP Code information?
    Do you need ZIP+4 information?
    Do you need city name information?
    Do you need county information?
    Do you need a nearest dealer locator system?

    We can HELP! We have affordable AS/400 software and data to do all of the above. Whether you need a simple city name retrieval system or a sophisticated CASS postal coding system, we have it for you!

    The ZIP/CITY system is based on 5-digit ZIP Codes. You can retrieve city names, state names, county names, area codes, time zones, latitude, longitude, and more just by knowing the ZIP Code. We supply information on all the latest area code changes. A nearest dealer locator function is also included. ZIP/CITY includes software, data, monthly updates, and unlimited support. The cost is $495 per year.

    PER/ZIP4 is a sophisticated CASS certified postal coding system for assigning ZIP Codes, ZIP+4, carrier route, and delivery point codes. PER/ZIP4 also provides county names and FIPS codes. PER/ZIP4 can be used interactively, in batch, and with callable programs. PER/ZIP4 includes software, data, monthly updates, and unlimited support. The cost is $3,900 for the first year, and $1,950 for renewal.

    Just call us and we’ll arrange for 30 days FREE use of either ZIP/CITY or PER/ZIP4.

    WorksRight Software, Inc.
    Phone: 601-856-8337
    Fax: 601-856-9432
    Email: software@worksright.com
    Website: www.worksright.com

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Four Hundred Monitor, January 7 LANSA Bought By Software Conglomerate Idera

    Leave a Reply Cancel reply

TFH Volume: 29 Issue: 1

This Issue Sponsored By

  • ProData Computer Services
  • iTech Solutions
  • RPG & DB2 Summit
  • Computer Keyes
  • Manta Technologies

Table of Contents

  • IBM’s Plan For Etching Power10 And Later Chips
  • LANSA Bought By Software Conglomerate Idera
  • Guru: Arranging Query Logic in DB2 for i Routines
  • Four Hundred Monitor, January 7
  • IBM i PTF Guide, Volume 20, Numbers 50 And 51

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • Meet The Next Gen Of IBMers Helping To Build IBM i
  • Looks Like IBM Is Building A Linux-Like PASE For IBM i After All
  • Will Independent IBM i Clouds Survive PowerVS?
  • Now, IBM Is Jacking Up Hardware Maintenance Prices
  • IBM i PTF Guide, Volume 27, Number 24
  • Big Blue Raises IBM i License Transfer Fees, Other Prices
  • Keep The IBM i Youth Movement Going With More Training, Better Tools
  • Remain Begins Migrating DevOps Tools To VS Code
  • IBM Readies LTO-10 Tape Drives And Libraries
  • IBM i PTF Guide, Volume 27, Number 23

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle