• 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
    Raz-Lee Security

    Start your Road to Zero Trust!

    Firewall Network security, controlling Exit Points, Open DB’s and SSH. Rule Wizards and graphical BI.

    Request Demo

    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

  • Liam Allan Shares What’s Coming Next With Code For IBM i
  • From Stable To Scalable: Visual LANSA 16 Powers IBM i Growth – Launching July 8
  • VS Code Will Be The Heart Of The Modern IBM i Platform
  • The AS/400: A 37-Year-Old Dog That Loves To Learn New Tricks
  • IBM i PTF Guide, Volume 27, Number 25
  • 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

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