Jared
Jared

Reputation: 101

How do I programmatically run a complex query on an as400?

I'm new at working on an as400 and I have a query the joins across 4 tables. The query itself is fine, it runs in STRSQL and displays the results.

What I am in struggling with is getting the query to be able to run programmatically (it will eventually be run from a scheduled CL script).

I tried have creating a physical file that contains the query running it with RUNQRY, but it simply displays the query itself, not the actual result set.

Does anyone know what I am doing wrong?


UPDATE

Thanks everyone for the direction and the resources, with them I was able to reach my goal. In case it helps anyone, this is what I ended up doing (all of this was done in it's own library, ALLOCATE):

  1. Created a source physical file (using CRTSRCPF): QSQLSRC, and created a member named SQLLEAGSEA, with the type of TXT, that contains the SQL statement.

  2. Created another source physical file: QCLSRC, and created a member named POPLEAGSEA, with the type of CLP, that changes the current library to ALLOCATE then runs the query using RUNSQLSTM (more detail on this below). Here is the actual command:

    RUNSQLSTM SRCFILE(QSQLSRC) SRCMBR(SQLLEAGSEA) COMMIT(*NONE) NAMING(*SYS)

  3. Added the CLP to the scheduled jobs (using ADDJOBSCDE), running the following command:

CALL PGM(ALLOCATE/POPLEAGSEA)

With regard to RUNSQLSTM, my research indicated that I wasn't going to be able to use this function, because it didn't support SELECT statements. What I didn't indicate in my question was what I needed to do with the the result - I was going to be inserting the resultant data into another table (had I done that I'm sure the help could have figured that out a lot quicker). So effectively, I wasn't going to be doing an SELECT, my end result is actually an INSERT. So my SQL statement (in SQLLEAGSEA) begins with:

INSERT INTO ALLOCATE/LEAGSEAS

SELECT ... BLAH BLAH BLAH ...

From my research, I gather that RUNSQLSTM doesn't support SELECT because it doesn't have a mechanism to do anything with the results. Once I stopped taking baby steps and realized I needed to SELECT AND INSERT in the same statement, it solved my main problem.

Thanks again everyone!

Upvotes: 10

Views: 25434

Answers (6)

kratenko
kratenko

Reputation: 7594

There is of course a totally different solution: You could write and compile a program containing the statement. It requires some longer reading into, especially if you are new to the platform, but it should give you most flexibility over what you do with results. You can use SQL in C, C++, RPG, RPG/LE, REXX, PL (of which I don't know, what it is) and COBOL. Doing that, you can react in any processable way on results from one query and start/create other queries based on what you get.

Although some oldfashioned RPG-programmers try everything to deny SQL in RPG exists, it is possible today for many cases, to write RPG-programs with SQL only and no direct file access (without F-Specs, for those who know RPG).

If your solution works for you, perfect. If you need to do something else, try a look into this pdf: http://publib.boulder.ibm.com/infocenter/iseries/v5r3/topic/rzajp/rzajp.pdf

The integration into RPG is not too bad. It works with the normal program flow. Would look something like this (in free form):

/free
    // init search values:
    searchval = 'Someguy';
    // so the sql query:
    exec sql
      SELECT colum1, colum2
      INTO :var1, :var2
      FROM somelib/somefile
      WHERE keycol=:searchval;
    // now do something with the values:
    some_proc(var1);
/end-free

In this, var1, var2, and searchval are ordinary RPG-variables. No quoting needed. Works also with datastructures (externally defined e.g., the record format of the file itself fits well). You can work with cursors and loops, too, of course. I feel that RPG-programs tend to be easier to read with this.

Upvotes: 1

user2466974
user2466974

Reputation: 11

This will work in two steps:

 RUNSQL SQL('CREATE TABLE QTEMP/REPORT AS (SELECT +         
          EXTRACT_DATE , SYSTEM, ODLBNM, SUM( +              
          OBJSIZE_MB ) AS LIB_SIZE FROM +                    
          ZSYSCOM/DISKRPTHST WHERE ODLBNM LIKE +             
          ''SIS%'' GROUP BY EXTRACT_DATE, SYSTEM, +          
          ODLBNM ORDER BY LIB_SIZE DESC) WITH +              
          DATA') COMMIT(*NONE) DATFMT(*USA) DATSEP(/)        

 RUNQRY     QRYFILE((QTEMP/REPORT)) OUTTYPE(*PRINTER) +          
          OUTFORM(*DETAIL) PRTDFN(*NO) PRTDEV(*PRINT)        

The first step creates a temporary table result in qtemp and the second step/line runs an adhoc query over just the temporary table to a spool file.

Thanks, Michael Frilot

Upvotes: 1

Bill M
Bill M

Reputation: 21

It is (now) possible to run SQL directly in a CL program without using QM Query, RUNSQLSTM or QShell.

Here is an article that discusses the RUNSQL statement in CL programs...

http://www.mcpressonline.com/cl/the-cl-corner-introducing-the-new-run-sql-command.html

The article contains information on what OS levels are supported as well as clear examples of several ways to use the RUNSQL statement.

Upvotes: 2

WarrenT
WarrenT

Reputation: 4542

QM Query

If all the SQL you need is the single complex SQL statement, and this is what it sounds like, then your best bet is to use Query Management Query (see QM Query manual here).

The results can be directed to a display, a spool file, or a physical file (ie a DB2 table). The default output when run interactively is to the screen, but when run in a (scheduled) batch job it will default to a spool file report.

You can create the QM Query interactively via WRKQMQRY, in prompted mode (much like Query/400) or in SQL mode. Or you can compile the QM Query from source, with the CRTQMQRY command.
To run your QM Query, STRQMQRY command.

RUNSQL cmd

If you are using a system that has IBM i 7.1 fully up-to-date, and has Technology Refresh 4 (TR4) installed, then you could also use the new RUNSQL command to execute a single statement. (see discussion in developerWorks)

SQL Scripting w/ RUNSQLSTM cmd

From CL you can run SQL scripts of multiple SQL statements from a source file member. There is no standard default source file name for this, but QSQLSRC is commonly used. The source member can contain multiple non-interactive SQL statements. This means you cannot use a SELECT statement (directly) since theoretically it will not know where to send the results. CL commands are even allowed if given a CL: prefix. Both SQL and CL statements should be terminated with a semicolon ;. While the SQL statements cannot display data directly to the screen, the same restriction does not apply to the scripted CL commands.

The STRQMQRY command can be embedded in the RUNSQLSTM script, by placing the prefix "CL: " in front of the command. Since STRQMQRY can direct output to the screen, a report, or an output table, this can come in very useful.

Remember that to direct your output from a SELECT query to a file you can use either the INSERT or CREATE TABLE statements.

CREATE TABLE newtbl AS
  ( full-select )
  WITH DATA;

Or, to put the results into a table you create in your job's QTEMP library:

DECLARE GLOBAL TEMPORARY TABLE AS
  ( full-select )
  WITH DATA;

[Note: If you create the source to be used by CRTQMQRY, you are advised to create it as CRTSRCPF yourlib/QQMQRYSRC RCDLEN(91), since the compiler will only use 79 columns of your source data (adding 12 for sequence and change date =91). However for QM Forms, which can be used to provide additional formatting, the CRTQMFORM compiler will use 81 columns so RCDLEN(93) is advised for QQMFORMSRC.]

Upvotes: 4

James Allman
James Allman

Reputation: 41208

The command is RUNSQLSTM to run a static SQL statement in a physical file member or stream file.

It is a non-interactive command so it will not execute sql statements that attempt to return a result set.

If you want more control, including the ability to run interactive statements, see the Qshell db2 utility.

For example:

QSH CMD('db2 -f /QSYS.LIB/MYLIB.LIB/MYSRCFILE.FILE/MYSQL.MBR')

Note that the db2 utility only accepts the *SQL naming convention.

Upvotes: 5

Buck Calabro
Buck Calabro

Reputation: 7633

RUNQRY is a utility that lets you execute a query that was created by another utility named WRKQRY. If you really want to process SQL statements held in a file try RUNSQLSTM. It uses a source physical file to store the statements, not a database file. The standard name for that source physical file is QQMQRYSRC. To create that file, CRTSRCPF yourlib/QQMQRYSRC. Then you can use PDM to work with that source PF. WRKMBRPDM yourlib/QQMQRYSRC. Use F6 to create a new source member. Make it source type TXT. Then use option 2 to will start an editor called SEU. Copy/paste your SQL statements into this editor. F3 to save the source. Once the source is saved, use RUNSQLSTM to execute it.

Upvotes: 2

Related Questions