• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • SQL Record Selection with Dynamic Lists

    September 28, 2005 Ted Holt

    SQL’s IN predicate provides an easily understood, practical way to select records (rows) of a database file (table) by comparing a field’s (column’s) value to a list of predetermined values. However, when using IN with a dynamic list, i.e., a list whose values and number of values are not specified until run time, IN has a drawback, namely that the programmer must allow for the number of values in the list in advance. This article will give you three ways to deal with dynamic lists.

    But first, a brief review of the IN predicate is in order. One way to use IN is to specify a list of hard-coded literals. The following SQL query selects data for anyone whose last names are Jones, Doe, or Vine.

    select cusnum,lstnam,init,city,state
      from qiws/qcustcdt
     where upper(lstnam) in ('JONES','DOE','VINE')
    

    The query returns these rows.

    CUSNUM    LSTNAM    INIT  CITY     STATE
    839,283   Jones     B D   Clay     NY
    392,859   Vine      S S   Broton   VT
    475,938   Doe       J W   Sutter   CA
    

    A second form of IN uses a subquery to generate the list.

    select cusnum,lstnam,init,city,state
      from qiws/qcustcdt
     where upper(lstnam) in
       (select name from qtemp/select)
    

    The SQL processor reads the SELECT table in library QTEMP and builds a list from the values in the NAME column.

    Let’s return to ways to deal with dynamic lists. Suppose you wish to allow the user to key one or more values of some type at run time. The user might key one, two, or a dozen values, and the keyed values are used to select records from a database file. It would be nice to place a varying number of host variables in a program, but each value requires its own host variable. The following embedded SQL command allows for 12 selection values.

    C/exec sql
    C+ declare Input cursor for
    C+    select x.* from qcustcdt as x
    C+     where upper(lstnam) in
    C+     (:Nam01, :Nam02, :Nam03, :Nam04,
    C+      :Nam05, :Nam06, :Nam07, :Nam08,
    C+      :Nam09, :Nam10, :Nam11, :Nam12)
    C/end-exec
    

    If it becomes necessary to allow for more values, more host variables must be added. If the user wishes to search for fewer than 12 names, the values in the unused host variables must not cause the search to return erroneous results. So, how can you deal with dynamic lists?

    One method is to allow for a maximum number of host variables and fill the unused ones with a value that is unlikely to be stored in the database. Since a customer is unlikely to have the name !@#$%, for example, you might fill unused list elements with such a value, as in the following RPG program fragment, in which the user has entered 10 customer names.

    C/exec sql
    C+ declare Input cursor for
    C+    select x.* from qcustcdt as x
    C+     where upper(lstnam) in
    C+     (:Nam01, :Nam02, :Nam03, :Nam04,
    C+      :Nam05, :Nam06, :Nam07, :Nam08,
    C+      :Nam09, :Nam10, :Nam11, :Nam12)
    C/end-exec
    
    C                   eval      Nam11 = '!@#$%'
    C                   eval      Nam12 = '!@#$%'
    

    A second method is to use a sub query instead of a list of host variables. Create a temporary work file, into which the record selection values can be inserted. The following SQL query selects records customers whose names are Jones, Doe, and Vine.

    create table qtemp/select (name char(12))
    insert into qtemp/select values ('JONES')
    insert into qtemp/select values ('DOE')
    insert into qtemp/select values ('VINE')
    
    select cusnum,lstnam,init,city,state
      from qiws/qcustcdt
     where upper(lstnam) in
       (select name from qtemp/select)
    

    Finally, a third method you can use is to create the list in a character string and use the LIKE predicate, rather than IN, to carry out record selection. The following RPG program accepts a list of last names in the second parameter.

     * Note: QIWS must be in the library list at compile time 
     *       and at run time.                                 
                                                              
    Fqsysprt   o    f  132        printer                     
                                                              
    D*entry plist                                             
    D AAA111R         pr                  extpgm('AAA111R')   
    D   ouStatus                     8a                       
    D   inList                     120a   const               
    D AAA111R         pi                                      
    D   ouStatus                     8a                       
    D   inList                     120a   const               
                                                              
    D AllOK           c                   const('00-00000')   
    D HostStruc     e ds                  extname(QCUSTCDT)   
    D List            s            120a   varying             
    D PssrIsActive    s               n                       
    D SqlEof          c                   const('02000')      
    D Status          s                   like(ouStatus) 
    D True            c                   const(*on)     
                                                         
    C/exec sql                                           
    C+     set option closqlcsr=*endmod                  
    C/end-exec                                           
                                                         
    C/exec sql                                           
    C+ declare Input cursor for                          
    C+    select x.* from qcustcdt as x                           
    C+     where ','||:List||','                         
    C+      like '%,'||trim(upper(lstnam))||',%'         
    C/end-exec                                           
    C                                                    
    C                   eval      *inlr = *on            
    C                   eval      Status = AllOK         
    C                   eval      List = %trim(inList)   
    C/exec sql                                             
    C+ open Input                                          
    C/end-exec                                             
    C                   if        SQLStt >= SqlEof         
    C                   eval      Status = '10-' + SqlStt  
    C                   exsr      ShutDown                 
    C                   endif                              
    C                                                      
    C                   dow       '1'                      
    C/exec sql                                             
    C+ fetch Input into :HostStruc                         
    C/end-exec                                             
    C                   select                             
    C                   when      SqlStt = SqlEof          
    C                   leave                              
    C                   when      SQLStt > SqlEof          
    C                   eval      Status = '20-' + SqlStt  
    C                   exsr      ShutDown                 
    C                   endsl                                    
    C                   except    pline                          
    C                   enddo                                    
    C                                                            
    C                   exsr      ShutDown                       
     * ========================================================= 
    C     *pssr         begsr                                    
    C                                                            
    C                   eval      *inlr = *on                    
    C                                                            
    C                   if        PssrIsActive                   
    C                   return                                   
    C                   endif                                    
    C                                                            
    C                   eval      PssrIsActive = true            
    C                                                            
    C                   eval      Status = '99-99999'            
    C                   exsr      Shutdown                       
    C                                                
    C                   endsr                        
    C* ============================================= 
    C     ShutDown      begsr                        
    C                                                
    C                   eval      *inlr = *on        
    C                                                
    C                   if        Status <> AllOK    
    C                   dump(a)                      
    C                   endif                        
    C                                                
    C                   if        %parms >= 1        
    C                   eval      ouStatus = Status  
    C                   endif                        
    C                                                
    C                   return                       
    C                                                
    C                   endsr                        
                                                   
    Oqsysprt   e            pline       1          
    O                       lstnam                 
    O                       init             +0001 
    O                       cusnum           +0001 
    O                       city             +0001 
    O                       state            +0001 
    

    The names must be separated by commas and there must be no embedded blanks in the list. Here are some examples of such lists.

    JONES
    JONES,SMITH
    JONES,DOE,SMITH,GREEN,WHITE
    

    If the user enters the names Doe and Vine, and the system retrieves a record for VINE, the WHERE clause resolves to this:

    where ',DOE,VINE,' like '%,VINE,%'         
    

    The system selects the record.


    On the other hand, suppose the system reads the record of customer Jones. The WHERE clause resolves to this:

    where ',DOE,VINE,' like '%,JONES,%'         
    

    The system does not select the record.

    Now you have three ways to use dynamic lists of unpredictable sizes in embedded SQL. Since selection from lists allows you to give the user powerful and flexible report and inquiry programs, these techniques are worth mastering.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    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

    MaxAv’s New Wizard Simplifies Remote Journaling Setup Bsafe Steps Forward with New OS/400 Security Tools, Partners

    Leave a Reply Cancel reply

Volume 5, Number 36 -- September 28, 2005
THIS ISSUE
SPONSORED BY:

T.L. Ashford
WorksRight Software
Profound Logic Software

Table of Contents

  • API Corner: Database APIs
  • SQL Record Selection with Dynamic Lists
  • Admin Alert: Limiting the Long Reach of OS/400 Security Officers

Content archive

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

Recent Posts

  • IBM Unveils Manzan, A New Open Source Event Monitor For IBM i
  • Say Goodbye To Downtime: Update Your Database Without Taking Your Business Offline
  • i-Rays Brings Observability To IBM i Performance Problems
  • Another Non-TR “Technology Refresh” Happens With IBM i TR6
  • IBM i PTF Guide, Volume 27, Number 18
  • Will The Turbulent Economy Downdraft IBM Systems Or Lift It?
  • How IBM Improved The Database With IBM i 7.6
  • Rocket Celebrates 35th Anniversary As Private Equity Owner Ponders Sale
  • 50 Acres And A Humanoid Robot With An AI Avatar
  • IBM i PTF Guide, Volume 27, Number 17

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