• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Numbering Rows in an SQL Result Set

    December 14, 2005 Ted Holt

    The code for this article is available for download.

    As I said on in an issue a few weeks ago, I like functions a lot. In this article, I present an SQL scalar function I wrote a few years ago that has proven itself to be handy. Consider it a Christmas present from Four Hundred Guru. I ho-ho-hope you like it.

    I call the function INCR, which is short for “increment.” I wrote it as a way to number the rows returned by an SQL SELECT query. INCR takes one parameter, a number that is one less than the first sequential number to be returned. If I had to do it over again, I would probably assign the starting value to the parameter, but I don’t have a compelling reason to rewrite working code and I would prefer to give you a version that is working than one that I haven’t used in production.

    In the following example, a customer file is sorted on last name and initials. The rows are numbered beginning with 1.

    SELECT incr(0),                                 
           LSTNAM, INIT, CUSNUM, CITY, STATE, ZIPCOD
      FROM qiws/qcustcdt                            
     ORDER BY 2,3
    

    Here’s the output from the query.

    INCR ( 0 )   LSTNAM    INIT   CUSNUM   CITY    STATE  ZIPCOD
             1   Abraham   M T   583,990   Isle     MN    56,342
             2   Alison    J S   846,283   Isle     MN    56,342
             3   Doe       J W   475,938   Sutter   CA    95,685
             4   Henning   G K   938,472   Dallas   TX    75,217
             5   Johnson   J A   938,485   Helen    GA    30,545
             6   Jones     B D   839,283   Clay     NY    13,041
             7   Lee       F L   192,837   Hector   NY    14,841
             8   Stevens   K L   389,572   Denver   CO    80,226
             9   Thomas    A N   693,829   Casper   WY    82,609
            10   Tyron     W E   397,267   Hector   NY    14,841
            11   Vine      S S   392,859   Broton   VT     5,046
            12   Williams  E D   593,029   Dallas   TX    75,218
    

    Here’s the same example, but the first row is numbered 10,000 instead of 1.

    SELECT incr(9999), 
           LSTNAM, INIT, CUSNUM, CITY, STATE, ZIPCOD
      FROM qiws/qcustcdt                            
     ORDER BY 2,3
    
    INCR ( 9999 )   LSTNAM    INIT   CUSNUM   CITY    STATE  ZIPCOD
           10,000   Abraham   M T   583,990   Isle     MN    56,342
           10,001   Alison    J S   846,283   Isle     MN    56,342
           10,002   Doe       J W   475,938   Sutter   CA    95,685
           10,003   Henning   G K   938,472   Dallas   TX    75,217
           10,004   Johnson   J A   938,485   Helen    GA    30,545
           10,005   Jones     B D   839,283   Clay     NY    13,041
           10,006   Lee       F L   192,837   Hector   NY    14,841
           10,007   Stevens   K L   389,572   Denver   CO    80,226
           10,008   Thomas    A N   693,829   Casper   WY    82,609
           10,009   Tyron     W E   397,267   Hector   NY    14,841
           10,010   Vine      S S   392,859   Broton   VT     5,046
           10,011   Williams  E D   593,029   Dallas   TX    75,218
    

    Here’s the the source code for the RPG program that increments the INCR function. I also call it INCR. Be sure to move the code right five places when you store the source code in a source physical file, or download this version.

     * =================================================================
     * Source code for the SQL INCR user-defined function.
     * =================================================================
     * On each call, this function returns one more than on the previous
     * call.  The function should be invoked with a parameter value one
     * less than than the first desired return value.
     * =================================================================
     * To create function in SQL:
     *
     *     create function MYLIB/incr
     *      (counter integer)
     *      returns integer
     *      external
     *      called on null input
     *      not deterministic
     *      language rpgle
     *      no sql
     *      parameter style db2sql
     *      scratchpad 4
     *      final call
     *      disallow parallel
     * =================================================================
     * To use in SQL:
     *      select xxx, incr(0), xxx from xxx  -- begin at 1
     *      select xxx, incr(999), xxx from xxx  -- begin at 1000
    
    H dftactgrp(*no) actgrp(*caller)
    
    D SeedValue       s             10i 0
    D ReturnValue     s             10i 0
    D SeedNull        s              5i 0
    D ReturnNull      s              5i 0
    D SQLState        s              5a
    D FunctionName    s            517a
    D SpecificName    s            128a
    D MsgText         s             70a   varying
    D Counter         s             10i 0
    D FinalCall       s             10i 0
    
    D FirstCall       c                   const(-1)
    D NormalCall      c                   const(0)
    D LastCall        c                   const(1)
    D
    D NullValue       c                   const(-1)
    D NotNullValue    c                   const(0)
    
    C     *entry        plist
    C                   parm                    SeedValue
    C                   parm                    ReturnValue
    C                   parm                    SeedNull
    C                   parm                    ReturnNull
    C* DB2SQL style parms
    C                   parm                    SQLState
    C                   parm                    FunctionName
    C                   parm                    SpecificName
    C                   parm                    MsgText
    C* Scratchpad
    C                   parm                    Counter
    C                   parm                    FinalCall
    
    C* if first call, and seed is not null, initialize to seed
    C                   if        FinalCall = FirstCall
    C                   if        SeedNull <> NullValue
    C                   eval      Counter = SeedValue
    C                   else
    C                   eval      Counter = *zero
    C                   endif
    C                   endif
    C
     * process normal call
    C                   if        FinalCall <> LastCall
    C                   eval      Counter = Counter + 1
    C                   eval      ReturnValue = Counter
    C                   else
    C                   eval      *inlr = *on
    C                   endif
    C
    C                   eval      ReturnNull = NotNullValue
    C                   eval      SQLState = '00000'
    C                   return
     * ===========================================================
    C     *pssr         begsr
    C
    C                   eval      SQLState = '38E01'
    C                   eval      MsgText = 'RPG program error -- INCR.'
    C                   return
    C
    C                   endsr
    

    Once you have the source on your system compile it using the Create Bound RPG (CRTBNDRPG) command. I suggest you compile it to run in the caller’s activation group. I’ve already set the activation group information in the H spec. Change it if you want something different.


    Then run the SQL CREATE FUNCTION command you’ll find in the comments of the RPG program.

      create function MYLIB/incr
         (counter integer)
         returns integer
         external
         called on null input
         not deterministic
         language rpgle
         no sql
         parameter style db2sql
         scratchpad 4
         final call
         disallow parallel
    

    I installed this function on the production system at my day job when I needed to load a file that required a unique value in a numeric key field. Without the INCR function, I would have had to use native I/O, rather than SQL, to load the file.

    INCR relies on a scratchpad to remember the value of the series from one row to the next. For more information and examples of use of the scratchpad, see the related articles.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    Rocket Software

    Software built on TRUST. Delivered with LOVE.

    For over 35 years, Rocket Software’s solutions have empowered businesses to modernize their infrastructure, unlock data value, and drive transformation – all while ensuring modernization without disruption.

    Learn More

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Robot/CONSOLE Keeps an Eye on iSeries Processor Usage Utility Service/400: Making the iSeries into a Different Market

    Leave a Reply Cancel reply

Volume 5, Number 46 -- December 14, 2005
THIS ISSUE
SPONSORED BY:

ProData Computer Svcs
Patrick Townsend & Associates
Twin Data

Table of Contents

  • Numbering Rows in an SQL Result Set
  • List Signed On Users From a Web Page
  • Admin Alert: The Great i5/OS Job Hunt

Content archive

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

Recent Posts

  • FAX/400 And CICS For i Are Dead. What Will IBM Kill Next?
  • Fresche Overhauls X-Analysis With Web UI, AI Smarts
  • Is It Time To Add The Rust Programming Language To IBM i?
  • Is IBM Going To Raise Prices On Power10 Expert Care?
  • IBM i PTF Guide, Volume 27, Number 20
  • POWERUp 2025 –Your Source For IBM i 7.6 Information
  • Maxava Consulting Services Does More Than HA/DR Project Management – A Lot More
  • Guru: Creating An SQL Stored Procedure That Returns A Result Set
  • As I See It: At Any Cost
  • IBM i PTF Guide, Volume 27, Number 19

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