Unit 1: Db2 Program Preparation
Unit 1: Db2 Program Preparation
DB2 PROGRAM PREPARATION SQL STATEMENT FORMATS (DELIMITERS) DB2 DATA TYPES - CHARACTER DATA TYPE GRAPHIC DATA TYPE NUMERIC DATA TYPE DATE / TIME DATA TYPES NULL ATTRIBUTE NULL ATTRIBUTE (Cont.) (NOT NULL) WITH DEFAULT USER DEFINED DEFAULT VALUES HOST VARIABLES HOST VARIABLES (Cont.) DB2 DATA TYPES VS HOST VARIABLES HOST STRUCTURES SELECTION OF A SINGLE ROW COMPILERS DONT UNDERSTAND SQL DB2 PROGRAM PREPARATION STEPS PRECOMPILATION DCLGEN COMMAND ..1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19
DCLGEN COMMAND (Cont.) SQL INCLUDE STATEMENT SQLCA DBRM DBRM (Cont.) COMPILATION AND LINK-EDIT BIND PACKAGE BIND PACKAGE (Cont.) PACKAGE PACKAGE (Cont.) COLLECTIONS APPLICATION PLAN CONSISTENCY TOKEN PROGRAM PREPARATION LOCATING PACKAGES AT EXECUTION TIME THE MISSING LINK PLAN AND PACKAGES BIND PLAN PACKAGE LIST BIND PLAN DBRMS
1.20 1.21 1.22 1.23 1.24 1.25 1.26 1.27 1.28 1.29 1.30 1.31 1.32 1.33 1.34 1.35 1.36
UNIT 3
: CURSOR HANDLING
3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8
OVERVIEW DEFINING CURSORS DEFINING CURSORS (Cont.) SAMPLE PROGRAM FOR CURSORS CURSOR DECLARATION UPDATING /DELETING WITH THE CURSORS READ-ONLY CURSORS READ-ONLY CURSORS (Cont.)
COBOL
PL/1
Notes: Whatever the language used, SQL statement will always have to be enclosed between delimiters so that they can be easily spotted and replaced by something the compilers will be able to understand. Different delimiters are used for different languages. These are the standard delimiters used in COBOL and PL/1.
CHAR(n) / CHARACTER(n) Fixed length string between 1 and 254 bytes VARCHAR(n) Variable length string
Notes : DB2 also supports DBCS (Double Byte Character Set) data like GRAPHIC
Notes: When calculations have to be performed Numeric Data Type have to be used.
Notes: DB2 does the necessary verifications on the data that is entered in these types. They can be manipulated using SQL scalar functions like DAYS, MONTH, YEAR .
NULL ATTRIBUTE
NULL is a special value indicating the absence of a value. Not consider for the column function evaluations (AVG) except COUNT. Two nulls are not considered as equal, except for GROUP BY ORDER BY
Notes: DB2 considers two null values as equal when it enforces the uniqueness of columns. You can change this by using the UNIQUE WHERE NOT NULL parameter.
Notes: The NULL attribute of a column is an important choice that will have to be made in cooperation with DBA.
NUMERIC columns fixed length CHARACTER columns fixed length GRAPHIC columns variable length CHARACTER and GRAPHIC columns. DATE data type. TIME data type. TIMESTAMP data type.
Notes: It is possible to provide your own default value. It will be used by DB2 if you fail to supply a value in the INSERT statement.
HOST VARIABLES
Host language variables that can be referenced in a SQL statement to supply values to DB2 or to receive values from DB2. They must be preceded by : when referenced in a SQL statement. Example EXEC SQL SELECT PHONENO INTO :PHONENO FROM EMP WHERE EMPNO = :EMPNO END-EXEC.
Notes: Host variables will be used by DB2 to: Retrieve data and put it in to host variable for use by application program INSERT data in to a table or to update it from the data in the host variable. Evaluate a WHERE or HAVING clause using the data in the host variable. However, host variable cannot be used to represent a table, view or a column. The colon( : ) is necessary to distinguish a host variable from a column name.
Example-COBOL DATA DIVISION. WORKING-STORAGE SECTION. 01 IOAREA. 02 INPEMPNO PIC 9 (6). 02 INPNAME PIC X (15). PROCEDURE DIVISION. MOVE HIGGINS TO INPNAME. MOVE 00260 TO INPEMPNO. EXEC SQL UPDATE EMP SET LASTNAME =:INPNAME WHERE EMPNO =:INPEMPNO END-EXEC.
Notes: This table shows how to define a host variable in a program to match a given DB2 data type. It is important to use the correct data type in our program. Although DB2 will, in many cases, convert the data type to make the data type match, this could lead to bad performance and should be avoided.
HOST STRUCTURES
COBOL
01 PHONEEMP. 05 EMPNO PIC X (06). 05 FIRSTNAME. 49 49 05 MIDINIT PIC X (01). 05 LASTNAME. 49 49 05 WORKDEPT 05 PHONENO
PL/1
DCL 1 5 5 5 5 5 5 PHONEEMP EMPNO FIRSTNAME MIDINIT LASTNAME WORKDEPT PHONENO CHAR (06), CAHR (12) VARYING, CAHR (01), CAHR (15) VARYING, CHAR (03), CHAR (04);
Notes: A host structure is a group of host variables referred to by a single name in an SQL statement. They are defined by statements of the host language.
Source Program
PRECOMPILER
DCLGEN
DB2 Bind converts the DBRM in to an executable format. The DB2 Catalog stores the information about the plan and the package. Bind Package Modified Source
DBRM
Bind Plan
Package
Compiler
Plan
Compiled Source
The DB2 Directory stored the actual plan and the package.
Linkage-Editor
DB2
Catalog
PRECOMPILATION
The DB2 application program contains COBOL code with SQL statements embedded in it. The COBOL compiler will not be able to recognize the SQL statements and will give compilation errors. So before running the COBOL compiler, the SQL statements must be removed from the source code. Recompilation does the following: Searches for and expands DB2 related INCLUDE members. Searches for SQL statements in the body of the programs source code. Creates a modified version of the source program in which every SQL statement in the program is commented and replaces with a CALL to the DB2 runtime interface module, along with applicable parameters. Extracts all the SQL statements and places them in a Database Request Module (DBRM). Places A Timestamp token in the modified source and the DBRM to ensure that these two items are inextricably tied. Reports on the success of failure of the precompiled process.
DCLGEN COMMAND
DCLGEN (Declaration Generator) Option 2 in DB2 Produces SQL DECLARE TABLE statement Host language variable declaration for a table or view Table (DECLARE table SQL) EXEC SQL DECLARE EMPTABLE (EMPNO CHAR (6) NOTNULL, Lang LASTNAME CHAR(15)) END-EXEC. (Data declaration source code) 01 DCLEMP. 05 EMPNO PIC X (6), 05 LASTNAME PICX(15).
Include member
DCLGEN
DB2 Catalog
Notes: The DCLGEN tool provided with DB2I produces a COBOL copybook, which contains SQL DECLARE TABLE along with the WORKING-STORAGE host variable definitions for each column of the table. Input will be the language (COBOL, PL/1) and the table name.
Notes: When DCLGEN command is issued, DB2 read the catalog to fetch the column definition for the table, and will generate an include member with the DECLARE TABLE and the host structure. DCLGEN command can be eliminated by hard coding in the application program. But it is a good practice to run the DCLGEN command for every table that will be embedded in a COBOL program. Then every program that accesses that table can INCLUDE that generated copybook. This reduces a lot of unnecessary coding. DCLGEN will generate the host variables with the same name as the column name and if the program uses two tables which have common column names, then edit the copybook and change the names.
Notes: SQLCA fields are updated by DB2; the application program must check value. SQCA SQLCODE and SQLSTATE fields used to check result other field used for more detailed on condition. In order to know what happened in the other side in DB2 we must provide DB2 with program storage where it can set a return code and other information DB2 wants to communicate
DBRM
Data Base Request Module contains the programs source SQL statements.
A DBRM
Contains the extracted, parsed SQL source. Is stored as a member in a partitioned dataset. One member created per precompile. Will become Input to BIND.
DBRM (Cont.)
One DBRM corresponds to exactly one source module. The SQL statements in the source program will be replaced by CALL to module DSNHLI statement with the following parameters. DBRM name (SQLPROGN) Timestamp (SQLTIME) Statement number (SQLSTNUM) Other parameters are Address of host variables. Address of SQLCA.
At this stage, the two components, (DBRM and modified source), will part and wont see each other again until program execution. Therefore the CALL must include necessary information for DB2 to be able to locate the access path needed to execute the SQL statement associated with the CALL.
The information about the DBRM that have been bound in to the application plans and packages is stored in the SYSIBM.SYSDBRM in the DB2 catalog table. If a DBRM is created and is not bound cannot be referenced from this table. When DBRM is bound to a plan, all the SQL statements are placed in to thSYSIBM.SYSTMTDB2 catalog table. When a DBRM is bound in to a package all the SQL statements are placed in to the SYSIBM.SYSPACKSTMT table.
done using: DB2I panels. JCL. PL/1 PRECOMPILER can precede the DB2 PRECOMPILER. CICS COMMAND TRANSTLATOR may have to be invoked.
COMPILE
Object Module
DSNELI DSNELI
LINK-EDIT
DSNHLI
Load Module
Notes: The modified program is now ready to be compiled and link-edited. The link-edit will have to include the necessary modules for the call to work properly. The appropriate LANGUAGE INTERFACE must be included. The program that has been prepared here will run in one of the many execution environments like TSO, CICS, IMS. Depending on the environment, a different interface module will have to be included in the link-edit stop. The name of the module will vary, but they will all have an entry point DSNHLI.
BIND PACKAGE
DB2 Catalog DBRM BIND PACKAGE
Validates SQL
Checks Privileges
Chooses an access path based on catalog statistics Stores source SQL in catalog Stores executable access path (PACKAGE) in Directory
PACKAGE
Access path selection consists of evaluating a number of different access paths and calculating their costs. The cheapest one will be retained. Those cost estimates are based on statistics, which are stored in the catalog. The RUNSTATS utility must be run to keep those statistics up-to-date.
The executable access code is stored in the directory, and the source SQL statements are stored in the DB2 catalog. They may be needed if the access path were to be evaluated at some later time.
PACKAGE
DBRM
dbrma
dbrma
PACKAGE (Cont.) A package is a single bound DBRM with optimized access path. By using packages the table access logic is packaged at a lower level for granularity at the package or program level. To execute a package it must be first be included in the package list of a plan. Package can never be directly executed; they are only executed when the plan in which they are contained is executed. A plan can consist of one or more DBRMs, one or more packages, or a combination of packages and DBRMs.
Package information is stored in its own DB2 catalog tables. When a package is bound, DB2 reads the following catalog tables:
SYSIBM.SYSCOLDIST, SYSIBM.SYSCOLUMNS, SYSIBM.SYSFIELDS, SYSIBM.SYSINDEXES,SYSIBM.SYSPACKAGES,SYSIBM.SYSTABLES SYSIBM.SYSPACKAUTH,SYSIBM.SYSTABLESPACE and SYSIBM.SYSUSERAUTH Of the above tables SYSIBM.SYSUSERAUTH table is read only for BIND ADD. The DB2 catalog stores information only about the packages. The executable form of the package is stored as a skeleton package table in the DB2 directory in the SYSIBM.SPTOI1 table. A package also contains a location identifier, a collection identifier and a package identifier. These are identifiers used to uniquely identify the packages.
COLLECTIONS
Test
pkg1 pkg1 pkg2
Prod
pkg2
Notes: A collection is a user-defined name (1 to 18 characters) that the programmer must specify for every package. A collection is not an actual, physical database object. A collection is a grouping of DB2 packages. By specifying different collection identifier, for a package, the same DBRM can be bound to different packages. This capability permits the programmer to use the same DBRM for different packages, enabling easy access to tables that have the same structure, but different owners.
APPLICATION PLAN
A plan is an executable module containing the access path, logic provided by the DB2 optimiser. It can be composed of one or more DBRMs and packages. Plans are created by the BIND command. When a plan is bound, DB2 reads the following catalog tables:
Pgm3
Pgm1
Pgm2
PRECOMPILE
Mprog2
Mprog3
Mprog1
Dbrm1
Dbrm3
Dbrm2
Compile / Link
Load module
Notes: The precompilation TIMESTAMP is included in each generated CALL in the modified source. The other twin brother (the DBRM) also contains this timestamp. It will be used by DB2 at program execution time to locate the correct package for the correct load module.
,1)
DB2 Directory
collx
colly
call
Dbrm1
Dbrm3
Dbrm1
call call
Dbrm2
collz
Notes: In between the load module and the packages there is a need for an additional structure that will guide DB2 in its searches for the appropriate package. This structure is called a plan and it will contain a package list, a list of logical pointers to packages. DB2 will look for the right (same timestamp) package by using each entry in the package list in turn until it has a hit. The mechanism is very similar to the search mechanism by the operating system to locate a member of a PDS on a concatenation of PDSs. Running a DB2 program is done by associating the plan with the load module. This is done outside the program.
A PACKAGE can be located and executed only via a PLAN A PLAN contains a PACKAGE list a list of pointers to packages. The DBRM name and the TIMESTAMP provided with the CALL are used to locate the correct package via the package list.
,1) ,2)
,2)
collx Dbrm3
colly
Dbrm4
collz
Notes: A PACKAGE LIST is a list of references to individual packages (E.G. COLLX.DBRM1) or to sets of packages (e.g. COLLY. *). A package list makes specific parts of the directory eligible for the package search.
Collx.dbrm1, collz. *
plana
Collx.dbrm1, collz. *
Dbrma Dbrm1
plana
Dbrm1
Dbrm2
Notes: Packages were introduced with DB2 V2.3, but plans already existed. Previously, the DBRMs were bound directly into the plan structure itself. For compatibility reasons, DB2 also supports this today.
DATA STORAGE
Logical storage
Physical storage
Notes: Logical storage is how the user sees the data. Physical storage is how data is actually stored. The total collection of stored data is divided into a number of user databases and system databases. Each database is divided into number of table spaces and index spaces. A space is a dynamically extendible collection of pages, where a page is a block of physical storage. The pages in a given space are all of the same size 4KB for index spaces and either 4KB or 32KB for table spaces. Each table space contains one or more tables. A stored table is a physical representation of a base table; it consists of a set of stored records, one for each row of the base table. A given stored table must be wholly contained with in a single table space. Each index space contains exactly one index. A given index must be wholly contained in an index space. A given stored table and all its associated indexes must be wholly contained with in a single database.
View
T A B LE SP A C E
View
View
Stored Table
Stored Table
Stored Table
Stored Table
Catalog Table
Catalog Table
Stored Table
Stored Table
Catalog Table
Stored Table
IN D E X SP A C E
User Database
User Database
Catalog Database
Storage Group 1
Storage Group 1
A simple table space can contain more than one stored table, though one is the best option. One reason for having more than one table is that related data can be kept together, making the access faster. Partitioned table spaces are intended for tables that are sufficiently large i.e. operationally difficult to deal with the entire table as a single unit. A partitioned table space thus contains exactly one table, partitioned in accordance with the value ranges of a partitioning column or column combination. In the segmented table spaces, the space with in the table space is divided in to segments, where each segment contains logically contiguous n pages where n must be a multiple of 4 and must range between 4 and 64 and should be the same in all segments. No segment will have records of more than one stored table and if the table grows in size to fill a segment a new segment will be obtained
NORMALIZATION 1-NF
Normalization is the process of steps that will identify for elimination of redundancies in a database design. FIRST NORMAL FORM: Eliminating repeating groups
067
Notes: Eliminating Repeating Groups: One of the first rules of relational tables is that all the rows must have the same number of columns and each column must mean the same thing in the same sequence in each row. In the example of EMP table, if it were required to represent the multiple skills of employees, this would be represented in an additional table where each skill for a given employee is represented in a row. If new skill is created and an employee already has the maximum number of skills allocated in the data structure, then the entire file structure and all the programs have to be changed, in an unnormalized file structure. If this table is normalized, then the new skill simply becomes a new row.
NORMALIZED TO 1NF-EMPL
EMPNO 000030 000250 000270 000300 LASTNAME KWAN SMITH PEREZ SMITH WORKDEPT GRE BLU RED BLU DEPTNAME OPERATIONS PLANNING MARKETING PLANNING
EMPL_SKILL TABLE
EMPNO SKILLSKILLDESC 000030141RESEARCH 000250002BID PREP 000250011NEGOTIATION 000250067PROD SPEC 000270415BENEFITS ANL 000270447TESTING 000300011NEGOTIATION 000300032INV CONTROL
NORMALIZATION 2-NF
Second normal form Eliminate the columns that depend only on part of the key
EMPNO
000030 000250 000250 000250 000270 000270 000300 000300
SKILL
141 002 011 067 415 447 001 032
SKILLDESC
RESEARCH BID PREP NEGOTIATION PROD SPEC BRNRFITS ANL TESTING NEGOTIATION INV CONTROL
Notes: Second normal form requires a close look at proposed tables that have multi-column primary keys. The objective is to eliminate all columns from a table design that are dependent on only part of the primary key
Notes: In the example of EMP table in the 1NF the skills of the employees was matched with the employees in a separate table and the skill description. But skill description depends only upon the skill number. The problems that arise due to this are: 1. The skill description will be repeated every time the skill is repeated. 2. If this description for the skill changes, then multiple rows will need to be changed, risking some update anomalies (data inconsistency due to not changing all rows). 3. If an employee is the sole source for a given skill and that person leaves the company, that particular skill and skill description is lost forever. (Delete anomaly).
NORMALIZATION 3-NF
Third normalization: Eliminate columns that dont depend on the key at all. Unnormalized EMPL EMPNO LAST NAME WORK DEPT DEPTNAME 000030 KWAN GRE OPERATIONS 000250 SMITH BLU PLANNING 000270 PEREZ RED MARKETING 000300 SMITH BLU PLANNING
Normalized to 3NF EMPNO LASTNAME 000030 KWAN 000250 SMITH 000270 PEREZ 000300 SMITH WORKDEPT GRE BLU RED BLU
Notes: Third normal form tables ensure that each columns value depends on the primary key or some other column with the table. In the example of the EMP table the Department number in the EMP table, that is necessary to reflect the relationship between the employee and the department tables many employees work for one department and the department name column is a fact about the department number column. The same three problems exist here as the 2NF and can be solved in the same way i.e. an additional table where the department number is the primary key and department name is dependent upon it.
NORMALIZATION 4-NF
Fourth normalization: Isolate independent multiple relationships, i.e. no table may contain more than 1:n or n:m relationships that arent directly related.
Notes: Suppose in the skills table of the 1NF the language that each employee knows is also included along with skills of each employee. So, now there is one-to-many relationship between employee and language in the same table, since an employee can know more than one language, which is a violation of fourth normalization. A separate table has to be created isolating language from skills UNLESS THERE IS A DIRECT RELATIONSHIP BETWEEN LANGUAGE AND SKILL, i.e. an employee requires certain language for certain skill, they should remain together.
NORMALIZATION 5-NF
Notes: Suppose in the above example the skills and languages are related to each other, there may be some other reason why they should be separated in to yet another table to resolve many-to-many relationship between them. So we should have three tables 1. 2. 3. Employee-Skill Employee-Language Skill-Language
NORMALIZATION RECOMMENDATION
Notes:
Normalization solves many problems like it eliminates redundancies that saves disk space and reduces update and delete anomalies. It helps in keeping data model flexible, which is a key factor in todays world of rapidly changing business requirements, but it may impact performance depending on user requirements if the datas are separated into many tables, but it is often retrieved, many I/O operations are required than if it is not normalized. These decisions and trade offs between normalizing and denormalizing has to be decided.
OPTIMIZER
SQL
DB2 Catalog
Notes: The Optimizer is the most important part of DB2. It is the brain of DB2. It analyzes the SQL statements and determines the most efficient access path available for satisfying the statement. In the SQL statements, we only say what we want, the optimizer decides how to get the things that we have asked for. It accomplishes this by parsing the SQL statements to determine which table must be accessed. It then queries statistics stored in DB2 catalog to determine the best method of accomplishing the tasks necessary to satisfy the SQL statements.
OPTIMIZER (Cont.)
Physical Data Independence:
The concept of optimizing data access in the DBMS is one of the most power full capabilities of DB2. Access to DB2 data is achieved by telling DB2 what you want and not how to get it. DB2 s optimizer accomplishes this task thus giving physical data independence. Regardless of how data is physically stored and manipulated, DB2 and SQL can still access data. This separation of access criteria from physical storage characteristics is called physical data independence. If indexes are removed DB2 can still access data (the performance is reduced). If a column is added to the table being accessed, the data can still be manipulated by DB2 with out changing the program code. This is all possible because the physical access path to DB2 data are not coded by programmers but generated by DB2.
1. Receive and verify the SQL statement. 2. Analyze the environment and optimize the method of satisfying the SQL statement. 3. Create machine-readable instructions to execute the optimized SQL. 4. Execute the instructions or store them for future execution. The optimizer has many types of strategies for optimizing the SQL. The strategy is a cost based one. This means that the optimizer will always attempt to find an access path that will reduce the overall cost. To accomplish this the DB2 optimizer evaluates four factors for each potential access path. Those factors are 1.CPU cost 2.I/O cost 3.DB2 catalog statistics 4.SQL statements.
CATALOG STRUCTURE
The DB2 catalog is structured as DB2 tables, but they are not standard tables. Many of the DB2 catalog tables are stored together hierarchically using a special relationship called link. The DB2 catalog table SYSIBM.SYSLINKS store the information defining the relationships between other catalog tables.
SYS TABLESPACE SYSTABLEPART
SYSSYNONYMS
SYSTABAUTH
SYSINDEXPART
SYSCOLAUTH
SYSKEYS
SYSPACKAGE
SYSAUTH
SYSPKSYSTEM
SYSPACKLIST
SYSPACKDEP
SYSSTMT
SYSVTREE
SYSVLTREE
SYSVIEWS
SYSVIEWDEP
SYSSTOGROUP
SYSDATABASE
SYSVOLUMES
SYSDBAUTH
SYSCOPY
SYSSTRINGS
SYSUSERAUTH
SYSRESAUTH
DB2 DIRECTORY
DB2 uses a second data directory, other than the catalog, called the DB2 Directory for storing detailed technical information about the aspects of DB2 s operation. The DB2 directory is for DB2 s internal use only. The SQL statements cannot access the data in the DB2 directory.
BIND
DB2 Catalog
Application Database
DATA LOCKING
DB2 guarantees data integrity by using several locking mechanisms.
LOCKING MECHANISM
DB2 supports locking at three levels. Table space level, Table level and Page level. Locks can be taken at any level in the locking hierarchy without taking a lock at the lower level. However, locks cannot be taken at a lower level with out compatible higher-level lock also being taken. For example, we can take a table space lock with out taking any other lock, but for taking a page lock we have to first get a table space lock. Different modes of locking are:
Table space/ Table locks Lock S U X IS Meaning SHARE UPDATE EXCLUSIVE INTENT SHARE Access Required Read only Read with intent to update Update Read only Access Allowed To Others Read only Read only No access Update
IX
SIX Page locks S U
INTENT EXCLUSIVE
SHARE/INTENT EXCLUSIVE
Update
Read or Update
Update
Read only
SHARE UPDATE
EXCLUSIVE
Update
No access
LOCKS VS LATCHES
A true lock is handled by DB2 using IRLM (IMS Resource Lock Manager). DB2 will try to lock pages without going to IRLM, whenever it is possible. This type of lock is referred to as a latch. True locks are always set in the IRLM. Latches, by contrast are set internally by DB2 with out going to the IRLM. When a latch is taken instead of lock, it is handled by internal DB2 code. So cross memory service calls to IRLM is eliminated. Also a latch requires about one third of instruction as a lock. Therefore, latches are more efficient than locks because they avoid the overhead associated with calling an external address space. Latches are used when a resource serialization is required for a short time. Prior to DB2 version 3, latches were generally used to lock only DB2 index spaces and internal DB2 resources. When running V3, DB2 uses latching more frequently. This includes data page latches.
OVERVIEW
DEFINING CURSORS
Two types of embedded SQL SELECT STATEMENTS. Singleton SELECT Cursor SELECT SQL statements operate on a set of data and return a set of data. Host language programs, on the other hand, operate on a row at a time. A singleton SELECT is simply on SQL SELECT statement that returns a single row. The singleton SELECT differs from the ordinary SELECT statement in that it contains an INTO clause. The INTO clause is where you code your host variables that accept the data returned by DB2. But if such a SELECT statement returns more than one row, the values of the first row is placed in the host variable and DB2 issues an SQLCODE of 811. So, in your application program, if the SELECT will return more than one row then one must use Cursors. DB2 uses cursors to navigate through a set of rows returned by an embedded SQL SELECT statement. A cursor can be compared to a pointer. The programmer declares a cursor and defines the SQL statement for the cursor. After that you can use the cursor like a sequential file. The cursor is opened, rows are fetched from the cursor, and one row at a time and at the end of processing the cursor is closed.
The four operations that must be performed for the successful working of cursors. DECLARE - This statement defines the cursors, gives a name to it and assigns an SQL statement to it. The DECLARE statement does not execute the SQL statement but merely defines it. OPEN This readies the cursor for row retrieval. OPEN is an executable statement. It reads the SQL search fields, executes the SQL statements and sometimes builds the result table. FETCH - This statement returns data from the result table one row at a time to the host variables. If the result table is not built at the OPEN time, it is built during FETCH. CLOSE Releases all resources used by the cursor.
CURSOR DECLARATION
EXEC SQL DECLARE CURSOR-NAME CURSOR (WITH HOLD) FOR select-statement A Cursor : Is required for select of multiple rows Is never used for INSERT May be reused (CLOSE + new OPEN) Will be closed at COMMIT Unless declared with WITH HOLD Multiple Cursors : May be defined in a program May work with the same table May be open simultaneously
Notes: The DECLARE CURSOR statement is used to associate a cursor with the SQL statement. No data access is performed at this stage. The WITH HOLD option is important if you want to issue COMMIT inside the fetch loop. If you omit this keyword, you will have to re-open (and DB2 will have to re-execute the access path) the cursor after each COMMIT, because its position will be lost due to the COMMIT.
READ-ONLY CURSORS
EXEC SQL DECLARE cursor-name CURSOR FOR select-statement FOR FETCH/READ ONLY The SELECT Statement contains FOR FETCH ONLY/FOR READ ONLY ORDER BY UNION or UNION ALL The first SELECT contains DISTINCT A FUNCTION OR EXPRESSION The outer subselect contains GROUP BY / HAVING
However, some cursors are read/only. The reason behind this is that for some SQL statements, it will not be possible for DB2 to position itself before the first result row without accessing the entire result set. Take the example of a SELECT..ORDER BY. DB2 will have to get all qualifying rows and sort them before it can position its cursor. In addition, the cursor will be positioned on an intermediate result table and not on the actual data itself.
OVERVIEW
STATIC SQL
DYNAMIC SQL
STATIC SQL
STATIC SQL Can be used if the statements TYPE TABLES COLUMNS, WHERE- Clause are known when you write your program The complete SQL statement is contained in the program, except for host variable referring to COLUMN VALUES. BIND creates the access path Only the EXECUTE privilege is checked before execution of the access path Program
EMPN Get host variable contents
DYNAMIC SQL
DYNAMIC SQL MUST be used if ANYTHING ELSE THAN COLUMN VALUES are unknown at program preparation The statement is contained in a host variable BIND cannot create an access path but an empty package will be created. Security is checked at execution time when the access path is created
Table ?
Column
name ?
SQL statement?
EXECUTE IMMEDIATE
EXECUTE IMMEDIATE implicitly prepares and executes complete SQL statements coded in host variables. Only a sub-set of SQL statements is available when you use this command, the prominent being SELECT and so this call of dynamic SQL cannot be used for data retrieval. So if you want any data to be retrieved then the SQL portion of your program consists of two steps. First moving the complete text for the statement to be executed to be executed into the host variable and second issue an EXECUTE IMMEDIATE command giving the host variable as an argument. The statement is prepared and execute automatically.
Ex: WORKING-STORAGE SECTION. : EXEC SQL INCLUDE SQLCA END-EXEC. 01 WS-HOST-VARIBLE. 49 WS-HOST-VARBLE-LEN PIC S9 (4) COMP. 49 WS-HOST-VARBLE-TXT PIC X(80). PROCEDURE DIVISION. MOVE +45 TO WS-HOST-VARBLE-LEN. MOVE DELETE FROM EMPLOYEE WHERE DEPT=CONSUL TO WS-HOST-VARBLE-TXT. EXEC SQL EXECUTE IMMEDIATE :WS-HOST-VARBLE END-EXEC.
The Execute Immediate supports following statements ALTER, CREATE, DELETE, DROP, EXPLAIN, COMMIT, GRANT, INSERT, REVOKE and UPDATE. Disadvantages of EXECUTE IMMEDIATE It does not support the SELECT statement. It can result in poor performance, if the same SQL statement is performed, the executable form of the SQL is destroyed and the program has to prepare the executable form when it executed again.
FIXED-LIST SELECT
A FIXED-LIST SELECT statement can be used to explicitly prepare and execute SQL SELECT statements when the column to be selected are known and unchanging. This is necessary to create the WORKING-STROAGE declaration for the host variable in the program. Example WORKING-STORAGE SECTION. 01 WS-HOST-VAR. 49 WS-HOST-VAR-LEN PIC S9 (4) COMP. 49 WS-HOST-VAR-TXT PIC X(100). 01 TVAL1. 49 TVAL1-LEN PIC S9 (4) COMP. 49 TVAL1-TXT PIC X(3). 01 TVAL2 PIC X (10 ). PROCEDUER DIVISION. MOVE SELECT S#, SNAME, STATUS, CITY FROM S WHERE S# = ? AND CITY= ? TO FLSQL. Move the SQL to execute to WS-HOST-VARBLE. EXEC SQL DECLARE CRS1 CURSOR FOR FLSQL END-EXEC.
EXEC SQL PREPARE FLSQL FROM :WS-HOST-VAR END-EXEC. Move the required values to the variables TVAL1 and TVAL2. EXEC SQL OPEN CRS1 USING :TVAL1, :TVAL2 END-EXEC. Loop until no more rows to fetch EXEC SQL FETCH CRS1 INTO :S#,:SNAME, :STATUS, :CITY END-EXEC. EXEC SQL CLOSE CRS1 END-EXEC.
VARYING-LIST SELECT
Varying-list SELECT SQL statements are used when you do not know the columns that will be retrieved by an application program. This class of SQLs provide more flexibility than any other dynamic SQLs. You can change tables, columns and predicated during the execution, since every thing about this SQL can change during execution, the number and type of host variables cannot be known beforehand. This is why, this class of SQL is the most complicated among the dynamic SQLs.
DESCRIBE PRST
INTO : SQLDA
PRST
SQLDA
Setup of host variables to receive rows and put addresses into SQLDA
Since we dont know which columns will be accessed, we cannot pre-allocate any storage for host variables until we know that information. This will be the thing to do. If we have an idea how many columns we will have to access, it will already simplify our case. In Order to now the data types and names of the columns, we will have to ask DB2 to DESCRIBE the table we access. DB2 needs storage to be able to do this describe. If you know how many columns you will need, you can at least allocate enough storage for DB2 to be able to do the DESCRIBE. Once this is done, you can allocate storage for the host variables and execute the statements.
DESCRIBE INTO SQLDA Column Name, Data Type And Length For Each Column Selected
SQLDA
This is the host structure used by DB2 describe an SQL statement (number of columns and data type of each column). This will be the input for the allocation of the host variable storage.
SQLDA - FORMAT
SQLDAID CHAR(8) SQLN SMALLINT SQLTYPE SMALLINT SQLDATA POINTER SQLNAME VARCHAR (30) OTHER SQLVARS
Notes:
The SQLDA has a header containing some very useful information ( number of columns, etc), and then for each column a descriptive are called SALVAR.
480
484 496 500
4
2(prec/scale) 4 2
SQLDA Technique 1
Allocate SQLDA1 for pre-defined number of columns (e.g. sqln = 50)
SQLDAID
SQLTYPE : :
SQLDABC
SQLTYPE
SQLN
SQLDATA
SQLD
SQLIND SQLNAME
SQLN
:
DESCRIBE statement INTO SQLDA1 If less than 50 columns returned Allocate host variable and indicator variable storage OPEN CURSOR and FETCH
#50
The problem is that you dont always know in advance how many columns will be returned, nor do you know how many SQLVARs you should allocate for the DESCRIBE. The first technique guesses that 50 will be about right. If it was optimistic and more than 50 columns are returned, two DESCRIBES will be necessary, a first one to find out how many rows will be returned (SQLD contains this info) and a second one in a freshly allocated, correctly sized SQLDA.
SQLDA Technique 2
Allocate minimal SQLDA1 (SQLN = 0)
SQLDAID SQLDABC SQLN SQLD
DESCRIBE statement INTO SQLDA1 Read SQLD (#of columns returned) Allocate large enough SQLDA2 (SQLN = SQLD) SQLDABC SQLTYPE SQLN SQLDATA SQLD SQLIND SQLNAME SQLN = SQLD
SQLDAID SQLTYPE : : :
Notes: This is the case where you have no idea at all about the number of returned columns or where you want to use the same processing logic whatever that number may be.
SQLDA
3. # of description SQLD If DB2 sets SQLD to zero : Statement is not a SELECT Issue an EXECUTE If DB2 sets SQLN to ZERO SQLDA is too small to use SQLD shows # of SQLVARs needed
SQLWARN3 CHAR(1)
SQLWARN4 CHAR(1) SQLAID CHAR(8) SQLCABC BIN FIX(31) SQLCODE BIN FIX(31)
SQLCA LAYOUT
Error handling is based on information, DB2 returns in the SQLCA (SQL Communication Area). The most important fields are the SQLSTATE and SQLCODE.
SQLSTATE
SQLSTATE is an SQL return code contained in a 5 digit character string. First digit : zero (successful) or not Zero First 2 digits : SQLSTATE CLASS
01
02 03
last 3 digits represent SQLSTATE SUBCODE Example : SQLSTATE 00000 : successful SQLSTATE01501 : string truncation SQLSTATE 02000: no more data
Notes: SQLSTATE is a return code that is common to all DB2 family products. If you base your error handling on SQLSTATE, your interpretation of the error situation will be independent of the platform where the SQL statement was actually executed. It is recommended, therefore to use SQLSTATE instead of SQLCODE.
SQLCA CODES
SQLCODE is the SQL return code for DB2 (on MVS) and contains a signed numeric
value.
Negative values
Positive values
Error Condition
OK
Exception condition
Unacceptable SQL statement Successful execution warning messages may have been issued. Row not found for FETCH, UPDATE or DELETE of the result of a query is an empty table.
SQLCODE is a return code that is specific to DB2 for MVS. Other platforms, like DB2/ VM also have SQLCODEs. However, the values dont always match.
CONDITION
INTEGER SQLCODE
Char(1) SQLWARNO
REQUEST STATUS
Error
Warning
Or w
Not found
Success
Notes:
00000
And
Success
The chart gives you a general overview of which return codes will be generated in the indicated warning or error situation.
ERROR HANDLING
Example of testing return codes : EXEC SQL SELECT IF SQLSTATE = 00000 THEN IF SQLSTATE = 02000 THEN DISPLAY RECORD NOT FOUND ELSE IF SUBSTR (SQLSTATE,1, 2) = 01 THEN DISPLAY WARNSQL ELSE DISPLAY ERRORSQL ELSE : :
Example of using WHENEVER EXEC SQL WHENEVER NOT FOUND GOTO NO MORE EXEC SQL WHENEVER SQLERROR GOTO ERRORSQL EXEC SQL WHENEVER SQLWARNING GOTO WARNSQL : : : EXEC SQL SELECT.. :
Various techniques can be used to detect error conditions. One thing is sure : you need error handling. The first technique is to react individually after every SQL statement. A more general error routine should be developed and called after each SQL statement. The second technique, WHENEVER, is not recommended for general use.
SCOPE OF WHENEVER
Execution flow
Soruce code
EXEC SQL WHENEVER SQLERROR GOTO LAB1 : EXEC SQL SELECT IF SQLCODE < 0 THEN GOTO LAB : LAB1 : EXEC SQL WHENEVER SQLERROR GOTO LAB2 :
Notes: As you can see, the WHENEVER statement forces you to use GOTO and it is, therefore, sensitive to where the WHENEVER is placed in the code. Going back to where you came from is difficult. It is also difficult to take specific actions for specific SQL statements (an error for an update might need another reaction than the same error for a select). WHENEVER actually adds the checks to each of your statements at precompile.
SMALLINT
SQLCA Error Information Size of message area
Different treatment needed for NOT FOUND after delete/ update/ insert. Coming back after WHENEVER Might want to intercept other return codes
SYSADM will normally provide a STANDARD error routine for everyone to use Only CALL DSNTIAR in error condition.
Notes: As mentioned previously, the use of WHENEVER is not recommended, and we advise using a general error routine that is called after each SQL statement
EXEC SQL SELECT PHONENO INTO :P-PHONE : P-PHONE-I FROM EMP WHERE EMPNO = :INP-EMP END-EXEC.
After the SELECT If PHONENO contains the NULL value : H-variable P-PHONE -> unchanged I- variable P-PHONE -> negative If PHONENO contains data : H-variable P-PHONE -> updated I- variable P-PHONE -> not negative
Notes : If a column can contain the NULL value, a special host variable called an Indicator Variable should be defined in the program. This variable is used by DB2 to signal the existence of a NULL value for that column.
01 PEMPL.
02 EMPNO PIC X(06). 02 FIRSTNME PIC X(12). 02 MIDINITPIC X(01). 02 LASTNAME PIC X(15). 02 WORKDEPT PIC X(03). 02 PHONENOPIC X(04).
Imbedded SQL :
EXEC SQL UPDATE PEMPL SET PHONENO = : PHONENO : PHONENO WHERE EMPNO = :EMPNO END-EXEC.
Notes: On the other hand, the indicator variable will allow you to pass a NULL value to DB2.
If the indicator variable NPHONE is set to a negative value, the statement is treated as
EXEC SQL SELECT LASTNAME, FIRSTNME FROM PEMPL WHERE PHONENO IS NULL END-EXEC.
Imbedded SQL :
EXEC SQL SELECT * INTO :PEMPL :INDSTRUC FROM PEMPL WHERE EMPNO = :EMPNO END-EXEC.
The example shows how a simple array can used to detect the NULL values for several columns. Remember that the DCLGEN function can generate the indicator variables for your DB2 table.
Notes: Indicator variables are also used by DB2 to signal arithmetic error conditions.
Declaration In program
01 01 01 MV1 MV2 MV3 PIC PIC PIC S9(4) COMP. S9(4) COMP. S9(4) COMP.
01
01 01 01 01 01
MV11
MV21 MV31 IV1 IV2 IV3
PIC
PIC PIC PIC PIC PIC
S9(4) COMP.
S9(4) COMP. S9(4) COMP. S9(4) COMP. S9(4) COMP. /* Indicator Variable */ /*Indicator Variable */
TABLE A values are SM1 1 2 3 4 INT1 123458 345678 123678 211111111 SMI2 1 0 1 4
Notes : Note the contents of the table and program definitions used for the coming examples
-n -2
Notes: An error handling routine could take specific actions for these error conditions. Error handling will generally be done through a standard routine that will be invoked after each SQL statement. Your DB2 or SYSADM will provide you with the details about the specific implementation chosen for your installation
Notes: A smart program could also handle those error condition. ABENDing the program is not always needed.
OVERVIEW UNDERSTAND THE CONCEPTS AND ADVANTAGES OF STORED PROCEDURES CODE A CLIENT PROGRAM CODE A STORED PROCEDURE SETUP THE SYSIBM.SYSPROCEDURES TABLE
Notes : A Stored procedure is a program that is controlled by DB2 that can be called through an SQL statement. The program can receive parameters and also has the ability to return data to the calling application.
CONNECT
CALL ---procedure- name ----------------------------------------------------------------------------Host- variable ----------------------------------------------------------------------Host-variable Constant NULL USING DESCRIPTOR NAME
EXEC SQL CALL A (:EMP, :PRJ, :ACT) EXEC SQL CALL A (:EMP :INDEMP, : PRJ :INDPRJ, :ACT :INDACT) EXEC SQL CALL A (103455, BUIL5, :ACT)
IN
IN OU T
OU T
SIMPLE WITH NULL LINKAGE Notes: Two linkage conventions can be used: SIMPLE : This type of linkage only allows the use of null for parameters that are defined as output parameters. For the output parameters you can add an indicator Variable. If that variable is set to a negative value, DB2 will not pass the whole variable to the procedure. This technique will help improve the speed of the call, as DB2 has less information to send.
SIMPLE WITH NULL : This type of linkage will require a null indicator for all parameters regardless of whether they are IN, OUT or INOUT.
For both types of linkages, you will have to define the nature of the parameter, which can be:
IN
OUT (the content is not passed along to the procedure) INOUT (data flows in both directions)
IN
IN OU T
OU T
To allow DB2 to know where and how the stored procedure is to be used, you will have to make an entry in a catalog table. This entry will give a description of who can use the procedure and what parameter conventions are used to call the procedure. You can specify different definitions for the same procedure based on the calling LU-name and use rid. The will allow you to test a new procedure while the old one is still used. The parm list has to contain a description of all the parameters that are included in the call and, of course, whether they are IN, OUT or INOUT. The ASUTIME column allows you to put a limit on the amount of resources that can be consumed by one invocation of a stored procedure.
DATA CONSISTENCY UTILITIES BACKUP AND RECOVERY UTILITIES. DATA ORGANIZATION UTILITIES. CATALOG MANIPULATION UTILITIES
CHECK:
The CHECK utility checks the integrity of data structures. It has two purposes. The first is to check the referential integrity between two tables, displaying and potentially resolving referential constraint violation. The second purpose of the CHECK utility is to check DB2 indexes for consistency. This consists of comparing the key values of the indexed columns to their corresponding table values, as well as evaluating the RIDs in the tables and indexes being checked. The CHECK utility has two options CHECK DATA and CHECK INDEX.
RUNSTATS: The RUNSTATS utility collects statistical information for DB2 tables, table spaces, partitions, indexes and columns. It can place this information into the DB2 Catalog Tables. The DB2 optimiser for determining the optimal access paths for the SQL queries reads the tables. The information can be queried using SQL statements.
LOAD
Index
Table space
Notes: Besides the CHECK DATA UTILITY, we also have load utility. It provides a way to LOAD a selfreferencing table. Load will load the input records from the sequential file in input file record sequence.
TABLE DEPT
DEPTNO E21
MGRNO 031435
ADMRDEPT E01
LOAD DATA INTO TABLE DEPT (DEPTNO (DEPTNAME (MGRNO (ADMRDEPT POSITION (7) POSITION (10) POSITION (36) POSITION (42) CHAR (3), CHAR (26), CHAR (6), CHAR (3))
TARGET COLUMN
01..234.
MGRNO 031435
ADMRDEPT E01
E21
Note: In some cases, the data types of the input record field and the target column dont match. In the example, the INTEGER EXTERNAL keyword tells DB2 that the record field contains numeric data formatted as characters. The LOAD utility will perform the necessary data conversion.
??????? E01
TABLE DEPT
DEPTNO E21
MGRNO ---------
ADMRDEPT E01
The MGRNO column allows NULL values so NULL values So NULL is its default. LOAD DATA INTO TABLE DEPT (DEPTNO POSITION (7:9) CHAR ,
(DEPTNAME
(MGRNO
(ADMRDEPT POSITION(42:44)CHAR(3)) A recognizable string of question marks is used in this example to trigger the loading of NULL values in the column.
DB2 SECURITY - STATIC SQL DB2 SECURITY - DYNAMIC SQL HOW TO INVOKE EXPLAIN. COMMIT AND ROLLBACK.
SECURITY definitions are made by issuing GRANT statements, such as GRANT SELECT ON TABLE EMP TO userid The opposite, withdrawing a GRANTed privileges, is done with the REVOKE Statement : REVOKE SELECT ON TABLE EMP FROM userid
TERMINAL
. .
(first) SQL 5
THREAD
. . .
PLAN A
PLAN A
SYSIBM. SYSPLANA
DIRECTORY CATALOG
. .
(first) SQL 7
THREAD 4
6,9
.
SQL.
SPUFIPLANA
PLANA
DYNAMIC RULES(RUN)
CATALOG DIRECTORY
EXPLAIN INVOCATION
USER A USER A
If you want to know what access path DB2 chose during a BIND or PREPARE operation, you must use the EXLPAIN function. You can do an EXPLAIN : - When you BIND a package or Plan(with DBRMs) by specifying EXPLAIN(YES) - Interactively ,by using the EXPLAIN SQL statement followed by the actual SQL statement of which you want the access path. The EXPLAIN output consists of a number of rows in a table called the PLAN_TABLE. Each user who does EXPLAIN needs his own PLAN_TABLE.
- Insert Access path information for application SQL into Userid.PLAN_TABLE - DB2 catalog remembers and will redo EXPLAIN at each new BIND / REBIND until BOUND WITH EXPLAIN(NO)
SELECT * FROM PLAN_TABLE WHERE APPLNA = PLAN1 AND PROGNAME =DBRM1 ORDER BY QUERYNO, QBLOCKNO,PLANNO, MIXOPSEQ
For PACKAGEs
SELECT * FROM PLAN_TABLE WHERE PROGNAME = PKG1 AND COLLID =COLL1 ORDER BY QUERYNO, QBLOCKNO,PLANNO, MIXOPSEQ
Those SQL statements will come in handy if you want access path information for all the statements of a package or plan. The ORDER BY clauses are essential to understand the access path.
Before getting details of COMMIT and ROLLBACK statements as such, we first need to know SYNCHRONIZATION POINT abbreviated as SYNCPOINT. A SYNCPOINT represents a boundary point between two consecutive transactions, loosely speaking, it corresponds to the end of a logical unit of work and thus to a point at which the database is in a state of consistency. Program initiation, COMMIT and ROLLBACK each establish a synchpoint and no other operation does.
COMMIT : The SQL COMMIT statement takes the form COMMIT (WORK) A successful end-of-transaction is signaled and a synchpoint is established. All updates made by the program since the previous synchpoint are committed. All open cursors are closed, except for cursors whose declaration includes the optional specification WITH HOLD , all rowlocks are released, except for locks needed to hold position for cursors not closed.
ROLLBACK: The SQL ROLLBACK statement takes the form ROLLBACK [WORK] An unsuccessful end-of-transaction is signed and a synchpoint is established. All updates made by the program since the previous synchpoint are undone. All open cursors are closed.
SAMPLE PROGRAM
IDENTIFICATION DIVISION. PROGRAM-ID. SAMPLE. ENVIRONMENT DIVISION. CONFIGURATION DIVISION. INPUT-OUTPUTSECTION. FILE-CONTROL. SELECT OUT-FILE ASSIGN TO DD1 DATA DIVISION. FILE SECTION. FD OUT-FILE. 01 OUTREC PIC X(80). WORKING-STORAGE SECTION. 01 R0. 03 FILLER PIC X (29) VALUE NAME. 03 FILLER PICX (05) VALUE PHONE 01 R1. 03 R1- FIRSTNME PIC X (12). 03 FILLER PIC X (01) VALUE . 03 R1-LASTNAME PIC X(15). 03 FILLER PIC X(01) VALUE . 03 R1-PHONENO PIC X(04). 01 PROMPT1 PIC X(80).
VALUE ENTER EMPNO OR 999999 TO STOP .. 01 ERR-NF VALUE ***** THIS EMPNO DOES NOT EXIST***** 01 ERR-UN-1 VALUE *****UNEXPECTED ERROORS*********** 01 ERR-UN-2 03 FILLER PIC X(13) VALUE ******SQLSTATE=. 03 EU2-SQLSTATE PIC 99999. 03 FILLER PIC X(08) VALUE **** 01 ERR-UN-3 PIC X(80) VALUE *************PROGRAM ENDS********. * ------------------------------------------------------------------------------------------------*COMPLETE THE DECLARATION FOR : * TABLE EMP * THE SQL COMMUNICATION AREA (SQLCA) *-------------------------------------------------------------------------------------------------EXEC SQL INCLUDE EMP END- EXEC. EXEC SQL INCLUDE SQLCA END-EXEC.
PROCEDURE DIVISION. MAIN-PARA. PERFORM INIT PERFORM DISP-EMP UNTIL EMPNO = 999999 PERFORM END-PARA. INIT-PARA. OPEN OUTPUT OUTFILE PERFORM GET-EMPNO. DISP-EMP SECTION. * ------------------------------------------------------------------------------------------------WRITE YOUR SELECT STATEMENT HERE * ------------------------------------------------------------------------------------------------EXEC SQL SELECT FIRSTNSME, LASTNAME, PHONENO INTO :FIRSTNME, :LASTNAME, :PHONENO FROM EMP WHERE EMPNO = : EMPNO END-EXEC. * ------------------------------------------------------------------------------------------------* THIS STATEMENT IS NEEDED TO INTERCEPT ERROR * CONDITIONS. YOU WILL LEARN ABOUT IT LATER IN THE COURSE * -------------------------------------------------------------------------------------------------
EVALUVATE SQLSTATE WHEN 00000 CONTINUE WHEN 02000 GO TO NOTFOUND-PARA WHEN OTHER GOTO ERROR-PARA END-EVALUVATE. MOVE FIRSTNME-TXT (1: FIRSTNME-LEN) TO R1-FIRSTNME MOVE FIRSTNME-TXT (1: FIRSTNME-LEN) TO R1-LASTTNME MOVE PHONENO TO R1 PHONENO WRITE OUTREC FROM R0 WRITE OUTREC FROM R1 GO TO EXIT.-PARA NOTFOUND-PARA. WRITE OUTREC FROM ERR-NF GO TO EXIT-PARA ERROR-PARA. MOVE SQLSTATE TO EU2-SQLSTATE WRITE OUTREC FROM ERR-UN-1 WRITE OUT-REC FROM ERR-UN-2 WRITE OUT- REC FROM ERR-UN-3 PERFORM END-PARA.
EXIT-PARA. PERFORM GET-EMPNO. GET-EMPNO-PARA. MOVE SPACE TO OUTREC. WRITE OUTREC. WRITE OUTREC FROM PROMPT1 ACCEPT EMPNO. END-PARA. CLOSE OUTFILE GOBACK.