• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Guru: Three Suboptimal I/O Practices

    February 5, 2018 Ted Holt

    I have on numerous occasions looked at source code that I had written in previous years and asked myself, “Why on earth did I do that? What could I have been thinking?” We live and learn, or at least we hope we learn. Today I share three database practices that I see from time to time that can be simplified. Maybe there’s something for you to learn today.

    Before I share the three examples, let me say that I do not consider the more cumbersome code to be wrong. To my way of thinking, any code that produces the correct results within an acceptable time and is easy to maintain is correct code. However, simpler is usually better, if for no other reason that simple code provides less room for error.

    Using A Cursor to Fetch One Row

    RPG programmers have traditionally lived and died by the CHAIN op code. CHAIN uses a search argument, which may be one or more fields, to randomly read one record from a keyed file. It’s understandable that an RPG programmer who is learning to use SQL for database I/O would use a cursor to accomplish the same. Here’s an example:

    D CustData      e ds                  extname(CUSTFILE25)
    
    D CustNumber      s              5p 0
    
      exec sql  declare c1 cursor for
                   select * from CUSTFILE25
                    where CustNo = :CustNumber
                    order by CustNo, SeqNo;
      exec sql  open c1;
      // check for error & handle accordingly
      exec sql  fetch c1 into :CustData;
      // check for error & handle accordingly
      exec sql  close c1;
    

    It’s necessary to use a cursor to retrieve a result set, but if you only want to retrieve one row, you can use SELECT INTO instead.

    D CustData      e ds                  extname(CUSTFILE25)
    
    D CustNumber      s              5p 0
    
      exec sql     select * into :CustData
                     from CUSTFILE25
                    where CustNo = :CustNumber
                    order by CustNo, SeqNo
                    fetch first row only;
      // check for error & handle accordingly
    

    In either case, you get one row, but the second is simpler. Be sure to include the FETCH FIRST ROW ONLY clause if more than one row could satisfy the query.

    Needlessly Re-execute A Dynamic SQL Statement

    Here a programmer executes a dynamically-built DELETE statement within a loop.

    D Command1        s             96a   varying
    D Where           s             96a   varying
    D CustNumber      s              5p 0
    D DueDate         s              7p 0
    D OrderType       s              1a
    D DOption         s              1a
    
      // Something sets DOption here
      dow '1';
         // something gets the data values from somewhere
         if CustNumber = *zero;
            leave;
         endif;
         select;
            when DOption = '1';
               Where = 'CustNo=' + %char(CustNumber);
            when DOption = '2';
               Where = 'DueDate=' + %char(DueDate);
            when DOption = '3';
               Where = 'OrdType=''' + OrderType + '''';
         endsl;
         Command1 = 'delete from SEM07161PF where ' + Where;
         exec sql execute immediate :Command1;
      // check for error & handle accordingly
      enddo;
    

    The same DELETE statement runs over and over within the loop, the only difference being the customer number, due date, or order type plugged into the WHERE clause. We can reduce a bit of overhead by preparing the statement in advance and passing the customer number, due date, or order type to the prepared statement as a parameter.

    D Command1        s             96a   varying
    D CustNumber      s              5p 0
    D DueDate         s              7p 0
    D OrderType       s              1a
    D DOption         s              1a
    
      // something sets DOption here
      Command1 = 'delete from SEM07161PF where';
      select;
         when DOption = '1';
            Command1 += ' CustNo=?';
         when DOption = '2';
            Command1 += ' DueDate=?';
         when DOption = '3';
            Command1 += ' OrdType=?';
      endsl;
      exec sql  prepare Stmt1 from :Command1;
      // check for error & handle accordingly
    
      dow '1';
         // something gets the customer number from somewhere
         if CustNumber = *zero;
            leave;
         endif;
         select;
            when DOption = '1';
               exec sql execute Stmt1 using :CustNumber;
            when DOption = '2';
               exec sql execute Stmt1 using :DueDate;
            when DOption = '3';
               exec sql execute Stmt1 using :OrderType;
         endsl;
         // check for error & handle accordingly
      enddo;
    

    Reading To Delete

    The last example comes from the world of record-level access (RLA). In the following example, the programmer deletes all records for a certain customer number.

    FCUSTFILE25uf   e           k disk
    
    D CustNumber      s              5p 0
    
      setll (CustNumber) CUSTFILE25;
      reade (CustNumber) CUSTFILE25;
      dow not %eof(CUSTFILE25);
         delete           CUSTFILE25;
         reade (CustNumber) CUSTFILE25;
      enddo;
    

    RPG’s DELETE op code may include a search argument in Factor 1, just as CHAIN does. The code may be simplified this way:

    FCUSTFILE25uf   e           k disk
    
    D CustNumber      s              5p 0
    
      dou not %found(CUSTFILE25);
         delete (CustNumber) CUSTFILE25;
      enddo;
    

    This feature of DELETE has been around for eons, but from what I see, the fact is not widely known. Notice that DELETE sets the %FOUND condition, not %EOF.

    There you have two SQL tips and one RLA tip. Even though I prefer SQL and use it as much as possible, I don’t think the native interfaces are obsolete. As Bob Cozzi pointed out to me in a recent email, there’s no SQL equivalent for CPYF . . . FMTOPT(*MAP *DROP).

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags: Tags: 400guru, Four Hundred Guru, Guru, IBM i, RPG, SQL

    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

    Will Blockchain Impact IBM i? Reckless or Riskless: IBM i App Dev Experts Talk Security

    2 thoughts on “Guru: Three Suboptimal I/O Practices”

    • Tim Molter says:
      April 3, 2020 at 9:36 am

      We had emailed Jon Paris on a similar question, and he said “Personally I view SQL as a set processing tool – so like you I would use it when retrieving a set of information – either multiple rows, or data from multiple tables. I would use a CHAIN when I was dealing with a known single entity.”

      My use of embedded SQL has always been when I want to process groups of records, like summarizing data. If I want to retrieve one record, I have always used a chain operation. I don’t remember being told to do this instead of a chain so what is your opinion on it?

      Reply
    • Ted Holt says:
      October 15, 2020 at 4:46 pm

      A set can have only one row in it. I don’t like mixing record-level access and SQL, so I use SQL when I can, even when I only want one row.

      Reply

    Leave a Reply Cancel reply

TFH Volume: 28 Issue: 9

This Issue Sponsored By

  • New Generation Software
  • WorksRight Software
  • RPG & DB2 Summit
  • Computer Keyes
  • Manta Technologies

Table of Contents

  • IBM Readies Mainstream Power9 Iron For Launch
  • Reckless or Riskless: IBM i App Dev Experts Talk Security
  • Guru: Three Suboptimal I/O Practices
  • Will Blockchain Impact IBM i?
  • The Persistence Of The IBM i Platform

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