Embedded SQL and Dynamic Sorting Subfiles

Embed Size (px)

Citation preview

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    1/17

    Embedded SQL and Dynamic Sorting Subfiles

    Contributed by Kevin VandeverFriday, 30 June 2000Last Updated Friday, 30 June 2000

    Sorting in RPG is a breeze with embedded SQL.

    When sorting data to be displayed in a subfile, the Open Query File (OPNQRYF) command is often used. This comes inhandy when you are providing the user with the ability to change how he displays the data in the subfile. I agree thatOPNQRYF is a powerful way to select and sort data before loading your subfile, but its real strength is sorting andselecting data in a batch environment. I have used it with subfile programs, and, althoughits a bit of a pain, it does work, especially if you use optimizing techniques. Another method for providing multiple sortingcriteria in your subfiles is to use logical files. One problem with logical files is that you are required to maintain an accesspath for every sort criterion required by your users. Another problem is the complexity of your subfile load routine whenusing multiple logical files to provide the users with different looks at the data. That gets ugly.

    What if you had a tool that allowed you the same select and sort capabilities as logical files and OPNQRYF but did so ina flexible and efficient manner, while allowing you to produce a well-structured, easily maintainable program? Wouldntthat be awesome? Well, with embedded SQL, thats just what you get. SQL embedded into your RPG program allows youto sort and select the data as you want, but it also provides the user with some added power.

    What if multiple users from different departments are going to use your subfile program but, as is usually the case withusers, they each want to see the data in a different order? You can certainly accomplish this by including enough logicalfiles in your program to cover every possible sorting criterion, but this may require many logical files, especially if the userwants secondary and tertiary sorts. This may also create unnecessary access path administration for the system if all the

    logical files are created for this one application. It also makes for an ugly subfile build routine in your RPG program.Another method to allow dynamically sorting subfiles is to use OPNQRYF. You could create one open query for eachpossible sort or dynamically create the open query based on what the user wants to do. Either way, you would bepassing parameters back and forth between the RPG and CL programs to either build the OPNQRYF command or selectwhich specific OPNQRYF command to use. Ive messed around with the latter method, and the CL can get cumbersomeif you try to give the users complete flexibility by allowing them to sort by more than one field at a time. I love users, butthats a lot of work just to provide them with a different view of the same data.

    By embedding SQL, you can dynamically build your SELECT statement based on how the user wants to sort the data, allin one neat little subroutine. You can also use techniques that allow you to provide this capability very efficiently and, witha couple of minor changes, for data on other AS/400s. Ill tell you how its done.

    Theres Nothing to See Here, Folks

    The DDS in Figure 1 is a standard load-all subfile. I have coded a window record format to allow the user to select fieldsby which to sort. I could have made this window a subfile window, but there are only four fields from which to choose, so Idecided to make the selection window a regular format.

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    2/17

    Look, Mom. No F-specs

    Well, thats not exactly true. In Figure 2 (page 96), there is one F-spec in the RPG program, but it is used for the displayfile. There are no F-specs for the data files; I will introduce them in the embedded SQL. The program is a basic load-allsubfile program to list the names from a database file. This program allows the user to display a window by using the F4

    key and selecting a field by which to sort. When the user presses the Enter key after selecting a field, the data is sortedby that field and redisplayed on the screen. Cool, huh? Take a look at the code, and I will explain what the embeddedSQL is doing.

    Behind Option 14

    Before I dig into the RPG code itself, I want to discuss the compile options you need to make this work. First of all, thissource member is type SQLRPGLE, not RPGLE. The SQL tells the compiler that there are embedded SQL statements inthis RPG code. The command used to create a program using an SQLRPGLE-type source member is Create SQL RPG

    ILE Program (CRTSQLRPGI). This command verifies, validates, and, if you choose, prepares the embedded SQLstatements during compile time. To use this command, you must have the SQL Development Kit licensed program.

    When using the CRTSQLRPGI command, there are some compile options you need to take into consideration. You maywant to tinker with some of the parameters when compiling SQLRPGLE source code. The Relational database (RDB)parameter tells you which database you are using. It can be the name of your local DB2 database, or, if you arenetworked using Distributed Relational Database Architecture (DRDA), it can contain the name of a remote AS/400database. If you use a remote database in the RDB parameter, you need to tell the compiler where to create the SQLpackage. This is done by entering a library and package name in the SQLPKG parameter. The Delay preparation(DLYPRP) parameter asks you if you want to delay preparation of your SQL statement until the program is run. Answer*YES to this parameter because you do not want to perform redundant access path validation. If you enter *NO in this

    parameter, access path validation is performed at compile time and again when the cursor is opened later duringruntime. By entering *YES, the validation is done only at runtime.

    There are many other parameters in the CRTSQLRPGI command. I have mentioned a few here that I commonly dealwith. However, I suggest you peruse them for yourself to see if there is anything of interest to your specificimplementation of this technique.

    The D-specs

    Now that you know how to compile an RPG program containing embedded SQL, you would probably like to know how tocode one. First, you create the basis for your dynamic selection capability. This is done with the help of D-specs. Definea 500-byte standalone field, SELCT1, to hold your initial SQL statement. (The number 500 was selected at random. Youneed a variable large enough to hold your SQL statement.) Initialize this field with your SQL statement. Define a second500-byte standalone field, SELCT2, to hold the user-defined SQL statement, which will be made up of the initial SQLstatement from

    SELCT1 plus the selection criteria assigned by the user. Also define a standalone field called ORDER and initialize it to

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    3/17

    DBLNAM, which is the last-name field in the database file. The ORDER variable will be used to append the field selectedby the user to the ORDER BY clause in the SELCT1 variable.

    Rules and Regulations

    All blocks of SQL code must begin with a slash (/) in position 7 followed by the EXEC SQL statement and must end witha slash in position 7 followed by the END-EXEC command. In between EXEC and END-EXEC is where you place all ofyour SQL code. Each line is signified by a plus sign (+) in position 7. The CONNECT RESET statement connects to thelocal DB2 database. If you were going to connect to a database on another machine, you would do so by replacing theRESET parameter with the name of the remote database.

    Prepare, Declare, and Open

    Now take a look at the rest of the mainline routine. First, you execute the PREP subroutine; this is where the dynamicSQL statement will be built. Create the dynamic SQL statement from what the user selected. Because this is the first timethrough, use the default value for the ORDER variable, setting it to DBLNAM in the D-specs. On subsequent timesthrough this subroutine, the user will have selected a field by which to sort, and that data will be placed in the ORDERvariable. Once you have appended the data in ORDER to the original SELECT statement defined in your D-specs, youhave a complete SELECT statement that will retrieve your data and order it appropriately.

    Now use that SELECT statement and retrieve your data. Then use the PREPARE statement to prepare a statementcalled SEL, using the new SELECT2 variable you just created. The PREPARE statement will validate the SQL statementcontained in the SELECT2 variable. Next, declare a cursor called MYCSR by using the DECLARE statement. You shouldallow this cursor the ability to scroll; create it from the SEL statement you just prepared in the previous line. Finally, open

    the cursor by using the OPEN command. Clear as spaghetti code, right?

    OK. Before I go on, let me explain cursors a little. When SQL runs a SELECT statement, the resulting rows create aresult table. A cursor provides a way to access that result table. Its kind of like a subfile in its own right. The cursor isused within an SQL program to maintain a position in the result table. SQL uses the cursor to work with the data in theresult table and make it available to your program. Your program may contain several cursors, although each must havea unique name.

    There are two types of cursors: serial and scrollable. A serial cursor is defined without using the SCROLL keyword. This

    type of cursor allows you to fetch each row onceand only once. If you want to retrieve a row more than one time, youmust close the cursor and reopen it. This kind of cursor is perfect for a load-all subfile because you want to see the dataonly once before loading it into your subfile. The subfile provides the scrolling of the data in this case.

    The scrollable cursor is what you have defined in your program, even though it is a load-all subfile. The advantage of ascrollable cursor is that you can move back and forth throughout the rows of data. By using different parameters in aFETCH statement, you can read the next or prior row, navigate to the first or last row, read the same row over again, orposition any number of rows forward or backward from the current row. This type of cursor can be used if you arebuilding your subfile one page at a time. The data remains in the cursor and is loaded into your subfile only one page at atime.

    OK. You have successfully validated the SELECT statement contained in your variable by using the PREPAREcommand; youve created a scrollable cursor that will contain the result table from your SELECT statement by using theDECLARE command;

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    4/17

    and youve opened the cursor by using the OPEN command. Now you are ready to load the subfile from the cursor.

    Here, BoyFetch!

    Check out the SFLBLD routine. Instead of loading the subfile directly from the database file, load it from the cursor byusing the SQL FETCH command. Notice that the FETCH command is inside your DO loop. Use the FETCH NEXTcommand and place the results in your display file field names. Because this is a scrollable cursor, you should use theNEXT parameter, but, as I mentioned before, you dont have to use a scrollable cursor when using a load-all subfile. I had

    you do this simply because I wanted to show you some of the parameters you can use with a scrollable cursor. Figure 3shows that, in addition to NEXT, there are other parameters with the FETCH command.

    Use SQLCOD to determine whether or not to write to the subfile record format. If you are astuteand I know you areyoumay have noticed that SQLCOD is not defined anywhere in the program or the display file. So where did it come from?Well, when you embed SQL in your program and use the CRTSQLRPGI command to create the program, a datastructure not unlike the file information data structure is included in your program. It is filled with all sorts of information onthe SQL statements embedded inside your program. One example of that information is the error code returned when anSQL statement is run. It is contained in the SQLCOD variable and is set to 0 upon successful execution of an SQLstatement. For more information on the SQL Data Area (SQLDA), look in IBMs DB2 for AS/400 SQL Programmingmanual. For this program, the only data you should use from the SQLDA is the SQLCOD variable.

    Once your subfile is loaded, you are ready to display it. Now go back to the mainline.

    Lets Kick It Up a Few Notches

    When displaying the subfile the first time, the data is sorted by last name because you initialized the ORDER variable tothe last-name field. Now that the user has the data in his control, he can press F4 to sort the data another way. If F4 is

    selected, a number of subroutines are executed. First, the SORT subroutine is executed, which determines what to placein the ORDER variable. Then, the CLEAN subroutine is executed. This simply closes the cursor, MYCSR. Once theORDER variable is given its proper value and the cursor is closed, the PREP and SFLBLD routines are executed again.You have already seen what they do.

    The last thing I want to take a look at is the SORT subroutine. There is no new, exciting subfile code in this routine, nor isthere any SQL. However, there is some code that may interest you. It is here that you determine what field to append tothe ORDER BY clause in your dynamic SQL statement. A window is displayed that lists the fields contained in thesubfile. The user can select one of these fields and press Enter. The program then determines which field was selectedand places that field in the ORDER variable. Pretty simple, huh? Well, if you really want to separate this technique fromwhats easily implemented by using logical files and open query files, you can allow the user to select more than one field.If the user wants to sort by first name, last name, and nickname, you allow him to enter a 1 next to first name, a 2 next tolast name, and a 3 next to nickname. Then, place logic in your SORT routine to interrogate all the fields selected, placethem in the correct order, and place that information in the ORDER variable. So instead of the ORDER variablecontaining one field to append to the ORDER BY clause, it now contains three.

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    5/17

    Now that the user has selected a field to sort by and pressed the Enter key, the subfile is redisplayed in the appropriateorder, with no open query files and no access paths to

    Voila!

    maintain. You have now seen how to use embedded SQL and subfiles to select and sort data dynamically. If you areinterested in learning more about SQL programming, I suggest you dig into IBMs DB2 for AS/400 SQL Programmingmanual. There you will learn all sorts of advanced techniques, such as allocating storage and loading the SQL data area(SQLDA) by using the SQL DESCRIBE command as well as implementing optimizing techniques to make your programs

    scream even more. Combining embedded SQL and subfile programming allows you to take your applications to newheights. Enjoy.

    REFERENCES AND RELATED MATERIALS

    DB2 for AS/400 SQL Programming (SC41-5611-03, CD-ROM QB3AQ803)

    A DSPSIZ(24 80 *DS3)

    A PRINT ERRSFL

    A CA03 CA12 CF04

    A*

    A R SFL1 SFL

    A DBLNAM R O 5 2REFFLD(DBLNAM SFL001PF)

    A DBFNAM R O 5 26REFFLD(DBFNAM SFL001PF)

    A DBMINI R O 5 50REFFLD(DBMINI SFL001PF)

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    6/17

    A DBNNAM R O 5 55REFFLD(DBNNAM SFL001PF)

    A*

    A R SF1CTL SFLCTL(SFL1)

    A SFLSIZ(0050) SFLPAG(0017)

    A OVERLAY

    A N32 SFLDSP

    A N31 SFLDSPCTL

    A 31 SFLCLR

    A 90 SFLEND(*MORE)

    A RRN1 4S 0H SFLRCDNBR

    A 4 2'Last Name' DSPATR(HI)

    A 4 26'First Name' DSPATR(HI)

    A 4 50'MI' DSPATR(HI)

    A 4 55'Nick Name' DSPATR(HI)

    A 1 2'SFL013RG'

    A 1 26'Dynamic Sort with Embedded SQL'

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    7/17

    A DSPATR(HI)

    A 1 71DATE EDTCDE(Y)

    A 2 71TIME

    A*

    A R FKEY1

    A 23 2'F3=Exit' COLOR(BLU)

    A +3'F4=Prompt' COLOR(BLU)

    A +3'F12=Cancel' COLOR(BLU)

    A R WINDOW1

    A WINDOW(*DFT 11 25)

    A TAB1 1 B 3 2

    A 3 5'Last Name'

    A TAB2 1 B 4 2

    A 4 5'First Name'

    A TAB3 1 B 5 2

    A 5 5'Middle Initial'

    A TAB4 1 B 6 2

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    8/17

    A 6 5'Nick Name'

    A 10 1'F3=Exit' COLOR(BLU)

    A 10 11'F12=Cancel' COLOR(BLU)

    A 1 3'Select a sort field'

    A DSPATR(HI)

    Figure 1: Using SQL to load a subfile requires no special DDS.

    *****************************************************************

    * To compile:

    * CRTSQLRPGI OBJ(xxx/SFL013RG) SRCFILE(xxx/QRPGLESRC) +

    * SRCMBR(SFL013RG) RDB(*LOCAL) OBJTYPE(*PGM) +

    * DLYPRP(*YES) SQLPKG(*OBJ)

    *****************************************************************

    Fsfl013df2 cf e workstn sfile(sfl1:rrn1)

    F infds(info)

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    9/17

    *

    * Information data structure to hold attention indicator byte.

    Dinfo ds

    D cfkey 369 369

    * Constants for attention indicator byte

    Dexit C const(X'33')

    Dprompt C const(X'34')

    Dcancel C const(X'3C')

    Denter C const(X'F1')

    Dorder S 8 INZ('dblnam')

    Dselct1 S 500A INZ('SELECT dblnam, dbfnam,D dbmini, dbnnamD FROM sfl001pfD ORDER BY ')

    Dselct2 S 500A INZ(' ')

    * Establish the connection to the remote machine. The -842 return

    * code indicates that the connection is already established. If

    * you want to connect to the local machine, use CONNECT.

    C/EXEC SQL

    C+ CONNECT RESET

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    10/17

    C/END-EXEC

    C exsr prep

    C exsr sflbld

    *

    C dou (cfkey = exit)

    C write fkey1

    C exfmt sf1ctl

    C select

    * prompt to selection sorting criteria

    C when cfkey = prompt

    C exsr sort

    C exsr clean

    C exsr prep

    C exsr sflbld

    C when cfkey = cancel

    C leave

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    11/17

    C endsl

    C enddo

    *

    C exsr clean

    * Disconnect the current connection.

    C/EXEC SQL

    C+ DISCONNECT CURRENT

    C/END-EXEC

    C eval *inlr = *on

    *****************************************************************

    * Prepare SQL cursor

    *****************************************************************

    C prep begsr

    *

    * Prepare the SQL statement for validation, since the program was

    * compiled with DLYPRP (*YES), it will wait until it is used before

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    12/17

    * it prepares the cursor.

    *

    C eval selct2 = %trimr(selct1) + ' ' + order

    *

    C/EXEC SQL

    C+ PREPARE sel FROM :selct2

    C/END-EXEC

    *

    * Declare the SQL cursor to hold the data retrieved from the SELECT

    C/EXEC SQL

    C+ DECLARE MYCSR SCROLL CURSOR FOR SEL

    C/END-EXEC

    *

    * Open the SQL cursor.

    C/EXEC SQL

    C+ OPEN MYCSR

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    13/17

    C/END-EXEC

    *

    C endsr

    *****************************************************************

    * Clean up before exiting

    *****************************************************************

    C clean begsr

    *

    * Close the SQL cursor after all processing is complete.

    C/EXEC SQL

    C+ CLOSE MYCSR

    C/END-EXEC

    *

    C endsr

    *****************************************************************

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    14/17

    * Build the subfile

    *****************************************************************

    C sflbld begsr

    *

    * Clear the subfile

    C eval *in31 = *on

    C write sf1ctl

    C eval *in31 = *off

    C eval rrn1 = 0

    *

    * Process the records in the SQL cursor until the return not = 0

    C dou sqlcod 0

    * Get the next row from the SQL cursor.

    C/EXEC SQL

    C+ FETCH NEXT FROM MYCSR

    C+ INTO :dblnam, :dbfnam, :dbmini, :dbnnam

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    15/17

    C/END-EXEC

    C if sqlcod = 0

    C eval rrn1 = rrn1 + 1

    C write sfl1

    C endif

    C enddo

    *

    C if rrn1 = 0

    C eval *in32 = *on

    C else

    C eval rrn1 = 1

    C endif

    *

    C eval *in90 = *on

    *

    C endsr

    *****************************************************************

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    16/17

    * SORT - prompt to select sort criteria

    *****************************************************************

    C sort begsr

    *

    C exfmt window1

    *

    C select

    C when tab1 *blank

    C movel(p) 'dblnam' order

    C clear tab1

    C when tab2 *blank

    C movel(p) 'dbfnam' order

    C clear tab2

    C when tab3 *blank

    C movel(p) 'dbmini' order

    C clear tab3

    MC Press Online

    http://www.mcpressonline.com Powered by Joomla! Generated: 28 September, 2008, 23:39

  • 7/27/2019 Embedded SQL and Dynamic Sorting Subfiles

    17/17

    C when tab4 *blank

    C movel(p) 'dbnnam' order

    C clear tab4

    C endsl

    *

    C endsr

    Figure 2: Embedded SQL makes powerful RPG.

    NEXT PRIOR FIRST LAST BEFORE AFTER CURRENT RELATIVE--+-host-variable-+--integer Figure 3: Additionalparameters for scrollable cursors allow easy access to a database.

    MC Press Online