Anda di halaman 1dari 906

AS/400e IBM

DB2 UDB for AS/400 SQL Programming


Version 4

RBAF-Y000-00
AS/400e IBM

DB2 UDB for AS/400 SQL Programming


Version 4

RBAF-Y000-00
© Copyright International Business Machines Corporation 1997, 1999. All rights reserved.
Note to U.S. Government Users — Documentation related to restricted rights — Use, duplication or disclosure is
subject to restrictions set forth in GSA ADP Schedule Contract with IBM Corp.
Contents
About DB2 UDB for AS/400 SQL Programming. . . . . . . . . . . . xvii
Who should read this book . . . . . . . . . . . . . . . . . . . . xvii
Assumptions Relating to Examples of SQL Statements . . . . . . . . . xvii
How to Interpret Syntax Diagrams in this Guide . . . . . . . . . . . xviii
AS/400 Operations Navigator . . . . . . . . . . . . . . . . . . . xix
Installing Operations Navigator. . . . . . . . . . . . . . . . . . xx
How this book has changed . . . . . . . . . . . . . . . . . . . . xxi
Prerequisite and related information . . . . . . . . . . . . . . . . . xxi
How to send your comments . . . . . . . . . . . . . . . . . . . xxi

Chapter 1. Introduction to DB2 UDB for AS/400 Structured Query


Language . . . . . . . . . . . . . . . . . . . . . . . . . 1
SQL Concepts . . . . . . . . . . . . . . . . . . . . . . . . . 1
Relational Database and Terminology . . . . . . . . . . . . . . . 3
Types of SQL Statements . . . . . . . . . . . . . . . . . . . 4
SQL Objects . . . . . . . . . . . . . . . . . . . . . . . . . 5
Collections . . . . . . . . . . . . . . . . . . . . . . . . . 6
Tables, Rows, and Columns. . . . . . . . . . . . . . . . . . . 6
Aliases . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Views . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Indexes . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Constraints . . . . . . . . . . . . . . . . . . . . . . . . . 8
Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Stored Procedures . . . . . . . . . . . . . . . . . . . . . . 9
User-defined functions . . . . . . . . . . . . . . . . . . . . . 9
Packages . . . . . . . . . . . . . . . . . . . . . . . . . 9
Application Program Objects . . . . . . . . . . . . . . . . . . . 9
User Source File Member . . . . . . . . . . . . . . . . . . . 11
Output Source File Member . . . . . . . . . . . . . . . . . . . 11
Program . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Package . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Module . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Service Program . . . . . . . . . . . . . . . . . . . . . . . 12

Chapter 2. Getting Started with SQL . . . . . . . . . . . . . . . . 13


Starting Interactive SQL . . . . . . . . . . . . . . . . . . . . . 13
Creating an SQL Collection . . . . . . . . . . . . . . . . . . . . 13
Example: Creating the SQL Collection (SAMPLECOLL) . . . . . . . . 13
Creating and Using a Table . . . . . . . . . . . . . . . . . . . . 14
Example: Creating a Table (INVENTORY_LIST) . . . . . . . . . . . 14
Creating the Supplier Table (SUPPLIERS) . . . . . . . . . . . . . 16
Using the LABEL ON Statement . . . . . . . . . . . . . . . . . . 16
Inserting Information into a Table . . . . . . . . . . . . . . . . . . 18
Example: Inserting Information into a Table (INVENTORY_LIST) . . . . . 18
Getting Information from a Single Table . . . . . . . . . . . . . . . 20
Getting Information from More Than One Table. . . . . . . . . . . . . 23
Changing Information in a Table . . . . . . . . . . . . . . . . . . 25
Example: Changing Information in a Table . . . . . . . . . . . . . 25
Deleting Information from a Table. . . . . . . . . . . . . . . . . . 28
Example: Deleting Information from a Table (INVENTORY_LIST) . . . . . 28
Creating and Using a View . . . . . . . . . . . . . . . . . . . . 28
Example: Creating a view on a single table . . . . . . . . . . . . . 29
Example: Creating a view combining data from more than one table . . . . 30

© Copyright IBM Corp. 1997, 1999 iii


Chapter 3. Basic Concepts and Techniques . . . . . . . . . . . . . 31
Using Basic SQL Statements and Clauses . . . . . . . . . . . . . . 31
The INSERT Statement . . . . . . . . . . . . . . . . . . . . 31
The UPDATE Statement . . . . . . . . . . . . . . . . . . . . 33
The DELETE Statement . . . . . . . . . . . . . . . . . . . . 34
The SELECT INTO Statement . . . . . . . . . . . . . . . . . . 35
Data retrieval errors. . . . . . . . . . . . . . . . . . . . . . 36
The SELECT Clause . . . . . . . . . . . . . . . . . . . . . 38
The WHERE Clause . . . . . . . . . . . . . . . . . . . . . 38
The GROUP BY Clause . . . . . . . . . . . . . . . . . . . . 40
The HAVING Clause . . . . . . . . . . . . . . . . . . . . . 42
The ORDER BY Clause . . . . . . . . . . . . . . . . . . . . 43
Using Null Values . . . . . . . . . . . . . . . . . . . . . . . 45
Using Special Registers . . . . . . . . . . . . . . . . . . . . . 45
Using Date, Time, and Timestamp . . . . . . . . . . . . . . . . . 47
Specifying Current Date and Time Values. . . . . . . . . . . . . . 47
Date/Time Arithmetic . . . . . . . . . . . . . . . . . . . . . 47
Creating and using ALIAS names. . . . . . . . . . . . . . . . . . 48
Using LABEL ON. . . . . . . . . . . . . . . . . . . . . . . . 48
Using COMMENT ON . . . . . . . . . . . . . . . . . . . . . . 49
Getting Comments . . . . . . . . . . . . . . . . . . . . . . 50
Using Sort Sequence in SQL . . . . . . . . . . . . . . . . . . . 50
Sort Sequence Used with ORDER BY and Record Selection . . . . . . 50
ORDER BY . . . . . . . . . . . . . . . . . . . . . . . . . 51
Record selection . . . . . . . . . . . . . . . . . . . . . . . 52
Sort Sequence and Views . . . . . . . . . . . . . . . . . . . 53
Sort Sequence and the CREATE INDEX Statement . . . . . . . . . . 53
Sort Sequence and Constraints . . . . . . . . . . . . . . . . . 54

Chapter 4. Using a Cursor . . . . . . . . . . . . . . . . . . . . 55


Types of cursors . . . . . . . . . . . . . . . . . . . . . . . . 55
Serial cursor . . . . . . . . . . . . . . . . . . . . . . . . 55
Scrollable cursor . . . . . . . . . . . . . . . . . . . . . . . 55
Example of Using a Cursor . . . . . . . . . . . . . . . . . . . . 56
Step 1: Define the Cursor . . . . . . . . . . . . . . . . . . . 58
Step 2: Open the Cursor . . . . . . . . . . . . . . . . . . . . 59
Step 3: Specify What to Do When End-of-Data Is Reached . . . . . . . 59
Step 4: Retrieve a Row Using a Cursor . . . . . . . . . . . . . . 60
Step 5a: Update the Current Row . . . . . . . . . . . . . . . . 61
Step 5b: Delete the Current Row . . . . . . . . . . . . . . . . . 61
Step 6: Close the Cursor . . . . . . . . . . . . . . . . . . . . 62
Using the Multiple-Row FETCH Statement . . . . . . . . . . . . . . 62
Multiple-Row FETCH Using a Host Structure Array . . . . . . . . . . 63
Multiple-Row FETCH Using a Row Storage Area . . . . . . . . . . . 64
Unit of Work and Open Cursors . . . . . . . . . . . . . . . . . . 68

Chapter 5. Advanced Coding Techniques . . . . . . . . . . . . . . 69


Advanced Insert Techniques . . . . . . . . . . . . . . . . . . . 69
Inserting Rows into a Table Using a Select-Statement . . . . . . . . . 69
Using the Blocked Insert Statement . . . . . . . . . . . . . . . . 70
Advanced Update Techniques . . . . . . . . . . . . . . . . . . . 70
Preventing Duplicate Rows . . . . . . . . . . . . . . . . . . . . 71
Performing Complex Search Conditions . . . . . . . . . . . . . . . 72
Keywords for Use in Search Conditions . . . . . . . . . . . . . . 72
Joining Data from More Than One Table . . . . . . . . . . . . . . . 75
Inner Join . . . . . . . . . . . . . . . . . . . . . . . . . 75

iv DB2 UDB for AS/400 SQL Programming V4R4


Left Outer Join . . . . . . . . . . . . . . . . . . . . . . . 76
Exception Join. . . . . . . . . . . . . . . . . . . . . . . . 77
Cross Join . . . . . . . . . . . . . . . . . . . . . . . . . 78
Using multiple join types in one statement . . . . . . . . . . . . . 78
Notes on Joins . . . . . . . . . . . . . . . . . . . . . . . 79
Using Table Expressions . . . . . . . . . . . . . . . . . . . . . 79
Using the UNION Keyword to Combine Subselects . . . . . . . . . . . 80
Specifying UNION ALL. . . . . . . . . . . . . . . . . . . . . 83
Using Subqueries . . . . . . . . . . . . . . . . . . . . . . . 84
Correlation . . . . . . . . . . . . . . . . . . . . . . . . . 85
Subqueries and Search Conditions . . . . . . . . . . . . . . . . 85
How Subqueries Are Used . . . . . . . . . . . . . . . . . . . 86
Using Subqueries with UPDATE and DELETE . . . . . . . . . . . . 88
Notes on Using Subqueries . . . . . . . . . . . . . . . . . . . 88
Correlated Subqueries . . . . . . . . . . . . . . . . . . . . . 88
Using Correlated Subqueries in an UPDATE Statement . . . . . . . . 91
Using Correlated Subqueries in a DELETE Statement . . . . . . . . . 92
Notes on Using Correlated Subqueries. . . . . . . . . . . . . . . 92
Changing a Table Definition . . . . . . . . . . . . . . . . . . . . 93
Adding a column . . . . . . . . . . . . . . . . . . . . . . . 93
Changing a column . . . . . . . . . . . . . . . . . . . . . . 93
Allowable Conversions. . . . . . . . . . . . . . . . . . . . . 93
Deleting a column . . . . . . . . . . . . . . . . . . . . . . 95
Order of operations for ALTER TABLE statement . . . . . . . . . . . 95
Creating and Using Views . . . . . . . . . . . . . . . . . . . . 95
Adding Indexes . . . . . . . . . . . . . . . . . . . . . . . . 96
Using the Catalog in Database Design . . . . . . . . . . . . . . . . 97
Getting Catalog Information about a Table . . . . . . . . . . . . . 97
Getting Catalog Information about a Column . . . . . . . . . . . . 98

Chapter 6. Data Integrity . . . . . . . . . . . . . . . . . . . . 99


Adding and Using Check Constraints . . . . . . . . . . . . . . . . 99
Referential Integrity . . . . . . . . . . . . . . . . . . . . . . . 99
Adding or dropping referential constraints . . . . . . . . . . . . . . 100
Removing Referential Constraints . . . . . . . . . . . . . . . . 102
Inserting into Tables with Referential Constraints . . . . . . . . . . . 102
Updating Tables with Referential Constraints . . . . . . . . . . . . 103
Deleting from Tables with Referential Constraints . . . . . . . . . . . 105
Check Pending . . . . . . . . . . . . . . . . . . . . . . . 107
WITH CHECK OPTION on a View . . . . . . . . . . . . . . . . . 108
WITH CASCADED CHECK OPTION . . . . . . . . . . . . . . . 108
WITH LOCAL CHECK OPTION . . . . . . . . . . . . . . . . . 109
DB2 UDB for AS/400 Trigger Support . . . . . . . . . . . . . . . . 111
Trigger Sample . . . . . . . . . . . . . . . . . . . . . . . 111

Chapter 7. Stored Procedures . . . . . . . . . . . . . . . . . . 117


Creating a Procedure . . . . . . . . . . . . . . . . . . . . . . 117
Defining an External Procedure . . . . . . . . . . . . . . . . . . 117
Defining an SQL Procedure . . . . . . . . . . . . . . . . . . . . 118
Invoking a Stored Procedure . . . . . . . . . . . . . . . . . . . 124
Using CALL Statement Where Procedure Definition Exists . . . . . . . 124
Using Embedded CALL Statement Where No Procedure Definition Exists . . 125
Using Embedded CALL Statement With an SQLDA . . . . . . . . . . 125
Using Dynamic CALL Statement Where No CREATE PROCEDURE Exists . 127
Parameter Passing Conventions for Stored Procedures . . . . . . . . . 128
Indicator Variables and Stored Procedures . . . . . . . . . . . . . . 132

Contents v
Returning a Completion Status to the Calling Program . . . . . . . . . . 134
Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 135
Example 1. ILE C and PL/I Procedures Called From ILE C Applications . . 136

Chapter 8. Using the Object-Relational Capabilities . . . . . . . . . . 145


Why Use the DB2 Object Extensions? . . . . . . . . . . . . . . . . 145
DB2 Approach to Supporting Objects . . . . . . . . . . . . . . . . 146
Using Large Objects (LOBs) . . . . . . . . . . . . . . . . . . . 146
Understanding Large Object Data Types (BLOB, CLOB, DBCLOB) . . . . 147
Understanding Large Object Locators . . . . . . . . . . . . . . . 147
Example: Using a Locator to Work With a CLOB Value . . . . . . . . . 148
Indicator Variables and LOB Locators . . . . . . . . . . . . . . . 151
LOB File Reference Variables . . . . . . . . . . . . . . . . . . 151
Example: Extracting a Document To a File . . . . . . . . . . . . . 152
Example: Inserting Data Into a CLOB Column . . . . . . . . . . . . 154
Display Layout of LOB Columns . . . . . . . . . . . . . . . . . 155
Journal Entry Layout of LOB Columns . . . . . . . . . . . . . . . 155
User-Defined Functions (UDF) . . . . . . . . . . . . . . . . . . . 156
Why Use UDFs? . . . . . . . . . . . . . . . . . . . . . . . 156
UDF Concepts. . . . . . . . . . . . . . . . . . . . . . . . 158
Implementing UDFs . . . . . . . . . . . . . . . . . . . . . . 160
Registering UDFs . . . . . . . . . . . . . . . . . . . . . . 161
Examples of Registering UDFs . . . . . . . . . . . . . . . . . 161
Using UDFs . . . . . . . . . . . . . . . . . . . . . . . . 164
User-defined Distinct Types (UDT) . . . . . . . . . . . . . . . . . 169
Why Use UDTs? . . . . . . . . . . . . . . . . . . . . . . . 169
Defining a UDT . . . . . . . . . . . . . . . . . . . . . . . 170
Resolving Unqualified UDTs . . . . . . . . . . . . . . . . . . . 171
Examples of Using CREATE DISTINCT TYPE . . . . . . . . . . . . 171
Defining Tables with UDTs . . . . . . . . . . . . . . . . . . . 171
Manipulating UDTs . . . . . . . . . . . . . . . . . . . . . . 172
Examples of Manipulating UDTs . . . . . . . . . . . . . . . . . 173
Synergy Between UDTs, UDFs, and LOBs . . . . . . . . . . . . . . 177
Combining UDTs, UDFs, and LOBs . . . . . . . . . . . . . . . . 177
Examples of Complex Applications . . . . . . . . . . . . . . . . 177
Using DataLinks . . . . . . . . . . . . . . . . . . . . . . . . 180
NO LINK CONTROL . . . . . . . . . . . . . . . . . . . . . 181
FILE LINK CONTROL (with File System Permissions) . . . . . . . . . 181
FILE LINK CONTROL (with Database Permissions) . . . . . . . . . . 181
Commands Used for Working with DataLinks . . . . . . . . . . . . 182

Chapter 9. Writing User-Defined Functions (UDFs) . . . . . . . . . . 185


UDF runtime environment . . . . . . . . . . . . . . . . . . . . 185
Length of time that the UDF runs . . . . . . . . . . . . . . . . . 185
Threads considerations . . . . . . . . . . . . . . . . . . . . 186
Parallel processing . . . . . . . . . . . . . . . . . . . . . . 186
Writing function code . . . . . . . . . . . . . . . . . . . . . . 186
Writing UDFs as SQL functions . . . . . . . . . . . . . . . . . 186
Writing UDFs as external functions . . . . . . . . . . . . . . . . 187
Examples of UDF code . . . . . . . . . . . . . . . . . . . . . 193
Example: Square of a number UDF . . . . . . . . . . . . . . . . 193
Example: Counter . . . . . . . . . . . . . . . . . . . . . . 194

Chapter 10. Dynamic SQL Applications. . . . . . . . . . . . . . . 197


Designing and Running a Dynamic SQL Application . . . . . . . . . . . 199
Processing Non-SELECT statements . . . . . . . . . . . . . . . . 199

vi DB2 UDB for AS/400 SQL Programming V4R4


CCSID of Dynamic SQL Statements. . . . . . . . . . . . . . . . 200
Using the PREPARE and EXECUTE Statements . . . . . . . . . . . 200
Processing SELECT Statements and Using an SQLDA. . . . . . . . . . 201
Fixed-List SELECT Statements . . . . . . . . . . . . . . . . . 201
Varying-List Select-Statements . . . . . . . . . . . . . . . . . . 202
The SQL Descriptor Area (SQLDA) . . . . . . . . . . . . . . . . 203
SQLDA Format . . . . . . . . . . . . . . . . . . . . . . . 204
Example of a Select-Statement for Allocating Storage for SQLDA . . . . . 208
Using a Cursor . . . . . . . . . . . . . . . . . . . . . . . 212
Using Parameter Markers . . . . . . . . . . . . . . . . . . . 213

Chapter 11. Common Concepts and Rules for Using SQL with Host
Languages . . . . . . . . . . . . . . . . . . . . . . . . . 215
Using Host Variables in SQL Statements . . . . . . . . . . . . . . . 215
Assignment Rules . . . . . . . . . . . . . . . . . . . . . . 216
Indicator Variables . . . . . . . . . . . . . . . . . . . . . . 219
Handling SQL Error Return Codes . . . . . . . . . . . . . . . . . 221
Handling Exception Conditions with the WHENEVER Statement . . . . . . 222

Chapter 12. Coding SQL Statements in C and C++ Applications . . . . . 225


Defining the SQL Communications Area . . . . . . . . . . . . . . . 225
Defining SQL Descriptor Areas. . . . . . . . . . . . . . . . . . . 226
Embedding SQL Statements . . . . . . . . . . . . . . . . . . . 227
Comments . . . . . . . . . . . . . . . . . . . . . . . . . 228
Continuation for SQL Statements . . . . . . . . . . . . . . . . . 228
Including Code . . . . . . . . . . . . . . . . . . . . . . . 228
Margins . . . . . . . . . . . . . . . . . . . . . . . . . . 229
Names . . . . . . . . . . . . . . . . . . . . . . . . . . 229
NULLs and NULs . . . . . . . . . . . . . . . . . . . . . . 229
Statement Labels . . . . . . . . . . . . . . . . . . . . . . 229
Preprocessor Sequence . . . . . . . . . . . . . . . . . . . . 229
Trigraphs. . . . . . . . . . . . . . . . . . . . . . . . . . 229
WHENEVER Statement . . . . . . . . . . . . . . . . . . . . 230
Using Host Variables . . . . . . . . . . . . . . . . . . . . . . 230
Declaring Host Variables . . . . . . . . . . . . . . . . . . . . 230
Using Host Structures . . . . . . . . . . . . . . . . . . . . . . 239
Host Structure Declarations . . . . . . . . . . . . . . . . . . . 240
Host Structure Indicator Array . . . . . . . . . . . . . . . . . . 241
Using Arrays of Host Structures . . . . . . . . . . . . . . . . . . 241
Host Structure Array . . . . . . . . . . . . . . . . . . . . . 242
Host Structure Array Indicator Structure . . . . . . . . . . . . . . 244
Using Pointer Data Types . . . . . . . . . . . . . . . . . . . . 244
Using ILE C for AS/400 External File Descriptions . . . . . . . . . . . 245
Determining Equivalent SQL and C or C++ Data Types. . . . . . . . . . 246
Notes on C and C++ Variable Declaration and Usage . . . . . . . . . 249
Using Indicator Variables . . . . . . . . . . . . . . . . . . . . . 249

Chapter 13. Coding SQL Statements in COBOL Applications . . . . . . 251


Defining the SQL Communications Area . . . . . . . . . . . . . . . 251
Defining SQL Descriptor Areas. . . . . . . . . . . . . . . . . . . 252
Embedding SQL Statements . . . . . . . . . . . . . . . . . . . 253
Comments . . . . . . . . . . . . . . . . . . . . . . . . . 253
Continuation for SQL Statements . . . . . . . . . . . . . . . . . 253
Including Code . . . . . . . . . . . . . . . . . . . . . . . 254
Margins . . . . . . . . . . . . . . . . . . . . . . . . . . 254
Sequence Numbers . . . . . . . . . . . . . . . . . . . . . . 254

Contents vii
Names . . . . . . . . . . . . . . . . . . . . . . . . . . 254
COBOL Compile-Time Options. . . . . . . . . . . . . . . . . . 254
Statement Labels . . . . . . . . . . . . . . . . . . . . . . 255
WHENEVER Statement . . . . . . . . . . . . . . . . . . . . 255
Multiple source programs. . . . . . . . . . . . . . . . . . . . 255
Using Host Variables . . . . . . . . . . . . . . . . . . . . . . 255
Declaring Host Variables . . . . . . . . . . . . . . . . . . . . 255
Using Host Structures . . . . . . . . . . . . . . . . . . . . . . 264
Host Structure . . . . . . . . . . . . . . . . . . . . . . . . 265
Host Structure Indicator Array . . . . . . . . . . . . . . . . . . 268
Using Host Structure Arrays . . . . . . . . . . . . . . . . . . . 268
Host Structure Array . . . . . . . . . . . . . . . . . . . . . 269
Host Array Indicator Structure . . . . . . . . . . . . . . . . . . 272
Using External File Descriptions . . . . . . . . . . . . . . . . . . 272
Using External File Descriptions for Host Structure Arrays. . . . . . . . 273
Determining Equivalent SQL and COBOL Data Types . . . . . . . . . . 274
Notes on COBOL Variable Declaration and Usage . . . . . . . . . . 276
Using Indicator Variables . . . . . . . . . . . . . . . . . . . . . 276

Chapter 14. Coding SQL Statements in PL/I Applications. . . . . . . . 279


Defining the SQL Communications Area . . . . . . . . . . . . . . . 279
Defining SQL Descriptor Areas. . . . . . . . . . . . . . . . . . . 280
Embedding SQL Statements . . . . . . . . . . . . . . . . . . . 280
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Comments . . . . . . . . . . . . . . . . . . . . . . . . . 281
Continuation for SQL Statements . . . . . . . . . . . . . . . . . 281
Including Code . . . . . . . . . . . . . . . . . . . . . . . 281
Margins . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Names . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Statement Labels . . . . . . . . . . . . . . . . . . . . . . 282
WHENEVER Statement . . . . . . . . . . . . . . . . . . . . 282
Using Host Variables . . . . . . . . . . . . . . . . . . . . . . 282
Declaring Host Variables . . . . . . . . . . . . . . . . . . . . 282
Using Host Structures . . . . . . . . . . . . . . . . . . . . . . 286
Host Structures . . . . . . . . . . . . . . . . . . . . . . . 287
Host Structure Indicator Arrays. . . . . . . . . . . . . . . . . . 288
Using Host Structure Arrays . . . . . . . . . . . . . . . . . . . . 289
Host Structure Array . . . . . . . . . . . . . . . . . . . . . 290
Using External File Descriptions . . . . . . . . . . . . . . . . . . 291
Determining Equivalent SQL and PL/I Data Types. . . . . . . . . . . . 292
Using Indicator Variables . . . . . . . . . . . . . . . . . . . . . 294
Differences in PL/I Because of Structure Parameter Passing Techniques . . . 294

Chapter 15. Coding SQL Statements in RPG for AS/400 Applications . . . 297
Defining the SQL Communications Area . . . . . . . . . . . . . . . 297
Defining SQL Descriptor Areas. . . . . . . . . . . . . . . . . . . 298
Embedding SQL Statements . . . . . . . . . . . . . . . . . . . 298
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 298
Comments . . . . . . . . . . . . . . . . . . . . . . . . . 299
Continuation for SQL Statements . . . . . . . . . . . . . . . . . 299
Including Code . . . . . . . . . . . . . . . . . . . . . . . 299
Sequence Numbers . . . . . . . . . . . . . . . . . . . . . . 299
Names . . . . . . . . . . . . . . . . . . . . . . . . . . 299
Statement Labels . . . . . . . . . . . . . . . . . . . . . . 300
WHENEVER Statement . . . . . . . . . . . . . . . . . . . . 300
Using Host Variables . . . . . . . . . . . . . . . . . . . . . . 300

viii DB2 UDB for AS/400 SQL Programming V4R4


Declaring Host Variables . . . . . . . . . . . . . . . . . . . . 300
Using Host Structures . . . . . . . . . . . . . . . . . . . . . . 300
Using Host Structure Arrays . . . . . . . . . . . . . . . . . . . . 301
Using External File Descriptions . . . . . . . . . . . . . . . . . . 302
External File Description Considerations for Host Structure Arrays. . . . . 303
Determining Equivalent SQL and RPG for AS/400 Data Types . . . . . . . 303
Notes on RPG for AS/400 Variable Declaration and Usage . . . . . . . 306
Using Indicator Variables . . . . . . . . . . . . . . . . . . . . . 306
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 306
Differences in RPG for AS/400 Because of Structure Parameter Passing
Techniques . . . . . . . . . . . . . . . . . . . . . . . . . 307
Ending a Called RPG for AS/400 Program Correctly . . . . . . . . . . . 307

Chapter 16. Coding SQL Statements in ILE RPG for AS/400 Applications . 309
Defining the SQL Communications Area . . . . . . . . . . . . . . . 309
Defining SQL Descriptor Areas. . . . . . . . . . . . . . . . . . . 310
Embedding SQL Statements . . . . . . . . . . . . . . . . . . . 311
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 311
Comments . . . . . . . . . . . . . . . . . . . . . . . . . 311
Continuation for SQL Statements . . . . . . . . . . . . . . . . . 311
Including Code . . . . . . . . . . . . . . . . . . . . . . . 312
Sequence Numbers . . . . . . . . . . . . . . . . . . . . . . 312
Names . . . . . . . . . . . . . . . . . . . . . . . . . . 312
Statement Labels . . . . . . . . . . . . . . . . . . . . . . 312
WHENEVER Statement . . . . . . . . . . . . . . . . . . . . 312
Using Host Variables . . . . . . . . . . . . . . . . . . . . . . 312
Declaring Host Variables . . . . . . . . . . . . . . . . . . . . 313
Using Host Structures . . . . . . . . . . . . . . . . . . . . . . 314
Using Host Structure Arrays . . . . . . . . . . . . . . . . . . . . 314
Declaring LOB Host Variables . . . . . . . . . . . . . . . . . . . 315
LOB Host Variables . . . . . . . . . . . . . . . . . . . . . . 315
LOB Locators . . . . . . . . . . . . . . . . . . . . . . . . 316
LOB File Reference Variables . . . . . . . . . . . . . . . . . . 316
Using External File Descriptions . . . . . . . . . . . . . . . . . . 316
External File Description Considerations for Host Structure Arrays. . . . . 317
Determining Equivalent SQL and RPG Data Types . . . . . . . . . . . 318
Notes on ILE/RPG 400 Variable Declaration and Usage . . . . . . . . 322
Using Indicator Variables . . . . . . . . . . . . . . . . . . . . . 322
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 322
SQLDA Example of the SQLDA for a Multiple Row-Area Fetch . . . . . . . 323

Chapter 17. Coding SQL Statements in REXX Applications . . . . . . . 325


Using the SQL Communications Area . . . . . . . . . . . . . . . . 325
Using SQL Descriptor Areas . . . . . . . . . . . . . . . . . . . 325
Embedding SQL Statements . . . . . . . . . . . . . . . . . . . 327
Comments . . . . . . . . . . . . . . . . . . . . . . . . . 328
Continuation of SQL Statements . . . . . . . . . . . . . . . . . 328
Including Code . . . . . . . . . . . . . . . . . . . . . . . 328
Margins . . . . . . . . . . . . . . . . . . . . . . . . . . 329
Names . . . . . . . . . . . . . . . . . . . . . . . . . . 329
Nulls . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
Statement Labels . . . . . . . . . . . . . . . . . . . . . . 329
Handling Errors and Warnings . . . . . . . . . . . . . . . . . . 329
Using Host Variables . . . . . . . . . . . . . . . . . . . . . . 329
Determining Data Types of Input Host Variables . . . . . . . . . . . 330
The Format of Output Host Variables . . . . . . . . . . . . . . . 331

Contents ix
Avoiding REXX Conversion . . . . . . . . . . . . . . . . . . . 332
Using Indicator Variables . . . . . . . . . . . . . . . . . . . . . 332

Chapter 18. Preparing and Running a Program with SQL Statements . . . 333
Basic Processes of the SQL Precompiler . . . . . . . . . . . . . . . 333
Input to the Precompiler . . . . . . . . . . . . . . . . . . . . 334
Source File CCSIDs . . . . . . . . . . . . . . . . . . . . . 334
Output from the Precompiler . . . . . . . . . . . . . . . . . . 335
Non-ILE Precompiler Commands . . . . . . . . . . . . . . . . . . 340
Compiling a Non-ILE Application Program . . . . . . . . . . . . . 340
ILE Precompiler Commands. . . . . . . . . . . . . . . . . . . . 341
Compiling an ILE Application Program . . . . . . . . . . . . . . . 341
Precompiling for the VisualAge C++ for OS/400 Compiler . . . . . . . . 342
Interpreting Application Program Compile Errors . . . . . . . . . . . . 343
Error and Warning Messages during a Compile . . . . . . . . . . . 343
Binding an Application . . . . . . . . . . . . . . . . . . . . . . 344
Program References . . . . . . . . . . . . . . . . . . . . . 345
Displaying Precompiler Options . . . . . . . . . . . . . . . . . . 345
Running a Program with Embedded SQL . . . . . . . . . . . . . . . 346
OS/400 DDM Considerations . . . . . . . . . . . . . . . . . . 346
Override Considerations . . . . . . . . . . . . . . . . . . . . 346
SQL Return Codes . . . . . . . . . . . . . . . . . . . . . . 347

Chapter 19. Using Interactive SQL . . . . . . . . . . . . . . . . 349


Basic Functions of Interactive SQL . . . . . . . . . . . . . . . . . 349
Starting Interactive SQL . . . . . . . . . . . . . . . . . . . . 350
Using Statement Entry Function . . . . . . . . . . . . . . . . . 351
Prompting . . . . . . . . . . . . . . . . . . . . . . . . . 351
Using the List Selection Function . . . . . . . . . . . . . . . . . 354
Session Services Description . . . . . . . . . . . . . . . . . . 356
Exiting Interactive SQL . . . . . . . . . . . . . . . . . . . . 357
Using an existing SQL Session . . . . . . . . . . . . . . . . . 358
Recovering an SQL Session . . . . . . . . . . . . . . . . . . 358
Accessing Remote Databases with Interactive SQL . . . . . . . . . . 359

Chapter 20. Using the SQL Statement Processor . . . . . . . . . . . 361


Execution of Statements After Errors Occur . . . . . . . . . . . . . . 362
Commitment Control in the SQL Statement Processor . . . . . . . . . . 362
Schemas in the SQL Statement Processor . . . . . . . . . . . . . . 362
Source Member Listing for the SQL Statement Processor . . . . . . . . . 363

Chapter 21. DB2 UDB for AS/400 Data Protection. . . . . . . . . . . 365


Security . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
Authorization ID . . . . . . . . . . . . . . . . . . . . . . . 366
Views . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
Auditing . . . . . . . . . . . . . . . . . . . . . . . . . . 366
Data Integrity . . . . . . . . . . . . . . . . . . . . . . . . . 366
Concurrency . . . . . . . . . . . . . . . . . . . . . . . . 367
Journaling . . . . . . . . . . . . . . . . . . . . . . . . . 368
Commitment Control . . . . . . . . . . . . . . . . . . . . . 369
Atomic Operations . . . . . . . . . . . . . . . . . . . . . . 373
Constraints . . . . . . . . . . . . . . . . . . . . . . . . . 375
Save/Restore . . . . . . . . . . . . . . . . . . . . . . . . 375
Damage Tolerance . . . . . . . . . . . . . . . . . . . . . . 376
Index Recovery . . . . . . . . . . . . . . . . . . . . . . . 376
Catalog Integrity . . . . . . . . . . . . . . . . . . . . . . . 377

x DB2 UDB for AS/400 SQL Programming V4R4


User Auxiliary Storage Pool (ASP) . . . . . . . . . . . . . . . . 378

Chapter 22. Testing SQL Statements in Application Programs . . . . . . 379


Establishing a Test Environment . . . . . . . . . . . . . . . . . . 379
Designing a Test Data Structure . . . . . . . . . . . . . . . . . 379
Testing Your SQL Application Programs . . . . . . . . . . . . . . . 380
The Program Debug Phase . . . . . . . . . . . . . . . . . . . 380
The Performance Verification Phase. . . . . . . . . . . . . . . . 381
CL Command Usage for SQL Application Performance Verification . . . . 381
Performance Information Messages . . . . . . . . . . . . . . . . 382
Performance Information Messages and Open Data Paths . . . . . . . 388

Chapter 23. Using the DB2 UDB for AS/400 Predictive Query Governor . . 391
Cancelling a Query . . . . . . . . . . . . . . . . . . . . . . . 392
General Implementation Considerations . . . . . . . . . . . . . . . 392
User Application Implementation Considerations . . . . . . . . . . . . 392
Controlling the Default Reply to the Inquiry Message . . . . . . . . . . 393
Using the Governor for Performance Testing. . . . . . . . . . . . . . 393
Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 394

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer
Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
General Optimization Tips . . . . . . . . . . . . . . . . . . . . 395
Data Management Methods . . . . . . . . . . . . . . . . . . . . 396
Access Path . . . . . . . . . . . . . . . . . . . . . . . . 396
Access Method . . . . . . . . . . . . . . . . . . . . . . . 397
Data Access Methods . . . . . . . . . . . . . . . . . . . . . . 420
The Optimizer . . . . . . . . . . . . . . . . . . . . . . . . . 422
Cost Estimation . . . . . . . . . . . . . . . . . . . . . . . 423
Access Plan Validation. . . . . . . . . . . . . . . . . . . . . 425
Optimizer Decision-Making Rules . . . . . . . . . . . . . . . . . 425
Join Optimization . . . . . . . . . . . . . . . . . . . . . . . 426
Grouping Optimization . . . . . . . . . . . . . . . . . . . . . 442
Effectively Using SQL Indexes . . . . . . . . . . . . . . . . . . . 446
Using Indexes With Sort Sequence . . . . . . . . . . . . . . . . . 449
Using Indexes and Sort Sequence With Selection, Joins, or Grouping . . . 449
Ordering . . . . . . . . . . . . . . . . . . . . . . . . . . 450
Example Indexes . . . . . . . . . . . . . . . . . . . . . . . 450
Tips for using VARCHAR and VARGRAPHIC data types . . . . . . . . . 456

Chapter 25. Additional SQL performance considerations . . . . . . . . 459


Improving Performance by Using Database Manager Blocking Considerations . 461
Improving Performance Using FETCH FOR n ROWS . . . . . . . . . . 462
Improving Performance with SQL Blocking . . . . . . . . . . . . . . 462
Improving Performance Using INSERT n ROWS . . . . . . . . . . . . 463
Improving Performance When Paging Interactively Displayed Data . . . . . 463
Improving Performance by Using SELECT Statements Effectively . . . . . . 464
Improving Performance by Using Live Data . . . . . . . . . . . . . . 464
Improving Performance by Using the ALWCPYDTA Parameter . . . . . . . 465
Improving Performance by Using the Optimize Clause . . . . . . . . . . 466
Improving Performance by Retaining Cursor Positions . . . . . . . . . . 467
Improving Performance by Retaining Cursor Positions for Non-ILE Program
Calls . . . . . . . . . . . . . . . . . . . . . . . . . . 467
Improving Performance by Retaining Cursor Positions across ILE Program
Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
General Rules for Retaining Cursor Positions For All Program Calls . . . . . 469

Contents xi
Improving Performance of SQL PREPARE Statements . . . . . . . . . . 470
Effects on Performance When Using Long Object Names . . . . . . . . . 470
Improving Performance Using the Precompile Options . . . . . . . . . . 471
Improving Performance by Using Structure Parameter Passing Techniques . . 472
Background Information on Parameter Passing. . . . . . . . . . . . 472
Some Differences Because of Structure Parameter Passing Techniques . . 473
Controlling Parallel Processing . . . . . . . . . . . . . . . . . . . 473
Controlling Parallel Processing System Wide . . . . . . . . . . . . 474
Controlling Parallel Processing for a Job . . . . . . . . . . . . . . 474

Chapter 26. Monitoring and Optimizing Query Performance Tools . . . . 477


Optimizing Query Performance Using Query Optimization Tools . . . . . . 477
Query optimizer debug messages . . . . . . . . . . . . . . . . . 477
Print SQL information . . . . . . . . . . . . . . . . . . . . . . 478
Database monitor statistics . . . . . . . . . . . . . . . . . . . . 478
Start Database Monitor (STRDBMON) Command . . . . . . . . . . . 479
End Database Monitor (ENDDBMON) Command . . . . . . . . . . . 480
Database Monitor Performance Records . . . . . . . . . . . . . . 481
Query Optimizer Index Advisor . . . . . . . . . . . . . . . . . . 482
Database Monitor Examples . . . . . . . . . . . . . . . . . . 482
Database Monitor Physical File DDS . . . . . . . . . . . . . . . 489
Database Monitor Logical File DDS . . . . . . . . . . . . . . . . 493
Memory Resident Database Monitor APIs. . . . . . . . . . . . . . . 524
External API Description . . . . . . . . . . . . . . . . . . . . 525
External File Description . . . . . . . . . . . . . . . . . . . . 525
Record Identification . . . . . . . . . . . . . . . . . . . . . 542
Comparison table of query optimization tools . . . . . . . . . . . . 542
Change query attributes . . . . . . . . . . . . . . . . . . . . . 543
Query Options File QAQQINI . . . . . . . . . . . . . . . . . . . 543
Specifying the QAQQINI file. . . . . . . . . . . . . . . . . . . 544
Creating the QAQQINI Query Options File . . . . . . . . . . . . . 544

Chapter 27. Solving Common Database Problems . . . . . . . . . . 551


Paging through Retrieved Data . . . . . . . . . . . . . . . . . . 551
Retrieving in Reverse Order. . . . . . . . . . . . . . . . . . . . 551
Establishing Position at the End of a Table . . . . . . . . . . . . . . 551
Adding Data to the End of a Table . . . . . . . . . . . . . . . . . 552
Updating Data as It Is Retrieved from a Table . . . . . . . . . . . . . 552
Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . 553
Updating Data Previously Retrieved . . . . . . . . . . . . . . . . . 553
Changing the Table Definition . . . . . . . . . . . . . . . . . . . 554

Chapter 28. Distributed Relational Database Function . . . . . . . . . 555


DB2 UDB for AS/400 Distributed Relational Database Support . . . . . . . 555
DB2 UDB for AS/400 Distributed Relational Database Example Program . . . 556
SQL Package Support . . . . . . . . . . . . . . . . . . . . . . 557
Valid SQL Statements in an SQL Package . . . . . . . . . . . . . 558
Considerations for Creating an SQL Package . . . . . . . . . . . . 558
CCSID Considerations for SQL . . . . . . . . . . . . . . . . . . 561
Connection Management and Activation Groups . . . . . . . . . . . . 561
Connections and conversations . . . . . . . . . . . . . . . . . 561
Source Code for PGM1: . . . . . . . . . . . . . . . . . . . . 562
Source Code for PGM2: . . . . . . . . . . . . . . . . . . . . 563
Source Code for PGM3: . . . . . . . . . . . . . . . . . . . . 563
Multiple Connections to the Same Relational Database. . . . . . . . . 565
Implicit Connection Management for the Default Activation Group . . . . . 565

xii DB2 UDB for AS/400 SQL Programming V4R4


Implicit Connection Management for Nondefault Activation Groups . . . . 566
Distributed Support . . . . . . . . . . . . . . . . . . . . . . . 566
Determining Connection Type . . . . . . . . . . . . . . . . . . 567
Connect and Commitment Control Restrictions . . . . . . . . . . . . 570
Determining Connection Status . . . . . . . . . . . . . . . . . 570
Distributed Unit of Work Connection Considerations . . . . . . . . . . 572
Ending Connections. . . . . . . . . . . . . . . . . . . . . . 573
Distributed Unit of Work . . . . . . . . . . . . . . . . . . . . . 573
Managing Distributed Unit of Work Connections . . . . . . . . . . . 574
Cursors and Prepared Statements . . . . . . . . . . . . . . . . 576
Application Requester Driver Programs . . . . . . . . . . . . . . . 577
Problem Handling . . . . . . . . . . . . . . . . . . . . . . . 578

Appendix A. DB2 UDB for AS/400 Sample Tables . . . . . . . . . . . 579


Department Table (CORPDATA.DEPARTMENT) . . . . . . . . . . . . 579
DEPARTMENT . . . . . . . . . . . . . . . . . . . . . . . 580
Employee Table (CORPDATA.EMPLOYEE) . . . . . . . . . . . . . . 580
Employee to Project Activity Table (CORPDATA.EMP_ACT) . . . . . . . . 581
EMP_ACT . . . . . . . . . . . . . . . . . . . . . . . . . 582
Project Table (CORPDATA.PROJECT) . . . . . . . . . . . . . . . . 584
PROJECT . . . . . . . . . . . . . . . . . . . . . . . . . 584
Class Schedule Table (CL_SCHED) . . . . . . . . . . . . . . . . . 585
In Tray Table (IN_TRAY) . . . . . . . . . . . . . . . . . . . . . 585

Appendix B. SQLCODEs and SQLSTATEs . . . . . . . . . . . . . 587


SQLCODE and SQLSTATE Descriptions . . . . . . . . . . . . . . . 589
Positive SQLCODEs . . . . . . . . . . . . . . . . . . . . . 589
Negative SQLCODEs . . . . . . . . . . . . . . . . . . . . . 591

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements . . 605
Examples of programs that use SQL statements . . . . . . . . . . . . 605
SQL Statements in ILE C and C++ Programs . . . . . . . . . . . . . 606
SQL Statements in COBOL and ILE COBOL Programs. . . . . . . . . . 613
SQL Statements in PL/I . . . . . . . . . . . . . . . . . . . . . 621
SQL Statements in RPG for AS/400 Programs . . . . . . . . . . . . . 628
SQL Statements in ILE RPG for AS/400 Programs . . . . . . . . . . . 634
SQL Statements in REXX Programs. . . . . . . . . . . . . . . . . 640
Report Produced by Sample Programs. . . . . . . . . . . . . . . . 643

Appendix D. DB2 UDB for AS/400 CL Command Descriptions . . . . . . 645


CRTSQLCBL (Create Structured Query Language COBOL) Command . . . . 645
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 648
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 648
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 661
CRTSQLCBLI (Create SQL ILE COBOL Object) Command . . . . . . . . 661
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 664
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 664
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 678
CRTSQLCI (Create Structured Query Language ILE C Object) Command . . . 678
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 681
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 681
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 695
CRTSQLCPPI (Create Structured Query Language C++ Object) Command . . 695
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 699
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 699
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 712

Contents xiii
CRTSQLPLI (Create Structured Query Language PL/I) Command. . . . . . 712
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 715
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 715
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 728
CRTSQLRPG (Create Structured Query Language RPG) Command . . . . . 728
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 731
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 732
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 744
CRTSQLRPGI (Create SQL ILE RPG Object) Command . . . . . . . . . 744
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 748
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 748
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 761
CRTSQLPKG (Create Structured Query Language Package) Command . . . 762
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 763
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 763
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 765
CVTSQLCPP (Convert Structured Query Language C++ Source) Command . . 766
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 769
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 769
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 781
DLTSQLPKG (Delete Structured Query Language Package) Command. . . . 781
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 782
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 782
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 783
PRTSQLINF (Print Structured Query Language Information) Command . . . . 783
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 783
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 783
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 784
RUNSQLSTM (Run Structured Query Language Statement) Command . . . . 784
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 786
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 786
Parameters for SQL procedures . . . . . . . . . . . . . . . . . 792
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 794
STRSQL (Start Structured Query Language) Command . . . . . . . . . 794
Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . 796
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . 796
Example . . . . . . . . . . . . . . . . . . . . . . . . . . 801

Appendix E. Using the C for AS/400 and FORTRAN for AS/400


Precompilers . . . . . . . . . . . . . . . . . . . . . . . . 803
Using the C for AS/400 Precompiler . . . . . . . . . . . . . . . . . 803
Access plans . . . . . . . . . . . . . . . . . . . . . . . . 803
Host variable data types . . . . . . . . . . . . . . . . . . . . 803
Using external file descriptions . . . . . . . . . . . . . . . . . . 803
CRTSQLC (Create Structured Query Language C) Command . . . . . . 804
Using the FORTRAN/400 Precompiler . . . . . . . . . . . . . . . . 819
CRTSQLFTN (Create Structured Query Language FORTRAN) Command . . 819

Appendix F. Coding SQL Statements in FORTRAN Applications . . . . . 837


Defining the SQL Communications Area . . . . . . . . . . . . . . . 837
Defining SQL Descriptor Areas. . . . . . . . . . . . . . . . . . . 838
Embedding SQL Statements . . . . . . . . . . . . . . . . . . . 839
Comments . . . . . . . . . . . . . . . . . . . . . . . . . 839
Debug Lines . . . . . . . . . . . . . . . . . . . . . . . . 839
Continuation for SQL statements . . . . . . . . . . . . . . . . . 839
Including Code . . . . . . . . . . . . . . . . . . . . . . . 840

xiv DB2 UDB for AS/400 SQL Programming V4R4


Margins . . . . . . . . . . . . . . . . . . . . . . . . . . 840
Names . . . . . . . . . . . . . . . . . . . . . . . . . . 840
Statement Labels . . . . . . . . . . . . . . . . . . . . . . 840
WHENEVER Statement . . . . . . . . . . . . . . . . . . . . 841
FORTRAN Compile-Time Options . . . . . . . . . . . . . . . . 841
Using Host Variables . . . . . . . . . . . . . . . . . . . . . . 841
Declaring Host Variables . . . . . . . . . . . . . . . . . . . . 841
Determining Equivalent SQL and FORTRAN Data Types . . . . . . . . . 842
Notes on FORTRAN Variable Declaration and Usage . . . . . . . . . 843
Using Indicator Variables . . . . . . . . . . . . . . . . . . . . . 844

Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . 845

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . 847

Readers’ Comments — We’d Like to Hear from You. . . . . . . . . . 879

Contents xv
xvi DB2 UDB for AS/400 SQL Programming V4R4
About DB2 UDB for AS/400 SQL Programming
This book explains to programmers and database administrators:
v How to use the DB2 SQL for AS/400 licensed program
v How to access data in a database
v How to prepare, run, test, and optimize an application program containing SQL
statements.

For more information on DB2 UDB for AS/400 SQL guidelines and examples for
implementation in an application programming environment, see the following
books:
v DB2 UDB for AS/400 SQL Reference
v DB2 UDB for AS/400 SQL Call Level Interface

Note: The DB2 UDB for AS/400 library will only be available in the AS/400e
Information Center beginning in Version 4, Release 4.
v DATABASE 2/400 Advanced Database Functions, GG24-4249.

Who should read this book


| This guide should be used by application programmers and database administrators
| who are familiar with and can program with COBOL for AS/400, ILE COBOL for
| AS/400, AS/400 PL/I, ILE C for AS/400, ILE C++, VisualAge C++ for AS/400, REXX,
| RPG III (part of RPG for AS/400), or ILE RPG for AS/400 language and who can
| understand basic database applications.

Assumptions Relating to Examples of SQL Statements


The examples of SQL statements shown in this guide are based on the sample
tables in Appendix A, ″DB2 UDB for AS/400 Sample Tables,″ and assume the
following:
v They are shown in the interactive SQL environment or they are written in ILE C
or in COBOL. EXEC SQL and END-EXEC are used to delimit an SQL statement
in a COBOL program. A description of how to use SQL statements in a COBOL
program is provided in ″Coding SQL Statements in COBOL Applications.″ A
description of how to use SQL statements in an ILE C program is provided in
″Coding SQL Statements in C Applications.″
v Each SQL example is shown on several lines, with each clause of the statement
on a separate line.
v SQL keywords are highlighted.
v Table names provided in Appendix A, ″DB2 UDB for AS/400 Sample Tables,″ use
the collection CORPDATA. Table names that are not found in Appendix A, ″DB2
UDB for AS/400 Sample Tables,″ should use collections you create.
v Calculated columns are enclosed in parentheses, (), and brackets, [].
v The SQL naming convention is used.
v The APOST and APOSTSQL precompiler options are assumed although they are
not the default options in COBOL. Character string literals within SQL and host
language statements are delimited by apostrophes (’).
v A sort sequence of *HEX is used, unless otherwise noted.

© Copyright IBM Corp. 1997, 1999 xvii


v The complete syntax of the SQL statement is usually not shown in any one
example. For the complete description and syntax of any of the statements
described in this guide, see the DB2 UDB for AS/400 SQL Reference

Whenever the examples vary from these assumptions, it is stated.

Because this guide is for the application programmer, most of the examples are
shown as if they were written in an application program. However, many examples
can be slightly changed and run interactively by using interactive SQL. The syntax
of an SQL statement, when using interactive SQL, differs slightly from the format of
the same statement when it is embedded in a program.

How to Interpret Syntax Diagrams in this Guide


Throughout this book, syntax is described using the structure defined as follows:
v Read the syntax diagrams from left to right, from top to bottom, following the path
of the line.
The ÊÊ─── symbol indicates the beginning of a statement.
The ───Ê symbol indicates that the statement syntax is continued on the next
line.
The Ê─── symbol indicates that a statement is continued from the previous line.
The ───ÊÍ symbol indicates the end of a statement.
Diagrams of syntactical units other than complete statements start with the Ê───
symbol and end with the ───Ê symbol.
v Required items appear on the horizontal line (the main path).

ÊÊ required_item ÊÍ

v Optional items appear below the main path.

ÊÊ required_item ÊÍ
optional_item

If an optional item appears above the main path, that item has no effect on the
execution of the statement and is used only for readability.

optional_item
ÊÊ required_item ÊÍ

v If you can choose from two or more items, they appear vertically, in a stack.
If you must choose one of the items, one item of the stack appears on the main
path.

ÊÊ required_item required_choice1 ÊÍ
required_choice2

If choosing one of the items is optional, the entire stack appears below the main
path.

xviii DB2 UDB for AS/400 SQL Programming V4R4


ÊÊ required_item ÊÍ
optional_choice1
optional_choice2

If one of the items is the default, it will appear above the main path and the
remaining choices will be shown below.

default_choice
ÊÊ required_item ÊÍ
optional_choice
optional_choice

v An arrow returning to the left, above the main line, indicates an item that can be
repeated.

ÊÊ required_item · repeatable_item ÊÍ

If the repeat arrow contains a comma, you must separate repeated items with a
comma.

ÊÊ required_item · repeatable_item ÊÍ

A repeat arrow above a stack indicates that you can repeat the items in the
stack.
v Keywords appear in uppercase (for example, FROM). They must be spelled exactly
as shown. Variables appear in all lowercase letters (for example, column-name).
They represent user-supplied names or values.
v If punctuation marks, parentheses, arithmetic operators, or other such symbols
are shown, you must enter them as part of the syntax.

AS/400 Operations Navigator


AS/400 Operations Navigator is a powerful graphical interface for Windows clients.
With AS/400 Operations Navigator, you can manage and administer your AS/400
systems from your Windows desktop.

You can use Operations Navigator to manage communications, printing, database,


security, and other system operations. Operations Navigator includes Management
Central for managing multiple AS/400 systems centrally.

Figure 1 on page xx shows an example of the Operations Navigator display:

About DB2 UDB for AS/400 SQL Programming xix


Figure 1. AS/400 Operations Navigator Display

This new interface has been designed to make you more productive and is the only
user interface to new, advanced features of OS/400. Therefore, IBM recommends
that you use AS/400 Operations Navigator, which has online help to guide you.
While this interface is being developed, you may still need to use a traditional
emulator such as PC5250 to do some of your tasks.

Installing Operations Navigator


To use AS/400 Operations Navigator, you must have Client Access installed on your
Windows PC. For help in connecting your Windows PC to your AS/400 system,
consult Client Access Express for Windows - Setup, SC41-5507-00.

AS/400 Operations Navigator is a separately installable component of Client Access


that contains many subcomponents. If you are installing for the first time and you
use the Typical installation option, the following options are installed by default:
v Operations Navigator base support
v Basic operations (messages, printer output, and printers)

To select the subcomponents that you want to install, select the Custom installation
option. (After Operations Navigator has been installed, you can add subcomponents
by using Client Access Selective Setup.)
1. Display the list of currently installed subcomponents in the Component
Selection window of Custom installation or Selective Setup.
2. Select AS/400 Operations Navigator.
3. Select any additional subcomponents that you want to install and continue with
Custom installation or Selective Setup.

After you install Client Access, double-click the AS400 Operations Navigator icon
on your desktop to access Operations Navigator and create an AS/400 connection.

xx DB2 UDB for AS/400 SQL Programming V4R4


How this book has changed
| The major new features covered in this manual include:
v Large objects (LOBs)
| v DataLinks
| v User-defined types
| v User-defined functions
| v Derived tables

Prerequisite and related information


Use the AS/400 Information Center as your starting point for looking up AS/400
technical information. You can access the Information Center from the AS/400e
Information Center CD-ROM (English version: SK3T-2027) or from one of these
Web sites:
http://www.as400.ibm.com/infocenter
http://publib.boulder.ibm.com/pubs/html/as400/infocenter.htm

The AS/400 Information Center contains important topics such as logical


partitioning, clustering, Java, TCP/IP, Web serving, and secured networks. It also
contains Internet links to Web sites such as the AS/400 Online Library and the
AS/400 Technical Studio. Included in the Information Center is a link that describes
at a high level the differences in information between the Information Center and
the Online Library.

For a list of related publications, see the “Bibliography” on page 845.

How to send your comments


Your feedback is important in helping to provide the most accurate and high-quality
information. If you have any comments about this book or any other AS/400
documentation, fill out the readers’ comment form at the back of this book.
v If you prefer to send comments by mail, use the readers’ comment form with the
address that is printed on the back. If you are mailing a readers’ comment form
from a country other than the United States, you can give the form to the local
IBM branch office or IBM representative for postage-paid mailing.
v If you prefer to send comments by FAX, use either of the following numbers:
– United States and Canada: 1-800-937-3430
– Other countries: 1-507-253-5192
v If you prefer to send comments electronically, use one of these e-mail addresses:
– Comments on books:
RCHCLERK@us.ibm.com
IBMMAIL, to IBMMAIL(USIB56RZ)
– Comments on the AS/400 Information Center:
RCHINFOC@us.ibm.com
Be sure to include the following:
v The name of the book.
v The publication number of the book.

About DB2 UDB for AS/400 SQL Programming xxi


v The page number or topic to which your comment applies.

xxii DB2 UDB for AS/400 SQL Programming V4R4


Chapter 1. Introduction to DB2 UDB for AS/400 Structured
Query Language
This guide describes the AS/400* system implementation of the Structured Query
Language (SQL) using DB2 UDB for AS/400 and the DB2 UDB Query Manager and
SQL Development Kit Version 4 licensed program. SQL manages information based
on the relational model of data. SQL statements can be embedded in high-level
languages, dynamically prepared and run, or run interactively.

SQL consists of statements and clauses that describe what you want to do with the
data in a database and under what conditions you want to do it.

SQL can access data in a remote relational database, using the IBM Distributed
Relational Database Architecture* (DRDA*). This function is described in
Chapter 28. Distributed Relational Database Function, of this guide. Further
information about DRDA is contained in the Distributed Database Programming
book.

SQL Concepts
DB2 UDB for AS/400 SQL consists of the following main parts:
v SQL run-time support
SQL run-time parses SQL statements and runs any SQL statements. This
support is that part of the Operating System/400* (OS/400) licensed program
which allows applications that contain SQL statements to be run on systems
where the DB2 UDB Query Manager and SQL Development Kit licensed program
is not installed.
v SQL precompilers
SQL precompilers support precompiling embedded SQL statements in host
languages. The following languages are supported:
– ILE C for AS/400*
– ILE C++ for AS/400
– VisualAge C++ for AS/400
– ILE COBOL for AS/400*
– COBOL for AS/400*
– AS/400 PL/I*
– RPG III (part of RPG for AS/400*)
– ILE RPG for AS/400*
The SQL host language precompilers prepare an application program containing
SQL statements. The host language compilers then compile the precompiled host
source programs. For more information on precompiling, see Chapter 18.
Preparing and Running a Program with SQL Statements. The precompiler
support is part of the DB2 UDB Query Manager and SQL Development Kit
licensed program.
v SQL interactive interface
SQL interactive interface allows you to create and run SQL statements. For more
information on interactive SQL, see Chapter 19. Using Interactive SQL.
Interactive SQL is part of the DB2 UDB Query Manager and SQL Development
Kit licensed program.
v Run SQL Statements CL command

© Copyright IBM Corp. 1997, 1999 1


RUNSQLSTM allows you to run a series of SQL statements, which are stored in
a source file. The RUNSQLSTM command is part of the DB2 UDB Query
Manager and SQL Development Kit licensed program. See Chapter 20. Using the
SQL Statement Processor for more information on the Run SQL Statements
command.
v DB2 Query Manager for AS/400
DB2 Query Manager for AS/400 provides a prompt-driven interactive interface
that allows you to create data, add data, maintain data, and run reports on the
databases. Query Manager is part of the DB2 UDB Query Manager and SQL
Development Kit licensed program. For more information, refer to the DB2 UDB
for AS/400 Query Manager Use book.
v SQL REXX Interface
The SQL REXX interface allows you to run SQL statements in a REXX
procedure. This interface is part of the DB2 UDB Query Manager and SQL
Development Kit licensed program. For more information on using SQL
statements in REXX procedures, see Chapter 17. Coding SQL Statements in
REXX Applications.
v SQL Call Level Interface
DB2 UDB for AS/400 supports the SQL Call Level Interface. This allows users of
any of the ILE languages to access SQL functions directly through procedure
calls to a service program provided by the system. Using the SQL Call Level
Interface, one can perform all the SQL functions without the need for a
precompile. This is a standard set of procedure calls to prepare SQL statements,
execute SQL statements, fetch rows of data, and even do advanced functions
such as accessing the catalogs and binding program variables to output columns.
For a complete description of all the available functions, and their syntax, see the
DB2 UDB for AS/400 SQL Call Level Interface book.
v QSQPRCED API
This Application Program Interface (API) provides an extended dynamic SQL
capability. SQL statements can be prepared into an SQL package and then
executed using this API. Statements prepared into a package by this API persist
until the package or statement is explicitly dropped. QSQPRCED is part of the
OS/400 licensed program. For more information on the QSQPRCED API, see the
System API Reference book.
v QSQCHKS API
This API syntax checks SQL statements. QSQCHKS is part of the OS/400
licensed program. For more information on the QSQCHKS API, see the System
API Reference book.
v DB2 Multisystem
This feature of the operating system allows your data to be distributed across
multiple AS/400 systems. For more information on DB2 Multisystem, see the DB2
Multisystem for AS/400 book.
v DB2 UDB Symmetric Multiprocessing
This feature of the operating system provides the query optimizer with additional
methods for retrieving data that include parallel processing. Symmetric
multiprocessing (SMP) is a form of parallelism achieved on a single system
where multiple processors (CPU and I/O processors) that share memory and disk
resource work simultaneously towards achieving a single end result. This parallel
processing means that the database manager can have more than one (or all) of
the system processors working on a single query simultaneously. See
“Controlling Parallel Processing” on page 473 for information on how to control
parallel processing.

2 DB2 UDB for AS/400 SQL Programming V4R4


Relational Database and Terminology
In the relational model of data, all data is perceived as existing in tables. DB2 UDB
for AS/400 objects are created and maintained as AS/400 system objects. The
following table shows the relationship between AS/400 system terms and SQL
relational database terms. For more information on database, see the DB2 UDB for
AS/400 Database Programming book.
Table 1. Relationship of System Terms to SQL Terms
System Terms SQL Terms
Library. Groups related objects and allows Collection. Consists of a library, a journal, a
you to find the objects by name. journal receiver, an SQL catalog, and
optionally a data dictionary. A collection
groups related objects and allows you to find
the objects by name.
Physical file. A set of records. Table. A set of columns and rows.
Record. A set of fields. Row. The horizontal part of a table
containing a serial set of columns.
Field. One or more characters of related Column. The vertical part of a table of one
information of one data type. data type.
Logical file. A subset of fields and records View. A subset of columns and rows of one
of one or more physical files. or more tables.
SQL Package. An object type that is used to Package. An object type that is used to run
run SQL statements. SQL statements.
User Profile Authorization name or Authorization ID.

SQL Terminology
There are two naming conventions that can be used in DB2 UDB for AS/400
programming: system (*SYS) and SQL (*SQL). The naming convention used affects
the method for qualifying file and table names and the terms used on the interactive
SQL displays. The naming convention used is selected by a parameter on the SQL
commands or, for REXX, selected through the SET OPTION statement.

System naming (*SYS): In the system naming convention, files are qualified by
library name in the form:
library/file

If the table name is not explicitly qualified and a default collection name is specified
for the default relational database collection (DFTRDBCOL) parameter of the
CRTSQLxxx 1 or the CRTSQLPKG commands, the default collection name is used.
If the table name is not explicitly qualified and the default collection name is not
specified, the qualification rules are:
v The following CREATE statements resolve to unqualified objects as follows:
– CREATE TABLE – The table is created in the current library (*CURLIB).
– CREATE VIEW – The view is created in the first library referenced in the
subselect.
– CREATE INDEX – The index is created into the collection or library that
contains the table on which the index is being built.

1. The xxx in this command refers to the host language indicators: CI for the ILE C for AS/400 language, CPPI for the ILE C++ for
AS/400 language, CBL for the COBOL for AS/400 language, CBLI for the ILE COBOL for AS/400 language, PLI for the AS/400
PL/I language, RPG for the RPG for AS/400 language, and RPGI for the ILE RPG for AS/400 language. The CVTSQLCPP
command is considered part of this group of commands even though it does not start with CRT.

Chapter 1. Introduction to DB2 UDB for AS/400 Structured Query Language 3


| – CREATE ALIAS – The alias is created into the collection or library that
| contains the table for which you defined the alias. If the table is not qualified
| or is not found, the alias is created in the current library (*CURLIB).
v All other SQL statements cause SQL to search the library list (*LIBL) for the
unqualified table.

The default relational database collection (DFTRDBCOL) parameter applies only to


static SQL statements.

SQL naming (*SQL): In the SQL naming convention, tables are qualified by the
collection name in the form:
collection.table

If the table name is not explicitly qualified and the default collection name is
specified in the default relational database collection (DFTRDBCOL) parameter of
the CRTSQLxxx command, the default collection name is used. If the table name is
not explicitly qualified and the default collection name is not specified, the rules are:
v For static SQL, the default qualifier is the user profile of the program owner.
v For dynamic SQL or interactive SQL, the default qualifier is the user profile of the
job running the statement.

Types of SQL Statements


There are four basic types of SQL statements: data definition language (DDL)
statements, data manipulation language (DML) statements, dynamic SQL
statements, and miscellaneous statements. SQL statements can operate on objects
that are created by SQL as well as AS/400 externally described physical files and
AS/400 single-format logical files, whether or not they reside in an SQL collection.
They do not refer to the IDDU dictionary definition for program-described files.
Program-described files appear as a table with only a single column.

4 DB2 UDB for AS/400 SQL Programming V4R4


SQL DDL Statements SQL DML Statements
ALTER TABLE CLOSE
COMMENT ON COMMIT
CREATE ALIAS DECLARE CURSOR
CREATE COLLECTION DELETE
CREATE DISTINCT TYPE FETCH
CREATE FUNCTION INSERT
CREATE INDEX LOCK TABLE
CREATE PROCEDURE OPEN
CREATE SCHEMA ROLLBACK
CREATE TABLE SELECT INTO
CREATE VIEW SET variable
DROP ALIAS UPDATE
DROP COLLECTION VALUES INTO
DROP DISTINCT TYPE
DROP FUNCTION
DROP INDEX
DROP PACKAGE
DROP PROCEDURE
DROP SCHEMA
DROP TABLE
DROP VIEW
GRANT DISTINCT TYPE
GRANT FUNCTION
GRANT PACKAGE
GRANT PROCEDURE
GRANT TABLE
LABEL ON
RENAME
REVOKE DISTINCT TYPE
REVOKE FUNCTION
REVOKE PACKAGE
REVOKE PROCEDURE
REVOKE TABLE

Dynamic SQL Statements Miscellaneous Statements


DESCRIBE BEGIN DECLARE SECTION
EXECUTE CALL
EXECUTE IMMEDIATE CONNECT
PREPARE DECLARE PROCEDURE
DECLARE STATEMENT
DECLARE VARIABLE
DESCRIBE TABLE
DISCONNECT
END DECLARE SECTION
FREE LOCATOR
INCLUDE
RELEASE
SET CONNECTION
SET OPTION
SET PATH
SET RESULT SETS
SET TRANSACTION
WHENEVER

SQL Objects
SQL objects used on the AS/400 system are collections, tables, aliases, views, SQL
packages, indexes, and catalogs. SQL creates and maintains these objects as
AS/400 database objects. A brief description of these objects follows.

Chapter 1. Introduction to DB2 UDB for AS/400 Structured Query Language 5


Collections
A collection provides a logical grouping of SQL objects. A collection consists of a
library, a journal, a journal receiver, a catalog, and optionally, a data dictionary.
Tables, views, and system objects (such as programs) can be created, moved, or
restored into any AS/400 library. All AS/400 files can be created or moved into an
SQL collection if the SQL collection does not contain a data dictionary. If the SQL
collection contains a data dictionary then:
v AS/400 source physical files or nonsource physical files with one member can be
created, moved, or restored into an SQL collection.
v AS/400 logical files cannot be placed in an SQL collection because they cannot
be described in the data dictionary.
You can create and own many collections.

Data Dictionary
A collection contains a data dictionary if it was created prior to Version 3 Release 1
or if the WITH DATA DICTIONARY clause was specified on the CREATE
COLLECTION or the CREATE SCHEMA statements. A data dictionary is a set of
tables containing object definitions. If SQL created the dictionary, then it is
automatically maintained by the system. You can work with data dictionaries by
using the interactive data definition utility (IDDU), which is part of the OS/400
program. For more information on IDDU, see the IDDU Use book.

Journals and Journal Receivers


A journal and journal receiver are used to record changes to tables and views in
the database. The journal and journal receiver are then used in processing SQL
COMMIT and ROLLBACK statements. The journal and journal receiver can also be
used as an audit trail or for forward or backward recovery. For more information on
journaling, see the Backup and Recovery book.

Catalogs
An SQL catalog consists of a set of tables and views which describe tables, views,
indexes, packages, procedures, files, and constraints. This information is contained
in a set of cross-reference tables in libraries QSYS and QSYS2. Library QSYS2
also contains a set of catalog views built over the QSYS catalog tables which
describe information about all the tables, views, indexes, packages, procedures,
files, and constraints on the system. In each SQL collection there is a set of views
built over the catalog tables which contains information about the tables, views,
indexes, packages, files, and constraints in the collection.

A catalog is automatically created when you create a collection. You cannot drop or
explicitly change the catalog.

For more information about SQL catalogs, see the DB2 UDB for AS/400 SQL
Reference book.

Tables, Rows, and Columns


A table is a two-dimensional arrangement of data consisting of rows and columns.
The row is the horizontal part containing one or more columns. The column is the
vertical part containing one or more rows of data of one data type. All data for a

6 DB2 UDB for AS/400 SQL Programming V4R4


column must be of the same type. A table in SQL is a keyed or nonkeyed physical
file. See the section on data types in the DB2 UDB for AS/400 SQL Reference book
for a description of data types.

Data in a table can be distributed across AS/400 systems. For more information
about distributed tables, see the DB2 Multisystem for AS/400 book.

The following is a sample SQL table:

Columns

PROJNO PROJNAME DEPTNO DEPTMGR PRSTAFF

Rows MA2100 MFG AUTOMATION D11 000060 12

MA2110 MFG PROGRAMMING E21 000100 3

MA2112 ROBOT DESIGN E01 000050 3

MA2113 PROD CONTROL PROG D11 000060 3

... ... ... ... ...


RV2W573-0

Aliases
An alias is an alternate name for a table or view. You can use an alias to refer to a
table or view in those cases where an existing table or view can be referred to. For
more information on aliases, see the DB2 UDB for AS/400 SQL Reference book.

Views
A view appears like a table to an application program; however, a view contains no
data. It is created over one or more tables. A view can contain all the columns of
given tables or some subset of them, and can contain all the rows of given tables or
some subset of them. The columns can be arranged differently in a view than they
are in the tables from which they are taken. A view in SQL is a special form of a
nonkeyed logical file.

The following figure shows a view created from the preceding example of an SQL
table. Notice that the view is created only over the PROJNO and PROJNAME
columns of the table and for rows MA2110 and MA2100.

Columns

PROJNO PROJNAME

Rows MA2100 MFG AUTOMATION

MA2110 MFG PROGRAMMING


RV2W574-0

Chapter 1. Introduction to DB2 UDB for AS/400 Structured Query Language 7


Indexes
An SQL index is a subset of the data in the columns of a table that are logically
arranged in either ascending or descending order. Each index contains a separate
arrangement. These arrangements are used for ordering (ORDER BY clause),
grouping (GROUP BY clause), and joining. An SQL index is a keyed logical file.

The index is used by the system for faster data retrieval. Creating an index is
optional. You can create any number of indexes. You can create or drop an index at
any time. The index is automatically maintained by the system. However, because
the indexes are maintained by the system, a large number of indexes can adversely
affect the performance of applications that change the table.

Constraints
Constraints are rules enforced by the database manager. DB2 UDB for AS/400
supports the following constraints:
v Unique constraints
A unique constraint is the rule that the values of the key are valid only if they
are unique. Unique constraints can be created using the CREATE TABLE and
ALTER TABLE statements. 2
Unique constraints are enforced during the execution of INSERT and UPDATE
statements. A PRIMARY KEY constraint is a form of UNIQUE constraint. The
difference is that a PRIMARY KEY cannot contain any nullable columns.
v Referential constraints
A referential constraint is the rule that the values of the foreign key are valid
only if:
– They appear as values of a parent key, or
– Some component of the foreign key is null.
Referential constraints are enforced during the execution of INSERT, UPDATE,
and DELETE statements.
v Check constraints
A check constraint is a rule that limits the values allowed in a column or group
of columns. Check constraints can be added using the CREATE TABLE and
ALTER TABLE statements. Check constraints are enforced during the execution
of INSERT and UPDATE statements. To satisfy the constraint, each row of data
inserted or updated in the table must make the specified condition either TRUE
or unknown (due to a null value).

For more information on constraints, see Chapter 6. Data Integrity.

Triggers
A trigger is a set of actions that are executed automatically whenever a specified
event occurs to a specified base table. An event can be an insert, update, or delete
operation. The trigger can be run either before or after the event. For more
information on triggers, see Chapter 6. Data Integrity in this book or see the DB2
UDB for AS/400 Database Programming book.

2. Although CREATE INDEX can create a unique index that also guarantees uniqueness, such an index is not a constraint.

8 DB2 UDB for AS/400 SQL Programming V4R4


Stored Procedures
| A stored procedure is a program that can be called using the SQL CALL
| statement. DB2 UDB for AS/400 supports external stored procedures and SQL
| procedures. External stored procedures can be any AS/400 program or REXX
| procedure. They cannot be System/36 programs or procedures, or service
| programs. An SQL procedure is defined entirely in SQL and can contain SQL
| statements including SQL control statements. For more information on stored
| procedures, see Chapter 7. Stored Procedures.

| User-defined functions
| A user-defined function is a program that can be invoked like any built-in function.
| DB2 UDB for AS/400 supports external functions, SQL functions, and sourced
| functions. External functions can be any AS/400 ILE program or service program.
| An SQL function is defined entirely in SQL and can contain SQL statements,
| including SQL control statements. A sourced function is built over any built-in or any
| existing user-defined function. For more information on user-defined functions, see
| “Chapter 9. Writing User-Defined Functions (UDFs)” on page 185.

Packages
An SQL package is an object that contains the control structure produced when the
SQL statements in an application program are bound to a remote relational
database management system (DBMS). The DBMS uses the control structure to
process SQL statements encountered while running the application program.

SQL packages are created when a relational database name (RDB parameter) is
specified on a Create SQL (CRTSQLxxx) command and a program object is
created. Packages can also be created using the CRTSQLPKG command. For
more information about packages and distributed relational database function, see
Chapter 28. Distributed Relational Database Function

SQL packages can also be created using the QSQPRCED API. For more
information on QSQPRCED, see the System API Reference book.

Application Program Objects


The process of creating a DB2 UDB for AS/400 application program may result in
the creation of several objects. This section briefly describes the process of creating
a DB2 UDB for AS/400 application. DB2 UDB for AS/400 supports both non-ILE and
ILE precompilers. Application programs may be either distributed or nondistributed.
Additional information on creating DB2 UDB for AS/400 application programs is in
Chapter 18. Preparing and Running a Program with SQL Statements.

With DB2 UDB for AS/400 you may need to manage the following objects:
v The original source
v Optionally, the module object for ILE programs
v The program or service program
v The SQL package for distributed programs

With a nondistributed non-ILE DB2 UDB for AS/400 program, you must manage
only the original source and the resulting program. The following shows the objects

Chapter 1. Introduction to DB2 UDB for AS/400 Structured Query Language 9


involved and steps that happen during the precompile and compile processes for a
nondistributed non-ILE DB2 UDB for AS/400 program:

User Temporary
Source Precompile Source Compile
Program
File File
Member Member

Processed Access
SQL Plan
Statements

RV2W565-1

With a nondistributed ILE DB2 UDB for AS/400 program, you may need to manage
the original source, the modules, and the resulting program or service program. The
following shows the objects involved and steps that happen during the precompile
and compile processes for a nondistributed ILE DB2 UDB for AS/400 program when
OBJTYPE(*PGM) is specified on the precompile command:

User Temporary
Source Precompile Source Compile Module Bind Program
File File
Member Member

Processed Processed Access


SQL SQL Plan
Statements Statements

RV2W569-0

With a distributed non-ILE DB2 UDB for AS/400 program, you must manage the
original source, the resulting program, and the resulting package. The following
shows the objects and steps that occur during the precompile and compile
processes for a distributed non-ILE DB2 UDB for AS/400 program:

Create
User Temporary
Source Precompile Source Compile SQL
Program SQL
File File Package
Member Package
Member

Processed Access
SQL Plan Access
Statements Plan

RV2W566-2

With a distributed ILE DB2 UDB for AS/400 program, you must manage the original
source, module objects, the resulting program or service program, and the resulting
packages. An SQL package can be created for each distributed module in a
distributed ILE program or service program. The following shows the objects and
steps that occur during the precompile and compile processes for a distributed ILE
DB2 UDB for AS/400 program:

10 DB2 UDB for AS/400 SQL Programming V4R4


Create
User Temporary SQL
Source Precompile Source Compile Module Bind Program Package SQL
File File Package
Member Member

Processed Processed Access Access


SQL SQL Plan Plan
Statements Statements

RV2W570-1

Note: The access plans associated with the DB2 UDB for AS/400 distributed
program object are not created until the program is run locally.

User Source File Member


A source file member contains the programmer’s application language and SQL
statements. You can create and maintain the source file member by using the
source entry utility (SEU), a part of the AS/400 Application Development Tools
licensed program.

Output Source File Member


The SQL precompile creates an output source file member. By default, the
precompile process (CRTSQLxxx commands) creates a temporary source file called
QSQLTEMP (QSQLTEMP1 for CRTSQLRPGI) in library QTEMP. If the precompile
process uses the QTEMP library, the system automatically deletes the file when the
job completes. You can specify the output source file as a permanent file name on
the precompile commands. A member with the same name as the program name is
added to the output source file. This member contains the following items:
v Calls to the SQL run-time support, which have replaced embedded SQL
statements
v Parsed and syntax-checked SQL statements
By default, the precompiler calls the host language compiler. For more information
on precompilers, see Chapter 18. Preparing and Running a Program with SQL
Statements.

Program
A program is the object which you can run that is created as a result of the compile
process for non-ILE compiles or as a result of the bind process for ILE compiles.

An access plan is a set of internal structures and information that tells SQL how to
run an embedded SQL statement most effectively. It is created only when the
program has successfully created. Access plans are not created during program
creation for SQL statements if the statements:
v Refer to a table or view that cannot be found
v Refer to a table or view to which you are not authorized

The access plans for such statements are created when the program is run. If, at
that time, the table or view still cannot be found or you are still not authorized, a
negative SQLCODE is returned. Access plans are stored and maintained in the
program object for nondistributed SQL programs and in the SQL package for
distributed SQL programs.

Chapter 1. Introduction to DB2 UDB for AS/400 Structured Query Language 11


Package
An SQL package contains the access plans for a distributed SQL program.

An SQL package is an object that is created when:


v A distributed SQL program is successfully created using the RDB parameter on
CRTSQLxxx commands.
v When the Create SQL Package (CRTSQLPKG) command is run.

When a distributed SQL program is created, the name of the SQL package and an
internal consistency token are saved in the program. These are used at run time to
find the SQL package and to verify that the SQL package is correct for this
program. Because the name of the SQL package is critical for running distributed
SQL programs, an SQL package cannot be:
v Moved
v Renamed
v Duplicated
v Restored to a different library

Module
A module is an Integrated Language Environment (ILE) object that is created by
compiling source code using the CRTxxxMOD command (or any of the CRTBNDxxx
commands where xxx is C, CBL, CPP, or RPG). You can run a module only if you
use the Create Program (CRTPGM) command to bind it into a program. You usually
bind several modules together, but you can bind a module by itself. Modules
contain information about the SQL statements; however, the SQL access plans are
not created until the modules are bound into either a program or service program.

Service Program
A service program is an Integrated Language Environment (ILE) object that
provides a means of packaging externally supported callable routines (functions or
procedures) into a separate object. Bound programs and other service programs
can access these routines by resolving their imports to the exports provided by a
service program. The connections to these services are made when the calling
programs are created. This improves call performance to these routines without
including the code in the calling program.

12 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 2. Getting Started with SQL
| This chapter describes how to create and work with SQL collections, tables, and
| views using SQL statements.

The syntax for each of the SQL statements used in this chapter is described in
detail in the DB2 UDB for AS/400 SQL Reference book. A description of how to use
SQL statements and clauses in more complex situations is provided in Chapter 3.
Basic Concepts and Techniques and Chapter 5. Advanced Coding Techniques.

| In this chapter, the examples use the interactive SQL interface to show the
| execution of SQL statements. Each SQL interface provides methods for using SQL
| statements to define tables, views, and other objects, methods for updating the
| objects, and methods for reading data from the objects. Some tasks described here
| can also be done using Operations Navigator. In those cases, the information about
| the task notes that it can be done using Operations Navigator.

Starting Interactive SQL


To start using interactive SQL for the following examples, type:
STRSQL NAMING(*SQL)

and press Enter. When the Enter SQL Statements display appears, you are ready
to start typing SQL Statements. For more information on interactive SQL and the
STRSQL command, see Chapter 19. Using Interactive SQL.

If you are reusing an existing interactive SQL session, make sure that you set the
naming mode to SQL naming. You can specify this on the F13 (Services) panel,
option 1 (Change session attributes).

Creating an SQL Collection


| An SQL collection is the basic object in which tables, views, indexes, and packages
| are placed. One way to create a collection (called a library) is by using Operations
| Navigator. Or you can use the SQL CREATE COLLECTION statement.

For an example of creating a collection using interactive SQL, see “Example:


Creating the SQL Collection (SAMPLECOLL)”.

Example: Creating the SQL Collection (SAMPLECOLL)


| You can create a sample collection, named SAMPLECOLL, by typing the following
| SQL statement on the Enter SQL Statements display and pressing Enter:

© Copyright IBM Corp. 1997, 1999 13


| Enter SQL Statements
|
| Type SQL statement, press Enter.
| Current connection is to relational database SYSTEM1
| ===> CREATE COLLECTION SAMPLECOLL_________________________________________
| _____________________________________________________________________
| _____________________________________________________________________
| _____________________________________________________________________
| Bottom
| F3=Exit F4=Prompt F6=Insert line F9=Retrieve F10=Copy line
| F12=Cancel F13=Services F24=More keys
|

| Note: Running this statement causes several objects to be created and takes
| several seconds.
| After you have successfully created a collection, you can create tables, views, and
| indexes in it. Tables, views, and indexes can also be created in libraries instead of
| collections.

Creating and Using a Table


| You can create a table by using the SQL CREATE TABLE statement or by using
| Operations Navigator. The CREATE TABLE statement allows you to create a table,
| define the physical attributes of the columns in the table, and define constraints to
| restrict the values that are allowed in the table.

For an example of creating a table using interactive SQL, see “Example: Creating a
Table (INVENTORY_LIST)”.

| When creating a table, you need to understand the concepts of null value and
| default value. A null value indicates the absence of a column value for a row. It is
| not the same as a value of zero or all blanks. It means ″unknown″. It is not equal to
| any value, not even to other null values. If a column does not allow the null value, a
| value must be assigned to the column, either a default value or a user supplied
| value.

| A default value is assigned to a column when a row is added to a table and no


| value is specified for that column. If a specific default value is not defined for a
| column, the system default value will be used. For more information on the default
| values used by INSERT, see “The INSERT Statement” on page 31

| Example: Creating a Table (INVENTORY_LIST)


| We are going to create a table to maintain information about the current inventory
| of a business. It will have information about the items kept in the inventory, their
| cost, quantity currently on hand, the last order date, and the number last ordered.
| The item number will be a required value. It cannot be null. The item name, quantity
| on hand, and order quantity will have user supplied default values. The last order
| date and quantity ordered will allow the null value.

| On the Enter SQL Statements display, type CREATE TABLE and press F4 (Prompt).
| The following display is shown (with the input areas not yet filled in):

14 DB2 UDB for AS/400 SQL Programming V4R4


| Specify CREATE TABLE Statement
|
| Type information, press Enter.
|
| Table . . . . . . . . . INVENTORY_LIST______ Name
| Collection . . . . . . SAMPLECOLL__ Name, F4 for list
|
| Nulls: 1=NULL, 2=NOT NULL, 3=NOT NULL WITH DEFAULT
|
| Column FOR Column Type Length Scale Nulls
| ITEM_NUMBER_______ ____________ CHAR___________ 6____ __ 2
| ITEM_NAME_________ ____________ VARCHAR________ 20___ __ 3
| UNIT_COST_________ ____________ DECIMAL________ 8____ 2_ 3
| QUANTITY_ON_HAND__ ____________ SMALLINT_______ _____ __ 1
| LAST_ORDER_DATE___ ____________ DATE___________ _____ __ 1
| ORDER_QUANTITY____ ____________ SMALLINT_______ _____ __ 1
| __________________ ____________ _______________ _____ __ 3
| Bottom
| Table CONSTRAINT . . . . . . . . . . . . . N Y=Yes, N=No
| Distributed Table . . . . . . . . . . . . N Y=Yes, N=No
|
| F3=Exit F4=Prompt F5=Refresh F6=Insert line F10=Copy line
| F11=Display more attributes F12=Cancel F14=Delete line F24=More keys
|

| Type the table name and collection name of the table you are creating,
| INVENTORY_LIST in SAMPLECOLL, for the Table and Collection prompts. Each
| column you want to define for the table is represented by an entry in the list on the
| lower part of the display. For each column, type the name of the column, the data
| type of the column, its length and scale, and the null attribute.

| Press F11 to see more attributes that can be specified for the columns. This is
| where a default value may be specified.
| Specify CREATE TABLE Statement
|
| Type information, press Enter.
|
| Table . . . . . . . . . INVENTORY_LIST______ Name
| Collection . . . . . . SAMPLECOLL__ Name, F4 for list
|
| Data: 1=BIT, 2=SBCS, 3=MIXED, 4=CCSID
|
| Column Data Allocate
CCSID CONSTRAINT Default
| ITEM NUMBER_______ _ __________ N __________________
| ITEM NAME_________ _ __________ N '***UNKNOWN***'___
| UNIT_COST_________ _ __________ N __________________
| QUANTITY_ON_HAND__ _ __________ N NULL______________
| LAST_ORDER_DATE___ _ __________ N __________________
| ORDER_QUANTITY____ _ __________ N 20________________
| __________________ _ __________ _ __________________
| Bottom
| Table CONSTRAINT . . . . . . . . . . . . . N Y=Yes, N=No
| Distributed Table . . . . . . . . . . . . N Y=Yes, N=No
|
| F3=Exit F4=Prompt F5=Refresh F6=Insert line F10=Copy line
| F11=Display more attributes F12=Cancel F14=Delete line F24=More keys
|

| Note: Another way of entering column definitions is to press F4 (Prompt) with your
| cursor on one of the column entries in the list. This will bring up a display
| that shows all of the attributes for defining a single column.

| When all the values have been entered, press Enter to create the table. The Enter
| SQL Statements display will be shown again with a message indicating that the
| table has been created.

Chapter 2. Getting Started with SQL 15


| You can directly key in this CREATE TABLE statement on the Enter SQL
| Statements display as follows:
| CREATE TABLE SAMPLECOLL.INVENTORY_LIST
| (ITEM_NUMBER CHAR(6) NOT NULL,
| ITEM_NAME VARCHAR(20) NOT NULL WITH DEFAULT '***UNKNOWN***',
| UNIT_COST DECIMAL(8,2) NOT NULL WITH DEFAULT,
| QUANTITY_ON_HAND SMALLINT DEFAULT NULL,
| LAST_ORDER_DATE DATE,
| ORDER_QUANTITY SMALLINT DEFAULT 20)

| Creating the Supplier Table (SUPPLIERS)


Later in our examples, we will need a second table as well. This table will contain
information about suppliers of our inventory items, which items they supply, and the
cost of the item from that supplier. To create it, either type it in directly on the Enter
SQL Statements display or press F4 (Prompt) to use the interactive SQL displays to
create the definition.
CREATE TABLE SAMPLECOLL.SUPPLIERS
(SUPPLIER_NUMBER CHAR(4) NOT NULL,
ITEM_NUMBER CHAR(6) NOT NULL,
SUPPLIER_COST DECIMAL(8,2))

Using the LABEL ON Statement


Normally, the column name is used as the column heading when showing the
output of a SELECT statement in interactive SQL. By using the LABEL ON
statement, you can create a more descriptive label for the column name. Since we
are going to be running our examples in interactive SQL, we will use the LABEL ON
statement to change the column headings. Even though the column names are
descriptive, it will be easier to read if the column headings show each part of the
name on a single line. It will also allow us to see more columns of our data on a
single display.

To change the labels for our columns, type LABEL ON COLUMN on the Enter SQL
Statements display and press F4 (Prompt). The following display will appear:

16 DB2 UDB for AS/400 SQL Programming V4R4


Specify LABEL ON Statement

Type choices, press Enter.

Label on . . . . 2 1=Table or view


2=Column
3=Package
4=Alias

Table or view INVENTORY_LIST______ Name, F4 for list


Collection . . SAMPLECOLL__ Name, F4 for list

Option . . . . . 1 1=Column heading


2=Text

F3=Exit F4=Prompt F5=Refresh F12=Cancel F20=Display full names


F21=Display statement

Type in the name of the table and collection containing the columns for which you
want to add labels and press Enter. The following display will be shown, prompting
you for each of the columns in the table.
Specify LABEL ON Statement

Type information, press Enter.

Column Heading
Column ....+....1....+....2....+....3....+....4....+....5....
ITEM_NUMBER 'ITEM NUMBER'___________________________
ITEM_NAME 'ITEM NAME'_____________________________
UNIT_COST 'UNIT COST'_____________________________
QUANTITY_ON_HAND 'QUANTITY ON HAND'_________
LAST_ORDER_DATE 'LAST ORDER DATE'_________
ORDER_QUANTITY 'NUMBER ORDERED'__________________________

Bottom
F3=Exit F5=Refresh F6=Insert line F10=Copy line F12=Cancel
F14=Delete line F19=Display system column names F24=More keys

Type the column headings for each of the columns. Column headings are defined in
20 character sections. Each section will be displayed on a different line when
showing the output of a SELECT statement. The ruler across the top of the column
heading entry area can be used to easily space the headings correctly. When the
headings are typed, press Enter.

The following message indicates that the LABEL ON statement was successful.
LABEL ON for INVEN00001 in SAMPLECOLL completed.

The table name in the message is the system table name for this table, not the
name that was actually specified in the statement. DB2 UDB for AS/400 maintains

Chapter 2. Getting Started with SQL 17


two names for tables with names longer than ten characters. For more information
on system table names, see the CREATE TABLE statement in the DB2 UDB for
AS/400 SQL Reference book.

The LABEL ON statement can also be keyed in directly on the Enter SQL
statements display as follows:
LABEL ON SAMPLECOLL/INVENTORY_LIST
(ITEM_NUMBER IS 'ITEM NUMBER',
ITEM_NAME IS 'ITEM NAME',
UNIT_COST IS 'UNIT COST',
QUANTITY_ON_HAND IS 'QUANTITY ON HAND',
LAST_ORDER_DATE IS 'LAST ORDER DATE',
ORDER_QUANTITY IS 'NUMBER ORDERED')

Inserting Information into a Table


After you create a table, you can insert, or add, information (data) into it by using
Operations Navigator. Or you can use the SQL INSERT statement.

| For an example of inserting data into a table using interactive SQL, see “Example:
| Inserting Information into a Table (INVENTORY_LIST)”.

| Example: Inserting Information into a Table (INVENTORY_LIST)


| To work with interactive SQL, on the Enter SQL Statements display, type INSERT
| and press F4 (Prompt). The Specify INSERT Statement display will be shown.
| Specify INSERT Statement
|
| Type choices, press Enter.
|
| INTO table . . . . . . . INVENTORY_LIST______ Name, F4 for list
| Collection . . . . . . SAMPLECOLL__ Name, F4 for list
|
| Select columns to insert
| INTO . . . . . . . . . Y Y=Yes, N=No
| Insertion method . . . . 1 1=Input VALUES
| 2=Subselect
|
| Type choices, press Enter.
|
| WITH isolation level . . 1 1=Current level, 2=NC (NONE)
| 3=UR (CHG), 4=CS, 5=RS (ALL)
| 6=RR
|
|
|
| F3=Exit F4=Prompt F5=Refresh F12=Cancel F20=Display full names
| F21=Display statement
|

Type the table name and collection name in the input fields as shown. Change the
Select columns to insert INTO prompt to Yes. Press Enter to see the display where
the columns you want to insert values into can be selected.

18 DB2 UDB for AS/400 SQL Programming V4R4


Specify INSERT Statement

Type sequence numbers (1-999) to make selections, press Enter.

Seq Column Type Length Scale


1__ ITEM_NUMBER CHARACTER 6
2__ ITEM_NAME VARCHAR 20
3__ UNIT_COST DECIMAL 8 2
4__ QUANTITY_ON_HAND SMALLINT 4
___ LAST_ORDER_DATE DATE
___ ORDER_QUANTITY SMALLINT 4

Bottom
F3=Exit F5=Refresh F12=Cancel F19=Display system column names
F20=Display entire name F21=Display statement

In this example, we only want to insert into four of the columns. We will let the other
| columns have their default value inserted. The sequence numbers on this display
| indicate the order that the columns and values will be listed in the INSERT
| statement. Press Enter to show the display where values for the selected columns
| can be typed.
| Specify INSERT Statement
|
| Type values to insert, press Enter.
|
| Column Value
| ITEM_NUMBER '153047'_____________________________________________
| ITEM_NAME 'Pencils, red'_______________________________________
| UNIT_COST 10.00________________________________________________
| QUANTITY_ON_HAND 25___________________________________________________
|
|
|
|
|
|
|
|
|
|
|
| Bottom
| F3=Exit F5=Refresh F6=Insert line F10=Copy line F11=Display type
| F12=Cancel F14=Delete line F15=Split line F24=More keys
|

| Note: To see the data type and length for each of the columns in the insert list,
| press F11 (Display type). This will show a different view of the insert values
| display, providing information about the column definition.

| Type the values to be inserted for all of the columns and press Enter. A row
| containing these values will be added to the table. The values for the columns that
| were not specified will have a default value inserted. For LAST_ORDER_DATE it
| will be the null value since no default was provided and the column allows the null
| value. For ORDER_QUANTITY it will be 20, the value specified as the default value
| on the CREATE TABLE statement.

| You can type the INSERT statement on the Enter SQL Statements display as:
| INSERT INTO SAMPLECOLL.INVENTORY_LIST
| (ITEM_NUMBER,
| ITEM_NAME,
| UNIT_COST,
| QUANTITY_ON_HAND)

Chapter 2. Getting Started with SQL 19


| VALUES('153047',
| 'Pencils, red',
| 10.00,
| 25)

| To add the next row to the table, press F9 (Retrieve) on the Enter SQL Statements
| display. This will copy the previous INSERT statement to the typing area. You can
| either type over the values from the previous INSERT statement or press F4
| (Prompt) to use the Interactive SQL displays to enter data.

| Continue using the INSERT statement to add the following rows to the table. Values
| not shown in the chart below should not be inserted so that the default will be used.
| In the INSERT statement column list, specify only the column names for which you
| want to insert a value. For example, to insert the third row, you would specify only
| ITEM_NUMBER and UNIT_COST for the column names and only the two values
| for these columns in the VALUES list.

ITEM_NUMBER ITEM_NAME UNIT_COST QUANTITY_ON_HAND


153047 Pencils, red 10.00 25
229740 Lined tablets 1.50 120
544931 5.00
303476 Paper clips 2.00 100
559343 Envelopes, legal 3.00 500
291124 Envelopes, standard
775298 Chairs, secretary 225.00 6
073956 Pens, black 20.00 25

Add the following rows to the SAMPLECOLL.SUPPLIERS table.

SUPPLIER_NUMBER ITEM_NUMBER SUPPLIER_COST


1234 153047 10.00
1234 229740 1.00
1234 303476 3.00
9988 153047 8.00
9988 559343 3.00
2424 153047 9.00
2424 303476 2.50
5546 775298 225.00
3366 303476 1.50
3366 073956 17.00

| The sample collection now contains two tables with several rows of data in each.

Getting Information from a Single Table


Now that we have inserted all the information into our tables, we need to be able to
look at it again. In SQL, this is done with the SELECT statement. The SELECT
statement is the most complex of all SQL statements. This statement is composed
of three main clauses:

20 DB2 UDB for AS/400 SQL Programming V4R4


1. The SELECT clause, which specifies those columns containing the desired
data.
2. The FROM clause, which specifies the table or tables containing the columns
with the desired data.
3. The WHERE clause, which supplies conditions that determine which rows of
data are retrieved.

In addition to the three main clauses, there are several other clauses described in
“Using Basic SQL Statements and Clauses” on page 31, and in the DB2 UDB for
AS/400 SQL Reference book, which affect the final form of returned data.

To see the values we inserted into the INVENTORY_LIST table, type SELECT and
press F4 (prompt). The following display will be shown:
Specify SELECT Statement

Type SELECT statement information. Press F4 for a list.

FROM tables . . . . . . . . SAMPLECOLL.INVENTORY_LIST____________________


SELECT columns . . . . . . . *____________________________________________
WHERE conditions . . . . . . _____________________________________________
GROUP BY columns . . . . . . _____________________________________________
HAVING conditions . . . . . _____________________________________________
ORDER BY columns . . . . . . _____________________________________________
FOR UPDATE OF columns . . . _____________________________________________

Bottom
Type choices, press Enter.

DISTINCT rows in result table . . . . . . . . . N Y=Yes, N=No


UNION with another SELECT . . . . . . . . . . . N Y=Yes, N=No
Specify additional options . . . . . . . . . . . N Y=Yes, N=No

F3=Exit F4=Prompt F5=Refresh F6=Insert line F9=Specify subquery


F10=Copy line F12=Cancel F14=Delete line F15=Split line F24=More keys

Type the table name in the FROM tables field on the display. To select all columns
from the table, type * for the SELECT columns field on the display. Press Enter and
the statement will run to select all of the data for all of the columns in the table. The
following output will be shown:
Display Data
Data width . . . . . . : 71
Position to line . . . . . Shift to column . . . . . .
....+....1....+....2....+....3....+....4....+....5....+....6....+....7.
ITEM ITEM UNIT QUANTITY LAST NUMBER
NUMBER NAME COST ON ORDER ORDERED
HAND DATE
153047 Pencils, red 10.00 25 - 20
229740 Lined tablets 1.50 120 - 20
544931 ***UNKNOWN*** 5.00 - - 20
303476 Paper clips 2.00 100 - 20
559343 Envelopes, legal 3.00 500 - 20
291124 Envelopes, standard .00 - - 20
775298 Chairs, secretary 225.00 6 - 20
073956 Pens, black 20.00 25 - 20
******** End of data ********

F3=Exit F12=Cancel F19=Left F20=Right F21=Split

The column headings that were defined using the LABEL ON statement are shown.
The ITEM_NAME for the third entry has the default value that was specified in the
CREATE TABLE statement. The QUANTITY_ON_HAND column has a null value for

Chapter 2. Getting Started with SQL 21


the rows where no value was inserted. The LAST_ORDER_DATE column contains
all null values since that column is not in any of the INSERT statements and the
column was not defined to have a default value. Similarly, the ORDER_QUANTITY
column contains the default value for all rows.

This statement could be entered on the Enter SQL Statements display as:
SELECT *
FROM SAMPLECOLL.INVENTORY_LIST

To limit the number of columns returned by the SELECT statement, the columns
you want to see must be specified. To restrict the number of output rows returned,
the WHERE clause is used. To see only the items that cost more than 10 dollars,
and only have the values for the columns ITEM_NUMBER, UNIT_COST, and
ITEM_NAME returned, type SELECT and press F4 (Prompt). The Specify SELECT
Statement display will be shown.
Specify SELECT Statement

Type SELECT statement information. Press F4 for a list.

FROM tables . . . . . . . . SAMPLECOLL.INVENTORY_LIST____________________


SELECT columns . . . . . . . ITEM_NUMBER, UNIT_COST, ITEM_NAME____________
WHERE conditions . . . . . . UNIT_COST > 10.00____________________________
GROUP BY columns . . . . . . _____________________________________________
HAVING conditions . . . . . _____________________________________________
ORDER BY columns . . . . . . _____________________________________________
FOR UPDATE OF columns . . . _____________________________________________

Bottom
Type choices, press Enter.

DISTINCT rows in result table . . . . . . . . . N Y=Yes, N=No


UNION with another SELECT . . . . . . . . . . . N Y=Yes, N=No
Specify additional options . . . . . . . . . . . N Y=Yes, N=No

F3=Exit F4=Prompt F5=Refresh F6=Insert line F9=Specify subquery


F10=Copy line F12=Cancel F14=Delete line F15=Split line F24=More keys

Although only one line is initially shown for each prompt on the Specify SELECT
Statement display, F6 (Insert line) can be used to add more lines to any of the input
areas in the top part of the display. This could be used if more columns were to be
entered in the SELECT columns list, or a longer, more complex WHERE condition
were needed.

Fill in the display as shown above. When Enter is pressed, the SELECT statement
is run. The following output will be seen:
Display Data
Data width . . . . . . : 41
Position to line . . . . . Shift to column . . . . . .
....+....1....+....2....+....3....+....4.
ITEM UNIT ITEM
NUMBER COST NAME
775298 225.00 Chairs, secretary
073956 20.00 Pens, black
******** End of data ********

F3=Exit F12=Cancel F19=Left F20=Right F21=Split

The only rows returned are those whose data values compare with the condition
specified in the WHERE clause. Furthermore, the only data values returned are

22 DB2 UDB for AS/400 SQL Programming V4R4


from the columns you explicitly specified in the SELECT clause. Data values of
columns other than those explicitly identified are not returned.

This statement could have been entered on the Enter SQL Statements display as:
SELECT ITEM_NUMBER, UNIT_COST, ITEM_NAME
FROM SAMPLECOLL.INVENTORY_LIST
WHERE UNIT_COST > 10.00

Getting Information from More Than One Table


SQL allows you to get information from columns contained in more than one table.
This operation is called a join operation. (For a more detailed description of the join
operation, see “Joining Data from More Than One Table” on page 75). In SQL, a
join operation is specified by placing the names of those tables you want to join
together into the same FROM clause of a SELECT statement.

Suppose you want to see a list of all the suppliers and the item numbers and item
names for their supplied items. The item name is not in the SUPPLIERS table. It is
in the INVENTORY_LIST table. Using the common column, ITEM_NUMBER, we
can see all three of the columns as if they were from a single table.

Whenever the same column name exists in two or more tables being joined, the
column name must be qualified by the table name to specify which column is really
being referenced. In this SELECT statement, the column name ITEM_NUMBER is
defined in both tables so the column name needs to be qualified by the table name.
If the columns had different names, there would be no confusion so qualification
would not be needed.

To perform this join, the following SELECT statement can be used. Enter it by
typing it directly on the Enter SQL Statements display or by prompting. If using
prompting, both table names need to be typed on the FROM tables input line.
SELECT SUPPLIER_NUMBER, SAMPLECOLL.INVENTORY_LIST.ITEM_NUMBER, ITEM_NAME
FROM SAMPLECOLL.SUPPLIERS, SAMPLECOLL.INVENTORY_LIST
WHERE SAMPLECOLL.SUPPLIERS.ITEM_NUMBER
= SAMPLECOLL.INVENTORY_LIST.ITEM_NUMBER

Another way to enter the same statement is to use a correlation name. A correlation
name provides another name for a table name to use in a statement. A correlation
name must be used when the table names are the same. It can be specified
following each table name in the FROM list. The previous statement could be
rewritten as:
SELECT SUPPLIER_NUMBER, Y.ITEM_NUMBER, ITEM_NAME
FROM SAMPLECOLL.SUPPLIERS X, SAMPLECOLL.INVENTORY_LIST Y
WHERE X.ITEM_NUMBER = Y.ITEM_NUMBER

In this example, SAMPLECOLL.SUPPLIERS is given a correlation name of X and


SAMPLECOLL.INVENTORY_LIST is given a correlation name of Y. The names X
and Y are then used to qualify the ITEM_NUMBER column name.

For more information on correlation names, see the DB2 UDB for AS/400 SQL
Reference book.

Running this example returns the following output:

Chapter 2. Getting Started with SQL 23


Display Data
Data width . . . . . . : 45
Position to line . . . . . Shift to column . . . . . .
....+....1....+....2....+....3....+....4....+
SUPPLIER_NUMBER ITEM ITEM
NUMBER NAME
1234 153047 Pencils, red
9988 153047 Pencils, red
2424 153047 Pencils, red
1234 229740 Lined tablets
1234 303476 Paper clips
2424 303476 Paper clips
3366 303476 Paper clips
9988 559343 Envelopes, legal
5546 775298 Chairs, secretary
3366 073956 Pens, black
******** End of data ********

F3=Exit F12=Cancel F19=Left F20=Right F21=Split

The data values in the result table represent a composite of the data values
contained in the two tables INVENTORY_LIST and SUPPLIERS. This result table
contains the supplier number from the SUPPLIER table and the item number and
item name from the INVENTORY_LIST table. Any item numbers that do not appear
in the SUPPLIER table are not shown in this result table. The results are not
guaranteed to be in any order unless the ORDER BY clause is specified for the
SELECT statement. Since we did not change any column headings for the
SUPPLIER table, the SUPPLIER_NUMBER column name is used as the column
heading.

The following is an example of using ORDER BY to guarantee the order of the


rows. The statement will first order the result table by the SUPPLIER_NUMBER
column. Rows with the same value for SUPPLIER_NUMBER will be ordered by
their ITEM_NUMBER.
SELECT SUPPLIER_NUMBER, Y.ITEM_NUMBER, ITEM_NAME
FROM SAMPLECOLL.SUPPLIERS X, SAMPLECOLL.INVENTORY_LIST Y
WHERE X.ITEM_NUMBER = Y.ITEM_NUMBER
ORDER BY SUPPLIER_NUMBER, Y.ITEM_NUMBER

Running the previous statement would produce the following output.

24 DB2 UDB for AS/400 SQL Programming V4R4


Display Data
Data width . . . . . . : 45
Position to line . . . . . Shift to column . . . . . .
....+....1....+....2....+....3....+....4....+
SUPPLIER_NUMBER ITEM ITEM
NUMBER NAME
1234 153047 Pencils, red
1234 229740 Lined tablets
1234 303476 Paper clips
2424 153047 Pencils, red
2424 303476 Paper clips
3366 073956 Pens, black
3366 303476 Paper clips
5546 775298 Chairs, secretary
9988 153047 Pencils, red
9988 559343 Envelopes, legal
******** End of data ********

F3=Exit F12=Cancel F19=Left F20=Right F21=Split

Changing Information in a Table


| You can use the SQL UPDATE statement to change the data values in some or all
| of the columns of a table. You may also use Operations Navigator to accomplish
| this task.

For an example of changing information in a table using interactive SQL, see


“Example: Changing Information in a Table”.

| If you want to limit the number of rows being changed during a single statement
| execution, use the WHERE clause with the UPDATE statement. For more
| information see, “The UPDATE Statement” on page 33. If you do not specify the
| WHERE clause, all of the rows in the specified table are changed. However, if you
| use the WHERE clause, the system changes only the rows satisfying the conditions
| that you specify. For more information, see “The WHERE Clause” on page 38.

| Example: Changing Information in a Table


| Suppose we want to use interactive SQL and are placing an order for more paper
| clips today. To update the LAST_ORDER_DATE and ORDER_QUANTITY for item
| number 303476, type UPDATE and press F4 (Prompt). The Specify UPDATE
| Statement display will be shown.

Chapter 2. Getting Started with SQL 25


| Specify UPDATE Statement
|
| Type choices, press Enter.
|
| Table . . . . . . . . INVENTORY_LIST______ Name, F4 for list
| Collection . . . . . SAMPLECOLL__ Name, F4 for list
|
| Correlation . . . . . ____________________ Name
|
|
|
|
|
|
|
|
|
|
|
|
|
| F3=Exit F4=Prompt F5=Refresh F12=Cancel F20=Display full names
| F21=Display statement
|

| After typing the table name and collection name, press Enter. The display will be
| shown again with the list of columns in the table.
| Specify UPDATE Statement
|
| Type choices, press Enter.
|
| Table . . . . . . . . INVENTORY_LIST______ Name, F4 for list
| Collection . . . . . SAMPLECOLL__ Name, F4 for list
|
| Correlation . . . . . ____________________ Name
|
|
| Type information, press Enter.
|
| Column Value
| ITEM_NUMBER _____________________________________________________
| ITEM_NAME _____________________________________________________
| UNIT_COST _____________________________________________________
| QUANTITY_ON_HAND _____________________________________________________
| LAST_ORDER_DATE CURRENT DATE_________________________________________
| ORDER_QUANTITY 50___________________________________________________
|
| Bottom
| F3=Exit F4=Prompt F5=Refresh F6=Insert line F10=Copy line
| F11=Display type F12=Cancel F14=Delete line F24=More keys
|

| Specifying CURRENT DATE for a value will change the date in all the selected
| rows to be today’s date.

| After typing the values to be updated for the table, press Enter to see the display
| on which the WHERE condition can be specified. If a WHERE condition is not
| specified, all the rows in the table will be updated using the values from the
| previous display.

26 DB2 UDB for AS/400 SQL Programming V4R4


| Specify UPDATE Statement
|
| Type WHERE conditions, press Enter. Press F4 for a list.
| ITEM_NUMBER = '303476'________________________________________________
| ______________________________________________________________________
|
|
|
| Bottom
| Type choices, press Enter.
|
| WITH isolation level . . . 1 1=Current level, 2=NC (NONE)
| 3=UR (CHG), 4=CS, 5=RS (ALL)
| 6=RR
|
|
|
|
|
|
|
| F3=Exit F4=Prompt F5=Refresh F6=Insert line F9=Specify subquery
| F10=Copy line F12=Cancel F14=Delete line F15=Split line F24=More keys
|

| After typing the condition, press Enter to perform the update on the table. A
| message will indicate that the function is complete.

| This statement could have been typed on the Enter SQL Statements display as:
| UPDATE SAMPLECOLL.INVENTORY_LIST
| SET LAST_ORDER_DATE = CURRENT DATE,
| ORDER_QUANTITY = 50
| WHERE ITEM_NUMBER = '303476'

| Running a SELECT statement to get all the rows from the table (SELECT * FROM
SAMPLECOLL.INVENTORY_LIST), returns the following result:
Display Data
Data width . . . . . . : 71
Position to line . . . . . Shift to column . . . . . .
....+....1....+....2....+....3....+....4....+....5....+....6....+....7.
ITEM ITEM UNIT QUANTITY LAST NUMBER
NUMBER NAME COST ON ORDER ORDERED
HAND DATE
153047 Pencils, red 10.00 25 - 20
229740 Lined tablets 1.50 120 - 20
544931 ***UNKNOWN*** 5.00 - - 20
303476 Paper clips 2.00 100 05/30/94 50
559343 Envelopes, legal 3.00 500 - 20
291124 Envelopes, standard .00 - - 20
775298 Chairs, secretary 225.00 6 - 20
073956 Pens, black 20.00 25 - 20
******** End of data ********
Bottom
F3=Exit F12=Cancel F19=Left F20=Right F21=Split

Only the entry for Paper clips was changed. The LAST_ORDER_DATE was
changed to be the current date. This date is always the date the update is run. The
NUMBER_ORDERED shows its updated value.

Chapter 2. Getting Started with SQL 27


Deleting Information from a Table
| You can delete data from a table by using Operations Navigator. Or, using the SQL
| DELETE statement, you can delete entire rows from a table when they no longer
| contain needed information. You can use the WHERE clause with the DELETE
| statement to identify rows to be deleted during a single statement execution. For
| more information, see “The DELETE Statement” on page 34.

| For an example of deleting information in a table using interactive SQL, see


| “Example: Deleting Information from a Table (INVENTORY_LIST)”.

Example: Deleting Information from a Table (INVENTORY_LIST)


If we want to remove all the rows in our table that have the null value for the
QUANTITY_ON_HAND column, you could enter the following statement on the
Enter SQL Statements display:
DELETE
FROM SAMPLECOLL.INVENTORY_LIST
WHERE QUANTITY_ON_HAND IS NULL

To check a column for the null value, the IS NULL comparison is used. Running
another SELECT statement after the delete has completed will return the following
result table:
Display Data
Data width . . . . . . : 71
Position to line . . . . . Shift to column . . . . . .
....+....1....+....2....+....3....+....4....+....5....+....6....+....7.
ITEM ITEM UNIT QUANTITY LAST NUMBER
NUMBER NAME COST ON ORDER ORDERED
HAND DATE
153047 Pencils, red 10.00 25 - 20
229740 Lined tablets 1.50 120 - 20
303476 Paper clips 2.00 100 05/30/94 50
559343 Envelopes, legal 3.00 500 - 20
775298 Chairs, secretary 225.00 6 - 20
073956 Pens, black 20.00 25 - 20
******** End of data ********
Bottom
F3=Exit F12=Cancel F19=Left F20=Right F21=Split

The rows with a null value for QUANTITY_ON_HAND were deleted.

Creating and Using a View


| You may find that no single table contains all the information you need. You may
| also want to give users access to only part of the data in a table. Views provide a
| way to subset the table so that you deal with only the data you need. A view
| reduces complexity and, at the same time, restricts access.

You can create a view using Operations Navigator. Or you can use the SQL
CREATE VIEW statement. Using the CREATE VIEW statement, defining a view on
a table is like creating a new table containing just the columns and rows you want.
When your application uses a view, it cannot access rows or columns of the table
that are not included in the view. However, rows that do not match the selection
criteria may still be inserted through a view if the SQL WITH CHECK OPTION is not
used. See Chapter 6. Data Integrity for more information on using WITH CHECK
OPTION.

28 DB2 UDB for AS/400 SQL Programming V4R4


| For examples of creating a view using interactive SQL, see the following:
| v Example: “Example: Creating a view on a single table” or
| v Example: “Example: Creating a view combining data from more than one table”
| on page 30

| In order to create a view you must have the proper authority to the tables or
physical files on which the view is based. See the CREATE VIEW statement in the
SQL Reference for a list of authorities needed.

If you do not specify column names in the view definition, the column names will be
the same as those for the table on which the view is based.

You can make changes to a table through a view even if the view has a different
number of columns or rows than the table. For INSERT, columns in the table that
are not in the view must have a default value.

You can use the view as though it were a table, even though the view is totally
dependent on one or more tables for data. The view has no data of its own and
therefore requires no storage for the data. Because a view is derived from a table
that exists in storage, when you update the view data, you are really updating data
in the table. Therefore, views are automatically kept up-to-date as the tables they
depend on are updated.

See “Creating and Using Views” on page 95 for additional information.

Example: Creating a view on a single table


The following example shows how to create a view on a single table. The view is
built on the INVENTORY_LIST table. The table has six columns, but the view uses
only three of the columns: ITEM_NUMBER, LAST_ORDER_DATE, and
QUANTITY_ON_HAND. The order of the columns in the SELECT clause is the
order in which they will appear in the view. The view will contain only the rows for
items that were ordered in the last two weeks. The CREATE VIEW statement looks
like this:
CREATE VIEW SAMPLECOLL.RECENT_ORDERS AS
SELECT ITEM_NUMBER, LAST_ORDER_DATE, QUANTITY_ON_HAND
FROM SAMPLECOLL.INVENTORY_LIST
WHERE LAST_ORDER_DATE > CURRENT DATE - 14 DAYS

In the example above, the columns in the view have the same name as the
columns in the table because no column list follows the view name. The collection
that the view is created into does not need to be the same collection as the table it
is built over. Any collection or library could be used. The following display is the
result of running the SQL statement:
SELECT * FROM SAMPLECOLL.RECENT_ORDERS

Chapter 2. Getting Started with SQL 29


Display Data
Data width . . . . . . : 26
Position to line . . . . . Shift to column . . . . . .
....+....1....+....2....+.
ITEM LAST QUANTITY
NUMBER ORDER ON
DATE HAND
303476 05/30/94 100
******** End of data ********
Bottom
F3=Exit F12=Cancel F19=Left F20=Right F21=Split

The only row selected by the view is the row that we updated to have the current
date. All other dates in our table still have the null value so they are not returned.

Example: Creating a view combining data from more than one table
You can create a view that combines data from two or more tables by naming more
than one table in the FROM clause. In the following example, the
INVENTORY_LIST table contains a column of item numbers called
ITEM_NUMBER, and a column with the cost of the item, UNIT_COST. These are
joined with the ITEM_NUMBER column and the SUPPLIER_COST column of the
SUPPLIERS table. A WHERE clause is used to limit the number of rows returned.
The view will only contain those item numbers for suppliers that can supply an item
at lower cost than the current unit cost.

The CREATE VIEW statement looks like this:


CREATE VIEW SAMPLECOLL.LOWER_COST AS
SELECT SUPPLIER_NUMBER, A.ITEM_NUMBER, UNIT_COST, SUPPLIER_COST
FROM SAMPLECOLL.INVENTORY_LIST A, SAMPLECOLL.SUPPLIERS B
WHERE A.ITEM_NUMBER = B.ITEM_NUMBER
AND UNIT_COST > SUPPLIER_COST

The following table is the result of running the SQL statement:


SELECT * FROM SAMPLECOLL.LOWER_COST

Display Data
Data width . . . . . . : 51
Position to line . . . . . Shift to column . . . . . .
....+....1....+....2....+....3....+....4....+....5.
SUPPLIER_NUMBER ITEM UNIT SUPPLIER_COST
NUMBER COST
9988 153047 10.00 8.00
2424 153047 10.00 9.00
1234 229740 1.50 1.00
3366 303476 2.00 1.50
3366 073956 20.00 17.00
******** End of data ********
Bottom
F3=Exit F12=Cancel F19=Left F20=Right F21=Split

The rows that can be seen through this view are only those rows that have a
supplier cost that is less than the unit cost.

30 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 3. Basic Concepts and Techniques
This chapter explains some of the concepts used in SQL statements. It discusses
many of the common statements and clauses in SQL. The examples in this chapter
refer to the tables shown in Appendix A. DB2 UDB for AS/400 Sample Tables.

Using Basic SQL Statements and Clauses


This section shows the basic SQL statements and clauses that retrieve, update,
delete, and insert data into tables and views. The SQL statements used are
SELECT, UPDATE, DELETE, and INSERT. FETCH statements can be used in an
application program to access data as well. This statement is covered in Chapter 4.
Examples using these SQL statements are supplied to help you develop SQL
applications. Detailed syntax and parameter descriptions for SQL statements are
given in the DB2 UDB for AS/400 SQL Reference book.

You can write SQL statements on one line or on many lines. The rules for the
continuation of lines are the same as those of the host language (the language the
program is written in).
Notes:
1. The SQL statements described in this section can be run on SQL tables and
views, and database physical and logical files. The tables, views, and files can
be either in an SQL collection or in a library.
2. Character strings specified in an SQL statement (such as those used with
WHERE or VALUES clauses) are case sensitive; that is, uppercase characters
must be entered in uppercase and lowercase characters must be entered in
lowercase.
WHERE ADMRDEPT='a00' (does not return a result)

WHERE ADMRDEPT='A00' (returns a valid department number)

Comparisons may not be case sensitive if a shared-weight sort sequence is


being used where uppercase and lowercase characters are treated as the same
character.

The INSERT Statement


You can use the INSERT statement to add new rows to a table or view in one of
the following ways:
v Specifying values in the INSERT statement for columns of the single row to be
added.
v Specifying the blocked form of the INSERT statement to add multiple rows.
“Using the Blocked Insert Statement” on page 70 explains how to use the
blocked form of the INSERT statement to add multiple rows to a table.
v Including a select-statement in the INSERT statement to tell SQL what data for
the new row is contained in another table or view. “Inserting Rows into a Table
Using a Select-Statement” on page 69 explains how to use the select-statement
within an INSERT statement to add zero, one, or many rows to a table.

Note: Because views are built on tables and actually contain no data, working with
views can be confusing. See “Creating and Using Views” on page 95 for
more information on inserting data by using a view.

© Copyright IBM Corp. 1997, 1999 31


For every row you insert, you must supply a value for each column defined with the
NOT NULL attribute if that column does not have a default value. The INSERT
statement for adding a row to a table or view may look like this:
INSERT INTO table-name
(column1, column2, ... )
VALUES (value-for-column1, value-for-column2, ... )

The INTO clause names the columns for which you specify values. The VALUES
clause specifies a value for each column named in the INTO clause.

You must provide a value in the VALUES clause for each column named in an
INSERT statement’s column list. The column name list can be omitted if all columns
in the table have a value provided in the VALUES clause. If a column has a default
value, the keyword DEFAULT may be used as a value on the VALUES clause.

It is a good idea to name all columns into which you are inserting values because:
v Your INSERT statement is more descriptive.
v You can verify that you are giving the values in the proper order based on the
column names.
v You have better data independence. The order in which the columns are defined
in the table does not affect your INSERT statement.

If the column is defined to allow null values or to have a default, you do not need to
name it in the column name list or specify a value for it. The default value is used.
If the column is defined to have a default value, the default value is placed in the
column. If DEFAULT was specified for the column definition without an explicit
default value, SQL places the default value for that data type in the column. If the
column does not have a default value defined for it, but is defined to allow the null
value (NOT NULL was not specified in the column definition), SQL places the null
value in the column.
v For numeric columns, the default value is 0.
v For fixed length character or graphic columns, the default is blanks.
| v For varying length character or graphic columns or LOB columns, the default is a
| zero length string.
v For date, time, and timestamp columns, the default value is the current date,
time, or timestamp. When inserting a block of records, the default date/time value
is extracted from the system when the block is written. This means that the
column will be assigned the same default value for each row in the block.
| v For DataLink columns, the default value corresponds to DLVALUE(’’,’URL’,’’).
| v For distinct-type columns, the default value is the default value of the
| corresponding source type.

When your program attempts to insert a row that duplicates another row already in
the table, an error might occur. Multiple null values may or may not be considered
duplicate values, depending on the option used when the index was created.
v If the table has a primary key, unique key, or unique index, the row is not
inserted. Instead, SQL returns an SQLCODE of −803.
v If the table does not have a primary key, unique key, or unique index, the row
can be inserted without error.

If SQL finds an error while running the INSERT statement, it stops inserting data. If
you specify COMMIT(*ALL), COMMIT(*CS), COMMIT(*CHG), or COMMIT(*RR), no
rows are inserted. Rows already inserted by this statement, in the case of INSERT

32 DB2 UDB for AS/400 SQL Programming V4R4


with a select-statement or blocked insert, are deleted. If you specify
COMMIT(*NONE), any rows already inserted are not deleted.

A table created by SQL is created with the Reuse Deleted Records parameter of
*YES. This allows the database manager to reuse any rows in the table that were
marked as deleted. The CHGPF command can be used to change the attribute to
*NO. This causes INSERT to always add rows to the end of the table.

The order in which rows are inserted does not guarantee the order in which they
will be retrieved.

If the row is inserted without error, the SQLERRD(3) field of the SQLCA has a value
of 1.

Note: For blocked INSERT or for INSERT with select-statement, more than one
row can be inserted. The number of rows inserted is reflected in
SQLERRD(3).

The UPDATE Statement


To change the data in a table, use the UPDATE statement. With the UPDATE
statement, you can change the value of one or more columns in each row that
satisfies the search condition of the WHERE clause. The result of the UPDATE
statement is one or more changed column values in zero or more rows of a table
(depending on how many rows satisfy the search condition specified in the WHERE
clause). The UPDATE statement looks like this:
UPDATE table-name
SET column-1 = value-1,
column-2 = value-2, ...
WHERE search-condition ...

For example, suppose an employee was relocated. To update several items of the
employee’s data in the CORPDATA.EMPLOYEE table to reflect the move, you can
specify:
UPDATE CORPDATA.EMPLOYEE
SET JOB = :PGM-CODE,
PHONENO = :PGM-PHONE
WHERE EMPNO = :PGM-SERIAL

Use the SET clause to specify a new value for each column you want to update.
The SET clause names the columns you want updated and provides the values you
want them changed to. The value you specify can be:
A column name. Replace the column’s current value with the contents of
another column in the same row.
A constant. Replace the column’s current value with the value provided in the
SET clause.
A null value. Replace the column’s current value with the null value, using the
keyword NULL. The column must be defined as capable of containing a null
value when the table was created, or an error occurs.
A host variable. Replace the column’s current value with the contents of a host
variable.
A special register. Replace the column’s current value with a special register
value; for example, USER.
An expression. Replace the column’s current value with the value that results
from an expression. The expression can contain any of the values in this list.

Chapter 3. Basic Concepts and Techniques 33


A scalar subselect. Replace the column’s current value with the value that the
subquery returns.
The DEFAULT keyword. Replace the column’s current value with the default
value of the column. The column must have a default value defined for it or
allow the NULL value, or an error occurs.

The following is an example of a statement that uses many different values:


UPDATE WORKTABLE
SET COL1 = 'ASC',
COL2 = NULL,
COL3 = :FIELD3,
COL4 = CURRENT TIME,
COL5 = AMT - 6.00,
COL6 = COL7
WHERE EMPNO = :PGM-SERIAL

To identify the rows to be updated, use the WHERE clause:


v To update a single row, use a WHERE clause that selects only one row.
v To update several rows, use a WHERE clause that selects only the rows you
want to update.

You can omit the WHERE clause. If you do, SQL updates each row in the table or
view with the values you supply.

If the database manager finds an error while running your UPDATE statement, it
stops updating and returns a negative SQLCODE. If you specify COMMIT(*ALL),
COMMIT(*CS), COMMIT(*CHG), or COMMIT(*RR), no rows in the table are
changed (rows already changed by this statement, if any, are restored to their
previous values). If COMMIT(*NONE) is specified, any rows already changed are
not restored to previous values.

If the database manager cannot find any rows that satisfy the search condition, an
SQLCODE of +100 is returned.

Note: UPDATE with a WHERE clause may have updated more than one row. The
number of rows updated is reflected in SQLERRD(3).

The DELETE Statement


To remove rows from a table, use the DELETE statement. When you DELETE a
row, you remove the entire row. DELETE does not remove specific columns from
the row. The result of the DELETE statement is the removal of zero or more rows of
a table (depending on how many rows satisfy the search condition specified in the
WHERE clause). If you omit the WHERE clause from a DELETE statement, SQL
removes all the rows of the table. The DELETE statement looks like this:
DELETE FROM table-name
WHERE search-condition ...

For example, suppose department D11 was moved to another place. You want to
delete each row in the CORPDATA.EMPLOYEE table with a WORKDEPT value of
D11 as follows:
DELETE FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = 'D11'

The WHERE clause tells SQL which rows you want to delete from the table. SQL
deletes all the rows that satisfy the search condition from the base table. You can

34 DB2 UDB for AS/400 SQL Programming V4R4


omit the WHERE clause, but it is best to include one, because a DELETE
statement without a WHERE clause deletes all the rows from the table or view. To
delete a table definition as well as the table contents, issue the DROP statement
(described in the DB2 UDB for AS/400 SQL Reference book).

If SQL finds an error while running your DELETE statement, it stops deleting data
and returns a negative SQLCODE. If you specify COMMIT(*ALL), COMMIT(*CS),
COMMIT(*CHG), or COMMIT(*RR), no rows in the table are deleted (rows already
deleted by this statement, if any, are restored to their previous values). If
COMMIT(*NONE) is specified, any rows already deleted are not restored to their
previous values.

If SQL cannot find any rows that satisfy the search condition, an SQLCODE of +100
is returned.

Note: DELETE with WHERE clause may have deleted more than one row. The
number of rows deleted is reflected in SQLERRD(3).

The SELECT INTO Statement


| You can use a variety of statements and clauses to query your data. One way to do
| this is to use the SELECT INTO statement in a program to retrieve a specific row
| (for example, the row for an employee). Furthermore, in this example, a variety of
| clauses are used to gather data in a specific way. You can use the “The WHERE
| Clause” on page 38, “The GROUP BY Clause” on page 40, “The HAVING Clause”
| on page 42, and “The ORDER BY Clause” on page 43 to tailor your query to
| gather data in a specific manner.

The format and syntax shown here are very basic. SELECT INTO statements can
be more varied than the examples presented in this chapter. A SELECT INTO
statement can include the following:
1. The name of each column you want
2. The name of each host variable used to contain retrieved data
3. The name of the table or view that contains the data
4. A search condition to uniquely identify the row that contains the information you
want
5. The name of each column used to group your data
6. A search condition that uniquely identifies a group that contains the information
you want
7. The order of the results so a specific row among duplicates can be returned.

A SELECT INTO statement looks like this:


SELECT column names
INTO host variables
FROM table or view name
WHERE search condition
GROUP BY column names
HAVING search condition
ORDER BY column-name

The SELECT, INTO, and FROM clauses must be specified. The other clauses are
optional.

Chapter 3. Basic Concepts and Techniques 35


The INTO clause names the host variables (variables in your program used to
contain retrieved column values). The value of the first column specified in the
SELECT clause is put into the first host variable named in the INTO clause; the
second value is put into the second host variable, and so on.

The result table for a SELECT INTO should contain just one row. For example,
each row in the CORPDATA.EMPLOYEE table has a unique EMPNO (employee
number) column. The result of a SELECT INTO statement for this table if the
WHERE clause contains an equal comparison on the EMPNO column, would be
exactly one row (or no rows). Finding more than one row is an error, but one row is
still returned. You can control which row will be returned in this error condition by
specifying the ORDER BY clause. If you use the ORDER BY clause, the first row in
the result table is returned.

If you want more than one row to be the result of a select-statement, use a
DECLARE CURSOR statement to select the rows, followed by a FETCH statement
to move the column values into host variables one or many rows at a time. Using
cursors is described in “Chapter 4. Using a Cursor” on page 55.

The FROM clause names the table (or view) that contains the data you are
interested in.

For example, assume that each department listed in the


CORPDATA.DEPARTMENT table has a unique department number. You want to
retrieve the department name and manager number from the
CORPDATA.DEPARTMENT table for department C01. To do this, your program can
set PGM-DEPT to the value C01 and issue:
SELECT DEPTNAME, MGRNO
INTO :PGM-DEPTNAME, :PGM-MGRNO
FROM CORPDATA.DEPARTMENT
WHERE DEPTNO = :PGM-DEPT

When the statement is run, the result is one row:

PGM-DEPTNAME PGM-MGRNO
INFORMATION CENTER 000030

These values are assigned to the host variables PGM-DEPTNAME and


PGM-MGRNO.

If SQL is unable to find a row that satisfies the search condition, an SQLCODE of
+100 is returned.

If SQL finds errors while running your select-statement, a negative SQLCODE is


returned. If SQL finds more host variables than results, +326 is returned.

You can retrieve data from a view in exactly the same way you retrieve data from a
table. However, there are several restrictions when you attempt to update, insert, or
delete data in a view. These restrictions are described in “Creating and Using
Views” on page 95.

Data retrieval errors


If SQL finds that a retrieved character or graphic column is too long to be placed in
a host variable, SQL does the following:

36 DB2 UDB for AS/400 SQL Programming V4R4


v Truncates the data while assigning the value to the host variable.
v Sets SQLWARN0 and SQLWARN1 in the SQLCA to the value 'W'.
v Sets the indicator variable, if provided, to the length of the value before
truncation.

If SQL finds a data mapping error while running a statement, one of two things
occurs:
v If the error occurs on an expression in the SELECT list and an indicator variable
is provided for the expression in error:
– SQL returns a −2 for the indicator variable corresponding to the expression in
error.
– SQL returns all valid data for that row.
– SQL returns a positive SQLCODE.
v If an indicator variable is not provided, SQL returns the corresponding negative
SQLCODE in the SQLCA.

Data mapping errors include:


v +138 - Argument of the substringing function is not valid.
v +180 - Syntax for a string representation of a date, time, or timestamp is not
valid.
v +181 - String representation of a date, time, or timestamp is not a valid value.
v +183 - Invalid result from a date/time expression. The resulting date or timestamp
is not within the valid range of dates or timestamps.
v +191 - MIXED data is not properly formed.
v +304 - Numeric conversion error (for example, overflow, underflow, or division by
zero).
v +331 - Characters cannot be converted.
v +420 - Character in the CAST argument is not valid.
v +802 - Data conversion or data mapping error.

For data mapping errors, the SQLCA reports only the last error detected. The
indicator variable corresponding to each result column having an error is set to −2.

If the full-select contains DISTINCT in the select list and a column in the select list
contains numeric data that is not valid, the data is considered equal to a null value
if the query is completed as a sort. If an existing index is used, the data is not
considered equal to a null.

The impact of data mapping errors on the ORDER BY clause depends on the
situation:
v If the data mapping error occurs while data is being assigned to a host variable
in a SELECT INTO or FETCH statement, and that same expression is used in
the ORDER BY clause, the result record is ordered based on the value of the
expression. It is not ordered as if it were a null (higher than all other values). This
is because the expression was evaluated before the assignment to the host
variable is attempted.
v If the data mapping error occurs while an expression in the select-list is being
evaluated and the same expression is used in the ORDER BY clause, the result
column is normally ordered as if it were a null value (higher than all other
values). If the ORDER BY clause is implemented by using a sort, the result
column is ordered as if it were a null value. If the ORDER BY clause is

Chapter 3. Basic Concepts and Techniques 37


implemented by using an existing index, in the following cases, the result column
is ordered based on the actual value of the expression in the index:
– The expression is a date column with a date format of *MDY, *DMY, *YMD, or
*JUL, and a date conversion error occurs because the date is not within the
valid range for dates.
– The expression is a character column and a character could not be converted.
– The expression is a decimal column and a numeric value that is not valid is
detected.

The SELECT Clause


With the SELECT clause (the first part of a select-statement), you specify the name
of each column you want to retrieve. For example:
SELECT EMPNO, LASTNAME, WORKDEPT
.
.
.

You can specify that only one column be retrieved, or as many as 8000 columns.
The value of each column you name is retrieved in the order specified in the
SELECT clause.

If you want to retrieve all columns (in the same order as they appear in the row),
use an asterisk (*) instead of naming the columns:
SELECT *
.
.
.

When using the select-statement in an application program, list the column names
to give your program more data independence. There are two reasons for this:
1. When you look at the source code statement, you can easily see the one-to-one
correspondence between the column names in the SELECT clause and the host
variables named in the INTO clause.
2. If a column is added to a table or view you access and you use “SELECT * ...,”
and you create the program again from source, the INTO clause does not have
a matching host variable named for the new column. The extra column causes
you to get a warning (not an error) in the SQLCA (SQLWARN4 will contain a
“W”).

The WHERE Clause


The WHERE clause specifies a search condition that identifies the row or rows you
want to retrieve, update, or delete. The number of rows you process with an SQL
statement then depends on the number of rows that satisfy the WHERE clause
search condition. A search condition consists of one or more predicates. A
predicate specifies a test that you want SQL to apply to a specified row or rows of a
table.

In the following example, WORKDEPT = 'C01' is a predicate, WORKDEPT and


'C01' are expressions, and the equal sign (=) is a comparison operator. Note that
character values are enclosed in apostrophes ('); numeric values are not. This
applies to all constant values wherever they are coded within an SQL statement.
For example, to specify that you are interested in the rows where the department
number is C01, you would say:
... WHERE WORKDEPT = 'C01'

38 DB2 UDB for AS/400 SQL Programming V4R4


In this case, the search condition consists of one predicate: WORKDEPT = 'C01'.

If the search condition contains character or UCS-2 graphic column predicates, the
sort sequence that is in effect when the query is run is applied to those predicates.
See “Using Sort Sequence in SQL” on page 50 for more information on sort
sequence and selection.

Using Expressions in the WHERE Clause


An expression in a WHERE clause names or specifies something you want to
compare to something else. Each expression, when evaluated by SQL, is a
character string, date/time/timestamp, or a numeric value. The expressions you
specify can be:
v A column name names a column. For example:
... WHERE EMPNO = '000200'

EMPNO names a column that is defined as a 6-byte character value. Equality


comparisons (that is, X = Y or X <> Y) can be performed on character data.
Other types of comparisons can also be evaluated for character data.

However, you cannot compare character strings to numbers. You also cannot
perform arithmetic operations on character data (even though EMPNO is a
character string that appears to be a number). You can add and subtract
date/time values.
v An expression identifies two values that are added (+), subtracted (−), multiplied
(*), divided (/), have exponentiation (**), or concatenated (CONCAT or ||) to result
in a value. The operands of an expression can be:
A constant (that is, a literal value)
A column
A host variable
A value returned from a function
A special register
Another expression

For example:
... WHERE INTEGER(PRENDATE - PRSTDATE) > 100

When the order of evaluation is not specified by parentheses, the expression is


evaluated in the following order:
1. Prefix operators
2. Exponentiation
3. Multiplication, division, and concatenation
4. Addition and subtraction

Operators on the same precedence level are applied from left to right.
v A constant specifies a literal value for the expression. For example:
... WHERE 40000 < SALARY

SALARY names a column that is defined as an 9-digit packed decimal value


(DECIMAL(9,2)). It is compared to the numeric constant 40000.
v A host variable identifies a variable in an application program. For example:
... WHERE EMPNO = :EMP

Chapter 3. Basic Concepts and Techniques 39


v A special register identifies a special value generated by the database manager.
For example:
... WHERE LASTNAME = USER
v The NULL value specifies the condition of having an unknown value.
... WHERE DUE_DATE IS NULL

A search condition need not be limited to two column names or constants separated
by arithmetic or comparison operators. You can develop a complex search condition
that specifies several predicates separated by AND and OR. No matter how
complex the search condition, it supplies a TRUE or FALSE value when evaluated
against a row. There is also an unknown truth value, which is effectively false. That
is, if the value of a row is null, this null value is not returned as a result of a search
because it is not less than, equal to, or greater than the value specified in the
search condition. More complex search conditions and predicates are described in
“Performing Complex Search Conditions” on page 72.

To fully understand the WHERE clause, you need to know how SQL evaluates
search conditions and predicates, and compares the values of expressions. This
topic is discussed in the DB2 UDB for AS/400 SQL Reference book.

Comparison Operators
SQL supports the following comparison operators:

= Equal to
<> or ¬= Not equal to
< Less than
> Greater than
<= or ¬> Less than or equal to (or not greater than)
> = or ¬< Greater than or equal to (or not less than)

The NOT Keyword


You can precede a predicate with the NOT keyword to specify that you want the
opposite of the predicate’s value (that is, TRUE if the predicate is FALSE, or vice
versa). NOT applies only to the predicate it precedes, not to all predicates in the
WHERE clause. For example, to indicate that you are interested in all employees
except those working in department C01, you could say:
... WHERE NOT WORKDEPT = 'C01'

which is equivalent to:


... WHERE WORKDEPT <> 'C01'

The GROUP BY Clause


Without a GROUP BY clause, the application of SQL column functions returns one
row. When GROUP BY is used, the function is applied to each group, thereby
returning as many rows as there are groups.

| The GROUP BY clause allows you to find the characteristics of groups of rows
| rather than individual rows. When you specify a GROUP BY clause, SQL divides
| the selected rows into groups such that the rows of each group have matching
| values in one or more columns or expressions. Next, SQL processes each group to
| produce a single-row result for the group. You can specify one or more columns or

40 DB2 UDB for AS/400 SQL Programming V4R4


| expressions in the GROUP BY clause to group the rows. The items you specify in
| the SELECT statement are properties of each group of rows, not properties of
| individual rows in a table or view.

For example, the CORPDATA.EMPLOYEE table has several sets of rows, and each
set consists of rows describing members of a specific department. To find the
average salary of people in each department, you could issue:

The SQL statement: Results in:


fetch WORK-DEPT AVG-SALARY
1 A00 42833
2 B01 41250
... ... ...

RV2W551-1

The result is several rows, one for each department.


Notes:
1. Grouping the rows does not mean ordering them. Grouping puts each selected
row in a group, which SQL then processes to derive characteristics of the group.
Ordering the rows puts all the rows in the results table in ascending or
descending collating sequence. ( “The ORDER BY Clause” on page 43
describes how to do this.)
2. If there are null values in the column you specify in the GROUP BY clause, a
single-row result is produced for the data in the rows with null values.
3. If the grouping occurs over character or UCS-2 graphic columns, the sort
sequence in effect when the query is run is applied to the grouping. See “Using
Sort Sequence in SQL” on page 50 for more information on sort sequence and
selection.

| When you use GROUP BY, you list the columns or expressions you want SQL to
| use to group the rows. For example, suppose you want a list of the number of
| people working on each major project described in the CORPDATA.PROJECT
| table. You could issue:

The SQL statement: Results in:


fetch SUM-PR MAJ-PROJ
1 6 AD3100
2 5 AD3110
3 10 MA2100
... ... ...

RV2W552-3

Chapter 3. Basic Concepts and Techniques 41


The result is a list of the company’s current major projects and the number of
people working on each project.

| You can also specify that you want the rows grouped by more than one column or
| expression. For example, you could issue a select-statement to find the average
| salary for men and women in each department, using the CORPDATA.EMPLOYEE
| table. To do this, you could issue:

The SQL statement: Results in:


fetch DEPT SEX AVG-WAGES
1 A00 F 52750
2 A00 M 37875
3 B01 M 41250
4 C01 F 30156
... ... ... ...

RV2W553-1

Because you did not include a WHERE clause in this example, SQL examines and
process all rows in the CORPDATA.EMPLOYEE table. The rows are grouped first
by department number and next (within each department) by sex before SQL
derives the average SALARY value for each group.

The HAVING Clause


You can use the HAVING clause to specify a search condition for the groups
selected based on a GROUP BY clause. The HAVING clause says that you want
only those groups that satisfy the condition in that clause. Therefore, the search
condition you specify in the HAVING clause must test properties of each group
rather than properties of individual rows in the group.

The HAVING clause follows the GROUP BY clause and can contain the same kind
of search condition you can specify in a WHERE clause. In addition, you can
specify column functions in a HAVING clause. For example, suppose you wanted to
retrieve the average salary of women in each department. To do this, you would
use the AVG column function and group the resulting rows by WORKDEPT and
specify a WHERE clause of SEX = 'F'.

To specify that you want this data only when all the female employees in the
selected department have an education level equal to or greater than 16 (a college
graduate), use the HAVING clause. The HAVING clause tests a property of the
group. In this case, the test is on MIN(EDLEVEL), which is a group property:

42 DB2 UDB for AS/400 SQL Programming V4R4


The SQL statement: Results in:
fetch DEPT AVG-WAGES MIN-EDUC
1 A00 52750 18
2 C01 30156 16
3 D11 24476 17

RV2W554-3

You can use multiple predicates in a HAVING clause by connecting them with AND
and OR, and you can use NOT for any predicate of a search condition.

Note: If you intend to update a column or delete a row, you cannot include a
GROUP BY or HAVING clause in the SELECT statement within a DECLARE
CURSOR statement. (The DECLARE CURSOR statement is described in
“Chapter 4. Using a Cursor” on page 55.)

Predicates with arguments that are not column functions can be coded in either
WHERE or HAVING clauses. It is usually more efficient to code the selection criteria
in the WHERE clause. It is processed during the initial phase of the query
processing. The HAVING selection is performed in post processing of the result
table.

If the search condition contains predicates involving character or UCS-2 graphic


columns, the sort sequence in effect when the query is run is applied to those
predicates. See “Using Sort Sequence in SQL” on page 50 for more information on
sort sequence and selection.

The ORDER BY Clause


| You can specify that you want selected rows retrieved in a particular order, sorted
| by ascending or descending collating sequence of a column’s value, with the
| ORDER BY clause. You can use an ORDER BY clause as you would a GROUP BY
| clause: specify the columns or expressions you want SQL to use when retrieving
| the rows in a collated sequence.

For example, to retrieve the names and department numbers of female employees
listed in the alphanumeric order of their department numbers, you could use this
select-statement:

Chapter 3. Basic Concepts and Techniques 43


The SQL statement: Results in:
fetch PGM-NAME3 DEPT
1 HAAS A00
2 KWAN C01
3 QUINTANA C01
4 NICHOLLS C01
5 PIANKA D11
6 SCOUTTEN D11
7 LUTZ D11
8 PULASKI D21
9 JOHNSON D21
10 PEREZ D21
11 HENDERSON E11
12 SCHNEIDER E11
13 SETRIGHT E11

RV2W555-3

Notes:
1. All columns named in the ORDER BY clause must also be named in the
SELECT list.
2. Null values are ordered as the highest value.

| To order by a column function, or something other than a column name, you can
| specify an AS clause in the select-list. To order by an expression, you can either
| specify the exact same expression in the ORDER BY clause, or you can specify an
| AS clause in the select-list.

The AS clause names the result column. This name can be specified in the ORDER
BY clause. To order by a name specified in the AS clause:
v The name must be unique in the select-list.
v The name must not be qualified.
For example, to retrieve the full name of employees listed in alphabetic order, you
could use this select-statement:
SELECT LASTNAME CONCAT FIRSTNAME AS FULLNAME ...
ORDER BY FULLNAME

| This select-statement could optionally be written as:


| SELECT LASTNAME CONCAT FIRSTNAME
| ORDER BY LASTNAME CONCAT FIRSTNAME

| Instead of naming the columns to order the results, you can use a number. For
example, ORDER BY 3 specifies that you want the results ordered by the third
column of the results table, as specified by the select-statement. Use a number to
order the rows of the results table when the sequencing value is not a named
column.

You can also specify whether you want SQL to collate the rows in ascending (ASC)
or descending (DESC) sequence. An ascending collating sequence is the default. In
the above select-statement, SQL first returns the row with the lowest department

44 DB2 UDB for AS/400 SQL Programming V4R4


number (alphabetically and numerically), followed by rows with higher department
numbers. To order the rows in descending collating sequence based on the
department number, specify:
... ORDER BY WORKDEPT DESC

As with GROUP BY, you can specify a secondary ordering sequence (or several
levels of ordering sequences) as well as a primary one. In the example above, you
might want the rows ordered first by department number, and within each
department, ordered by employee name. To do this, specify:
... ORDER BY WORKDEPT, LASTNAME

If character columns or UCS-2 graphic columns are used in the ORDER BY clause,
ordering for these columns is based on the sort sequence in effect when the query
is run. See “Using Sort Sequence in SQL” on page 50 for more information on sort
sequence and its affect on ordering.

Using Null Values


A null value indicates the absence of a column value in a row. A null value is not
the same as zero or all blanks. A null value is the same as “unknown”. Null values
can be used as a condition in the WHERE and HAVING clauses, and as a
mathematical argument. For example, a WHERE clause can specify a column that,
for some rows, contains a null value. Normally, a comparison predicate using a
column that contains null values does not select a row that has a null value for the
column. This is because a null value is neither less than, equal to, nor greater than
the value specified in the condition. To select the values for all rows that contain a
null value for the manager number, you could specify:
SELECT DEPTNO, DEPTNAME, ADMRDEPT
FROM CORPDATA.DEPARTMENT
WHERE MGRNO IS NULL

The result would be:

DEPTNO DEPTNAME ADMRDEPT


D01 DEVELOPMENT A00
CENTER

To get the rows that do not have a null value for the manager number, you could
change the WHERE clause like this:
WHERE MGRNO IS NOT NULL

For more information on the use of null values, see the DB2 UDB for AS/400 SQL
Reference book.

Using Special Registers


You can specify certain “special registers” in SQL statements. For locally run SQL
statements, the special registers and their contents are shown in the following table:

Special Registers Contents


CURRENT DATE The current date.
CURRENT_DATE

Chapter 3. Basic Concepts and Techniques 45


Special Registers Contents
CURRENT TIME The current time.
CURRENT_TIME
CURRENT TIMESTAMP The current date and time in timestamp
CURRENT_TIMESTAMP format.
CURRENT TIMEZONE A duration of time that links local time to
CURRENT_TIMEZONE Universal Coordinated Time (UTC) using the
formula:
local time - CURRENT TIMEZONE = UTC

It is taken from the system value


QUTCOFFSET.
CURRENT SERVER The name of the relational database as
CURRENT_SERVER contained in the relational database directory
table in the relational database directory.
USER The run-time authorization identifier (user
profile) of the job.
CURRENT PATH The SQL path used to resolve unqualified
CURRENT_PATH data type names, procedure names, and
CURRENT FUNCTION PATH function names.

If a single statement contains more than one reference to any of CURRENT DATE,
CURRENT TIME, or CURRENT TIMESTAMP special registers, or the CURDATE,
CURTIME, or NOW scalar functions, all values are based on a single clock reading.

For remotely run SQL statements, the special registers and their contents are
shown in the following table:

Special Registers Contents


CURRENT DATE The current date and time at the remote
CURRENT_DATE system, not the local system.
CURRENT TIME
CURRENT_TIME
CURRENT TIMESTAMP
CURRENT_TIMESTAMP
CURRENT TIMEZONE A duration of time that links the remote
CURRENT_TIMEZONE system time to UTC.
CURRENT SERVER The name of the relational database as
CURRENT_SERVER contained in the relational database directory
table in the relational database directory.
USER The run-time authorization identifier of the
server job on the remote system.
CURRENT PATH The current path value at the remote system.
CURRENT_PATH
CURRENT FUNCTION PATH

When a query over a distributed table references a special register, the contents of
the special register on the system that requests the query are used. For more
information on distributed tables, see DB2 Multisystem for AS/400 book.

46 DB2 UDB for AS/400 SQL Programming V4R4


Using Date, Time, and Timestamp
Date, time, and timestamp are data types represented in an internal form not seen
by the SQL user. Date, time, and timestamp can be represented by character string
values and assigned to character string variables. The database manager
recognizes the following as date, time, and timestamp values:
v A value returned by the DATE, TIME, or TIMESTAMP scalar functions.
v A value returned by the CURRENT DATE, CURRENT TIME, or CURRENT
TIMESTAMP special registers.
v A character string when it is an operand of an arithmetic expression or a
comparison and the other operand is a date, time, or timestamp. For example, in
the predicate:
... WHERE HIREDATE < '1950-01-01'

if HIREDATE is a date column, the character string ’1950-01-01’ is interpreted as


a date.
v A character string variable or constant used to set a date, time, or timestamp
column in either the SET clause of an UPDATE statement, or the VALUES
clause of an INSERT statement.
For more information on character string formats of date, time, and timestamp
values, see Chapter 2 of the DB2 UDB for AS/400 SQL Reference book .

Specifying Current Date and Time Values


You can specify a current date, time, or timestamp in an expression by specifying
one of three special registers: CURRENT DATE, CURRENT TIME, or CURRENT
TIMESTAMP. The value of each is based on a time-of-day clock reading obtained
during the running of the statement. Multiple references to CURRENT DATE,
CURRENT TIME, or CURRENT TIMESTAMP within the same SQL statement use
the same value. The following statement returns the age (in years) of each
employee in the EMPLOYEE table when the statement is run:
SELECT YEAR(CURRENT DATE - BIRTHDATE)
FROM CORPDATA.EMPLOYEE

The CURRENT TIMEZONE special register allows a local time to be converted to


Universal Coordinated Time (UTC). For example, if you have a table named
DATETIME, containing a time column type with a name of STARTT, and you want
to convert STARTT to UTC, you can use the following statement:
SELECT STARTT - CURRENT TIMEZONE
FROM DATETIME

Date/Time Arithmetic
Addition and subtraction are the only arithmetic operators applicable to date, time,
and timestamp values. You can increment and decrement a date, time, or
timestamp by a duration; or subtract a date from a date, a time from a time, or a
timestamp from a timestamp. For a detailed description of date and time arithmetic,
see Chapter 2 of the DB2 UDB for AS/400 SQL Reference book.

Chapter 3. Basic Concepts and Techniques 47


Creating and using ALIAS names
| When you refer to an existing table or view to an AS/400 physical file that consists
| of multiple members, you can avoid using file overrides by creating an alias. You
| can use the SQL CREATE ALIAS statement to do this. Or you can use Operations
| Navigator.

You can create an alias for


v A table or view
| v A member of a table

| A table alias defines a name for the file, including the specific member name. You
| can use this alias name in an SQL statement in the same way that you would use a
| table name. Unlike overrides, alias names are objects that exist until they are
| dropped.

For example, if there is a multiple member file MYLIB.MYFILE with members MBR1
and MBR2, an alias can be created for the second member so that SQL can easily
refer to it.
CREATE ALIAS MYLIB.MYMBR2_ALIAS FOR MYLIB.MYFILE (MBR2)

When alias MYLIB.MYMBR2_ALIAS is specified on the following insert statement,


the values are inserted into member MBR2 in MYLIB.MYFILE.
INSERT INTO MYLIB.MYMBR2_ALIAS VALUES('ABC', 6)

Alias names can also be specified on DDL statements. Assume that alias
MYLIB.MYALIAS exists and is an alias for table MYLIB.MYTABLE. The following
DROP statement will drop table MYLIB.MYTABLE.
DROP TABLE MYLIB.MYALIAS

If you really want to drop the alias name instead, specify the ALIAS keyword on the
drop statement:
DROP ALIAS MYLIB.MYALIAS

Using LABEL ON
Sometimes the table name, column name, view name, alias name, or SQL package
name does not clearly define data that is shown on an interactive display of the
table. By using the LABEL ON statement, you can create a more descriptive label
for the table name, column name, view name, alias name, or SQL package name.
These labels can be seen in the SQL catalog in the LABEL column.

The LABEL ON statement looks like this:


LABEL ON
TABLE CORPDATA.DEPARTMENT IS 'Department Structure Table'

LABEL ON
COLUMN CORPDATA.DEPARTMENT.ADMRDEPT IS 'Reports to Dept.'

After these statements are run, the table named DEPARTMENT displays the text
description as Department Structure Table and the column named ADMRDEPT
displays the heading Reports to Dept. The label for tables, views, SQL packages,

48 DB2 UDB for AS/400 SQL Programming V4R4


and column text cannot be more than 50 characters and the label for column
headings cannot be more than 60 characters (blanks included). The following are
examples of LABEL ON statements:

This LABEL ON statement provides column heading 1 and column heading 2.


*...+....1....+....2....+....3....+....4....+....5....+....6..*
LABEL ON COLUMN CORPDATA.EMPLOYEE.EMPNO IS
'Employee Number'

This LABEL ON statement provides 3 levels of column headings for the SALARY
column.
*...+....1....+....2....+....3....+....4....+....5....+....6..*
LABEL ON COLUMN CORPDATA.EMPLOYEE.SALARY IS
'Yearly Salary (in dollars)'

This LABEL ON statement removes the column heading for SALARY.


*...+....1....+....2....+....3....+....4....+....5....+....6..*
LABEL ON COLUMN CORPDATA.EMPLOYEE.SALARY IS ''

An example of a DBCS column heading with two levels specified.


*...+....1....+....2....+....3....+....4....+....5....+....6..*
LABEL ON COLUMN CORPDATA.EMPLOYEE.SALARY IS
'<AABBCCDD> <EEFFGG>'

This LABEL ON statement provides column text for the EDLEVEL column.
*...+....1....+....2....+....3....+....4....+....5....+....6..*
LABEL ON COLUMN CORPDATA.EMPLOYEE.EDLEVEL TEXT IS
'Number of years of formal education'

For more information about the LABEL ON statement, see the DB2 UDB for AS/400
SQL Reference book.

Using COMMENT ON
| After you create an SQL object such as a table, view, index, package, procedure,
| parameter, user-defined type, or function, you can supply information about it for
| future referral, such as the purpose of the object, who uses it, and anything unusual
| or special about it. You can also include similar information about each column of a
| table or view. Your comment must not be more than 2000 bytes.

A comment is especially useful if your names do not clearly indicate the contents of
the columns or objects. In that case, use a comment to describe the specific
contents of the column or objects.

An example of using COMMENT ON follows:


COMMENT ON TABLE CORPDATA.EMPLOYEE IS
'Employee table. Each row in this table represents
one employee of the company.'

Chapter 3. Basic Concepts and Techniques 49


Getting Comments
| After running a COMMENT ON statement for a table, your comments are stored in
| the REMARKS column of SYSTABLES. Comments for the other objects are stored
| in the REMARKS column of the appropriate catalog table. (If the indicated row had
| already contained a comment, the old comment is replaced by the new one.) The
| following example gets the comments added by the COMMENT ON statement in
| the previous example:
| SELECT REMARKS
| FROM CORPDATA.SYSTABLES
| WHERE NAME = 'EMPLOYEE'
|
Using Sort Sequence in SQL
A sort sequence defines how characters in a character set relate to each other
when they are compared or ordered. For more information on sort sequences, see
Chapter 1 in DB2 UDB for AS/400 SQL Reference book.

The sort sequence is used for all character and UCS-2 graphic comparisons
performed in SQL statements. There are sort sequence tables for both single byte
and double byte character data. Each single byte sort sequence table has an
associated double byte sort sequence table, and vice versa. Conversion between
the two tables is performed when necessary to implement a query. In addition, the
CREATE INDEX statement has the sort sequence (in effect at the time the
statement was run) applied to the character columns referred to in the index.

Sort Sequence Used with ORDER BY and Record Selection


To see how to use a sort sequence, run the examples in this section against the
STAFF table shown in Table 2. Notice that the values in the JOB column are in
mixed case. You can see the values 'Mgr', 'MGR', and 'mgr'.
Table 2. The STAFF Table
ID NAME DEPT JOB YEARS SALARY COMM
10 Sanders 20 Mgr 7 18357.50 0
20 Pernal 20 Sales 8 18171.25 612.45
30 Merenghi 38 MGR 5 17506.75 0
40 OBrien 38 Sales 6 18006.00 846.55
50 Hanes 15 Mgr 10 20659.80 0
60 Quigley 38 SALES 0 16808.30 650.25
70 Rothman 15 Sales 7 16502.83 1152.00
80 James 20 Clerk 0 13504.60 128.20
90 Koonitz 42 sales 6 18001.75 1386.70
100 Plotz 42 mgr 6 18352.80 0

In the following examples, the results are shown for each statement using:
v *HEX sort sequence
v Shared-weight sort sequence using the language identifier ENU
v Unique-weight sort sequence using the language identifier ENU

50 DB2 UDB for AS/400 SQL Programming V4R4


Note: ENU is chosen as a language identifier by specifying either
SRTSEQ(*LANGIDUNQ), or SRTSEQ(*LANGIDSHR) and LANGID(ENU), on
the CRTSQLxxx, STRSQL, or RUNSQLSTM commands, or by using the
SET OPTION statement.

ORDER BY
The following SQL statement causes the result table to be sorted using the values
in the JOB column:
SELECT * FROM STAFF ORDER BY JOB

Table 3 shows the result table using a *HEX sort sequence. The rows are sorted
based on the EBCDIC value in the JOB column. In this case, all lowercase letters
sort before the uppercase letters.
Table 3. ″SELECT * FROM STAFF ORDER BY JOB″ Using the *HEX Sort Sequence.
ID NAME DEPT JOB YEARS SALARY COMM
100 Plotz 42 mgr 6 18352.80 0
90 Koonitz 42 sales 6 18001.75 1386.70
80 James 20 Clerk 0 13504.60 128.20
10 Sanders 20 Mgr 7 18357.50 0
50 Hanes 15 Mgr 10 20659.80 0
30 Merenghi 38 MGR 5 17506.75 0
20 Pernal 20 Sales 8 18171.25 612.45
40 OBrien 38 Sales 6 18006.00 846.55
70 Rothman 15 Sales 7 16502.83 1152.00
60 Quigley 38 SALES 0 16808.30 650.25

Table 4 shows how sorting is done for a unique-weight sort sequence. After the sort
sequence is applied to the values in the JOB column, the rows are sorted. Notice
that after the sort, lowercase letters are before the same uppercase letters, and the
values 'mgr', 'Mgr', and 'MGR' are adjacent to each other.
Table 4. ″SELECT * FROM STAFF ORDER BY JOB″ Using the Unique-Weight Sort
Sequence for the ENU Language Identifier.
ID NAME DEPT JOB YEARS SALARY COMM
80 James 20 Clerk 0 13504.60 128.20
100 Plotz 42 mgr 6 18352.80 0
10 Sanders 20 Mgr 7 18357.50 0
50 Hanes 15 Mgr 10 20659.80 0
30 Merenghi 38 MGR 5 17506.75 0
90 Koonitz 42 sales 6 18001.75 1386.70
20 Pernal 20 Sales 8 18171.25 612.45
40 OBrien 38 Sales 6 18006.00 846.55
70 Rothman 15 Sales 7 16502.83 1152.00
60 Quigley 38 SALES 0 16808.30 650.25

Table 5 on page 52 shows how sorting is done for a shared-weight sort sequence.
After the sort sequence is applied to the values in the JOB column, the rows are
sorted. For the
Chapter 3. Basic Concepts and Techniques 51
sort comparison, each lowercase letter is treated the same as the corresponding
uppercase letter. In Table 5, notice that all the values 'MGR', 'mgr' and 'Mgr' are
mixed together.
Table 5. ″SELECT * FROM STAFF ORDER BY JOB″ Using the Shared-Weight Sort
Sequence for the ENU Language Identifier.
ID NAME DEPT JOB YEARS SALARY COMM
80 James 20 Clerk 0 13504.60 128.20
10 Sanders 20 Mgr 7 18357.50 0
30 Merenghi 38 MGR 5 17506.75 0
50 Hanes 15 Mgr 10 20659.80 0
100 Plotz 42 mgr 6 18352.80 0
20 Pernal 20 Sales 8 18171.25 612.45
40 OBrien 38 Sales 6 18006.00 846.55
60 Quigley 38 SALES 0 16808.30 650.25
70 Rothman 15 Sales 7 16502.83 1152.00
90 Koonitz 42 sales 6 18001.75 1386.70

Record selection
The following SQL statement selects records with the value 'MGR' in the JOB
column:
SELECT * FROM STAFF WHERE JOB='MGR'

Table 6 shows how record selection is done with a *HEX sort sequence. In Table 6,
the rows that match the record selection criteria for the column 'JOB' are selected
exactly as specified in the select statement. Only the uppercase 'MGR' is selected.
Table 6. ″SELECT * FROM STAFF WHERE JOB=’MGR’ Using the *HEX Sort Sequence.″
ID NAME DEPT JOB YEARS SALARY COMM
30 Merenghi 38 MGR 5 17506.75 0

Table 7 shows how record selection is done with a unique-weight sort sequence. In
Table 7, the lowercase and uppercase letters are treated as unique. The lowercase
'mgr' is not treated the same as uppercase 'MGR'. Therefore, the lower case 'mgr'
is not selected.
Table 7. ″SELECT * FROM STAFF WHERE JOB = ’MGR’ ″ Using Unique-Weight Sort
Sequence for the ENU Language Identifier.
ID NAME DEPT JOB YEARS SALARY COMM
30 Merenghi 38 MGR 5 17506.75 0

Table 8 shows how record selection is done with a shared-weight sort sequence. In
Table 8, the rows that match the record selection criteria for the column 'JOB' are
selected by treating uppercase letters the same as lowercase letters. Notice that in
Table 8 all the values 'mgr', 'Mgr' and 'MGR' are selected.
Table 8. ″SELECT * FROM STAFF WHERE JOB = ’MGR’ ″ Using the Shared-Weight Sort
Sequence for the ENU Language Identifier.
ID NAME DEPT JOB YEARS SALARY COMM
10 Sanders 20 Mgr 7 18357.50 0

52 DB2 UDB for AS/400 SQL Programming V4R4


Table 8. ″SELECT * FROM STAFF WHERE JOB = ’MGR’ ″ Using the Shared-Weight Sort
Sequence for the ENU Language Identifier. (continued)
ID NAME DEPT JOB YEARS SALARY COMM
30 Merenghi 38 MGR 5 17506.75 0
50 Hanes 15 Mgr 10 20659.80 0
100 Plotz 42 mgr 6 18352.80 0

Sort Sequence and Views


Views are created with the sort sequence that was in effect when the CREATE
VIEW statement was run. When the view is referred to in a FROM clause, that sort
sequence is used for any character comparisons in the subselect of the CREATE
VIEW. At that time, an intermediate result table is produced from the view
subselect. The sort sequence in effect when the query is being run is then applied
to all the character and UCS-2 graphic comparisons (including those comparisons
involving implicit conversions to character or UCS-2 graphic) specified in the query.

The following SQL statements and tables show how views and sort sequences
work. View V1, used in the following examples, was created with a shared-weight
sort sequence of SRTSEQ(*LANGIDSHR) and LANGID(ENU). The CREATE VIEW
statement would be as follows:
CREATE VIEW V1 AS SELECT *
FROM STAFF
WHERE JOB = 'MGR' AND ID < 100

Table 9 shows the result table from the view.


Table 9. ″SELECT * FROM V1″
ID NAME DEPT JOB YEARS SALARY COMM
10 Sanders 20 Mgr 7 18357.50 0
30 Merenghi 38 MGR 5 17506.75 0
50 Hanes 15 Mgr 10 20659.80 0

Any queries run against view V1 are run against the result table shown in Table 9.
The query shown below is run with a sort sequence of SRTSEQ(*LANGIDUNQ)
and LANGID(ENU).
Table 10. ″SELECT * FROM V1 WHERE JOB = ’MGR’″ Using the Unique-Weight Sort
Sequence for Language Identifier ENU
ID NAME DEPT JOB YEARS SALARY COMM
30 Merenghi 38 MGR 5 17506.75 0

Sort Sequence and the CREATE INDEX Statement


Indexes are created using the sort sequence that was in effect when the CREATE
INDEX statement was run. An entry is added to the index every time an insert is
made into the table over which the index is defined. Index entries contain the
weighted value for character key and UCS-2 graphic key columns. The system gets
the weighted value by converting the key value based on the sort sequence of the
index.

Chapter 3. Basic Concepts and Techniques 53


When selection is made using that sort sequence and that index, the character or
UCS-2 graphic keys do not need to be converted prior to comparison. This
improves the performance of the query.

Sort Sequence and Constraints


Unique constraints are implemented with indexes. If the table on which a unique
constraint is added was defined with a sort sequence, the index will be created with
that same sort sequence.

If defining a referential constraint, the sort sequence between the parent and
dependent table must match. For more information on sort sequence and
constraints, see the DB2 UDB for AS/400 Database Programming book.

The sort sequence used at the time a check constraint is defined is the same sort
sequence the system uses to validate adherence to the constraint at the time of an
INSERT or UPDATE.

54 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 4. Using a Cursor
When SQL runs a select statement, the resulting rows comprise the result table. A
cursor provides a way to access a result table. It is used within an SQL program to
maintain a position in the result table. SQL uses a cursor to work with the rows in
the result table and to make them available to your program. Your program can
have several cursors, although each must have a unique name.

Statements related to using a cursor include the following:


v A DECLARE CURSOR statement to define and name the cursor and specify the
rows to be retrieved with the embedded select statement.
v OPEN and CLOSE statements to open and close the cursor for use within the
program. The cursor must be opened before any rows can be retrieved.
v A FETCH statement to retrieve rows from the cursor’s result table or to position
the cursor on another row.
v An UPDATE ... WHERE CURRENT OF statement to update the current row of a
cursor.
v A DELETE ... WHERE CURRENT OF statement to delete the current row of a
cursor.

Types of cursors
SQL supports serial and scrollable cursors. The type of cursor determines the
positioning methods which can be used with the cursor.

Serial cursor
A serial cursor is one defined without the SCROLL keyword.

For a serial cursor, each row of the result table can be fetched only once per OPEN
of the cursor. When the cursor is opened, it is positioned before the first row in the
result table. When a FETCH is issued, the cursor is moved to the next row in the
result table. That row is then the current row. If host variables are specified (with
the INTO clause on the FETCH statement), SQL moves the current row’s contents
into your program’s host variables.

This sequence is repeated each time a FETCH statement is issued until the
end-of-data (SQLCODE = 100) is reached. When you reach the end-of-data, close
the cursor. You cannot access any rows in the result table after you reach the
end-of-data. To use the cursor again, you must first close the cursor and then
re-issue the OPEN statement. You can never back up.

Scrollable cursor
For a scrollable cursor, the rows of the result table can be fetched many times. The
cursor is moved through the result table based on the position option specified on
the FETCH statement. When the cursor is opened, it is positioned before the first
row in the result table. When a FETCH is issued, the cursor is positioned to the row
in the result table that is specified by the position option. That row is then the
current row. If host variables are specified (with the INTO clause on the FETCH

© Copyright IBM Corp. 1997, 1999 55


statement), SQL moves the current row’s contents into your program’s host
variables. Host variables cannot be specified for the BEFORE and AFTER position
options.

This sequence is repeated each time a FETCH statement is issued. The cursor
does not need to be closed when an end-of-data or beginning-of-data condition
occurs. The position options enable the program to continue fetching rows from the
table.

The following scroll options are used to position the cursor when issuing a FETCH
statement. These positions are relative to the current cursor location in the result
table.

NEXT Positions the cursor on the next row. This is the default if no
position is specified.
PRIOR Positions the cursor on the previous row.
FIRST Positions the cursor on the first row.
LAST Positions the cursor on the last row.
BEFORE Positions the cursor before the first row.
AFTER Positions the cursor after the last row.
CURRENT Does not change the cursor position.
RELATIVE n Evaluates a host variable or integer n in relationship to the
cursor’s current position. For example, if n is -1, the cursor is
positioned on the previous row of the result table. If n is +3,
the cursor is positioned three rows after the current row.

Example of Using a Cursor


Suppose your program examines data about people in department D11. The
following examples show the SQL statements you would include in a program to
define and use a serial and a scrollable cursor. These cursors can be used to
obtain information about the department from the CORPDATA.EMPLOYEE table.

For the serial cursor example, the program processes all of the rows from the table,
updating the job for all members of department D11 and deleting the records of
employees from the other departments.
Table 11. A Serial Cursor Example
Serial Cursor SQL Statement Described in Section
EXEC SQL “Step 1: Define the Cursor” on page 58.
DECLARE THISEMP CURSOR FOR
SELECT EMPNO, LASTNAME,
WORKDEPT, JOB
FROM CORPDATA.EMPLOYEE
FOR UPDATE OF JOB
END-EXEC.
EXEC SQL “Step 2: Open the Cursor” on page 59.
OPEN THISEMP
END-EXEC.
EXEC SQL “Step 3: Specify What to Do When
WHENEVER NOT FOUND End-of-Data Is Reached” on page 59.
GO TO CLOSE-THISEMP
END-EXEC.

56 DB2 UDB for AS/400 SQL Programming V4R4


Table 11. A Serial Cursor Example (continued)
Serial Cursor SQL Statement Described in Section
EXEC SQL “Step 4: Retrieve a Row Using a Cursor” on
FETCH THISEMP page 60.
INTO :EMP-NUM, :NAME2,
:DEPT, :JOB-CODE
END-EXEC.
... for all employees “Step 5a: Update the Current Row” on
in department D11, update page 61.
the JOB value:

EXEC SQL
UPDATE CORPDATA.EMPLOYEE
SET JOB = :NEW-CODE
WHERE CURRENT OF THISEMP
END-EXEC.

... then print the row.


... for other employees, “Step 5b: Delete the Current Row” on
delete the row: page 61.

EXEC SQL
DELETE FROM CORPDATA.EMPLOYEE
WHERE CURRENT OF THISEMP
END-EXEC.
Branch back to fetch and process the next
row.
CLOSE-THISEMP. “Step 6: Close the Cursor” on page 62.
EXEC SQL
CLOSE THISEMP
END-EXEC.

For the scrollable cursor example, the program uses the RELATIVE position option
to obtain a representative sample of salaries from department D11.
Table 12. Scrollable Cursor Example
Scrollable Cursor SQL Statement Described in Section
EXEC SQL “Step 1: Define the Cursor” on page 58.
DECLARE THISEMP DYNAMIC SCROLL CURSOR FOR
SELECT EMPNO, LASTNAME,
SALARY
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = ’D11’
END-EXEC.
EXEC SQL “Step 2: Open the Cursor” on page 59.
OPEN THISEMP
END-EXEC.
EXEC SQL “Step 3: Specify What to Do When
WHENEVER NOT FOUND End-of-Data Is Reached” on page 59.
GO TO CLOSE-THISEMP
END-EXEC.

Chapter 4. Using a Cursor 57


Table 12. Scrollable Cursor Example (continued)
Scrollable Cursor SQL Statement Described in Section
...initialize program summation “Step 4: Retrieve a Row Using a Cursor” on
salary variable page 60.
EXEC SQL
FETCH RELATIVE 3 FROM THISEMP
INTO :EMP-NUM, :NAME2,
:JOB-CODE
END-EXEC.
...add the current salary to
program summation salary
...branch back to fetch and
process the next row.
...calculate the average
salary
CLOSE-THISEMP. “Step 6: Close the Cursor” on page 62.
EXEC SQL
CLOSE THISEMP
END-EXEC.

Step 1: Define the Cursor


To define a result table to be accessed with a cursor, use the DECLARE CURSOR
statement.

The DECLARE CURSOR statement names a cursor and specifies a


select-statement. The select-statement defines a set of rows that, conceptually,
make up the result table. For a serial cursor, the statement looks like this (the FOR
UPDATE OF clause is optional):
EXEC SQL
DECLARE cursor-name CURSOR FOR
SELECT column-1, column-2 ,...
FROM table-name , ...
FOR UPDATE OF column-2 ,...
END-EXEC.

For a scrollable cursor, the statement looks like this (the WHERE clause is
optional):
EXEC SQL
DECLARE cursor-name DYNAMIC SCROLL CURSOR FOR
SELECT column-1, column-2 ,...
FROM table-name ,...
WHERE column-1 = expression ...
END-EXEC.

The select-statements shown here are rather simple. However, you can code
several other types of clauses in a select-statement within a DECLARE CURSOR
statement for a serial and a scrollable cursor.

If you intend to update any columns in any or all of the rows of the identified table
(the table named in the FROM clause), include the FOR UPDATE OF clause. It
names each column you intend to update. If you do not specify the names of
columns, and you specify either the ORDER BY clause or FOR READ ONLY
clause, a negative SQLCODE is returned if an update is attempted. If you do not

58 DB2 UDB for AS/400 SQL Programming V4R4


specify the FOR UPDATE OF clause, the FOR READ ONLY clause, or the ORDER
BY clause, and the result table is not read-only, you can update any of the columns
of the specified table.

You can update a column of the identified table even though it is not part of the
result table. In this case, you do not need to name the column in the SELECT
statement. When the cursor retrieves a row (using FETCH) that contains a column
value you want to update, you can use UPDATE ... WHERE CURRENT OF to
update the row.

For example, assume that each row of the result table includes the EMPNO,
LASTNAME, and WORKDEPT columns from the CORPDATA.EMPLOYEE table. If
you want to update the JOB column (one of the columns in each row of the
CORPDATA.EMPLOYEE table), the DECLARE CURSOR statement should include
FOR UPDATE OF JOB ... even though JOB is omitted from the SELECT statement.

The result table and cursor are read-only if any of the following are true:
v The first FROM clause identifies more than one table or view.
v The first FROM clause identifies a read-only view.
v The first SELECT clause specifies the keyword DISTINCT.
v The outer subselect contains a GROUP BY clause.
v The outer subselect contains a HAVING clause.
v The first SELECT clause contains a column function.
v The select-statement contains a subquery such that the base object of the outer
subselect and of the subquery is the same table.
v The select-statement contains a UNION or UNION ALL operator.
v The select-statement contains an ORDER BY clause, and the FOR UPDATE OF
clause and DYNAMIC SCROLL are not specified.
v The select-statement includes a FOR READ ONLY clause.
v The SCROLL keyword is specified without DYNAMIC.
| v The select-list includes a DataLink column and a FOR UPDATE OF clause is not
| specified.

Step 2: Open the Cursor


To begin processing the rows of the result table, issue the OPEN statement. When
your program issues the OPEN statement, SQL processes the select-statement
within the DECLARE CURSOR statement to identify a set of rows, called a result
table 3, using the current value of any host variables specified in the
select-statement. The OPEN statement looks like this:
EXEC SQL
OPEN cursor-name
END-EXEC.

Step 3: Specify What to Do When End-of-Data Is Reached


To find out when the end of the result table is reached, test the SQLCODE field for
a value of 100 or test the SQLSTATE field for a value of '02000' (that is,

3. A result table can contain zero, one, or many rows, depending on the extent to which the search condition is satisfied.

Chapter 4. Using a Cursor 59


end-of-data). This condition occurs when the FETCH statement has retrieved the
last row in the result table and your program issues a subsequent FETCH. For
example:
...
IF SQLCODE =100 GO TO DATA-NOT-FOUND.

or

IF SQLSTATE ='02000' GO TO DATA-NOT-FOUND.

An alternative to this technique is to code the WHENEVER statement. Using


WHENEVER NOT FOUND can result in a branch to another part of your program,
where a CLOSE statement is issued. The WHENEVER statement looks like this:
EXEC SQL
WHENEVER NOT FOUND GO TO symbolic-address
END-EXEC.

Your program should anticipate an end-of-data condition whenever a cursor is used


to fetch a row, and should be prepared to handle this situation when it occurs.

When you are using a serial cursor and the end-of-data is reached, every
subsequent FETCH statement returns the end-of-data condition. You cannot
position the cursor on rows that are already processed. The CLOSE statement is
the only operation that can be performed on the cursor.

When you are using a scrollable cursor and the end-of-data is reached, the result
table can still process more data. You can position the cursor anywhere in the result
table using a combination of the position options. You do not need to CLOSE the
cursor when the end-of-data is reached.

Step 4: Retrieve a Row Using a Cursor


To move the contents of a selected row into your program’s host variables, use the
FETCH statement. The SELECT statement within the DECLARE CURSOR
statement identifies rows that contain the column values your program wants.
However, SQL does not retrieve any data for your application program until the
FETCH statement is issued.

When your program issues the FETCH statement, SQL uses the current cursor
position as a starting point to locate the requested row in the result table. This
changes that row to the current row. If an INTO clause was specified, SQL moves
the current row’s contents into your program’s host variables. This sequence is
repeated each time the FETCH statement is issued.

SQL maintains the position of the current row (that is, the cursor points to the
current row) until the next FETCH statement for the cursor is issued. The UPDATE
statement does not change the position of the current row within the result table,
although the DELETE statement does.

The serial cursor FETCH statement looks like this:


EXEC SQL
FETCH cursor-name
INTO :host variable-1[, :host variable-2] ...
END-EXEC.

The scrollable cursor FETCH statement looks like this:

60 DB2 UDB for AS/400 SQL Programming V4R4


EXEC SQL
FETCH RELATIVE integer
FROM cursor-name
INTO :host variable-1[, :host variable-2] ...
END-EXEC.

Step 5a: Update the Current Row


When your program has positioned the cursor on a row, you can update its data by
using the UPDATE statement with the WHERE CURRENT OF clause. The WHERE
CURRENT OF clause specifies a cursor that points to the row you want to update.
The UPDATE ... WHERE CURRENT OF statement looks like this:
EXEC SQL
UPDATE table-name
SET column-1 = value [, column-2 = value] ...
WHERE CURRENT OF cursor-name
END-EXEC.

When used with a cursor, the UPDATE statement:


v Updates only one row—the current row
v Identifies a cursor that points to the row to be updated
v Requires that the columns updated be named previously in the FOR UPDATE
OF clause of the DECLARE CURSOR statement, if an ORDER BY clause was
also specified

After you update a row, the cursor’s position remains on that row (that is, the
current row of the cursor does not change) until you issue a FETCH statement for
the next row.

Step 5b: Delete the Current Row


When your program has retrieved the current row, you can delete the row by using
the DELETE statement. To do this, you issue a DELETE statement designed for
use with a cursor; the WHERE CURRENT OF clause specifies a cursor that points
to the row you want to delete. The DELETE ... WHERE CURRENT OF statement
looks like this:
EXEC SQL
DELETE FROM table-name
WHERE CURRENT OF cursor-name
END-EXEC.

When used with a cursor, the DELETE statement:


v Deletes only one row—the current row
v Uses the WHERE CURRENT OF clause to identify a cursor that points to the
row to be deleted

After you delete a row, you cannot update or delete another row using that cursor
until you issue a FETCH statement to position the cursor.

“The DELETE Statement” on page 34 shows you how to use the DELETE
statement to delete all rows that meet a specific search condition. You can also use
the FETCH and DELETE ... WHERE CURRENT OF statements when you want to
obtain a copy of the row, examine it, then delete it.

Chapter 4. Using a Cursor 61


Step 6: Close the Cursor
If you processed the rows of a result table for a serial cursor, and you want to use
the cursor again, issue a CLOSE statement to close the cursor prior to re-opening
it.
EXEC SQL
CLOSE cursor-name
END-EXEC.

If you processed the rows of a result table and you do not want to use the cursor
again, you can let the system close the cursor. The system automatically closes the
cursor when:
v A COMMIT without HOLD statement is issued and the cursor is not declared
using the WITH HOLD clause.
v A ROLLBACK without HOLD statement is issued.
v The job ends.
v The activation group ends and CLOSQLCSR(*ENDACTGRP) was specified on
the precompile.
v The first SQL program in the call stack ends and neither
CLOSQLCSR(*ENDJOB) or CLOSQLCSR(*ENDACTGRP) was specified when
the program was precompiled.
v The connection to the application server is ended using the DISCONNECT
statement.
v The connection to the application server was released and a successful COMMIT
occurred.
v An *RUW CONNECT occurred.
Because an open cursor still holds locks on referred-to-tables or views, you
should explicitly close any open cursors as soon as they are no longer needed.

Using the Multiple-Row FETCH Statement


The multiple-row FETCH statement can be used to retrieve multiple rows from a
table or view with a single FETCH. The program controls the blocking of rows by
the number of rows requested on the FETCH statement (OVRDBF has no effect).
The maximum number of rows that can be requested on a single fetch call is
32767. Once the data is retrieved, the cursor is positioned on the last row retrieved.

There are two ways to define the storage where fetched rows are placed: a host
structure array or a row storage area with an associated descriptor. Both methods
can be coded in all of the languages supported by the SQL precompilers, with the
exception of the host structure array in REXX. Refer to Chapter 12. Coding SQL
Statements in C and C++ Applications, through Chapter 17. Coding SQL
Statements in REXX Applications, for more information on the programming
languages. Both forms of the multiple-row FETCH statement allow the application to
code a separate indicator array. The indicator array should contain one indicator for
each host variable that is null capable.

The multiple-row FETCH statement can be used with both serial and scrollable
cursors. The operations used to define, open, and close a cursor for a multiple-row
FETCH remain the same. Only the FETCH statement changes to specify the
number of rows to retrieve and the storage where the rows are placed.

62 DB2 UDB for AS/400 SQL Programming V4R4


After each multiple-row FETCH, information is returned to the program through the
SQLCA. In addition to the SQLCODE and SQLSTATE fields, the SQLERRD
provides the following information:
v SQLERRD3 contains the number of rows retrieved on the multiple-row FETCH
statement. If SQLERRD3 is less than the number of rows requested, then an
error or end-of-data condition occurred.
v SQLERRD4 contains the length of each row retrieved.
v SQLERRD5 contains an indication that the last row in the table was fetched. It
can be used to detect the end-of-data condition in the table being fetched when
the cursor does not have immediate sensitivity to updates. Cursors which do
have immediate sensitivity to updates should continue fetching until an
SQLCODE +100 is received to detect an end-of-data condition.

Multiple-Row FETCH Using a Host Structure Array


To use the multiple-row FETCH with the host structure array, the application must
define a host structure array that can be used by SQL. Each language has its own
conventions and rules for defining a host structure array. Host structure arrays can
be defined by using variable declarations or by using compiler directives to retrieve
External File Descriptions (such as the COBOL COPY directive).

The host structure array consists of an array of structures. Each structure


corresponds to one row of the result table. The first structure in the array
corresponds to the first row, the second structure in the array corresponds to the
second row, and so on. SQL determines the attributes of elementary items in the
host structure array based on the declaration of the host structure array. To
maximize performance, the attributes of the items that make up the host structure
array should match the attributes of the columns being retrieved.

Consider the following COBOL example:

EXEC SQL INCLUDE SQLCA


END-EXEC.

...

01 TABLE-1.
02 DEPT OCCURS 10 TIMES.
05 EMPNO PIC X(6).
05 LASTNAME.
49 LASTNAME-LEN PIC S9(4) BINARY.
49 LASTNAME-TEXT PIC X(15).
05 WORKDEPT PIC X(3).
05 JOB PIC X(8).
01 TABLE-2.
02 IND-ARRAY OCCURS 10 TIMES.
05 INDS PIC S9(4) BINARY OCCURS 4 TIMES.

...
EXEC SQL
DECLARE D11 CURSOR FOR
SELECT EMPNO, LASTNAME, WORKDEPT, JOB
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = "D11"
END-EXEC.

...

EXEC SQL
OPEN D11

Chapter 4. Using a Cursor 63


END-EXEC.
PERFORM FETCH-PARA UNTIL SQLCODE NOT EQUAL TO ZERO.
ALL-DONE.
EXEC SQL CLOSE D11 END-EXEC.

...

FETCH-PARA.
EXEC SQL WHENEVER NOT FOUND GO TO ALL-DONE END-EXEC.
EXEC SQL FETCH D11 FOR 10 ROWS INTO :DEPT :IND-ARRAY
END-EXEC.

...

In this example, a cursor was defined for the CORPDATA.EMPLOYEE table to


select all rows where the WORKDEPT column equals 'D11'. The result table
contains eight rows. The DECLARE CURSOR and OPEN statements do not have
any special syntax when they are used with a multiple-row FETCH statement.
Another FETCH statement that returns a single row against the same cursor can be
coded elsewhere in the program. The multiple-row FETCH statement is used to
retrieve all of the rows in the result table. Following the FETCH, the cursor position
remains on the last row retrieved.

The host structure array DEPT and the associated indicator array IND-ARRAY are
defined in the application. Both arrays have a dimension of ten. The indicator array
has an entry for each column in the result table.

The attributes of type and length of the DEPT host structure array elementary items
match the columns that are being retrieved.

When the multiple-row FETCH statement has successfully completed, the host
structure array contains the data for all eight rows. The indicator array, IND_ARRAY,
contains zeros for every column in every row because no NULL values were
returned.

The SQLCA that is returned to the application contains the following information:
v SQLCODE contains 0
v SQLSTATE contains '00000'
v SQLERRD3 contains 8, the number of rows fetched
v SQLERRD4 contains 34, the length of each row
v SQLERRD5 contains +100, indicating the last row in the result table is in the
block

See Appendix B of the DB2 UDB for AS/400 SQL Reference book for a description
of the SQLCA.

Multiple-Row FETCH Using a Row Storage Area


The application must define a row storage area and an associated description area
before the application can use a multiple-row FETCH with a row storage area. The
row storage area is a host variable defined in the application program. The row
storage area contains the results of the multiple-row FETCH. A row storage area
can be a character variable with enough bytes to hold all of the rows requested on
the multiple-row FETCH.

64 DB2 UDB for AS/400 SQL Programming V4R4


An SQLDA that contains the SQLTYPE and SQLLEN for each returned column is
defined by the associated descriptor used on the row storage area form of the
multiple-row FETCH. The information provided in the descriptor determines the data
mapping from the database to the row storage area. To maximize performance, the
attribute information in the descriptor should match the attributes of the columns
retrieved.

See Appendix C of the DB2 UDB for AS/400 SQL Reference book for a description
of the SQLDA.

Consider the following PL/I example:

Chapter 4. Using a Cursor 65


*....+....1....+....2....+....3....+....4....+....5....+....6....+....7...*
EXEC SQL INCLUDE SQLCA;
EXEC SQL INCLUDE SQLDA;

...

DCL DEPTPTR PTR;


DCL 1 DEPT(10) BASED(DEPTPTR),
3 EMPNO CHAR(6),
3 LASTNAME CHAR(15) VARYING,
3 WORKDEPT CHAR(3),
3 JOB CHAR(8);
DCL I BIN(31) FIXED;
DEC J BIN(31) FIXED;
DCL ROWAREA CHAR(2000);

...

ALLOCATE SQLDA SET(SQLDAPTR);


EXEC SQL
DECLARE D11 CURSOR FOR
SELECT EMPNO, LASTNAME, WORKDEPT, JOB
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = 'D11';

...

EXEC SQL
OPEN D11;
/* SET UP THE DESCRIPTOR FOR THE MULTIPLE-ROW FETCH */
/* 4 COLUMNS ARE BEING FETCHED */
SQLD = 4;
SQLN = 4;
SQLDABC = 366;
SQLTYPE(1) = 452; /* FIXED LENGTH CHARACTER - */
/* NOT NULLABLE */
SQLLEN(1) = 6;
SQLTYPE(2) = 456; /*VARYING LENGTH CHARACTER */
/* NOT NULLABLE */
SQLLEN(2) = 15;
SQLTYPE(3) = 452; /* FIXED LENGTH CHARACTER - */
SQLLEN(3) = 3;
SQLTYPE(4) = 452; /* FIXED LENGTH CHARACTER - */
/* NOT NULLABLE */
SQLLEN(4) = 8;
/*ISSUE THE MULTIPLE-ROW FETCH STATEMENT TO RETRIEVE*/
/*THE DATA INTO THE DEPT ROW STORAGE AREA */
/*USE A HOST VARIABLE TO CONTAIN THE COUNT OF */
/*ROWS TO BE RETURNED ON THE MULTIPLE-ROW FETCH */

J = 10; /*REQUESTS 10 ROWS ON THE FETCH */


...

Figure 2. Example of Multiple-Row FETCH Using a Row Storage Area (Part 1 of 2)

66 DB2 UDB for AS/400 SQL Programming V4R4


EXEC SQL
WHENEVER NOT FOUND
GOTO FINISHED;
EXEC SQL
WHENEVER SQLERROR
GOTO FINISHED;
EXEC SQL
FETCH D11 FOR :J ROWS
USING DESCRIPTOR :SQLDA INTO :ROWAREA;
/* ADDRESS THE ROWS RETURNED */
DEPTPTR = ADDR(ROWAREA);
/*PROCESS EACH ROW RETURNED IN THE ROW STORAGE */
/*AREA BASED ON THE COUNT OF RECORDS RETURNED */
/*IN SQLERRD3. */
DO I = 1 TO SQLERRD(3);
IF EMPNO(I) = '000170' THEN
DO;
:
END;
END;
IF SQLERRD(5) = 100 THEN
DO;
/* PROCESS END OF FILE */
END;
FINISHED:

Figure 2. Example of Multiple-Row FETCH Using a Row Storage Area (Part 2 of 2)

In this example, a cursor has been defined for the CORPDATA.EMPLOYEE table to
select all rows where the WORKDEPT column equal 'D11'. The sample EMPLOYEE
table in Appendix A. DB2 UDB for AS/400 Sample Tables shows the result table
contains eight rows. The DECLARE CURSOR and OPEN statements do not have
special syntax when they are used with a multiple-row FETCH statement. Another
FETCH statement that returns a single row against the same cursor can be coded
elsewhere in the program. The multiple-row FETCH statement is used to retrieve all
rows in the result table. Following the FETCH, the cursor position remains on the
eighth record in the block.

The row area, ROWAREA, is defined as a character array. The data from the result
table is placed in the host variable. In this example, a pointer variable is assigned to
the address of ROWAREA. Each item in the rows that are returned is examined
and used with the based structure DEPT.

The attributes (type and length) of the items in the descriptor match the columns
that are retrieved. In this case, no indicator area is provided.

After the FETCH statement is completed, the ROWAREA contains eight rows. The
SQLCA that is returned to the application contains the following:
v SQLCODE contains 0
v SQLSTATE contains '00000'
v SQLERRD3 contains 8, the number of rows returned
v SQLERRD4 contains 34, for the length of the row fetched
v SQLERRD5 contains +100, indicating the last row in the result table was fetched

In this example, the application has taken advantage of the fact that SQLERRD5
contains an indication of the end of the file being reached. As a result, the
application does not need to call SQL again to attempt to retrieve more rows. If the

Chapter 4. Using a Cursor 67


cursor has immediate sensitivity to inserts, you should call SQL in case any records
were added. Cursors have immediate sensitivity when the commitment control level
is something other than *RR.

Unit of Work and Open Cursors


When your program completes a unit of work, it should commit or rollback the
changes you made. Unless you specified HOLD on the COMMIT or ROLLBACK
statement, all open cursors are automatically closed by SQL. Cursors that are
declared with the WITH HOLD clause are not automatically closed on COMMIT.
They are automatically closed on a ROLLBACK (the WITH HOLD clause specified
on the DECLARE CURSOR statement is ignored).

If you want to continue processing from the current cursor position after a COMMIT
or ROLLBACK, you must specify COMMIT HOLD or ROLLBACK HOLD. When
HOLD is specified, any open cursors are left open and keep their cursor position so
processing can resume. On a COMMIT statement, the cursor position is
maintained. On a ROLLBACK statement, the cursor position is restored to just after
the last row retrieved from the previous unit of work. All record locks are still
released.

After issuing a COMMIT or ROLLBACK statement without HOLD, all locks are
released and all cursors are closed. You can open the cursor again, but you will
begin processing at the first row of the result table.

Note: Specification of the ALWBLK(*ALLREAD) parameter of the CRTSQLxxx


commands can change the restoration of the cursor position for read-only
cursors. See Chapter 10. Dynamic SQL Applications for information on the
use of the ALWBLK parameter and other performance related options on the
CRTSQLxxx commands.

68 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 5. Advanced Coding Techniques
This chapter covers the more advanced SQL coding techniques. The topics
included in this chapter are:
v inserting rows
v updating rows
v preventing duplicate rows
v searching
v joining
v using UNION
v using subqueries
v using views
v using indexes
v using the system catalog

Advanced Insert Techniques


The next two sections cover two advanced techniques on how to insert rows into a
table. The first section Inserting Rows into a Table Using a Select-Statement
discusses how to insert more than one row at a time using a select statement. The
second section Using the Blocked Insert Statement discusses how to insert multiple
rows that are in a host structure array. The second method can be used with all
languages except REXX.

Inserting Rows into a Table Using a Select-Statement


You can use a select-statement within an INSERT statement to insert zero, one, or
more rows selected from the table or view you specify into another table. The table
you select the rows from can be the same table you are inserting into. If they are
the same table, SQL will create a temporary result table containing the selected
rows and then insert from the temporary table into the target table.

One use for this kind of INSERT statement is to move data into a table you created
for summary data. For example, suppose you want a table that shows each
employee’s time commitments to projects. You could create a table called
EMPTIME with the columns EMPNUMBER, PROJNUMBER, STARTDATE,
ENDDATE, and TTIME, and then use the following INSERT statement to fill the
table:
INSERT INTO CORPDATA.EMPTIME
(EMPNUMBER, PROJNUMBER, STARTDATE, ENDDATE)
SELECT EMPNO, PROJNO, EMSTDATE, EMENDATE
FROM CORPDATA.EMP_ACT

The select-statement embedded in the INSERT statement is no different from the


select-statement you use to retrieve data. With the exception of FOR READ ONLY,
FOR UPDATE OF, or the OPTIMIZE clause, you can use all the keywords, column
functions, and techniques used to retrieve data. SQL inserts all the rows that meet
the search conditions into the table you specify. Inserting rows from one table into
another table does not affect any existing rows in either the source table or the
target table.

© Copyright IBM Corp. 1997, 1999 69


Notes on Multiple-Row Insertion
You should consider the following when inserting multiple rows into a table:
v The number of columns implicitly or explicitly listed in the INSERT statement
must equal the number of columns listed in the select-statement.
v The data in the columns you are selecting must be compatible with the columns
you are inserting into when using the INSERT with select-statement.
v In the event the select-statement embedded in the INSERT returns no rows, an
SQLCODE of 100 is returned to alert you that no rows were inserted. If you
successfully insert rows, the SQLERRD(3) field of the SQLCA has an integer
representing the number of rows SQL actually inserted.
v If SQL finds an error while running the INSERT statement, SQL stops the
operation. If you specify COMMIT (*CHG), COMMIT(*CS), COMMIT (*ALL), or
COMMIT(*RR), nothing is inserted into the table and a negative SQLCODE is
returned. If you specify COMMIT(*NONE), any rows inserted prior to the error
remain in the table.
v You can join two or more tables with a select-statement in an INSERT statement.
Loaded in this manner, the table can be operated on with UPDATE, DELETE,
and INSERT statements, because the rows exist as physically stored rows in a
table.

Using the Blocked Insert Statement


A blocked INSERT can be used to insert multiple rows into a table with a single
statement. The blocked INSERT statement is supported in all of the languages
except REXX. The data inserted into the table must be in a host structure array. If
indicator variables are used with a blocked INSERT, they must also be in a host
structure array. For information on host structure arrays for a particular language,
refer to the chapter on that language.

For example, to add ten employees to the CORPDATA.EMPLOYEE table:


INSERT INTO CORPDATA.EMPLOYEE
(EMPNO,FIRSTNME,MIDINIT,LASTNAME,WORKDEPT)
10 ROWS VALUES(:DSTRUCT:ISTRUCT)

DSTRUCT is a host structure array with five elements that is declared in the
program. The five elements correspond to EMPNO, FIRSTNME, MIDINIT,
LASTNAME, and WORKDEPT. DSTRUCT has a dimension of at least ten to
accommodate inserting ten rows. ISTRUCT is a host structure array that is declared
in the program. ISTRUCT has a dimension of at least ten small integer fields for the
indicators.

Blocked INSERT statements are supported for non-distributed SQL applications and
for distributed applications where both the application server and the application
requester are AS/400 systems.

Advanced Update Techniques


The SET clause of an UPDATE statement can be used in many ways to determine
the actual values to be set in each row being updated. The following example lists
each column with its corresponding value:

70 DB2 UDB for AS/400 SQL Programming V4R4


UPDATE EMPLOYEE
SET WORKDEPT = 'D11',
PHONENO = '7213',
JOB = 'DESIGNER'
WHERE EMPNO = '000270'

The previous update can also be written by specifying all of the columns and then
all of the values:
UPDATE EMPLOYEE
SET (WORKDEPT, PHONENO, JOB)
= ('D11', '7213', 'DESIGNER')
WHERE EMPNO = '000270'

Another way to select a value (or multiple values) for an update is to use a
scalar-subselect. The scalar-subselect allows you to update one or more columns
by setting them to one or more values selected from another table. In the following
example, an employee moves to a different department but continues working on
the same projects. The employee table has already been updated to contain the
new department number. Now the project table needs to be updated to reflect the
new department number of this employee (employee number is ’000030’).
UPDATE PROJECT
SET DEPTNO =
(SELECT WORKDEPT FROM EMPLOYEE
WHERE PROJECT.RESPEMP = EMPLOYEE.EMPNO)
WHERE RESPEMP='000030'

This same technique could be used to update a list of columns with multiple values
returned from a single select.

It is also possible to update an entire row in one table with values from a row in
another table.

Suppose there is a master class schedule table that needs to be udpated with
changes that have been made in a copy of the table. The changes are made to the
work copy and merged into the master table every night. The two tables have
exactly the same columns and one column, CLASS_CODE, is a unique key
column.
UPDATE CL_SCHED
SET ROW =
(SELECT * FROM MYCOPY
WHERE CL_SCHED.CLASS_CODE = MYCOPY.CLASS_CODE)

This update will update all of the rows in CL_SCHED with the values from
MYCOPY.

Preventing Duplicate Rows


When SQL evaluates a select-statement, several rows might qualify to be in the
result table, depending on the number of rows that satisfy the select-statement’s
search condition. Some of the rows in the result table might be duplicates. You can
specify that you do not want any duplicates by using the DISTINCT keyword,
followed by the list of column names:
SELECT DISTINCT JOB, SEX
...

DISTINCT means you want to select only the unique rows. If a selected row
duplicates another row in the result table, the duplicate row is ignored (it is not put

Chapter 5. Advanced Coding Techniques 71


into the result table). For example, suppose you want a list of employee job codes.
You do not need to know which employee has what job code. Because it is
probable that several people in a department have the same job code, you can use
DISTINCT to ensure that the result table has only unique values.

The following example shows how to do this:


DECLARE XMP2 CURSOR FOR
SELECT DISTINCT JOB
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = :JOB-DEPT
...
FETCH XMP2
INTO :JOB

The result is two rows (in this example, JOB-DEPT is set to D11).

fetch JOB
1 Designer
RV2W557-2

If you do not include DISTINCT in a SELECT clause, you might find duplicate rows
in your result, because SQL retrieves the JOB column’s value for each row that
satisfies the search condition. Null values are treated as duplicate rows for
DISTINCT.

If you include DISTINCT in a SELECT clause and you also include a shared-weight
sort sequence, fewer values are returned. The sort sequence causes values that
contain the same characters to be weighted the same. If 'MGR', 'Mgr', and 'mgr'
were all in the same table, only one of these values would be returned.

Performing Complex Search Conditions


The following section explains more advanced things you can do with search
conditions.

Keywords for Use in Search Conditions


A search condition can contain any of the keywords BETWEEN, IN, IS NULL, and
LIKE.

Note: Constants are shown in the following examples to keep the examples simple.
However, you could just as easily code host variables instead. Remember to
precede each host variable with a colon.

For character and UCS-2 graphic column predicates, the sort sequence is applied
to the operands before evaluation of the predicates for BETWEEN, IN, EXISTS, and
LIKE clauses. See “Using Sort Sequence in SQL” on page 50 for more information
on the using sort sequence with selection.
v BETWEEN ... AND ... is used to specify a search condition that is satisfied by
any value that falls on or between two other values. For example, to find all
employees who were hired in 1987, you could use this:
... WHERE HIREDATE BETWEEN '1987-01-01' AND '1987-12-31'

72 DB2 UDB for AS/400 SQL Programming V4R4


The BETWEEN keyword is inclusive. A more complex, but explicit, search
condition that produces the same result is:
... WHERE HIREDATE >= '1987-01-01' AND HIREDATE <= '1987-12-31'
v IN says you are interested in rows in which the value of the specified expression
is among the values you listed. For example, to find the names of all employees
in departments A00, C01, and E21, you could specify:
... WHERE WORKDEPT IN ('A00', 'C01', 'E21')
v LIKE says you are interested in rows in which a column value is similar to the
value you supply. When you use LIKE, SQL searches for a character string
similar to the one you specify. The degree of similarity is determined by two
special characters used in the string that you include in the search condition:
_ An underline character stands for any single character.
% A percent sign stands for an unknown string of 0 or more characters. If
the percent sign starts the search string, then SQL allows 0 or more
character(s) to precede the matching value in the column. Otherwise, the
search string must begin in the first position of the column.

Note: If you are operating on MIXED data, the following distinction applies: an
SBCS underline character refers to one SBCS character. No such
restriction applies to the percent sign; that is, a percent sign refers to any
number of SBCS or DBCS characters. See the DB2 UDB for AS/400 SQL
Reference book for more information on the LIKE predicate and MIXED
data.

Use the underline character or percent sign either when you do not know or do
not care about all the characters of the column’s value. For example, to find out
which employees live in Minneapolis, you could specify:
... WHERE ADDRESS LIKE '%MINNEAPOLIS%'

In this case, you should be sure that MINNEAPOLIS was not part of a street
address or part of another city name. SQL returns any row with the string
MINNEAPOLIS in the ADDRESS column, no matter where the string occurs.

In another example, to list the towns whose names begin with 'SAN', you could
specify:
... WHERE TOWN LIKE 'SAN%'

If you want to search for a character string that contains either the underscore or
percent character, use the ESCAPE clause to specify an escape character. For
example, to see all businesses that have a percent in their name, you could
specify:
... WHERE BUSINESS_NAME LIKE '%@%%' ESCAPE '@'

The first and last percent characters are interpreted as usual. The combination
’@%’ is taken as the actual percent character.

Special Considerations for LIKE


v When host variables are used in place of string constants in a search pattern,
you should consider using varying length host variables. This allows you to:
– Assign previously used string constants to host variables without any change.
– Obtain the same selection criteria and results as if a string constant was used.
v When fixed-length host variables are used in place of string constants in a
search pattern, you should ensure the value specified in the host variable

Chapter 5. Advanced Coding Techniques 73


matches the pattern previously used by the string constants. All characters in a
host variable that are not assigned a value are initialized with a blank.
For example, if you did a search using the string pattern ’ABC%’, these are some
of the values that could be returned:
'ABCD ' 'ABCDE' 'ABCxxx' 'ABC '

For example, if you did a search using the search pattern ’ABC%’ contained in a
host variable with a fixed length of 10, these are some the values that could be
returned assuming the column has a length of 12:
'ABCDE ' 'ABCD ' 'ABCxxx ' 'ABC '

Note that all returned values start with ’ABC’ and end with at least six blanks.
This is because the last six characters in the host variable were not assigned a
specific value so blanks were used.

If you wanted to do a search on a fixed-length host variable where the last 7


characters could be anything, you would search for ’ABC%%%%%%%’. These
are some values that could be returned:
'ABCDEFGHIJ' 'ABCXXXXXXX' 'ABCDE' 'ABCDD'

Multiple Search Conditions within a WHERE Clause


You saw how to qualify a request using one search condition. You can qualify your
request further by coding a search condition that includes several predicates. The
search condition you specify can contain any of the comparison operators or the
keywords BETWEEN, IN, LIKE, IS NULL, and IS NOT NULL.

You can join any two predicates with the connectors AND and OR. In addition, you
can use the NOT keyword to specify that the desired search condition is the
negated value of the specified search condition. A WHERE clause can have as
many predicates as you want.
v AND says that, for a row to qualify, the row must satisfy both predicates of the
search condition. For example, to find out which employees in department D21
were hired after December 31, 1987, you would specify:
...
WHERE WORKDEPT = 'D21' AND HIREDATE > '1987-12-31'
v OR says that, for a row to qualify, the row can satisfy the condition set by either
or both predicates of the search condition. For example, to find out which
employees are in either department C01 or D11, you could specify 4:
...
WHERE WORKDEPT = 'C01' OR WORKDEPT = 'D11'
v NOT says that, to qualify, a row must not meet the criteria set by the search
condition or predicate that follows the NOT. For example, to find all employees in
department E11 except those with a job code equal to analyst, you could specify:
...
WHERE WORKDEPT = 'E11' AND NOT JOB = 'ANALYST'

When SQL evaluates search conditions that contain these connectors, it does so in
a specific order. SQL first evaluates the NOT clauses, next evaluates the AND
clauses, and then the OR clauses.

4. You could also use IN to specify this request: WHERE WORKDEPT IN ('C01', 'D11').

74 DB2 UDB for AS/400 SQL Programming V4R4


You can change the order of evaluation by using parentheses. The search
conditions enclosed in parentheses are evaluated first. For example, to select all
employees in departments E11 and E21 who have education levels greater than 12,
you could specify:
...
WHERE EDLEVEL > 12 AND
(WORKDEPT = 'E11' OR WORKDEPT = 'E21')

The parentheses determine the meaning of the search condition. In this example,
you want all rows that have a:
WORKDEPT value of E11 or E21, and
EDLEVEL value greater than 12

If you did not use parentheses:


...
WHERE EDLEVEL > 12 AND WORKDEPT = 'E11'
OR WORKDEPT = 'E21'

Your result is different. The selected rows are rows that have:
WORKDEPT = E11 and EDLEVEL > 12, or
WORKDEPT = E21, regardless of the EDLEVEL value

Joining Data from More Than One Table


Sometimes the information you want to see is not in a single table. To form a row of
the result table, you might want to retrieve some column values from one table and
some column values from another table. You can retrieve and join column values
from two or more tables into a single row.

Four different types of joins are supported by DB2 UDB for AS/400: inner join, left
outer join, exception join, and cross join.
v An “Inner Join” returns only the rows from each table that have matching values
in the join columns. Any rows that do not have a match between the tables will
not appear in the result table.
v A “Left Outer Join” on page 76 returns values for all of the rows from the first
table (the table on the left) and the values from the second table for the rows that
match. Any rows that do not have a match in the second table will return the null
value for all columns from the second table.
v An “Exception Join” on page 77 returns only the rows from the left table that do
not have a match in the right table. Columns in the result table that come from
the right table have the null value.
v A “Cross Join” on page 78 returns a row in the result table for each combination
of rows from the tables being joined (a Cartesian Product).

Inner Join
With an inner join, column values from one row of a table are combined with
column values from another row of another (or the same) table to form a single row
of data. SQL examines both tables specified for the join to retrieve data from all the
rows that meet the search condition for the join. There are two ways of specifying
an inner join: using the JOIN syntax, and using the WHERE clause.

Chapter 5. Advanced Coding Techniques 75


Suppose you want to retrieve the employee numbers, names, and project numbers
for all employees that are responsible for a project. In other words, you want the
EMPNO and LASTNAME columns from the CORPDATA.EMPLOYEE table and the
PROJNO column from the CORPDATA.PROJECT table. Only employees with last
names starting with ’S’ or later should be considered. To find this information, you
need to join the two tables.

Inner Join Using JOIN Syntax


To use the inner join syntax, both of the tables you are joining are listed in the
FROM clause, along with the join condition that applies to the tables. The join
condition is specified after the ON keyword and determines how the two tables are
to be compared to each other to produce the join result. The condition can be any
comparison operator; it does not need to be the equal operator. Multiple join
conditions can be specified in the ON clause separated by the AND keyword. Any
additional conditions that do not relate to the actual join are specified in either the
WHERE clause or as part of the actual join in the ON clause.
SELECT EMPNO, LASTNAME, PROJNO
FROM CORPDATA.EMPLOYEE INNER JOIN CORPDATA.PROJECT
ON EMPNO = RESPEMP
WHERE LASTNAME > 'S'

In this example, the join is done on the two tables using the EMPNO and
RESPEMP columns from the tables. Since only employees that have last names
starting with at least ’S’ are to be returned, this additional condition is provided in
the WHERE clause.

This query returns the following output:

EMPNO LASTNAME PROJNO


000020 THOMPSON PL2100
000060 STERN MA2110
000100 SPENSER OP2010
000250 SMITH AD3112

Inner Join Using the WHERE Clause


Using the WHERE clause to perform this same join is written with both the join
condition and the additional selection condition in the WHERE clause. The tables to
be joined are listed in the FROM clause, separated by commas.
SELECT EMPNO, LASTNAME, PROJNO
FROM CORPDATA.EMPLOYEE, CORPDATA.PROJECT
WHERE EMPNO = RESPEMP
AND LASTNAME > 'S'

This query returns the same output as the previous example.

Left Outer Join


A left outer join will return all the rows that an inner join returns plus one row for
each of the other rows in the first table that did not have a match in the second
table.

Suppose you want to find all employees and the projects they are currently
responsible for. You want to see those employees that are not currently in charge of

76 DB2 UDB for AS/400 SQL Programming V4R4


a project as well. The following query will return a list of all employees whose
names are greater than ’S’, along with their assigned project numbers.
SELECT EMPNO, LASTNAME, PROJNO
FROM CORPDATA.EMPLOYEE LEFT OUTER JOIN CORPDATA.PROJECT
ON EMPNO = RESPEMP
WHERE LASTNAME > 'S'

The result of this query contains some employees that do not have a project
number. They are listed in the query, but have the null value returned for their
project number.

EMPNO LASTNAME PROJNO


000020 THOMPSON PL2100
000060 STERN MA2110
000100 SPENSER OP2010
000170 YOSHIMURA -
000180 SCOUTTEN -
000190 WALKER -
000250 SMITH AD3112
000280 SCHNEIDER -
000300 SMITH -
000310 SETRIGHT -

Notes
Using the RRN scalar function to return the relative record number for a column in
the table on the right in a left outer join or exception join will return a value of 0 for
the unmatched rows.

Exception Join
An exception join returns only the records from the first table that do NOT have a
match in the second table. Using the same tables as before, return those
employees that are not responsible for any projects.
SELECT EMPNO, LASTNAME, PROJNO
FROM CORPDATA.EMPLOYEE EXCEPTION JOIN CORPDATA.PROJECT
ON EMPNO = RESPEMP
WHERE LASTNAME > 'S'

This join returns the output:

EMPNO LASTNAME PROJNO


000170 YOSHIMURA -
000180 SCOUTTEN -
000190 WALKER -
000280 SCHNEIDER -
000300 SMITH -
000310 SETRIGHT -

An exception join can also be written as a subquery using the NOT EXISTS
predicate. The previous query could be rewritten in the following way:

Chapter 5. Advanced Coding Techniques 77


SELECT EMPNO, LASTNAME
FROM CORPDATA.EMPLOYEE
WHERE LASTNAME > 'S'
AND NOT EXISTS
(SELECT * FROM CORPDATA.PROJECT
WHERE EMPNO = RESPEMP)

The only difference in this query is that it cannot return values from the PROJECT
table.

Cross Join
A cross join (or Cartesian Product join) will return a result table where each row
from the first table is combined with each row from the second table. The number of
rows in the result table is the product of the number of rows in each table. If the
tables involved are large, this join can take a very long time.

A cross join can be specified in two ways: using the JOIN syntax or by listing the
tables in the FROM clause separated by commas without using a WHERE clause
to supply join criteria.

Suppose the following tables exist.


Table 13. Table A
T1COL1 T1COL2
A1 AA1
A2 AA2
A3 AA3

Table 14. Table B


T2COL1 T2COL2
B1 BB1
B2 BB2

The following two select statements produce identical results.


SELECT * FROM A CROSS JOIN B
SELECT * FROM A, B

The result table for either of these select statements looks like this:

T1COL1 T1COL2 T2COL1 T2COL2


A1 AA1 B1 BB1
A1 AA1 B2 BB2
A2 AA2 B1 BB1
A2 AA2 B2 BB2
A3 AA3 B1 BB1
A3 AA3 B2 BB2

Using multiple join types in one statement


There are times when more than two tables need to be joined to produce the
desired result. If you wanted to return all the employees, their department name,
and the project they are responsible for, if any, the EMPLOYEE table,

78 DB2 UDB for AS/400 SQL Programming V4R4


DEPARTMENT table, and PROJECT table would all need to be joined to get the
information. The following example shows the query and the results.
SELECT EMPNO, LASTNAME, DEPTNAME, PROJNO
FROM CORPDATA.EMPLOYEE INNER JOIN CORPDATA.DEPARTMENT
ON WORKDEPT = DEPTNO
LEFT OUTER JOIN CORPDATA.PROJECT
ON EMPNO = RESPEMP
WHERE LASTNAME > 'S'

EMPNO LASTNAME DEPTNAME PROJNO


000020 THOMPSON PLANNING PL2100
000060 STERN MANUFACTURING SYSTEMS MA2110
000100 SPENSER SOFTWARE SUPPORT OP2010
000170 YOSHIMURA MANUFACTURING SYSTEMS -
000180 SCOUTTEN MANUFACTURING SYSTEMS -
000190 WALKER MANUFACTURING SYSTEMS -
000250 SMITH ADMINISTRATION SYSTEMS AD3112
000280 SCHNEIDER OPERATIONS -
000300 SMITH OPERATIONS -
000310 SETRIGHT OPERATIONS -

Notes on Joins
When you join two or more tables:
v If there are common column names, you must qualify each common name with
the name of the table (or a correlation name). Column names that are unique do
not need to be qualified.
v If you do not list the column names you want, but instead use SELECT *, SQL
returns rows that consist of all the columns of the first table, followed by all the
columns of the second table, and so on.
v You must be authorized to select rows from each table or view specified in the
FROM clause.
v The sort sequence is applied to all character and UCS-2 graphic columns being
joined.
|
| Using Table Expressions
| You can use table expressions to specify an intermediate result table. They can be
| used in place of a view to avoid creating the view when general use of the view is
| not required. Table expressions consist of nested table expressions and common
| table expressions.

| Nested table expressions are specified within parentheses in the FROM clause. For
| example, suppose you want a result table that shows the manager number,
| department number, and maximum salary for each department. The manager
| number is in the DEPARTMENT table, the department number is in both the
| DEPARTMENT and EMPLOYEE tables, and the salaries are in the EMPLOYEE
| table. You can use a table expression in the from clause to select the maximum
| salary for each department. You add a correlation name, T2, following the nested
| table expression to name the derived table. The outer select then uses T2 to qualify
| columns that are selected from the derived table, in this case MAXSAL and

Chapter 5. Advanced Coding Techniques 79


| WORKDEPT. Note that the MAX(SALARY) column selected in the nested table
| expression must be named in order to be referenced in the outer select. The AS
| clause is used to do that.
| SELECT MGRNO, T1.DEPTNO, MAXSAL
| FROM CORPDATA.DEPARTMENT T1,
| (SELECT MAX(SALARY) AS MAXSAL, WORKDEPT
| FROM CORPDATA.EMPLOYEE E1
| GROUP BY WORKDEPT) T2
| WHERE T1.DEPTNO = T2.WORKDEPT
| ORDER BY DEPTNO

| The result of the query is:


| MGRNO DEPTNO MAXSAL
| 000010 A00 52,750.00
| 000020 B01 41,250.00
| 000030 C01 38,250.00
| 000060 D11 32,250.00
| 000070 D21 36,170.00
| 000050 E01 40,175.00
| 000090 E11 29,750.00
| 000100 E21 26,150.00

| Common table expressions can be specified prior to the full-select in a SELECT


| statement, an INSERT statement, or a CREATE VIEW statement. They can be
| used when the same result table needs to be shared in a full-select. Common table
| expressions are preceeded with the keyword WITH.

| For example, suppose you want a table that shows the minimum and maximum of
| the average salary of a certain set of departments. The first character of the
| department number has some meaning and you want to get the minimum and
| maximum for those departments that start with the letter ’D’ and those that start
| with the letter ’E’. You can use a common table expression to select the average
| salary for each department. Again, you must name the derived table; in this case,
| the name is DT. You can then specify a SELECT statement using a WHERE clause
| to restrict the selection to only the departments that begin with a certain letter.
| Specify the minimum and maximum of column AVGSAL from the derived table DT.
| Specify a UNION to get the results for the letter ’E’ and the results for the letter ’D’.
| WITH DT AS (SELECT E.WORKDEPT AS DEPTNO, AVG(SALARY) AS AVGSAL
| FROM CORPDATA.DEPARTMENT D , CORPDATA.EMPLOYEE E
| WHERE D.DEPTNO = E.WORKDEPT
| GROUP BY E.WORKDEPT)
| SELECT 'E', MAX(AVGSAL), MIN(AVGSAL) FROM DT
| WHERE DEPTNO LIKE 'E%'
| UNION
| SELECT 'D', MAX(AVGSAL), MIN(AVGSAL) FROM DT
| WHERE DEPTNO LIKE 'D%'

| The result of the query is:


| MAX ( AVGSAL ) MIN ( AVGSAL )
| E 40,175.00 20,998.00
| D 25,153.33 24,677.77
|
Using the UNION Keyword to Combine Subselects
Using the UNION keyword, you can combine two or more subselects to form a
single select-statement. When SQL encounters the UNION keyword, it processes
each subselect to form an interim result table, then it combines the interim result
table of each subselect and deletes duplicate rows to form a combined result table.

80 DB2 UDB for AS/400 SQL Programming V4R4


You use UNION to merge lists of values from two or more tables. You can use any
of the clauses and techniques you have learned so far when coding
select-statements, including ORDER BY.

You can use UNION to eliminate duplicates when merging lists of values obtained
from several tables. For example, you can obtain a combined list of employee
numbers that includes:
v People in department D11
v People whose assignments include projects MA2112, MA2113, and AD3111

The combined list is derived from two tables and contains no duplicates. To do this,
specify:
MOVE 'D11' TO WORK-DEPT.
...
EXEC SQL
DECLARE XMP6 CURSOR FOR
SELECT EMPNO
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = :WORK-DEPT
UNION
SELECT EMPNO
FROM CORPDATA.EMP_ACT
WHERE PROJNO = 'MA2112' OR
PROJNO = 'MA2113' OR
PROJNO = 'AD3111'
ORDER BY EMPNO
END-EXEC.
...
EXEC SQL
FETCH XMP6
INTO :EMP-NUMBER
END-EXEC.

To better understand what results from these SQL statements, imagine that SQL
goes through the following process:

Chapter 5. Advanced Coding Techniques 81


Step 1: SQL processes the Which results in an interim
first SELECT statement: result table:
(from CORPDATA.EMPLOYEE)
000060
000150
000160
000170
...

Step 2: SQL processes the Which results in another


second SELECT statement: interim result table:

(from CORPDATA.EMP ACT)


000230
000230
000230
...

Which results in a combined


Step 3: SQL combines the result table with values in
two interim result tables: ascending sequence:

fetch EMP-NUMBER
1 000060
2 000150
3 000160
4 000170
5 000180
... ...

RV3W186-0

When you use UNION:


v Any ORDER BY clause must appear after the last subselect that is part of the
union. In this example, the results are sequenced on the basis of the first
selected column, EMPNO. The ORDER BY clause specifies that the combined
result table is to be in collated sequence.
v A name may be specified on the ORDER BY clause if the result columns are
named. A result column is named if the corresponding columns in each of the
unioned select-statements have the same name. An AS clause can be used to
assign a name to columns in the select list.
SELECT A + B AS X ...
UNION SELECT X ... ORDER BY X

If the result columns are unnamed, use numbers to order the result. The number
refers to the position of the expression in the list of expressions you include in
your subselects.
SELECT A + B ...
UNION SELECT X ... ORDER BY 1

You cannot use UNION when creating a view.

82 DB2 UDB for AS/400 SQL Programming V4R4


To identify which subselect each row is from, you can include a constant at the end
of the select list of each subselect in the union. When SQL returns your results, the
last column contains the constant for the subselect that is the source of that row.
For example, you can specify:
SELECT A, B, 'A1' ... UNION SELECT X, Y, 'B2'

When a row is presented to your program, it includes a value (either A1 or B2) to


indicate the table that is the source of the row’s values. If the column names in the
union are different, SQL uses the set of column names specified in the first
subselect when interactive SQL displays or prints the results, or in the SQLDA
resulting from processing an SQL DESCRIBE statement.

For information on compatibility of the length and data type for columns in a
UNION, see chapter 4 of the DB2 UDB for AS/400 SQL Reference book.

Note: Sort sequence is applied after the fields across the UNION pieces are made
compatible. The sort sequence is used for the distinct processing that
implicitly occurs during UNION processing.

Specifying UNION ALL


If you want to keep duplicates in the result of a UNION, specify UNION ALL instead
of just UNION.

Step 3. SQL combines two Resulting in a result table that


interim result tables: includes duplicates:

fetch EMP-NUMBER
1 000060
2 000150
3 000150
4 000150
5 000160
6 000160
7 000170
8 000170
... ...

RV3W187-0

v The UNION ALL operation is associative, for example:


(SELECT PROJNO FROM CORPDATA.PROJECT
UNION ALL
SELECT PROJNO FROM CORPDATA.PROJECT)
UNION ALL
SELECT PROJNO FROM CORPDATA.EMP_ACT

gives the same result as:


SELECT PROJNO FROM CORPDATA.PROJECT
UNION ALL
(SELECT PROJNO FROM CORPDATA.PROJECT
UNION ALL
SELECT PROJNO FROM CORPDATA.EMP_ACT)
v When you include the UNION ALL in the same SQL statement as a UNION
operator, however, the result of the operation depends on the order of evaluation.

Chapter 5. Advanced Coding Techniques 83


Where there are no parentheses, evaluation is from left to right. Where
parentheses are included, the parenthesized subselect is evaluated first,
followed, from left to right, by the other parts of the statement.

Using Subqueries
In the WHERE and HAVING clauses you have seen so far, you specified a search
condition by using a literal value, a column name, an expression, or the registers. In
those search conditions, you know that you are searching for a specific value, but
sometimes you cannot supply that value until you have retrieved other data from a
table. For example, suppose you want a list of the employee numbers, names, and
job codes of all employees working on a particular project, say project number
MA2100. The first part of the statement is easy to write:
DECLARE XMP CURSOR FOR
SELECT EMPNO, LASTNAME, JOB
FROM CORPDATA.EMPLOYEE
WHERE EMPNO ...

But you cannot go further because the CORPDATA.EMPLOYEE table does not
include project number data. You do not know which employees are working on
project MA2100 without issuing another SELECT statement against the
CORPDATA.EMP_ACT table.

With SQL, you can nest one SELECT statement within another to solve this
problem. The inner SELECT statement is called a subquery. The SELECT
statement surrounding the subquery is called the outer-level SELECT. Using a
subquery, you could issue just one SQL statement to retrieve the employee
numbers, names, and job codes for employees who work on project MA2100:
DECLARE XMP CURSOR FOR
SELECT EMPNO, LASTNAME, JOB
FROM CORPDATA.EMPLOYEE
WHERE EMPNO IN
(SELECT EMPNO
FROM CORPDATA.EMP_ACT
WHERE PROJNO = 'MA2100')

To better understand what will result from this SQL statement, imagine that SQL
goes through the following process:

84 DB2 UDB for AS/400 SQL Programming V4R4


Step 1: SQL evaluates the Which results in an interim
subquery to obtain a list results table:
of EMPNO values:

(from CORPDATA.EMP ACT)

000010
000110

Step 2: The interim results The final result table looks like this:
table then serves as a list
in the search condition of
the outer-level SELECT.
Essentially, this is what is
executed.

fetch EMPNO LASTNAME JOB


1 000010 HAAS PRES
2 000110 LUCCHESSI SALESREP

RV2W559-2

Correlation
The purpose of a subquery is to supply information needed to qualify a row
(WHERE clause) or a group of rows (HAVING clause). This is done through the
result table that the subquery produces. Conceptually, the subquery is evaluated
whenever a new row or group of rows must be qualified. In fact, if the subquery is
the same for every row or group, it is evaluated only once. For example, the
previous subquery has the same content for every row of the table
CORPDATA.EMPLOYEE. Subqueries like this are said to be uncorrelated.

Some subqueries vary in content from row to row or group to group. The
mechanism that allows this is called correlation, and the subqueries are said to be
correlated. More information on correlated subqueries can be found in “Correlated
Subqueries” on page 88. Even so, what is said before that point applies equally to
correlated and uncorrelated subqueries.

Subqueries and Search Conditions


A subquery is always part of a search condition. The search condition is in the form
operand operator (subquery). In the example, the operand is EMPNO and
operator is IN. The search condition can be part of a WHERE or HAVING clause.
The clause can include more than one search condition that contains a subquery. A
search condition containing a subquery, like any other search condition, can be
enclosed in parentheses, can be preceded by the keyword NOT, and can be linked

Chapter 5. Advanced Coding Techniques 85


to other search conditions through the keywords AND and OR. For example, the
WHERE clause of some query could look something like this:
WHERE X IN (subquery1) AND (Y > SOME (subquery2) OR Z = 100)

Subqueries can also appear in the search conditions of other subqueries. Such
subqueries are said to be nested at some level of nesting. For example, a
subquery within a subquery within an outer-level SELECT is nested at a nesting
level of two. SQL allows nesting down to a nesting level of 32, but few queries
require a nesting level greater than 1.

How Subqueries Are Used


There are four ways to include a subquery in either a WHERE or HAVING clause:

Basic Comparisons
You can use a subquery immediately after any of the comparison operators. If you
do, the subquery can return at most one value. The value can be the result of a
column function or an arithmetic expression. SQL then compares the value that
results from the subquery with the value to the left of the comparison operator. For
example, suppose you want to find the employee numbers, names, and salaries for
employees whose education level is higher than the average education level
throughout the company.
DECLARE XMP CURSOR FOR
SELECT EMPNO, LASTNAME, SALARY
FROM CORPDATA.EMPLOYEE
WHERE EDLEVEL >
(SELECT AVG(EDLEVEL)
FROM CORPDATA.EMPLOYEE)

SQL first evaluates the subquery and then substitutes the result in the WHERE
clause of the SELECT statement. In this example, the result is (as it should be) the
company-wide average educational level. Besides returning a single value, a
subquery could return no value at all. If it does, the result of the compare is
unknown. Consider, for example, the first query shown in this section, and assume
that there are not any employees currently working on project MA2100. Then the
subquery would return no value, and the search condition would be unknown for
every row. In this case, then, the result produced by the query would be an empty
table.

Quantified Comparisons (ALL, ANY, and SOME)


You can use a subquery after a comparison operator followed by the keyword ALL,
ANY, or SOME. When used in this way, the subquery can return zero, one, or many
values, including null values. You can use ALL, ANY, and SOME in the following
ways:
v Use ALL to indicate that the value you supplied must compare in the indicated
way to ALL the values the subquery returns. For example, suppose you use the
greater-than comparison operator with ALL:
... WHERE expression > ALL (subquery)

To satisfy this WHERE clause, the value in the expression must be greater than
all the values (that is, greater than the highest value) returned by the subquery. If
the subquery returns an empty set (that is, no values were selected), the
condition is satisfied.

86 DB2 UDB for AS/400 SQL Programming V4R4


v Use ANY or SOME to indicate that the value you supplied must compare in the
indicated way to at least one of the values the subquery returns. For example,
suppose you use the greater-than comparison operator with ANY:
... WHERE expression > ANY (subquery)

To satisfy this WHERE clause, the value in the expression must be greater than
at least one of the values (that is, greater than the lowest value) returned by the
subquery. If what the subquery returns is empty, the condition is not satisfied.

Note: The results when a subquery returns one or more null values may surprise
you, unless you are familiar with formal logic. For applicable rules, read the
discussion of quantified predicates in the DB2 UDB for AS/400 SQL
Reference .

Using the IN Keyword


You can use IN to say that the value in the expression must be among the values
returned by the subquery. The first example in this chapter illustrates this type of
usage. Using IN is equivalent to using =ANY or =SOME. Using ANY and SOME
were previously described. You could also use the IN keyword with the NOT
keyword in order to select rows when the value is not among the values returned by
the subquery. For example, you could use:
... WHERE WORKDEPT NOT IN (SELECT ...)

Using the EXISTS Keyword


In the subqueries presented so far, SQL evaluates the subquery and uses the result
as part of the WHERE clause of the outer-level SELECT. In contrast, when you use
the keyword EXISTS, SQL simply checks whether the subquery returns one or
more rows. If it does, the condition is satisfied. If it does not (if it returns no rows),
the condition is not satisfied. For example:
DECLARE XMP CURSOR FOR
SELECT EMPNO,LASTNAME
FROM CORPDATA.EMPLOYEE
WHERE EXISTS
(SELECT *
FROM CORPDATA.PROJECT
WHERE PRSTDATE > '1982-01-01');

In the example, the search condition holds if any project represented in the
CORPDATA.PROJECT table has an estimated start date that is later than January
1, 1982. Please note that this example does not show the full power of EXISTS,
because the result is always the same for every row examined for the outer-level
SELECT. As a consequence, either every row appears in the results, or none
appear. In a more powerful example, the subquery itself would be correlated, and
would change from row to row. See “Correlated Subqueries” on page 88 for more
information on correlated subqueries.

As shown in the example, you do not need to specify column names in the
subquery of an EXISTS clause. Instead, you can code SELECT *.

You could also use the EXISTS keyword with the NOT keyword in order to select
rows when the data or condition you specify does not exist. That is, you could use:
... WHERE NOT EXISTS (SELECT ...)

For all general types of usage for subqueries but one (using a subquery with the
EXISTS keyword), the subquery must produce a one-column result table. This

Chapter 5. Advanced Coding Techniques 87


means that the SELECT clause in a subquery must name a single column, or
contain a single expression. For example, both of the following SELECT clauses
would be allowed for all four usage types:
SELECT AVG(SALARY)
SELECT EMPNO

The result table produced by a subquery can have zero or more rows. For some
usages, no more than one row is allowed.

Using Subqueries with UPDATE and DELETE


In the examples shown so far, you have seen subqueries within SELECT
statements. You can also use subqueries in the WHERE clause of the UPDATE or
DELETE statements or in the SET clause of an UPDATE. For the most part, this is
not very different from using subqueries with outer-level SELECTs.

Notes on Using Subqueries


| 1. When nesting SELECT statements, you can use as many as you need to satisfy
| your requirements (1 to 31 subqueries), although performance is slower for
| each additional subquery. A maximum of 128 tables can be specified in an SQL
| statement.
2. When the outer statement is a SELECT statement (at any level of nesting):
v The subquery can be based on the same table or view as the outer
statement, or on a different table or view.
v You can use a subquery in the WHERE clause of the outer-level SELECT,
even when the outer-level SELECT is part of a DECLARE CURSOR,
CREATE VIEW, or INSERT statement.
v You can use a subquery in the HAVING clause of a SELECT statement.
When you do, SQL evaluates the subquery and uses it to qualify each group.
3. When the statement is an UPDATE or DELETE statement, you can use
subqueries in the WHERE clause of the UPDATE or DELETE statement.
4. When a subquery is used in the SET clause of an UPDATE statement, the
result table of a subselect must contain the same number of values as the
corresponding list of columns to be updated. In all other cases, the result table
for a subquery must consist of a single column, unless the subquery is being
used with the EXISTS keyword. The number of rows in this table can vary from
zero to many, but for comparisons not involving the keywords ALL, ANY, or
SOME, the number of rows must be zero or one.
5. A subquery cannot include the ORDER BY, UNION, UNION ALL, FOR READ
ONLY, UPDATE, or OPTIMIZE clauses.
6. In any subquery, as in any search condition, the values compared must be
compatible.
7. Using a column function or an arithmetic expression with a column name in a
subquery does not make it incompatible. The data type of the column does not
change after SQL applies a column function or arithmetic operator.

Correlated Subqueries
In the subqueries previously discussed, SQL evaluates the subquery once,
substitutes the result of the subquery in the right side of the search condition, and
evaluates the outer-level SELECT based on the value of the search condition. You
can also write a subquery that SQL may have to re-evaluate as it examines each

88 DB2 UDB for AS/400 SQL Programming V4R4


new row (WHERE clause) or group of rows (HAVING clause) in the outer-level
SELECT. This is called a correlated subquery.

Example of a Correlated Subquery in a WHERE Clause


Suppose that you want a list of all the employees whose education levels are
higher than the average education levels in their respective departments. To get this
information, SQL must search the CORPDATA.EMPLOYEE table. For each
employee in the table, SQL needs to compare the employee’s education level to the
average education level for the employee’s department. In the subquery, you tell
SQL to calculate the average education level for the department number in the
current row. For example:
DECLARE XMP CURSOR FOR
SELECT EMPNO, LASTNAME, WORKDEPT, EDLEVEL
FROM CORPDATA.EMPLOYEE X
WHERE EDLEVEL >
(SELECT AVG(EDLEVEL)
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = X.WORKDEPT)

A correlated subquery looks like an uncorrelated one, except for the presence of
one or more correlated references. In the example, the single correlated reference
is the occurrence of X.WORKDEPT in the subselect’s FROM clause. Here, the
qualifier X is the correlation name defined in the FROM clause of the outer SELECT
statement. In that clause, X is introduced as the correlation name of the table
CORPDATA.EMPLOYEE.

Now, consider what happens when the subquery is executed for a given row of
CORPDATA.EMPLOYEE. Before it is executed, the occurrence of X.WORKDEPT is
replaced with the value of the WORKDEPT column for that row. Suppose, for
example, that the row is for CHRISTINE I HAAS. Her work department is A00,
which is the value of WORKDEPT for this row. The subquery executed for this row
is:
(SELECT AVG(EDLEVEL)
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = 'A00')

Thus, for the row considered, the subquery produces the average education level of
Christine’s department. This is then compared in the outer statement to Christine’s
own education level. For some other row for which WORKDEPT has a different
value, that value appears in the subquery in place of A00. For example, for the row
for MICHAEL L THOMPSON, this value would be B01, and the subquery for his row
would deliver the average education level for department B01.

The result table produced by the query would have the following values:

Chapter 5. Advanced Coding Techniques 89


(from CORPDATA.EMPLOYEE)

fetch EMPNO LASTNAME WORKDEPT EDLEVEL

1 000010 HAAS A00 18


2 000030 KWAN C01 20
3 000070 PULASKI D21 16
4 000090 HENDERSON E11 16

RV2W560-3

Example of a Correlated Subquery in a HAVING Clause


Suppose that you want a list of all the departments whose average salary is higher
than the average salary of their area (all departments whose WORKDEPT begins
with the same letter belong to the same area). To get this information, SQL must
search the CORPDATA.EMPLOYEE table. For each department in the table, SQL
compares the department’s average salary to the average salary of the area. In the
subquery, SQL calculates the average salary for the area of the department in the
current group. For example:
DECLARE XMP CURSOR FOR
SELECT WORKDEPT, DECIMAL(AVG(SALARY),8,2)
FROM CORPDATA.EMPLOYEE X
GROUP BY WORKDEPT
HAVING AVG(SALARY) >
(SELECT AVG(SALARY)
FROM CORPDATA.EMPLOYEE
WHERE SUBSTR(X.WORKDEPT,1,1) = SUBSTR(WORKDEPT,1,1))

Consider what happens when the subquery is executed for a given department of
CORPDATA.EMPLOYEE. Before it is executed, the occurrence of X.WORKDEPT is
replaced with the value of the WORKDEPT column for that group. Suppose, for
example, that the first group selected has A00 for the value of WORKDEPT. The
subquery executed for this group is:
(SELECT AVG(SALARY)
FROM CORPDATA.EMPLOYEE
WHERE SUBSTR('A00',1,1) = SUBSTR(WORKDEPT,1,1))

Thus, for the group considered, the subquery produces the average salary for the
area. This is then compared in the outer statement to the average salary for
department 'A00'. For some other group for which WORKDEPT is ’B01’, the
subquery would result in the average salary for the area where department B01
belongs.

The result table produced by the query would have the following values:

90 DB2 UDB for AS/400 SQL Programming V4R4


(from CORPDATA.EMPLOYEE)
AVG
fetch WORKDEPT SALARY
1 D21 25153.33
2 E01 40175.00
RV2W561-3

Correlated Names and References


A correlated reference can appear only in a search condition in a subquery. The
reference is always of the form X.C, where X is a correlation name and C is the
name of a column in the table that X represents. In the preceding example, for
instance, X represents the table CORPDATA.EMPLOYEE, and C identifies the
column WORKDEPT in this table.

The correlation name is defined in the FROM clause of some query. This query
could be the outer-level SELECT, or any of the subqueries that contain the one with
the reference. Suppose, for example, that a query contains subqueries A, B, and C,
and that A contains B and B contains C. Then a correlation name used in C could
be defined in B, A, or the outer-level SELECT.

You can define a correlation name for each table name appearing in a FROM
clause. Simply include the correlation names after the table names. Leave one or
more blanks between a table name and its correlation name, and place a comma
after the correlation name if it is followed by another table name. The following
FROM clause, for example, defines the correlation names TA and TB for the tables
TABLEA and TABLEB, and no correlation name for the table TABLEC.
FROM TABLEA TA, TABLEC, TABLEB TB

Any number of correlated references can appear in a subquery. There are no


restrictions on variety. For example, one correlated name in a reference could be
defined in the outer-level SELECT, while another could be defined in a containing
subquery.

Before the subquery is executed, a value from the referenced column is always
substituted for the correlated reference. The value is determined as follows:

Note: Use D to designate the query in which the correlation name is defined. Then
the subquery is either in the WHERE clause of D, or in its HAVING clause.
v If the subquery is in the WHERE clause, its results are used by D to qualify a
row. The substituted value is then taken from this row. This is the case for the
example, where the defining query is the outer one and the subquery appears in
the outer query’s WHERE clause.
v If the subquery is in the HAVING clause, its results are used by D to qualify a
group of rows. The substituted value is then taken from this group. Note that in
this case, the column specified must be identified in the GROUP BY clause in D.
If it is not, the specified column could have more than one value for the group.

Using Correlated Subqueries in an UPDATE Statement


When you use a correlated subquery in an UPDATE statement, the correlation
name refers to the rows you are interested in updating. For example, when all

Chapter 5. Advanced Coding Techniques 91


activities of a project must be completed before September 1983, your department
considers that project to be a priority project. You could use the SQL statement
below to evaluate the projects in the CORPDATA.PROJECT table, and write a 1 (a
flag to indicate PRIORITY) in the PRIORITY column (a column you added to
CORPDATA.PROJECT for this purpose) for each priority project.
UPDATE CORPDATA.PROJECT X
SET PRIORITY = 1
WHERE '1983-09-01' >
(SELECT MAX(EMENDATE)
FROM CORPDATA.EMP_ACT
WHERE PROJNO = X.PROJNO)

As SQL examines each row in the CORPDATA.EMP_ACT table, it determines the


maximum activity end date (EMENDATE) for all activities of the project (from the
CORPDATA.PROJECT table). If the end date of each activity associated with the
project is prior to September 1983, the current row in the CORPDATA.PROJECT
table qualifies and is updated.

Using Correlated Subqueries in a DELETE Statement


When you use a correlated subquery in a DELETE statement, the correlation name
represents the row you delete. SQL evaluates the correlated subquery once for
each row in the table named in the DELETE statement to decide whether or not to
delete the row.

Suppose a row in the CORPDATA.PROJECT table was deleted. Rows related to


the deleted project in the CORPDATA.EMP_ACT table must also be deleted. To do
this, you can use:
DELETE FROM CORPDATA.EMP_ACT X
WHERE NOT EXISTS
(SELECT *
FROM CORPDATA.PROJECT
WHERE PROJNO = X.PROJNO)

SQL determines, for each row in the CORPDATA.EMP_ACT table, whether a row
with the same project number exists in the CORPDATA.PROJECT table. If not, the
CORPDATA.EMP_ACT row is deleted.

Notes on Using Correlated Subqueries


v The correlation name is separated from its associated table name with a space.
To specify another table name, precede the table name with a comma, for
example:
FROM CORPDATA.EMPLOYEE X, CORPDATA.PROJECT ....
v The correlated subquery and the outer-level statement can refer to the same
table or to different tables.
v In an INSERT statement, neither the correlated subquery nor an outer-level
SELECT within the INSERT statement can be based on the same table into
which you are inserting.
v The outer-level SELECT that defines the correlation name can join two or more
tables.
v You can use correlated subqueries in HAVING clauses. When you do, SQL
evaluates the subquery, once per group, of the outer-level SELECT. The column
you refer to in the HAVING clause must specify a property of each group (for
example, WORKDEPT) either the columns you grouped the rows by or another
column with one of the column functions.

92 DB2 UDB for AS/400 SQL Programming V4R4


v You can nest correlated subqueries.

Changing a Table Definition


| Changing the definition of a table allows you to add new columns, change an
| existing column definition (change its length, default value, and so on), drop existing
| columns, and add and remove constraints. You can change the definition of a table
| using Operations Navigator. Or, use the SQL ALTER TABLE statement.

You can add, change, or drop columns and add or remove constraints all with one
ALTER TABLE statement. However, a single column can be referenced only once in
the ADD COLUMN, ALTER COLUMN, and DROP COLUMN clauses. That is, you
cannot add a column and then alter that column in the same ALTER TABLE
statement.

Adding a column
| You can add a column to a table using Operations Navigator. Or use the ADD
| COLUMN clause of the SQL ALTER TABLE statement.

When you add a new column to a table, the column is initialized with its default
value for all existing rows. If NOT NULL is specified, a default value must also be
specified.

| The altered table may consist of up to 8000 columns. The sum of the byte counts of
| the columns must not be greater than 32766 or, if a VARCHAR or VARGRAPHIC
| column is specified, 32740. If a LOB column is specified, the sum of record data
| byte counts of the columns must not be greater than 15 728 640.

Changing a column
| You can change a column in a table using Operations Navigator. Or, you can use
| the ALTER COLUMN clause of the ALTER TABLE statement. When you change the
| data type of an existing column, the old and new attributes must be compatible.
| “Allowable Conversions” shows the conversions with compatible attributes.

| When you convert to a data type with a longer length, data will be padded with the
| appropriate pad character. When you convert to a data type with a shorter length,
| data may be lost due to truncation. An inquiry message prompts you to confirm the
| request.

| If you have a column that does not allow the null value and you want to change it to
| now allow the null value, use the DROP NOT NULL clause. If you have a column
| that allows the null value and you want to prevent the use of null values, use the
| SET NOT NULL clause. If any of the existing values in that column are the null
| value, the ALTER TABLE will not be performed and an SQLCODE of -190 will
| result.

Allowable Conversions
Table 15. Allowable Conversions
FROM data type TO data type
Decimal Numeric

Chapter 5. Advanced Coding Techniques 93


Table 15. Allowable Conversions (continued)
FROM data type TO data type
Decimal Integer, Smallint
Decimal Float
Numeric Decimal
Numeric Integer, Smallint
Numeric Float
Integer, Smallint Decimal
Integer, Smallint Numeric
Integer, Smallint Float
Float Numeric
Float Integer, Smallint
Character DBCS-open
Character UCS-2 graphic
DBCS-open Character
DBCS-open UCS-2 graphic
DBCS-either Character
DBCS-either DBCS-open
DBCS-either UCS-2 graphic
DBCS-only DBCS-open
DBCS-only DBCS graphic
DBCS-only UCS-2 graphic
DBCS graphic UCS-2 graphic
UCS-2 graphic Character
UCS-2 graphic DBCS-open
UCS-2 graphic DBCS graphic
| distinct type source type
| source type distinct type

| When modifying an existing column, only the attributes that you specify will be
| changed. All other attributes will remain unchanged. For example, given the
| following table definition:
| CREATE TABLE EX1 (COL1 CHAR(10) DEFAULT 'COL1',
| COL2 VARCHAR(20) ALLOCATE(10) CCSID 937,
| COL3 VARGRAPHIC(20) ALLOCATE(10)
| NOT NULL WITH DEFAULT)

| After running the following ALTER TABLE statement:


ALTER TABLE EX1 ALTER COLUMN COL2 SET DATA TYPE VARCHAR(30)
ALTER COLUMN COL3 DROP NOT NULL

COL2 would still have an allocated length of 10 and CCSID 937, and COL3 would
still have an allocated length of 10.

94 DB2 UDB for AS/400 SQL Programming V4R4


Deleting a column
| You can delete a column using Operations Navigator. Or you can delete a column
| using the DROP COLUMN clause of the ALTER TABLE statement.

Dropping a column deletes that column from the table definition. If CASCADE is
specified, any views, indexes, and constraints dependent on that column will also
be dropped. If RESTRICT is specified, and any views, indexes, or constraints are
dependent on the column, the column will not be dropped and SQLCODE of -196
will be issued.

Order of operations for ALTER TABLE statement


| An ALTER TABLE statement is performed as a set of steps as follows:
| 1. Drop constraints
| 2. Drop columns for which the RESTRICT option was specified
| 3. Alter column definitions (this includes adding columns and dropping columns for
| which the CASCADE option was specified)
| 4. Add constraints

| Within each of these steps, the order in which you specify the clauses is the order
in which they are performed, with one exception. If any columns are being dropped,
that operation is logically done before any column definitions are added or altered,
in case record length is increased as a result of the ALTER TABLE statement.

Creating and Using Views


A view can be used to access part of the data in one or more tables. You can
define the columns of the view in the SELECT clause and the tables the view is
based on in the FROM clause. To define the rows in the view, you can specify a
WHERE clause, a GROUP by clause, or a HAVING clause.

For example, to create a view that selects only the last name and the department of
all the managers, specify:
CREATE VIEW CORPDATA.EMP_MANAGERS AS
SELECT LASTNAME, WORKDEPT FROM CORPDATA.EMPLOYEE
WHERE JOB = 'MANAGER'

If the select list contains elements other than columns such as expressions,
functions, constants, or special registers, and the AS clause was not used to name
the columns, a column list must be specified for the view. In the following example,
the columns of the view are LASTNAME and YEARSOFSERVICE.
CREATE VIEW CORPDATA.EMP_YEARSOFSERVICE
(LASTNAME, YEARSOFSERVICE) AS
SELECT LASTNAME, YEARS (CURRENT DATE - HIREDATE)
FROM CORPDATA.EMPLOYEE

The previous view can also be defined by using the AS clause in the select list to
name the columns in the view. For example:
CREATE VIEW CORPDATA.EMP_YEARSOFSERVICE AS
SELECT LASTNAME,
YEARS (CURRENT_DATE - HIREDATE) AS YEARSOFSERVICE
FROM CORPDATA.EMPLOYEE

Chapter 5. Advanced Coding Techniques 95


Once you have created the view, you can use it to select the data or possibly
change the data in the base table.

The following restrictions must be considered when creating the view:


v You cannot change, insert, or delete data in a read-only view. A view is read-only
if it includes any of the following:
– The first FROM clause identifies more than one table (join).
– The first FROM clause identifies a read-only view.
– The first SELECT clause contains any of the SQL column functions (SUM,
MAX, MIN, AVG, COUNT, STDDEV, or VAR).
– The first SELECT clause specifies the keyword DISTINCT.
– The outer subselect contains a GROUP BY or HAVING clause.
– A subquery, such that the base object of the outer-most subselect and a table
of a subquery are the same table
In the above cases, you can get data from the views by means of the SQL
SELECT statement, but you cannot use statements such as INSERT,
UPDATE, or DELETE.
v You cannot insert a row in a view if:
– The table on which the view is based has a column that has no default value,
does not allow nulls, and is not in the view.
– The view has a column resulting from an expression, a constant, a function,
or a special register and the column was specified in the INSERT column list.
– The WITH CHECK OPTION was specified when the view was created and
the row does not match the selection criteria.
v You cannot update a column of a view that results from an expression, a
constant, a function, or a special register.
v You cannot use UNION, UNION ALL, FOR UPDATE OF, FOR READ ONLY,
ORDER BY, or OPTIMIZE FOR n ROWS in the definition of a view.

Views are created with the sort sequence in effect at the time the CREATE VIEW
statement is run. The sort sequence applies to all character and UCS-2 graphic
comparisons in the CREATE VIEW statement subselect. See “Using Sort Sequence
in SQL” on page 50 for more information on sort sequences.

Views can also be created using the WITH CHECK OPTION to specify the level of
checking that should be done when data is inserted or updated through the view.
See “WITH CHECK OPTION on a View” on page 108 for more information.

Adding Indexes
| You can use indexes to sort and select data. In addition, indexes help the system
| retrieve data faster for better query performance.

| You can create an index when creating a table using Operations Navigator. Or use
| the SQL CREATE INDEX statement. The following example creates an index over
| the column LASTNAME in the CORPDATA.EMPLOYEE table:
| CREATE INDEX CORPDATA.INX1 ON CORPDATA.EMPLOYEE (LASTNAME)

96 DB2 UDB for AS/400 SQL Programming V4R4


| You can create a number of indexes. However, because the indexes are maintained
| by the system, a large number of indexes can adversely affect performance. For
| more information about indexes and query performance, see “Effectively Using SQL
| Indexes” on page 446.

| A new type of index, the encoded vector index, allows for faster scans that can be
| more easily processed in parallel. You create encoded vector indexes by using the
| SQL CREATE INDEX statement. For more information about accelerating your
| queries with encoded vector indexes , go to the DB2 for AS/400 webpages.

| If an index is created that has exactly the same attributes as an existing index, the
| new index shares the existing indexes’ binary tree. Otherwise, another binary tree is
| created. If the attributes of the new index are exactly the same as another index,
| except the new index has fewer columns, another binary tree is still created. It is
| still created because the extra columns would prevent the index from being used by
| cursors or UPDATE statements which update those extra columns.

Indexes are created with the sort sequence in effect at the time the CREATE
INDEX statement is run. The sort sequence applies to all SBCS character fields
and UCS-2 graphic fields of the index. See “Using Sort Sequence in SQL” on page
50 for more information on sort sequences.

Using the Catalog in Database Design


A catalog is automatically created when you create a collection. There is also a
system-wide catalog that is always in the QSYS2 library. When an SQL object is
created in a collection, information is added to both the system catalog tables and
the collection’s catalog tables. When an SQL object is created in a library, only the
QSYS2 catalog is updated. For more information about catalogs, see the DB2 UDB
for AS/400 SQL Reference book.

As the following examples show, you can display catalog information. You cannot
INSERT, DELETE, or UPDATE catalog information. You must have SELECT
privileges on the catalog views to run the following examples.

Attention: Operations that normally update the SQL catalog for a collection can no
longer update the catalog if the collection is saved, restored, and given a different
name. Saving in one collection and restoring to another is not supported by the
product.

Getting Catalog Information about a Table


SYSTABLES contains a row for every table and view in the SQL collection. It tells
you if the object is a table or view, the object name, the owner of the object, what
SQL collection it is in, and so forth.

The following sample statement displays information for the


CORPDATA.DEPARTMENT table:
SELECT *
FROM CORPDATA.SYSTABLES
WHERE NAME = 'DEPARTMENT'

Chapter 5. Advanced Coding Techniques 97


Getting Catalog Information about a Column
SYSCOLUMNS contains a row for each column of every table and view in the
collection.

The following sample statement displays all the column names in the
CORPDATA.DEPARTMENT table:
SELECT *
FROM CORPDATA.SYSCOLUMNS
WHERE TBNAME = 'DEPARTMENT'

The result of the previous sample statement is a row of information for each column
in the table. Some of the information is not visible because the width of the
information is wider than the display screen.

For more information about each column, specify a select-statement like this:
SELECT NAME, TBNAME, COLTYPE, LENGTH, DEFAULT
FROM CORPDATA.SYSCOLUMNS
WHERE TBNAME = 'DEPARTMENT'

In addition to the column name for each column, the select-statement shows:
v The name of the table that contains the column
v The data type of the column
v The length attribute of the column
v If the column allows default values

The result looks like this:

NAME TBNAME COLTYPE LENGTH DEFAULT


DEPTNO DEPARTMENT CHAR 3 N
DEPTNAME DEPARTMENT VARCHAR 29 N
MGRNO DEPARTMENT CHAR 6 Y
ADMRDEPT DEPARTMENT CHAR 3 N

98 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 6. Data Integrity
Data integrity is the principle of ensuring data values between tables of a collection
are kept in a state which makes sense to the business. For example, if a bank has
a list of customers in table A and a list of customer accounts in table B, it would not
make sense to allow a new account to be added to table B unless an associated
customer exists in table A.

This chapter describes the different ways the system automatically enforces these
kinds of relationships. Referential integrity, check constraints, and triggers are all
ways of accomplishing data integrity. Additionally, the WITH CHECK OPTION
clause on a CREATE VIEW constrains the inserting or updating of data through a
view.

For comprehensive information about data integrity, see the DB2 UDB for AS/400
Database Programming book.

Adding and Using Check Constraints


| A check constraint assures the validity of data during inserts and updates by limiting
| the allowable values in a column or group of columns. You can add check
| constraints using Operations Navigator when creating a table. Or use the SQL
| CREATE TABLE and ALTER TABLE statements to add or drop check constraints.

In this example, the following statement creates a table with three columns and a
check constraint over COL2 which limits the values allowed in that column to
positive integers:
CREATE TABLE T1 (COL1 INT, COL2 INT CHECK (COL2>0), COL3 INT)

Given this table, the following statement:


INSERT INTO T1 VALUES (-1, -1, -1)

would fail because the value to be inserted into COL2 does not meet the check
constraint; that is, -1 is not greater than 0.

The following statement would be successful:


INSERT INTO T1 VALUES (1, 1, 1)

Once that row is inserted, the following statement would fail:


ALTER TABLE T1 ADD CONSTRAINT C1 CHECK (COL1=1 AND COL1<COL2)

This ALTER TABLE statement attempts to add a second check constraint which
limits the value allowed in COL1 to 1 and also effectively rules that values in COL2
be greater than 1. This constraint would not be be allowed because the second part
of the constraint is not met by the existing data (the value of ’1’ in COL2 is not less
than the value of ’1’ in COL1).

Referential Integrity
| Referential integrity is the condition of a set of tables in a database in which all
| references from one table to another are valid.

© Copyright IBM Corp. 1997, 1999 99


| Consider the following example: (These sample tables are given in Appendix A.
| DB2 UDB for AS/400 Sample Tables:
| v CORPDATA.EMPLOYEE serves as a master list of employees.
| v CORPDATA.DEPARTMENT acts as a master list of all valid department numbers.
| v CORPDATA.EMP_ACT provides a master list of activities performed for projects.
| Other tables refer to the same entities described in these tables. When a table
| contains data for which there is a master list, that data should actually appear in the
| master list, or the reference is not valid. The table that contains the master list is
| the parent table, and the table that refers to it is a dependent table. When the
| references from the dependent table to the parent table are valid, the condition of
| the set of tables is called referential integrity.

| Stated another way, referential integrity is the state of a database in which all
| values of all foreign keys are valid. Each value of the foreign key must also exist in
| the parent key or be null. This definition of referential integrity requires an
| understanding of the following terms:
| v A unique key is a column or set of columns in a table which uniquely identify a
| row. Although a table can have several unique keys, no two rows in a table can
| have the same unique key value.
| v A primary key is a unique key that does not allow nulls. A table cannot have
| more than one primary key.
| v A parent key is either a unique key or a primary key which is referenced in a
| referential constraint.
| v A foreign key is a column or set of columns whose values must match those of a
| parent key. If any column value used to build the foreign key is null, then the rule
| does not apply.
| v A parent table is a table that contains the parent key.
| v A dependent table is the table that contains the foreign key.
| v A descendent table is a table that is a dependent table or a descendent of a
| dependent table.

| Enforcement of referential integrity prevents the violation of the rule which states
that every non-null foreign key must have a matching parent key.

SQL supports the referential integrity concept with the CREATE TABLE and ALTER
TABLE statements. For detailed descriptions of these commands, see the DB2 UDB
for AS/400 SQL Reference book.

Adding or dropping referential constraints


| “Constraints” on page 375 are rules that ensure that references from one table, a
| dependent table, to data in another table, the parent table, are valid. You use
| referential constraints to ensure “Referential Integrity” on page 99.

| You can add referential constraints using Operations Navigator when creating a
| table. Or, use the SQL CREATE TABLE and ALTER TABLE statements to add or
| change referential constraints.

| With a referential constraint, non-null values of the foreign key are valid only if they
| also appear as values of a parent key. When you define a referential constraint, you
| specify:
| v A primary or unique key

100 DB2 UDB for AS/400 SQL Programming V4R4


| v A foreign key
| v Delete and update rules that specify the action taken with respect to dependent
| rows when the parent row is deleted or updated.

| Optionally, you can specify a name for the constraint. If a name is not specified,
| one is automatically generated.

| Once a referential constraint is defined, the system enforces the constraint on every
| INSERT, DELETE, and UPDATE operation performed through SQL or any other
| interface including Operations Navigator, CL commands, utilities, or high-level
| language statements.

Example: adding referential constraints


The rule that every department number shown in the sample employee table must
appear in the department table is a referential constraint. This constraint ensures
that every employee belongs to an existing department. The following SQL
statements create the CORPDATA.DEPARTMENT and CORPDATA.EMPLOYEE
tables with those constraint relationships defined.
CREATE TABLE CORPDATA.DEPARTMENT
(DEPTNO CHAR(3) NOT NULL PRIMARY KEY,
DEPTNAME VARCHAR(29) NOT NULL,
MGRNO CHAR(6),
ADMRDEPT CHAR(3) NOT NULL
CONSTRAINT REPORTS_TO_EXISTS
REFERENCES CORPDATA.DEPARTMENT (DEPTNO)
ON DELETE CASCADE)

CREATE TABLE CORPDATA.EMPLOYEE


(EMPNO CHAR(6) NOT NULL PRIMARY KEY,
FIRSTNAME VARCHAR(12) NOT NULL,
MIDINIT CHAR(1) NOT NULL,
LASTNAME VARCHAR(15) NOT NULL,
WORKDEPT CHAR(3) CONSTRAINT WORKDEPT_EXISTS
REFERENCES CORPDATA.DEPARTMENT (DEPTNO)
ON DELETE SET NULL ON UPDATE RESTRICT,
PHONENO CHAR(4),
HIREDATE DATE,
JOB CHAR(8),
EDLEVEL SMALLINT NOT NULL,
SEX CHAR(1),
BIRTHDATE DATE,
SALARY DECIMAL(9,2),
BONUS DECIMAL(9,2),
COMM DECIMAL(9,2),
CONSTRAINT UNIQUE_LNAME_IN_DEPT UNIQUE (WORKDEPT, LASTNAME))

In this case, the DEPARTMENT table has a column of unique department numbers
(DEPTNO) which functions as a primary key, and is a parent table in two constraint
relationships:
REPORTS_TO_EXISTS
is a self-referencing constraint in which the DEPARTMENT table is both the
parent and the dependent in the same relationship. Every non-null value of
ADMRDEPT must match a value of DEPTNO. A department must report to
an existing department in the database. The DELETE CASCADE rule
indicates that if a row with a DEPTNO value n is deleted, every row in the
table for which the ADMRDEPT is n is also deleted.
WORKDEPT_EXISTS
establishes the EMPLOYEE table as a dependent table, and the column of

Chapter 6. Data Integrity 101


employee department assignments (WORKDEPT) as a foreign key. Thus,
every value of WORKDEPT must match a value of DEPTNO. The DELETE
SET NULL rule says that if a row is deleted from DEPARTMENT in which
the value of DEPTNO is n, then the value of WORKDEPT in EMPLOYEE is
set to null in every row in which the value was n. The UPDATE RESTRICT
rule says that a value of DEPTNO in DEPARTMENT cannot be updated if
there are values of WORKDEPT in EMPLOYEE that match the current
DEPTNO value.

Constraint UNIQUE_LNAME_IN_DEPT in the EMPLOYEE table causes last names


to be unique within a department. While this constraint is unlikely, it illustrates how
a constraint made up of several columns can be defined at the table level.

Removing Referential Constraints


| The ALTER TABLE statement can be used to add or drop one constraint at a time
| for a table. If the constraint being dropped is the parent key in some referential
| constraint relationship, the constraint between this parent file and any dependent
| files is also removed.

DROP TABLE and DROP COLLECTION statements also remove any constraints
on the table or collection being dropped.

Example of Removing Constraints


The following example removes the primary key over column DEPTNO in table
DEPARTMENT. The constraints REPORTS_TO_EXISTS and WORKDEPT_EXISTS
defined on tables DEPARTMENT and EMPLOYEE respectively will be removed as
well, since the primary key being removed is the parent key in those constraint
relationships.
ALTER TABLE CORPDATA.EMPLOYEE DROP PRIMARY KEY

You can also remove a constraint by name, as in the following example:


ALTER TABLE CORPDATA.DEPARTMENT
DROP CONSTRAINT UNIQUE_LNAME_IN_DEPT

Inserting into Tables with Referential Constraints


There are some important things to remember when inserting data into tables with
referential constraints. If you are inserting data into a parent table with a parent key,
SQL does not allow:
v Duplicate values for the parent key
v If the parent key is a primary key, a null value for any column of the primary key

If you are inserting data into a dependent table with foreign keys:
v Each non-null value you insert into a foreign key column must be equal to some
value in the corresponding parent key of the parent table.
v If any column in the foreign key is null, the entire foreign key is considered null. If
all foreign keys that contain the column are null, the INSERT succeeds (as long
as there are no unique index violations).

Example of Inserting Data with Constraints


Alter the sample application project table (PROJECT) to define two foreign keys:

102 DB2 UDB for AS/400 SQL Programming V4R4


v A foreign key on the department number (DEPTNO) which references the
department table
v A foreign key on the employee number (RESPEMP) which references the
employee table.
ALTER TABLE CORPDATA.PROJECT ADD CONSTRAINT RESP_DEPT_EXISTS
FOREIGN KEY (DEPTNO)
REFERENCES CORPDATA.DEPARTMENT
ON DELETE RESTRICT

ALTER TABLE CORPDATA.PROJECT ADD CONSTRAINT RESP_EMP_EXISTS


FOREIGN KEY (RESPEMP)
REFERENCES CORPDATA.EMPLOYEE
ON DELETE RESTRICT

Notice that the parent table columns are not specified in the REFERENCES clause.
The columns are not required to be specified as long as the referenced table has a
primary key or eligible unique key which can be used as the parent key.

Every row inserted into the PROJECT table must have a value of DEPTNO that is
equal to some value of DEPTNO in the department table. (The null value is not
allowed because DEPTNO in the project table is defined as NOT NULL.) The row
must also have a value of RESPEMP that is either equal to some value of EMPNO
in the employee table or is null.

The tables with the sample data as they appear in Appendix A. DB2 UDB for
AS/400 Sample Tables conform to these constraints. The following INSERT
statement fails because there is no matching DEPTNO value (’A01’) in the
DEPARTMENT table.
INSERT INTO CORPDATA.PROJECT (PROJNO, PROJNAME, DEPTNO, RESPEMP)
VALUES ('AD3120', 'BENEFITS ADMIN', 'A01', '000010')

Likewise, the following INSERT statement would be unsuccessful since there is no


EMPNO value of ’000011’ in the EMPLOYEE table.
INSERT INTO CORPDATA.PROJECT (PROJNO, PROJNAME, DEPTNO, RESPEMP)
VALUES ('AD3130', 'BILLING', 'D21', '000011')

The following INSERT statement completes successfully because there is a


matching DEPTNO value of ’E01’ in the DEPARTMENT table and a matching
EMPNO value of ’000010’ in the EMPLOYEE table.
INSERT INTO CORPDATA.PROJECT (PROJNO, PROJNAME, DEPTNO, RESPEMP)
VALUES ('AD3120', 'BENEFITS ADMIN', 'E01', '000010')

Updating Tables with Referential Constraints


If you are updating a parent table, you cannot modify a primary key for which
dependent rows exist. Changing the key violates referential constraints for
dependent tables and leaves some rows without a parent. Furthermore, you cannot
give any part of a primary key a null value.

Update Rules
The action taken on dependent tables when an UPDATE is performed on a parent
table depends on the update rule specified for the referential constraint. If no
update rule was defined for a referential constraint, the UPDATE NO ACTION rule
is used.
v UPDATE NO ACTION

Chapter 6. Data Integrity 103


Specifies that the row in the parent table can be updated if no other row depends
on it. If a dependent row exists in the relationship, the UPDATE fails. The check
for dependent rows is performed at the end of the statement.
v UPDATE RESTRICT
Specifies that the row in the parent table can be updated if no other row depends
on it. If a dependent row exists in the relationship, the UPDATE fails. The check
for dependent rows is performed immediately.

The subtle difference between RESTRICT and NO ACTION rules is easiest seen
when looking at the interaction of triggers and referential constraints. Triggers can
be defined to fire either before or after an operation (an UPDATE statement, in this
case). A before trigger fires before the UPDATE is performed and therefore before
any checking of constraints. An after trigger is fired after the UPDATE is performed,
and after a constraint rule of RESTRICT (where checking is performed
immediately), but before a constraint rule of NO ACTION (where checking is
performed at the end of the statement). The triggers and rules would occur in the
following order:
1. A before trigger would be fired before the UPDATE and before a constraint rule
of RESTRICT or NO ACTION.
2. An after trigger would be fired after a constraint rule of RESTRICT, but before a
NO ACTION rule.

If you are updating a dependent table, any non-null foreign key values that you
change must match the primary key for each relationship in which the table is a
dependent. For example, department numbers in the employee table depend on the
department numbers in the department table. You can assign an employee to no
department (the null value), but not to a department that does not exist.

If an UPDATE against a table with a referential constraint fails, all changes made
during the update operation are undone. For more information on the implications of
commitment control and journaling when working with constraints, see “Journaling”
on page 368 and “Commitment Control” on page 369.

Examples of UPDATE Rules


For example, you cannot update a department number from the department table if
it is still responsible for some project, which is described by a dependent row in the
project table.

The following UPDATE fails because the PROJECT table has rows which are
dependent on DEPARTMENT.DEPTNO having a value of ’D01’ (the row targeted by
the WHERE statement). If this UPDATE were allowed, the referential constraint
between the PROJECT and DEPARTMENT tables would be broken.
UPDATE CORPDATA.DEPARTMENT
SET DEPTNO = 'D99'
WHERE DEPTNAME = 'DEVELOPMENT CENTER'

The following statement fails because it violates the referential constraint that exists
between the primary key DEPTNO in DEPARTMENT and the foreign key DEPTNO
in PROJECT:
UPDATE CORPDATA.PROJECT
SET DEPTNO = 'D00'
WHERE DEPTNO = 'D01';

104 DB2 UDB for AS/400 SQL Programming V4R4


The statement attempts to change all department numbers of D01 to department
number D00. Since D00 is not a value of the primary key DEPTNO in
DEPARTMENT, the statement fails.

Deleting from Tables with Referential Constraints


If a table has a primary key but no dependents, DELETE operates as it does
without referential constraints. The same is true if a table has only foreign keys, but
no primary key. If a table has a primary key and dependent tables, DELETE deletes
or updates rows according to the delete rules specified. All delete rules of all
affected relationships must be satisfied in order for the delete operation to succeed.
If a referential constraint is violated, the DELETE fails.

The action to be taken on dependent tables when a DELETE is performed on a


parent table depends on the delete rule specified for the referential constraint. If no
delete rule was defined, the DELETE NO ACTION rule is used.
v DELETE NO ACTION
Specifies that the row in the parent table can be deleted if no other row depends
on it. If a dependent row exists in the relationship, the DELETE fails. The check
for dependent rows is performed at the end of the statement.
v DELETE RESTRICT
Specifies that the row in the parent table can be deleted if no other row depends
on it. If a dependent row exists in the relationship, the DELETE fails. The check
for dependent rows is performed immediately.
For example, you cannot delete a department from the department table if it is
still responsible for some project which is described by a dependent row in the
project table.
v DELETE CASCADE
Specifies that first the designated rows in the parent table are deleted. Then, the
dependent rows are deleted.
For example, you can delete a department by deleting its row in the department
table. Deleting the row from the department table also deletes:
– The rows for all departments that report to it
– All departments that report to those departments and so forth.
v DELETE SET NULL
Specifies that each nullable column of the foreign key in each dependent row is
set to its default value. This means that the column is only set to its default value
if it is a member of a foreign key that references the row being deleted. Only the
dependent rows that are immediate descendents are affected.
v DELETE SET DEFAULT
Specifies that each column of the foreign key in each dependent row is set to its
default value. This means that the column is only set to its default value if it is a
member of a foreign key that references the row being deleted. Only the
dependent rows that are immediate descendants are affected.
For example, you can delete an employee from the employee table even if the
employee manages some department. In that case, the value of MGRNO for
each employee who reported to the manager is set to blanks in the department
table. If some other default value was specified on the create of the table, that
value is used.
This is due to the REPORTS_TO_EXISTS constraint defined for the department
table.

Chapter 6. Data Integrity 105


If a descendent table has a delete rule of RESTRICT or NO ACTION and a row is
found such that a descendant row cannot be deleted, the entire DELETE fails.

When running this statement with a program, the number of rows deleted is
returned in SQLERRD(3) in the SQLCA. This number includes only the number of
rows deleted in the table specified in the DELETE statement. It does not include
those rows deleted according to the CASCADE rule. SQLERRD(5) in the SQLCA
contains the number of rows that were affected by referential constraints in all
tables.

The subtle difference between RESTRICT and NO ACTION rules is easiest seen
when looking at the interaction of triggers and referential constraints. Triggers can
be defined to fire either before or after an operation (a DELETE statement, in this
case). A before trigger fires before the DELETE is performed and therefore before
any checking of constraints. An after trigger is fired after the DELETE is performed,
and after a constraint rule of RESTRICT (where checking is performed
immediately), but before a constraint rule of NO ACTION (where checking is
performed at the end of the statement). The triggers and rules would occur in the
following order:
1. A before trigger would be fired before the DELETE and before a constraint rule
of RESTRICT or NO ACTION.
2. An after trigger would be fired after a constraint rule of RESTRICT, but before a
NO ACTION rule.

Example of DELETE Cascade Rule


Deleting a department from the department table sets WORKDEPT (in the
employee table) to null for every employee assigned to that department. Consider
the following DELETE statement:
DELETE FROM CORPDATA.DEPARTMENT
WHERE DEPTNO = 'E11'

Given the tables and the data as they appear in Appendix A. DB2 UDB for AS/400
Sample Tables, one row is deleted from table DEPARTMENT, and table
EMPLOYEE is updated to set the value of WORKDEPT to its default wherever the
value was ’E11’. A question mark (’?’) in the sample data below reflects the null
value. The results would appear as follows:
Table 16. DEPARTMENT Table. Contents of the table after the DELETE statement is
complete.
DEPTNO DEPTNAME MGRNO ADMRDEPT
A00 SPIFFY COMPUTER SERVICE DIV. 000010 A00
B01 PLANNING 000020 A00
C01 INFORMATION CENTER 000030 A00
D01 DEVELOPMENT CENTER ? A00
D11 MANUFACTURING SYSTEMS 000060 D01
D21 ADMINISTRATION SYSTEMS 000070 D01
E01 SUPPORT SERVICES 000050 A00
E21 SOFTWARE SUPPORT 000100 E01

Note that there were no cascaded deletes in the DEPARTMENT table because no
department reported to department ’E11’.

106 DB2 UDB for AS/400 SQL Programming V4R4


Below are snapshots of the affected portion of the EMPLOYEE table before and
after the DELETE statement is completed.
Table 17. Partial EMPLOYEE Table. Partial contents before the DELETE statement.
EMPNO FIRSTNME MI LASTNAME WORKDEPT PHONENO HIREDATE
000230 JAMES J JEFFERSON D21 2094 1966-11-21
000240 SALVATORE M MARINO D21 3780 1979-12-05
000250 DANIEL S SMITH D21 0961 1960-10-30
000260 SYBIL P JOHNSON D21 8953 1975-09-11
000270 MARIA L PEREZ D21 9001 1980-09-30
000280 ETHEL R SCHNEIDER E11 0997 1967-03-24
000290 JOHN R PARKER E11 4502 1980-05-30
000300 PHILIP X SMITH E11 2095 1972-06-19
000310 MAUDE F SETRIGHT E11 3332 1964-09-12
000320 RAMLAL V MEHTA E21 9990 1965-07-07
000330 WING LEE E21 2103 1976-02-23
000340 JASON R GOUNOT E21 5696 1947-05-05
Table 18. Partial EMPLOYEE Table. Partial contents after the DELETE statement.
EMPNO FIRSTNME MI LASTNAME WORKDEPT PHONENO HIREDATE
000230 JAMES J JEFFERSON D21 2094 1966-11-21
000240 SALVATORE M MARINO D21 3780 1979-12-05
000250 DANIEL S SMITH D21 0961 1960-10-30
000260 SYBIL P JOHNSON D21 8953 1975-09-11
000270 MARIA L PEREZ D21 9001 1980-09-30
000280 ETHEL R SCHNEIDER ? 0997 1967-03-24
000290 JOHN R PARKER ? 4502 1980-05-30
000300 PHILIP X SMITH ? 2095 1972-06-19
000310 MAUDE F SETRIGHT ? 3332 1964-09-12
000320 RAMLAL V MEHTA E21 9990 1965-07-07
000330 WING LEE E21 2103 1976-02-23
000340 JASON R GOUNOT E21 5696 1947-05-05

Check Pending
Referential constraints and check constraints can be in a state known as check
pending, where potential violations of the constraint exist. For referential constraints,
a violation occurs when potential mismatches exist between parent and foreign
keys. For check constraints, a violation occurs when potential values exist in
columns which are limited by the check constraint. When the system determines
that the constraint may have been violated (such as after a restore operation), the
constraint is marked as check pending. When this happens, restrictions are placed
on the use of tables involved in the constraint. For referential constraints, the
following restrictions apply:
v No input or output operations are allowed on the dependent file.
v Only read and insert operations are allowed on the parent file.

Chapter 6. Data Integrity 107


When a check constraint is in check pending, the following restrictions apply:
v Read operations are not allowed on the file.
v Inserts and updates are allowed and the constraint is enforced.

To get a constraint out of check pending, you must:


1. Disable the relationship with the Change Physical File Constraint (CHGPFCST)
CL command.
2. Correct the key (foreign, parent, or both) data for referential constraints or
column data for check constraints.
3. Enable the constraint again with the CHGPFCST CL command.
You can identify the rows that are in violation of the constraint with the Display
Check Pending Constraint (DSPCPCST) CL command.

For more information on working with tables in check pending, see the DB2 UDB
for AS/400 Database Programming book.

WITH CHECK OPTION on a View


WITH CHECK OPTION is an optional clause on the CREATE VIEW statement that
specifies the level of checking to be done when inserting or updating data through a
view. If the option is specified, every row that is inserted or updated through the
view must conform to the definition of that view.

WITH CHECK OPTION cannot be specified if the view is read-only. The definition of
the view must not include a subquery.

If the view is created without a WITH CHECK OPTION clause, insert and update
operations that are performed on the view are not checked for conformance to the
view definition. Some checking might still occur if the view is directly or indirectly
dependent on another view that includes WITH CHECK OPTION. Because the
definition of the view is not used, rows might be inserted or updated through the
view that do not conform to the definition of the view. This means that the rows
could not be selected again using the view.

The checking can either be CASCADED or LOCAL. See the DB2 UDB for AS/400
SQL Reference book for additional discussion of WITH CHECK OPTION.

WITH CASCADED CHECK OPTION


The WITH CASCADED CHECK OPTION specifies that every row that is inserted or
updated through the view must conform to the definition of the view. In addition, the
search conditions of all dependent views are checked when a row is inserted or
updated. If a row does not conform to the definition of the view, that row cannot be
retrieved using the view.

For example, consider the following updateable view:


CREATE VIEW V1 AS SELECT COL1
FROM T1 WHERE COL1 > 10

Because no WITH CHECK OPTION is specified, the following INSERT statement is


successful even though the value being inserted does not meet the search
condition of the view.
INSERT INTO V1 VALUES (5)

108 DB2 UDB for AS/400 SQL Programming V4R4


Create another view over V1, specifying the WITH CASCADED CHECK OPTION:
CREATE VIEW V2 AS SELECT COL1
FROM V1 WITH CASCADED CHECK OPTION

The following INSERT statement fails because it would produce a row that does not
conform to the definition of V2:
INSERT INTO V2 VALUES (5)

Consider one more view created over V2:


CREATE VIEW V3 AS SELECT COL1
FROM V2 WHERE COL1 < 100

The following INSERT statement fails only because V3 is dependent on V2, and V2
has a WITH CASCADED CHECK OPTION.
INSERT INTO V3 VALUES (5)

However, the following INSERT statement is successful because it conforms to the


definition of V2. Because V3 does not have a WITH CASCADED CHECK OPTION,
it does not matter that the statement does not conform to the definition of V3.
INSERT INTO V3 VALUES (200)

WITH LOCAL CHECK OPTION


WITH LOCAL CHECK OPTION is identical to WITH CASCADED CHECK OPTION
except that you can update a row so that it no longer can be retrieved through the
view. This can only happen when the view is directly or indirectly dependent on a
view that was defined with no WITH CHECK OPTION clause.

For example, consider the same updateable view used in the previous example:
CREATE VIEW V1 AS SELECT COL1
FROM T1 WHERE COL1 > 10

Create second view over V1, this time specifying WITH LOCAL CHECK OPTION:
CREATE VIEW V2 AS SELECT COL1
FROM V1 WITH LOCAL CHECK OPTION

The same INSERT that failed in the previous CASCADED CHECK OPTION
example would succeed now because V2 does not have any search conditions, and
the search conditions of V1 do not need to be checked since V1 does not specify a
check option.
INSERT INTO V2 VALUES (5)

If we again consider one more view created over V2:


CREATE VIEW V3 AS SELECT COL1
FROM V2 WHERE COL1 < 100

The following INSERT is successful again because the search condition on V1 is


not checked due to the WITH LOCAL CHECK OPTION on V2, versus the WITH
CASCADED CHECK OPTION in the previous example.
INSERT INTO V3 VALUES (5)

The difference between LOCAL and CASCADED CHECK OPTION lies in how
many of the dependent views’ search conditions are checked when a row is
inserted or updated.

Chapter 6. Data Integrity 109


v WITH LOCAL CHECK OPTION specifies that the search conditions of only those
dependent views that have the WITH LOCAL CHECK OPTION or WITH
CASCADED CHECK OPTION are checked when a row is inserted or updated.
v WITH CASCADED CHECK OPTION specifies that the search conditions of all
dependent views are checked when a row is inserted or updated.

Example
Use the following table and views:
CREATE TABLE T1 (COL1 CHAR(10))

CREATE VIEW V1 AS SELECT COL1


FROM T1 WHERE COL1 LIKE 'A%'

CREATE VIEW V2 AS SELECT COL1


FROM V1 WHERE COL1 LIKE '%Z'
WITH LOCAL CHECK OPTION

CREATE VIEW V3 AS SELECT COL1


FROM V2 WHERE COL1 LIKE 'AB%'

CREATE VIEW V4 AS SELECT COL1


FROM V3 WHERE COL1 LIKE '%YZ'
WITH CASCADED CHECK OPTION

CREATE VIEW V5 AS SELECT COL1


FROM V4 WHERE COL1 LIKE 'ABC%'

Different search conditions are going to be checked depending on which view is


being operated on with an INSERT or UPDATE.
v If V1 is operated on, no conditions are checked because V1 does not have a
WITH CHECK OPTION specified.
v If V2 is operated on,
– COL1 must end in the letter Z, but it doesn’t have to start with the letter A.
This is because the check option is LOCAL, and view V1 does not have a
check option specified.
v If V3 is operated on,
– COL1 must end in the letter Z, but it does not have to start with the letter A.
V3 does not have a check option specified, so its own search condition must
not be met. However, the search condition for V2 must be checked since V3
is defined on V2, and V2 has a check option.
v If V4 is operated on,
– COL1 must start with ’AB’, and must end with ’YZ’. Because V4 has the WITH
CASCADED CHECK OPTION specified, every search condition for every view
on which V4 is dependent must be checked.
v If V5 is operated on,
– COL1 must start with ’AB’, but not necessarily ’ABC’. This is because V5 does
not specify a check option, so its own search condition does not need to be
checked. However, because V5 is defined on V4, and V4 had a cascaded
check option, every search condition for V4, V3, V2, and V1 must be checked.
That is, COL1 must start with ’AB’ and end with ’YZ’.

If V5 were created WITH LOCAL CHECK OPTION, operating on V5 would mean


that COL1 must start with ’ABC’ and end with ’YZ’. The LOCAL CHECK OPTION
adds the additional requirement that the third character must be a ’C’.

110 DB2 UDB for AS/400 SQL Programming V4R4


DB2 UDB for AS/400 Trigger Support
A trigger is a set of actions that are run automatically when a specified change
operation is performed on a specified physical database file. In this discussion, a
table is a physical file. The change operation can be an insert, update, or delete
high level language statement in an application program, or an SQL INSERT,
UPDATE, or DELETE statement. Triggers are useful for tasks such as enforcing
business rules, validating input data, and keeping an audit trail.

In DB2 UDB for AS/400, the program containing the set of trigger actions can be
defined in any supported high level language. The trigger program can have SQL
embedded in it. To use trigger support, you must create a trigger program and add
it to a physical file using the ADDPFTRG CL command. To add a trigger to a file,
you must:
v Identify the physical file
v Identify the kind of operation
v Identify the program that performs the desired actions.

There is no SQL statement to associate a physical file with a trigger program. SQL
is only involved in that the trigger program can contain embedded SQL statements,
and that it could be an SQL INSERT, UPDATE, or DELETE that causes the trigger
to be fired.

Once a trigger program is associated with a physical file, the system trigger support
calls the trigger program when a change operation is initiated against the physical
file or table, or any logical file or view created over the physical file.

Each change operation can call a trigger before or after the change operation
occurs. Thus, a physical file can be associated with a maximum of six triggers
v Before delete trigger
v Before insert trigger
v Before update trigger
v After delete trigger
v After insert trigger
v After update trigger

Trigger Sample
A sample trigger program follows. It is written in ILE C, with embedded SQL.

See the DB2 UDB for AS/400 Database Programming book for a full discussion and
more examples of trigger usage in DB2 UDB for AS/400.

Chapter 6. Data Integrity 111


#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include <recio.h>
#include <xxcvt.h>
#include "qsysinc/h/trgbuf" /* Trigger input parameter */
#include "lib1/csrc/msghand1" /* User defined message handler */
/*********************************************************************/
/* This is a trigger program which is called whenever there is an */
/* update to the EMPLOYEE table. If the employee's commission is */
/* greater than the maximum commission, this trigger program will */
/* increase the employee's salary by 1.04 percent and insert into */
/* the RAISE table. */
/* */
/* The EMPLOYEE record information is passed from the input parameter*/
/* to this trigger program. */
/*********************************************************************/

Qdb_Trigger_Buffer_t *hstruct;
char *datapt;

/*******************************************************/
/* Structure of the EMPLOYEE record which is used to */
/* store the old or the new record that is passed to */
/* this trigger program. */
/* */
/* Note : You must ensure that all the numeric fields */
/* are aligned at 4 byte boundary in C. */
/* Used either Packed struct or filler to reach */
/* the byte boundary alignment. */
/*******************************************************/

_Packed struct rec{


char empn[6];
_Packed struct { short fstlen ;
char fstnam[12];
} fstname;
char minit[1];
_Packed struct { short lstlen;
char lstnam[15];
} lstname;
char dept[3];
char phone[4];
char hdate[10];
char jobn[8];
short edclvl;
char sex1[1];
char bdate[10];
decimal(9,2) salary1;
decimal(9,2) bonus1;
decimal(9,2) comm1;
} oldbuf, newbuf;
EXEC SQL INCLUDE SQLCA;

Figure 3. Sample Trigger Program (Part 1 of 5)

112 DB2 UDB for AS/400 SQL Programming V4R4


main(int argc, char **argv)
{
int i;
int obufoff; /* old buffer offset */
int nuloff; /* old null byte map offset */
int nbufoff; /* new buffer offset */
int nul2off; /* new null byte map offset */
short work_days = 253; /* work days during in one year */
decimal(9,2) commission = 2000.00; /* cutoff to qualify for */
decimal(9,2) percentage = 1.04; /* raised salary as percentage */
char raise_date[12] = "1982-06-01";/* effective raise date */

struct {
char empno[6];
char name[30];
decimal(9,2) salary;
decimal(9,2) new_salary;
} rpt1;

/*******************************************************/
/* Start to monitor any exception. */
/*******************************************************/

_FEEDBACK fc;
_HDLR_ENTRY hdlr = main_handler;
/****************************************/
/* Make the exception handler active. */
/****************************************/
CEEHDLR(&hdlr, NULL, &fc);
/****************************************/
/* Ensure exception handler OK */
/****************************************/
if (fc.MsgNo != CEE0000)
{
printf("Failed to register exception handler.\n");
exit(99);
};

/*******************************************************/
/* Move the data from the trigger buffer to the local */
/* structure for reference. */
/*******************************************************/

hstruct = (Qdb_Trigger_Buffer_t *)argv[1];


datapt = (char *) hstruct;

obufoff = hstruct ->Old_Record_Offset; /* old buffer */


memcpy(&oldbuf,datapt+obufoff,; hstruct->Old_Record_Len);

nbufoff = hstruct ->New_Record_Offset; /* new buffer */


memcpy(&newbuf,datapt+nbufoff,; hstruct->New_Record_Len);

Figure 3. Sample Trigger Program (Part 2 of 5)

Chapter 6. Data Integrity 113


EXEC SQL WHENEVER SQLERROR GO TO ERR_EXIT;

/*******************************************************/
/* Set the transaction isolation level to the same as */
/* the application based on the input parameter in the */
/* trigger buffer. */
/*******************************************************/

if(strcmp(hstruct->Commit_Lock_Level,"0") == 0)
EXEC SQL SET TRANSACTION ISOLATION LEVEL NONE;
else{
if(strcmp(hstruct->Commit_Lock_Level,"1") == 0)
EXEC SQL SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED, READ
WRITE;
else {
if(strcmp(hstruct->Commit_Lock_Level,"2") == 0)
EXEC SQL SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
else
if(strcmp(hstruct->Commit_Lock_Level,"3") == 0)
EXEC SQL SET TRANSACTION ISOLATION LEVEL ALL;
}
}

/********************************************************/
/* If the employee's commission is greater than maximum */
/* commission, then increase the employee's salary */
/* by 1.04 percent and insert into the RAISE table. */
/********************************************************/

if (newbuf.comm1 >= commission)


{
EXEC SQL SELECT EMPNO, EMPNAME, SALARY
INTO :rpt1.empno, :rpt1.name, :rpt1.salary
FROM TRGPERF/EMP_ACT
WHERE EMP_ACT.EMPNO=:newbuf.empn ;

if (sqlca.sqlcode == 0) then
{
rpt1.new_salary = salary * percentage;
EXEC SQL INSERT INTO TRGPERF/RAISE VALUES(:rpt1);
}
goto finished;
}
err_exit:
exit(1);

/* All done */
finished:
return;
} /* end of main line */

Figure 3. Sample Trigger Program (Part 3 of 5)

114 DB2 UDB for AS/400 SQL Programming V4R4


/******************************************************************/
/* INCLUDE NAME : MSGHAND1 */
/* */
/* DESCRIPTION : Message handler to signal an exception to */
/* the application to inform that an */
/* error occured in the trigger program. */
/* */
/* NOTE : This message handler is a user defined routine. */
/* */
/******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <recio.h>
#include <leawi.h>

#pragma linkage (QMHSNDPM, OS)


void QMHSNDPM(char *, /*
Message identifier */
void *, /*
Qualified message file name */
void *, /*
Message data or text */
int, /*
Length of message data or text */
char *, /*
Message type */
char *, /*
Call message queue */
int, /*
Call stack counter */
void *, /*
Message key */
void *, /*
Error code */
...); /*
Optionals:
length of call message queue
name
Call stack entry qualification
display external messages
screen wait time */
/*********************************************************************/
/******** This is the start of the exception handler function. */
/*********************************************************************/
void main_handler(_FEEDBACK *cond, _POINTER *token, _INT4 *rc,
_FEEDBACK *new)
{
/****************************************/
/* Initialize variables for call to */
/* QMHSNDPM. */
/* User must create a message file and */
/* define a message ID to match the */
/* following data. */
/****************************************/
char message_id[7] = "TRG9999";
char message_file[20] = "MSGF LIB1 ";
char message_data[50] = "Trigger error " ;
int message_len = 30;
char message_type[10] = "*ESCAPE ";
char message_q[10] = "_C_pep ";
int pgm_stack_cnt = 1;
char message_key[4];

Figure 3. Sample Trigger Program (Part 4 of 5)

Chapter 6. Data Integrity 115


/****************************************/
/* Declare error code structure for */
/* QMHSNDPM. */
/****************************************/
struct error_code {
int bytes_provided;
int bytes_available;
char message_id[7];
} error_code;

error_code.bytes_provided = 15;
/****************************************/
/* Set the error handler to resume and */
/* mark the last escape message as */
/* handled. */
/****************************************/
*rc = CEE_HDLR_RESUME;
/****************************************/
/* Send my own *ESCAPE message. */
/****************************************/
QMHSNDPM(message_id,
&message_file,
&message_data,
message_len,
message_type,
message_q,
pgm_stack_cnt,
&message_key,
&error_code );
/****************************************/
/* Check that the call to QMHSNDPM */
/* finished correctly. */
/****************************************/
if (error_code.bytes_available != 0)
{
printf("Error in QMHOVPM : %s\n", error_code.message_id);
}
}

Figure 3. Sample Trigger Program (Part 5 of 5)

116 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 7. Stored Procedures
DB2 SQL for AS/400 stored procedure support provides a way for an SQL
application to define and then invoke a procedure through SQL statements. Stored
procedures can be used in both distributed and non-distributed DB2 SQL for AS/400
applications. One of the big advantages in using stored procedures is that for
distributed applications, the execution of one CALL statement on the application
requester, or client, can perform any amount of work on the application server.

You may define a procedure as either an SQL procedure or an external procedure.


An external procedure can be any supported high level language program (except
System/36* programs and procedures) or a REXX procedure. The procedure does
not need to contain SQL statements, but it may contain SQL statements. An SQL
procedure is defined entirely in SQL, and can contain SQL statements that include
SQL control statements.

Coding stored procedures requires that the user understand the following:
v Stored procedure definition through the CREATE PROCEDURE statement
v Stored procedure invocation through the CALL statement
v Parameter passing conventions
v Methods for returning a completion status to the program invoking the procedure.

| You may define stored procedures by using the CREATE PROCEDURE statement.
| The CREATE PROCEDURE statement adds procedure and parameter definitions to
| the catalog tables SYSROUTINES and SYSPARMS. These definitions are then
| accessible by any SQL CALL statement on the system.

The following sections describe the SQL statements used to define and invoke the
stored procedure, information on passing parameters to the stored procedure, and
examples of stored procedure usage.

Creating a Procedure
A procedure (often called a stored procedure) is a program that can be called to
perform operations that can include both host language statements and SQL
statements. Procedures in SQL provide the same benefits as procedures in a host
language. That is, a common piece of code need only be written and maintained
once and can be called from several programs.

To create an external procedure or an SQL procedure, you can use the SQL
CREATE PROCEDURE statement. Or, you can use Operations Navigator.

Defining an External Procedure


The CREATE PROCEDURE statement for an external procedure:
v Names the procedure
v Defines the parameters and their attributes
v Gives other information about the procedure which will the system uses when it
calls the procedure.

Consider the following example:

© Copyright IBM Corp. 1997, 1999 117


EXEC SQL CREATE PROCEDURE P1
(INOUT PARM1 CHAR(10))
EXTERNAL NAME MYLIB.PROC1
LANGUAGE C
GENERAL WITH NULLS;

This CREATE PROCEDURE statement:


v Names the procedure P1
v Defines one parameter which is used both as an input parameter and an output
parameter. The parameter is a character field of length ten. Parameters can be
defined to be type IN, OUT, or INOUT. The parameter type determines when the
values for the parameters get passed to and from the procedure.
v Defines the name of the program which corresponds to the procedure, which is
PROC1 in MYLIB. MYLIB.PROC1 is the program which is called when the
procedure is invoked on a CALL statement.
v Indicates that the procedure P1 (program MYLIB.PROC1) is written in C. The
language is important since it impacts the types of parameters that can be
passed. It also affects how the parameters are passed to the procedure (for
example, for ILE C procedures, a NUL-terminator is passed on character,
graphic, date, time, and timestamp parameters).
v Defines the CALL type to be GENERAL WITH NULLS. This indicates that the
parameter for the procedure can possibly contain the NULL value, and therefore
would like an additional argument passed to the procedure on the CALL
statement. The additional argument is an array of N short integers, where N is
the number of parameters that are declared in the CREATE PROCEDURE
statement. In this example, the array contains only one element since there is
only parameter.

It is important to note that it is not necessary to define a procedure in order to call


it. However, if no procedure definition is found, either from a prior CREATE
PROCEDURE or from a DECLARE PROCEDURE in this program, certain
restrictions and assumptions are made when the procedure is invoked on the CALL
statement. For example, the NULL indicator argument cannot be passed. See
“Using Embedded CALL Statement Where No Procedure Definition Exists” on
page 125 for an example of a CALL statement without a corresponding procedure
definition.

Defining an SQL Procedure


The CREATE PROCEDURE statement for SQL procedures:
v Names the procedure
v Defines the parameters and their attributes
v Provides other information about the procedure which will be used when the
procedure is called
v Defines the procedure body. The procedure body is the executable part of the
procedure and is a single SQL statement.

Consider the following simple example that takes as input an employee number and
a rate and updates the employee’s salary:
EXEC SQL CREATE PROCEDURE UPDATE_SALARY_1
(IN EMPLOYEE_NUMBER CHAR(10),
IN RATE DECIMAL(6,2))

118 DB2 UDB for AS/400 SQL Programming V4R4


LANGUAGE SQL MODIFIES SQL DATA
UPDATE CORPDATA.EMPLOYEE
SET SALARY = SALARY * RATE
WHERE EMPNO = EMPLOYEE_NUMBER;

This CREATE PROCEDURE statement:


v Names the procedure UPDATE_SALARY_1.
v Defines parameter EMPLOYEE_NUMBER which is an input parameter and is a
character data type of length 6 and parameter RATE which is an input parameter
and is a decimal data type.
v Indicates the procedure is an SQL procedure that modifies SQL data.
v Defines the procedure body as a single UPDATE statement. When the procedure
is called, the UPDATE statement is executed using the values passed for
EMPLOYEE_NUMBER and RATE.

Instead of a single UPDATE statement, logic can be added to the SQL procedure
using SQL control statements. SQL control statements consist of the following:
v an assignment statement
v a CALL statement
v a CASE statement
v a compound statement
v a FOR statement
v an IF statement
v a LOOP statement
v a REPEAT statement
v a WHILE statement

| The following example takes as input the employee number and a rating that was
| received on the last evaluation. The procedure uses a CASE statement to
| determine the appropriate increase and bonus for the update:
| EXEC SQL CREATE PROCEDURE UPDATE_SALARY_2
| (IN EMPLOYEE_NUMBER CHAR(6),
| IN RATING INT)
| LANGUAGE SQL MODIFIES SQL DATA
| CASE RATING
| WHEN 1 THEN
| UPDATE CORPDATA.EMPLOYEE
| SET SALARY = SALARY * 1.10,
| BONUS = 1000
| WHERE EMPNO = EMPLOYEE_NUMBER;
| WHEN 2 THEN
| UPDATE CORPDATA.EMPLOYEE
| SET SALARY = SALARY * 1.05,
| BONUS = 500
| WHERE EMPNO = EMPLOYEE_NUMBER;
| ELSE
| UPDATE CORPDATA.EMPLOYEE
| SET SALARY = SALARY * 1.03
| BONUS = 0
| WHERE EMPNO = EMPLOYEE_NUMBER;
| END CASE;

| This CREATE PROCEDURE statement:


v Names the procedure UPDATE_SALARY_2.

Chapter 7. Stored Procedures 119


v Defines parameter EMPLOYEE_NUMBER which is an input parameter and is a
character data type of length 6 and parameter RATING which is an input
parameter and is an integer data type.
v Indicates the procedure is an SQL procedure that modifies SQL data.
v Defines the procedure body. When the procedure is called, input parameter
RATING is checked and the appropriate update statement is executed.

Multiple statements can be added to a procedure body by adding a compound


statement. Within a compound statement, any number of SQL statements can be
specified. In addition, SQL variables, cursors, and handlers can be declared.

The following example takes as input the department number. It returns the total
salary of all the employees in that department and the number of employees in that
department who get a bonus.
EXEC SQL
CREATE PROCEDURE RETURN_DEPT_SALARY
(IN DEPT_NUMBER CHAR(3),
OUT DEPT_SALARY DECIMAL(15,2),
OUT DEPT_BONUS_CNT INT)
LANGUAGE SQL READS SQL DATA
P1: BEGIN
DECLARE EMPLOYEE_SALARY DECIMAL(9,2);
DECLARE EMPLOYEE_BONUS DECIMAL(9,2);
DECLARE TOTAL_SALARY DECIMAL(15,2);
DECLARE BONUS_CNT INT DEFAULT 0;
DECLARE END_TABLE INT DEFAULT 0;
DECLARE C1 CURSOR FOR
SELECT SALARY, BONUS FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = DEPT_NUMBER;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET END_TABLE = 1;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
SET DEPT_SALARY = NULL;
OPEN C1;
FETCH C1 INTO EMPLOYEE_SALARY, EMPLOYEE_BONUS;
WHILE END_TABLE = 0 DO
SET TOTAL_SALARY = TOTAL_SALARY + EMPLOYEE_SALARY + EMPLOYEE_BONUS;
IF EMPLOYEE_BONUS > 0 THEN
SET BONUS_CNT = BONUS_CNT + 1;
END IF;
FETCH C1 INTO EMPLOYEE_SALARY, EMPLOYEE_BONUS;
END WHILE;
CLOSE C1;
SET DEPT_SALARY = TOTAL_SALARY;
SET DEPT_BONUS_CNT = BONUS_CNT;
END P1;

This CREATE PROCEDURE statement:


v Names the procedure RETURN_DEPT_SALARY.
v Defines parameter DEPT_NUMBER which is an input parameter and is a
character data type of length 3, parameter DEPT_SALARY which is an output
parameter and is a decimal data type, and parameter DEPT_BONUS_CNT which
is an output parameter and is an integer data type.
v Indicates the procedure is an SQL procedure that reads SQL data
v Defines the procedure body.
– Declares SQL variables EMPLOYEE_SALARY and TOTAL_SALARY as
decimal fields.
– Declares SQL variables BONUS_CNT and END_TABLE which are integers
and are initialized to 0.

120 DB2 UDB for AS/400 SQL Programming V4R4


– Declares cursor C1 that selects the columns from the employee table.
– Declares a continue handler for NOT FOUND, which, when invoked sets
variable END_TABLE to 1. This handler is invoked when the FETCH has no
more rows to return. When the handler is invoked, SQLCODE and SQLSTATE
are reinitialized to 0.
– Declares an exit handler for SQLEXCEPTION. If invoked, DEPT_SALARY is
set to NULL and the processing of the compound statement is terminated.
This handler is invoked if any errors occur, ie, the SQLSTATE class is not ’00’,
’01’ or ’02’. Since indicators are always passed to SQL procedures, the
indicator value for DEPT_SALARY is −1 when the procedure returns. If this
handler is invoked, SQLCODE and SQLSTATE are reinitialized to 0.
If the handler for SQLEXCEPTION is not specified and an error occurs that is
not handled in another handler, execution of the compound statement is
terminated and the error is returned in the SQLCA. Similar to indicators, the
SQLCA is always returned from SQL procedures.
– Includes an OPEN, FETCH, and CLOSE of cursor C1. If a CLOSE of the
cursor is not specified, the cursor is closed at the end of the compound
statement since SET RESULT SETS is not specified in the CREATE
PROCEDURE statement.
– Includes a WHILE statement which loops until the last record is fetched. For
each row retrieved, the TOTAL_SALARY is incremented and, if the
employee’s bonus is more than 0, the BONUS_CNT is incremented.
– Returns DEPT_SALARY and DEPT_BONUS_CNT as output parameters.

Compound statements can be made atomic so if an error occurs that is not


expected, the statements within the atomic statement are rolled back. When a
procedure that contains an atomic compound statement is called, the transaction
must be at a commit boundary. If the compound statement is successful, the
transaction is committed.

The following example takes as input the department number. It ensures the
EMPLOYEE_BONUS table exists, and inserts the name of all employees in the
department who get a bonus. The procedure returns the total count of all
employees who get a bonus.
EXEC SQL
CREATE PROCEDURE CREATE_BONUS_TABLE
(IN DEPT_NUMBER CHAR(3),
INOUT CNT INT)
LANGUAGE SQL MODIFIES SQL DATA
CS1: BEGIN ATOMIC
DECLARE NAME VARCHAR(30) DEFAULT NULL;
DECLARE CONTINUE HANDLER FOR 42710
SELECT COUNT(*) INTO CNT
FROM DATALIB.EMPLOYEE_BONUS;
DECLARE CONTINUE HANDLER FOR 23505
SET CNT = CNT + 1;
DECLARE UNDO HANDLER FOR SQLEXCEPTION
SET CNT = NULL;
IF DEPT_NUMBER IS NOT NULL THEN
CREATE TABLE DATALIB.EMPLOYEE_BONUS
(FULLNAME VARCHAR(30),
BONUS DECIMAL(10,2))
PRIMARY KEY (FULLNAME);
FOR_1:FOR V1 AS C1 CURSOR FOR
SELECT FIRSTNME, MIDINIT, LASTNAME, BONUS
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = CREATE_BONUS_TABLE.DEPT_NUMBER;
IF BONUS > 0 THEN

Chapter 7. Stored Procedures 121


SET NAME = FIRSTNME || ' ' || MIDINIT || ' '||LASTNAME;
INSERT INTO DATALIB.EMPLOYEE_BONUS
VALUES(CS1.NAME, FOR_1.BONUS);
SET CNT = CNT + 1;
END IF;
END FOR FOR_1;
END IF;
END CS1;

This CREATE PROCEDURE statement:


v Names the procedure CREATE_BONUS_TABLE.
v Defines parameter DEPT_NUMBER which is an input parameter and is a
character data type of length 3 and parameter CNT which is an input/output
parameter and is an integer data type.
v Indicates the procedure is an SQL procedure that modifies SQL data
v Defines the procedure body.
– Declares SQL variable NAME as varying character.
– Declares a continue handler for SQLSTATE 42710, table already exists. If the
EMPLOYEE_BONUS table already exists, the handler is invoked and
retrieves the number of records in the table. The SQLCODE and SQLSTATE
are reset to 0 and processing continues with the FOR statement.
– Declares a continue handler for SQLSTATE 23505, duplicate key. If the
procedure attempts to insert a name that already exists in the table, the
handler is invoked and decrements CNT. Processing continues on the SET
statement following the INSERT statement.
– Declares an UNDO handler for SQLEXCEPTION. If invoked, the previous
statements are rolled back, CNT is set to 0, and processing continues after
the compound statement. In this case, since there is no statement following
the compound statement, the procedure returns.
– Uses the FOR statement to declare cursor C1 to read the records from the
EMPLOYEE table. Within the FOR statement, the column names from the
select list are used as SQL variables that contain the data from the row
fetched. For each row, data from columns FIRSTNME, MIDINIT, and
LASTNAME are concatenated together with a blank in between and the result
is put in SQL variable NAME. SQL variables NAME and BONUS are inserted
into the EMPLOYEE_BONUS table. Because the data type of the select list
items must be known when the procedure is created, the table specified in the
FOR statement must exist when the procedure is created.
An SQL variable name can be qualified with the label name of the FOR
statement or compound statement in which it is defined. In the example,
FOR_1.BONUS refers to the SQL variable that contains the value of column
BONUS for each row selected. CS1.NAME is the variable NAME defined in
the compound statement with the beginning label CS1. Parameter names can
also be qualified with the procedure name.
CREATE_BONUS_TABLE.DEPT_NUMBER is the DEPT_NUMBER parameter
for the procedure CREATE_BONUS_TABLE. If unqualified SQL variable
names are used in SQL statements where column names are also allowed,
and the variable name is the same as a column name, the name will be used
to refer to the column.

You can also use dynamic SQL in an SQL procedure. The following example
creates a table that contains all employees in a specific department. The
department number is passed as input to the procedure and is concatenated to the
table name.

122 DB2 UDB for AS/400 SQL Programming V4R4


CREATE PROCEDURE CREATE_DEPT_TABLE (IN P_DEPT CHAR(3))
LANGUAGE SQL
BEGIN
DECLARE STMT CHAR(1000);
DECLARE MESSAGE CHAR(20);
DECLARE TABLE_NAME CHAR(30);
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
SET MESSAGE = 'ok';
SET TABLE_NAME = 'DEPT_' ³³ P_DEPT ³³ '_T';
SET STMT = 'DROP TABLE ' ³³ TABLE_NAME;
PREPARE S1 FROM STMT;
EXECUTE S1;
SET STMT = 'CREATE TABLE ' ³³ TABLE_NAME ³³
'( EMPNO CHAR(6) NOT NULL,
FIRSTNME VARCHAR(6) NOT NULL,
MIDINIT CHAR(1) NOT NULL,
LASTNAME CHAR(15) NOT NULL,
SALARY DECIMAL(9,2))';
PREPARE S2 FROM STMT;
EXECUTE S2;
SET STMT = 'INSERT INTO ' ³³ TABLE_NAME ³³
'SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, SALARY
FROM EMPLOYEE
WHERE WORKDEPT = ?';
PREPARE S3 FROM STMT;
EXECUTE S3 USING P_DEPT;
END;

This CREATE PROCEDURE statement:


v Names the procedure CREATE_DEPT_TABLE
v Defines parameter P_DEPT which is an input parameter and is a character data
type of length 3.
v Indicates the procedure is an SQL procedure.
v Defines the procedure body.
– Declares SQL variable STMT and an SQL variable TABLE_NAME as
character.
– Declares a CONTINUE handler. The procedure attempts to DROP the table in
case it already exists. If the table does not exist, the first EXECUTE would
fail. With the handler, processing will continue.
– Sets variable TABLE_NAME to ’DEPT_’ followed by the characters passed in
parameter P_DEPT, followed by ’_T’.
– Sets variable STMT to the DROP statement, and prepares and executes the
statement.
– Sets variable STMT to the CREATE statement, and prepares and executes
the statement.
– Sets variable STMT to the INSERT statement, and prepares and executes the
statement. A parameter marker is specified in the where clause. When the
statement is executed, the variable P_DEPT is passed on the USING clause.
If the procedure is called passing value ’D21’ for the department, table
DEPT_D21_T is created and the table is initialized with all the employees that are
in department ’D21’.

Chapter 7. Stored Procedures 123


Invoking a Stored Procedure
The CALL statement invokes a stored procedure. On the CALL statement, the
name of the stored procedure and any arguments are specified. Arguments may be
constants, special registers, or host variables. The external stored procedure
specified in the CALL statement does not need to have a corresponding CREATE
PROCEDURE statement. Programs created by SQL procedures can only be called
by invoking the procedure name specified on the CREATE PROCEDURE
statement. There are three types of CALL statements which need to be addressed
since DB2 SQL for AS/400 has different rules for each type. They are:
v Embedded or dynamic CALL statement where a procedure definition exists
v Embedded CALL statement where no procedure definition exists
v Dynamic CALL statement where no CREATE PROCEDURE exists

Note: Dynamic here refers to:


v A dynamically prepared and executed CALL statement
v A CALL statement issued in an interactive environment (for example,
through STRSQL or Query Manager)
v A CALL statement executed in an EXECUTE IMMEDIATE statement.

Following is a discussion of each type.

Using CALL Statement Where Procedure Definition Exists


This type of CALL statement gets all the information about the procedure and the
argument attributes from the CREATE PROCEDURE catalog definition. The
following PL/I example shows a CALL statement which corresponds to the CREATE
PROCEDURE statement shown.
DCL HV1 CHAR(10);
DCL IND1 FIXED BIN(15);
:
EXEC SQL CREATE P1 PROCEDURE
(INOUT PARM1 CHAR(10))
EXTERNAL NAME MYLIB.PROC1
LANGUAGE C
GENERAL WITH NULLS;
:
EXEC SQL CALL P1 (:HV1 :IND1);
:

When this CALL statement is invoked, a call to program MYLIB/PROC1 is made


and two arguments are passed. Since the language of the program is ILE C, the
first argument is a C NUL-terminated string eleven characters long containing the
contents of host variable HV1. Note that on a call to an ILE C procedure, DB2 SQL
for AS/400 adds one character to the parameter declaration if the parameter is
declared to be a character, graphic, date, time, or timestamp variable. The second
argument is the indicator array. In this case, it is one short integer since there is
only one parameter in the CREATE PROCEDURE statement. This argument
contains the contents of indicator variable IND1 on entry to the procedure.

Since the first parameter is declared as INOUT, SQL updates the host variable HV1
and the indicator variable IND1 with the values returned from MYLIB.PROC1 before
returning to the user program.

124 DB2 UDB for AS/400 SQL Programming V4R4


Note: The procedure names specified on the CREATE PROCEDURE and CALL
statements must match EXACTLY in order for the link between the two to be
made during the SQL precompile of the program.

Note: For an embedded CALL statement where both a CREATE PROCEDURE


and a DECLARE PROCEDURE statement exist, the DECLARE
PROCEDURE statement will be used.

Using Embedded CALL Statement Where No Procedure Definition


Exists
A static CALL statement without a corresponding CREATE PROCEDURE statement
is processed with the following rules:
v All host variable arguments are treated as INOUT type parameters.
v The CALL type is GENERAL (no indicator argument is passed).
v The program to call is determined based on the procedure name specified on the
CALL, and, if necessary, the naming convention.
v The language of the program to call is determined based on information retrieved
from the system about the program.

Example of Embedded CALL Statement Where No Procedure


Definition Exists
The following is a PL/I example of an embedded CALL statement where no
procedure definition exists:

DCL HV2 CHAR(10);


:
EXEC SQL CALL P2 (:HV2);
:

When the CALL statement is invoked, DB2 SQL for AS/400 attempts to find the
program based on standard SQL naming conventions. For the above example,
assume that the naming option of *SYS (system naming) is used and that a
DFTRDBCOL parameter was not specified on the CRTSQLPLI command. In this
case, the library list is searched for a program named P2. Since the call type is
GENERAL, no additional argument is passed to the program for indicator variables.

Note: If an indicator variable is specified on the CALL statement and its value is
less than zero when the CALL statement is executed, an error results
because there is no way to pass the indicator to the procedure.

Assuming program P2 is found in the library list, the contents of host variable HV2
are passed in to the program on the CALL and the argument returned from P2 is
mapped back to the host variable after P2 has completed execution.

Using Embedded CALL Statement With an SQLDA


In either type of embedded CALL (where a procedure definition may or may not
exist), an SQLDA may be passed rather than a parameter list, as illustrated in the
following C example. Assume that the stored procedure is expecting 2 parameters,
the first of type SHORT INT and the second of type CHAR with a length of 4.

Chapter 7. Stored Procedures 125


#define SQLDA_HV_ENTRIES 2
#define SHORTINT 500
#define NUL_TERM_CHAR 460

exec sql include sqlca;


exec sql include sqlda;
...
typedef struct sqlda Sqlda;
typedef struct sqlda* Sqldap;
...
main()
{
Sqldap dap;
short col1;
char col2[4];
int bc;
dap = (Sqldap) malloc(bc=SQLDASIZE(SQLDA_HV_ENTRIES));
/* SQLDASIZE is a macro defined in the sqlda include */
col1 = 431;
strcpy(col2,"abc");
strncpy(dap->sqldaid,"SQLDA ",8);
dap->sqldabc = bc; /* bc set in the malloc statement above */
dap->sqln = SQLDA_HV_ENTRIES;
dap->sqld = SQLDA_HV_ENTRIES;
dap->sqlvar[0].sqltype = SHORTINT;
dap->sqlvar[0].sqllen = 2;
dap->sqlvar[0].sqldata = (char*) &col1;
dap->sqlvar[0].sqlname.length = 0;
dap->sqlvar[1].sqltype = NUL_TERM_CHAR;
dap->sqlvar[1].sqllen = 4;
dap->sqlvar[1].sqldata = col2;
...
EXEC SQL CALL P1 USING DESCRIPTOR :*dap;
...
}

It should be noted that the name of the called procedure may also be stored in a
host variable and the host variable used in the CALL statement, instead of the
hard-coded procedure name. For example:
...
main()
{
char proc_name[15];
...
strcpy (proc_name, "MYLIB.P3");
...
EXEC SQL CALL :proc_name ...;
...
}

In the above example, if MYLIB.P3 is expecting parameters, then either a


parameter list or an SQLDA passed with the USING DESCRIPTOR clause may be
used, as shown in the previous example.

When a host variable containing the procedure name is used in the CALL statement
and a CREATE PROCEDURE catalog definition exists, it will be used. The
procedure name cannot be specified as a parameter marker.

More examples for calling stored procedures may be found later in this chapter and
also in the DATABASE 2 Advanced Database Functions book.

126 DB2 UDB for AS/400 SQL Programming V4R4


Using Dynamic CALL Statement Where No CREATE PROCEDURE
Exists
The following rules pertain to the processing of a dynamic CALL statement when
there is no CREATE PROCEDURE definition:
v All arguments are treated as IN type parameters.
v The CALL type is GENERAL (no indicator argument is passed).
v The program to call is determined based on the procedure name specified on the
CALL and the naming convention.
v The language of the program to call is determined based on information retrieved
from the system about the program.

Example of Dynamic CALL Statement Where No CREATE


PROCEDURE Exists
The following is a C example of a dynamic CALL statement:
char hv3[10],string[100];
:
strcpy(string,"CALL MYLIB.P3 ('P3 TEST')");
EXEC SQL EXECUTE IMMEDIATE :string;
:

This example shows a dynamic CALL statement executed through an EXECUTE


IMMEDIATE statement. The call is made to program MYLIB.P3 with one parameter
passed as a character variable containing ’P3 TEST’.

When executing a CALL statement and passing a constant, as in the previous


example, the length of the expected argument in the program must be kept in mind.
If program MYLIB.P3 expected an argument of only 5 characters, the last 2
characters of the constant specified in the example would be lost to the program.

Note: For this reason, it is always safer to use host variables on the CALL
statement so that the attributes of the procedure can be matched exactly and
so that characters are not lost. For dynamic SQL, host variables can be
specified for CALL statement arguments if the PREPARE and EXECUTE
statements are used to process it.

For numeric constants passed on a CALL statement, the following rules apply:
v All integer constants are passed as fullword binary integers.
v All decimal constants are passed as packed decimal values. Precision and scale
are determined based on the constant value. For instance, a value of 123.45 is
passed as a packed decimal(5,2). Likewise, a value of 001.01 is also passed
with a precision and scale of 5 and 2, respectively.
v All floating point constants are passed as double-precision floating point.

Special registers specified on a dynamic CALL statement are passed as follows:


v CURRENT DATE
Passed as a 10-byte character string in ISO format.
v CURRENT TIME
Passed as an 8-byte character string in ISO format.
v CURRENT TIMESTAMP
Passed as a 26-byte character string in IBM SQL format.

Chapter 7. Stored Procedures 127


v CURRENT TIMEZONE
Passed as a packed decimal number with a precision of 6 and a scale of 0.
v CURRENT SERVER
Passed as an 18-byte varying length character string.
v USER
Passed as an 18-byte varying length character string.
v CURRENT PATH
| Passed as a 558-byte varying character length character string.

Parameter Passing Conventions for Stored Procedures


The CALL statement can pass arguments to programs written in all supported host
languages and REXX procedures. Each language supports different data types
which are tailored to it. The SQL data type is contained in the leftmost column of
the following table. Other columns in that row contain an indication of whether that
data type is supported as a parameter type for a particular language. If the column
contains a dash (-), the data type is not supported as a parameter type for that
language. A host variable declaration indicates that DB2 SQL for AS/400 supports
this data type as a parameter in this language. The declaration indicates how host
variables must be declared to be received and set properly by the procedure. When
calling an SQL procedure, all SQL data types are supported so no column is
provided in the table.
Table 19. Data Types of Parameters
COBOL for AS/400 and
SQL Data Type C and C++ CL ILE COBOL for AS/400
SMALLINT short - PIC S9(4) BINARY
INTEGER long - PIC S9(9) BINARY
DECIMAL(p,s) decimal(p,s) TYPE(*DEC) LEN(p s) PIC S9(p-s)V9(s)
PACKED-DECIMAL Note:
Precision must not be
greater than 18.
NUMERIC(p,s) - - PIC S9(p-s)V9(s) DISPLAY
SIGN LEADING SEPARATE
Note: Precision must not be
greater than 18.
REAL or FLOAT(p) float - COMP-1 Note: Only
supported for ILE COBOL
for AS/400.
DOUBLE PRECISION or double - COMP-2 Note: Only
FLOAT or FLOAT(p) supported for ILE COBOL
for AS/400.
CHARACTER(n) char ... [n+1] TYPE(*CHAR) LEN(n) PIC X(n)
VARCHAR(n) char ... [n+1] - Varying-Length Character
String (see COBOL chapter)
Note: Only supported for
ILE COBOL for AS/400.
VARCHAR(n) FOR BIT VARCHAR structured form - Varying-Length Character
DATA (see C chapter) String (see COBOL chapter)
Note: Only supported for
ILE COBOL for AS/400.

128 DB2 UDB for AS/400 SQL Programming V4R4


Table 19. Data Types of Parameters (continued)
COBOL for AS/400 and
SQL Data Type C and C++ CL ILE COBOL for AS/400
GRAPHIC(n) wchar_t ... [n+1] - PIC G(n) DISPLAY-1 or PIC
N(n) Note: Only
supported for ILE COBOL
for AS/400.
VARGRAPHIC(n) VARGRAPHIC structured - Varying-Length Graphic
form (see C chapter) String (see COBOL chapter)
Note: Only supported for
ILE COBOL for AS/400.
DATE char ... [11] TYPE(*CHAR) LEN(10) PIC X(10)
For ILE COBOL for AS/400
only, FORMAT DATE.
TIME char ... [9] TYPE(*CHAR) LEN(8) PIC X(8)
For ILE COBOL for AS/400
only, FORMAT TIME.
TIMESTAMP char ... [27] TYPE(*CHAR) LEN(26) PIC X(26)
For ILE COBOL for AS/400
only, FORMAT
TIMESTAMP.
Indicator Variable short - PIC S9(4) BINARY
| CLOB CLOB structured form (see - CLOB string (see COBOL
| C chapter) chapter). Note: only
| supported for ILE COBOL
| for AS/400.
| BLOB BLOB structured form (see - BLOB string (see COBOL
| C chapter) chapter). Note: only
| supported for ILE COBOL
| for AS/400.
| DBCLOB DBCLOB structured form - DBCLOB string (see
| (see C chapter) COBOL chapter). Note:
| only supported for ILE
| COBOL for AS/400.

Table 20. Data Types of Parameters


SQL Data Type FORTRAN PL/I REXX
SMALLINT INTEGER*2 FIXED BIN(15) -
INTEGER INTEGER*4 FIXED BIN(31) numeric string with no
decimal (and an optional
leading sign).
DECIMAL(p,s) - FIXED DEC(p,s) numeric string with a
decimal (and an optional
leading sign)
NUMERIC(p,s) - - -
REAL or FLOAT(p) REAL*4 FLOAT BIN(p) string with digits, then an E,
(then an optional sign), then
digits
DOUBLE PRECISION or REAL*8 FLOAT BIN(p) string with digits, then an E,
FLOAT or FLOAT(p) (then an optional sign), then
digits
CHARACTER(n) CHARACTER*n CHAR(n) string with n characters
within two apostrophes

Chapter 7. Stored Procedures 129


Table 20. Data Types of Parameters (continued)
SQL Data Type FORTRAN PL/I REXX
VARCHAR(n) - CHAR(n) VAR string with n characters
within two apostrophes
VARCHAR(n) FOR BIT - CHAR(n) VAR string with n characters
DATA within two apostrophes
GRAPHIC(n) - - string starting with G’, then
n double byte characters,
then ’
VARGRAPHIC(n) - - string starting with G’, then
n double byte characters,
then ’
DATE CHARACTER*10 CHAR(10) string with 10 characters
within two apostrophes
TIME CHARACTER*8 CHAR(8) string with 8 characters
within two apostrophes
TIMESTAMP CHARACTER*26 CHAR(26) string with 26 characters
within two apostrophes
Indicator Variable INTEGER*2 FIXED BIN(15) numeric string with no
decimal (and an optional
leading sign).
| CLOB - CLOB structured form (see -
| PL/I chapter)
| BLOB - BLOB structured form (see -
| PL/I chapter)
| DBCLOB - DBCLOB structured form -
| (see PL/I chapter)

Table 21. Data Types of Parameters


SQL Data Type RPG ILE RPG
SMALLINT Data structure that contains a single Data specification. B in position 40, length
sub-field. B in position 43, length must be must be <= 4, and 00 in positions 41-42
2, and 0 in position 52 of the sub-field of the sub-field specification.
specification.
INTEGER Data structure that contains a single Data specification. B in position 40, length
sub-field. B in position 43, length must be must be <=09 and >=05, and 00 in
4, and 0 in position 52 of the sub-field positions 41-42 of the sub-field
specification. specification.
DECIMAL(p,s) Data structure that contains a single Data specification. P in position 40 and 00
sub-field. P in position 43 and 0 through 9 through 31 in positions 41-42 of the
in position 52 of the sub-field specification. sub-field specification.
or A numeric input field or calculation result
field.
NUMERIC(p,s) Data structure that contains a single Data specification. S in position 40, or
sub-field. Blank in position 43 and 0 Blank in position 40 and 00 through 31 in
through 9 in position 52 of the sub-field position 41-42 of the sub-field
specification. specification.
REAL or FLOAT(p) - Data specification. F in position 40, length
must be 4.
DOUBLE PRECISION or - Data specification. F in position 40, length
FLOAT or FLOAT(p) must be 8.

130 DB2 UDB for AS/400 SQL Programming V4R4


Table 21. Data Types of Parameters (continued)
SQL Data Type RPG ILE RPG
CHARACTER(n) Data structure field without sub-fields or Data specification. A in position 40, or
data structure that contains a single Blank in position 40 and 41-42 of the
sub-field. Blank in position 43 and 52 of sub-field specification.
the sub-field specification. or A character
input field or calculation result field.
VARCHAR(n) - Data specification. A in position 40, or
Blank in position 40 and 41-42 of the
sub-field specification and the keyword
VARYING in positions 44-80.
VARCHAR(n) FOR BIT - Data specification. A in position 40, or
DATA Blank in position 40 and 41-42 of the
sub-field specification and the keyword
VARYING in positions 44-80.
GRAPHIC(n) - Data specification. G in position 40 of the
sub-field specification.
VARGRAPHIC(n) - Data specification. G in position 40 of the
sub-field specification and the keyword
VARYING in positions 44-80.
DATE Data structure field without sub-fields or Data specification. D in position 40 of the
data structure that contains a single sub-field specification. DATFMT(*ISO) in
sub-field. Blank in position 43 and 52 of position 44-80.
the sub-field specification. Length is 10. or
A character input field or calculation result
field.
TIME Data structure field without sub-fields or Data specification. T in position 40 of the
data structure that contains a single sub-field specification. TIMFMT(*ISO) in
sub-field. Blank in position 43 and 52 of position 44-80.
the sub-field specification. Length is 8. or A
character input field or calculation result
field.
TIMESTAMP Data structure field without sub-fields or Data specification. Z in position 40 of the
data structure that contains a single sub-field specification.
sub-field. Blank in position 43 and 52 of
the sub-field specification. Length is 26. or
A character input field or calculation result
field.
Indicator Variable Data structure that contains a single Data specification. B in position 40, length
sub-field. B in position 43, length must be must be <=4, and 00 in positions 41-42 of
2, and 0 in position 52 of the sub-field the sub-field specification.
specification.
| CLOB - CLOB structured form (see RPG chapter)
| BLOB - BLOB structured form (see RPG chapter)
| DBCLOB - DBCLOB structured form (see RPG
| chapter)

Chapter 7. Stored Procedures 131


Indicator Variables and Stored Procedures
Indicator variables can be used with the CALL statement, provided host variables
are used for the parameters, to pass additional information to and from the
procedure. Indicator variables are the SQL standard means of denoting that the
associated host variable should be interpreted as containing the null value, and this
is their primary use.

To indicate that an associated host variable contains the null value, the indicator
variable, which is a two-byte integer, is set to a negative value. A CALL statement
with indicator variables is processed as follows:
v If the indicator variable is negative, this denotes the null value. A default value is
passed for the associated host variable on the CALL and the indicator variable is
passed unchanged.
v If the indicator variable is not negative, this denotes that the host variable
contains a non-null value. In this case, the host variable and the indicator
variable are passed unchanged.

Note that these rules of processing are the same for input parameters to the
procedure as well as output parameters returned from the procedure. When
indicator variables are used with stored procedures, the correct method of coding
their handling is to check the value of the indicator variable first before using the
associated host variable.

The following example illustrates the handling of indicator variables in CALL


statements. Notice that the logic checks the value of the indicator variable before
using the associated variable. Also note the method that the indicator variables are
passed into procedure PROC1 (as a third argument consisting of an array of
two-byte values).

Assume a procedure was defined as follows:


CREATE PROCEDURE PROC1
(INOUT DECIMALOUT DECIMAL(7,2), INOUT DECOUT2 DECIMAL(7,2))
EXTERNAL NAME LIB1.PROC1 LANGUAGE RPGLE
GENERAL WITH NULLS)

132 DB2 UDB for AS/400 SQL Programming V4R4


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Program CRPG
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D INOUT1 S 7P 2
D INOUT1IND S 4B 0
D INOUT2 S 7P 2
D INOUT2IND S 4B 0
C EVAL INOUT1 = 1
C EVAL INOUT1IND = 0
C EVAL INOUT2 = 1
C EVAL INOUT2IND = -2
C/EXEC SQL CALL PROC1 (:INOUT1 :INOUT1IND , :INOUT2
C+ :INOUT2IND)
C/END-EXEC
C EVAL INOUT1 = 1
C EVAL INOUT1IND = 0
C EVAL INOUT2 = 1
C EVAL INOUT2IND = -2
C/EXEC SQL CALL PROC1 (:INOUT1 :INOUT1IND , :INOUT2
C+ :INOUT2IND)
C/END-EXEC
C INOUT1IND IFLT 0
C* :
C* HANDLE NULL INDICATOR
C* :
C ELSE
C* :
C* INOUT1 CONTAINS VALID DATA
C* :
C ENDIF
C* :
C* HANDLE ALL OTHER PARAMETERS
C* IN A SIMILAR FASHION
C* :
C RETURN
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
End of PROGRAM CRPG
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Figure 4. Handling of Indicator Variables in CALL Statements (Part 1 of 2)

Chapter 7. Stored Procedures 133


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Program PROC1
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D INOUTP S 7P 2
D INOUTP2 S 7P 2
D NULLARRAY S 4B 0 DIM(2)
C *ENTRY PLIST
C PARM INOUTP
C PARM INOUTP2
C PARM NULLARRAY
C NULLARRAY(1) IFLT 0
C* :
C* INOUTP DOES NOT CONTAIN MEANINGFUL DATA
C*
C ELSE
C* :
C* INOUTP CONTAINS MEANINGFUL DATA
C* :
C ENDIF
C* PROCESS ALL REMAINING VARIABLES
C*
C* BEFORE RETURNING, SET OUTPUT VALUE FOR FIRST
C* PARAMETER AND SET THE INDICATOR TO A NON-NEGATIV
C* VALUE SO THAT THE DATA IS RETURNED TO THE CALLING
C* PROGRAM
C*
C EVAL INOUTP2 = 20.5
C EVAL NULLARRAY(2) = 0
C*
C* INDICATE THAT THE SECOND PARAMETER IS TO CONTAIN
C* THE NULL VALUE UPON RETURN. THERE IS NO POINT
C* IN SETTING THE VALUE IN INOUTP SINCE IT WON'T BE
C* PASSED BACK TO THE CALLER.
C EVAL NULLARRAY(1) = -5
C RETURN
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
End of PROGRAM PROC1
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Figure 4. Handling of Indicator Variables in CALL Statements (Part 2 of 2)

Returning a Completion Status to the Calling Program


One method of returning a status to the SQL program issuing the CALL statement
is to code an extra INOUT type parameter and set it prior to returning from the
procedure. When the procedure being called is an existing program, this is not
always possible.

Another method of returning a status to the SQL program issuing the CALL
statement is to send an escape message to the calling program (operating system
program QSQCALL) which invokes the procedure. The calling program that invokes
the procedure is QSQCALL. Each language has methods for signalling conditions
and sending messages. Refer to the respective language reference to determine
the proper way to signal a message. When the message is signalled, QSQCALL
turns the error into SQLCODE/SQLSTATE -443/38501.

134 DB2 UDB for AS/400 SQL Programming V4R4


Examples
These examples show how the arguments of the CALL statement are passed to the
procedure for several languages. They also show how to receive the arguments into
local variables in the procedure.

The first example shows the calling ILE C program that uses the CREATE
PROCEDURE definitions to call the P1 and P2 procedures. Procedure P1 is written
in C and has 10 parameters. Procedure P2 is written in PL/I and also has 10
parameters.

Assume two procedures are defined as follows:


EXEC SQL CREATE PROCEDURE P1 (INOUT PARM1 CHAR(10),
INOUT PARM2 INTEGER,
INOUT PARM3 SMALLINT,
INOUT PARM4 FLOAT(22),
INOUT PARM5 FLOAT(53),
INOUT PARM6 DECIMAL(10,5),
INOUT PARM7 VARCHAR(10),
INOUT PARM8 DATE,
INOUT PARM9 TIME,
INOUT PARM10 TIMESTAMP)
EXTERNAL NAME TEST12.CALLPROC2
LANGUAGE C GENERAL WITH NULLS

EXEC SQL CREATE PROCEDURE P2 (INOUT PARM1 CHAR(10),


INOUT PARM2 INTEGER,
INOUT PARM3 SMALLINT,
INOUT PARM4 FLOAT(22),
INOUT PARM5 FLOAT(53),
INOUT PARM6 DECIMAL(10,5),
INOUT PARM7 VARCHAR(10),
INOUT PARM8 DATE,
INOUT PARM9 TIME,
INOUT PARM10 TIMESTAMP)
EXTERNAL NAME TEST12.CALLPROC
LANGUAGE PLI GENERAL WITH NULLS

Chapter 7. Stored Procedures 135


Example 1. ILE C and PL/I Procedures Called From ILE C Applications
/**************************************************************/
/*********** START OF SQL C Application ***********************/

#include <stdio.h>
#include <string.h>
#include <decimal.h>
main()
{
EXEC SQL INCLUDE SQLCA;
char PARM1[10];
signed long int PARM2;
signed short int PARM3;
float PARM4;
double PARM5;
decimal(10,5) PARM6;
struct { signed short int parm7l;
char parm7c[10];
} PARM7;
char PARM8[10]; /* FOR DATE */
char PARM9[8]; /* FOR TIME */
char PARM10[26]; /* FOR TIMESTAMP */

Figure 5. Sample of CREATE PROCEDURE and CALL (Part 1 of 2)

136 DB2 UDB for AS/400 SQL Programming V4R4


/*******************************************************/
/* Initialize variables for the call to the procedures */
/*******************************************************/
strcpy(PARM1,"PARM1");
PARM2 = 7000;
PARM3 = -1;
PARM4 = 1.2;
PARM5 = 1.0;
PARM6 = 10.555;
PARM7.parm7l = 5;
strcpy(PARM7.parm7c,"PARM7");
strncpy(PARM8,"1994-12-31",10); /* FOR DATE */
strncpy(PARM9,"12.00.00",8); /* FOR TIME */
strncpy(PARM10,"1994-12-31-12.00.00.000000",26);
/* FOR TIMESTAMP */
/***********************************************/
/* Call the C procedure */
/* */
/* */
/***********************************************/
EXEC SQL CALL P1 (:PARM1, :PARM2, :PARM3,
:PARM4, :PARM5, :PARM6,
:PARM7, :PARM8, :PARM9,
:PARM10 );
if (strncmp(SQLSTATE,"00000",5))
{
/* Handle error or warning returned on CALL statement */
}

/* Process return values from the CALL. */


:

/***********************************************/
/* Call the PLI procedure */
/* */
/* */
/***********************************************/
/* Reset the host variables prior to making the CALL */
/* */
:
EXEC SQL CALL P2 (:PARM1, :PARM2, :PARM3,
:PARM4, :PARM5, :PARM6,
:PARM7, :PARM8, :PARM9,
:PARM10 );
if (strncmp(SQLSTATE,"00000",5))
{
/* Handle error or warning returned on CALL statement */
}
/* Process return values from the CALL. */
:
}

/******** END OF C APPLICATION **********************************/


/****************************************************************/

Figure 5. Sample of CREATE PROCEDURE and CALL (Part 2 of 2)

Chapter 7. Stored Procedures 137


/******** START OF C PROCEDURE P1 *******************************/
/* PROGRAM TEST12/CALLPROC2 */
/****************************************************************/

#include <stdio.h>
#include <string.h>
#include <decimal.h>
main(argc,argv)
int argc;
char *argv[];
{
char parm1[11];
long int parm2;
short int parm3,i,j,*ind,ind1,ind2,ind3,ind4,ind5,ind6,ind7,
ind8,ind9,ind10;
float parm4;
double parm5;
decimal(10,5) parm6;
char parm7[11];
char parm8[10];
char parm9[8];
char parm10[26];
/* *********************************************************/
/* Receive the parameters into the local variables - */
/* Character, date, time, and timestamp are passed as */
/* NUL terminated strings - cast the argument vector to */
/* the proper data type for each variable. Note that */
/* the argument vector could be used directly instead of */
/* copying the parameters into local variables - the copy */
/* is done here just to illustrate the method. */
/* *********************************************************/

/* Copy 10 byte character string into local variable */


strcpy(parm1,argv[1]);

/* Copy 4 byte integer into local variable */


parm2 = *(int *) argv[2];

/* Copy 2 byte integer into local variable */


parm3 = *(short int *) argv[3];

/* Copy floating point number into local variable */


parm4 = *(float *) argv[4];

/* Copy double precision number into local variable */


parm5 = *(double *) argv[5];

/* Copy decimal number into local variable */


parm6 = *(decimal(10,5) *) argv[6];

Figure 6. Sample Procedure P1 (Part 1 of 2)

138 DB2 UDB for AS/400 SQL Programming V4R4


/**********************************************************/
/* Copy NUL terminated string into local variable. */
/* Note that the parameter in the CREATE PROCEDURE was */
/* declared as varying length character. For C, varying */
/* length are passed as NUL terminated strings unless */
/* FOR BIT DATA is specified in the CREATE PROCEDURE */
/**********************************************************/
strcpy(parm7,argv[7]);

/**********************************************************/
/* Copy date into local variable. */
/* Note that date and time variables are always passed in */
/* ISO format so that the lengths of the strings are */
/* known. strcpy would work here just as well. */
/**********************************************************/
strncpy(parm8,argv[8],10);

/* Copy time into local variable */


strncpy(parm9,argv[9],8);

/**********************************************************/
/* Copy timestamp into local variable. */
/* IBM SQL timestamp format is always passed so the length*/
/* of the string is known. */
/**********************************************************/
strncpy(parm10,argv[10],26);

/**********************************************************/
/* The indicator array is passed as an array of short */
/* integers. There is one entry for each parameter passed */
/* on the CREATE PROCEDURE (10 for this example). */
/* Below is one way to set each indicator into separate */
/* variables. */
/**********************************************************/
ind = (short int *) argv[11];
ind1 = *(ind++);
ind2 = *(ind++);
ind3 = *(ind++);
ind4 = *(ind++);
ind5 = *(ind++);
ind6 = *(ind++);
ind7 = *(ind++);
ind8 = *(ind++);
ind9 = *(ind++);
ind10 = *(ind++);
:
/* Perform any additional processing here */
:
return;
}
/******** END OF C PROCEDURE P1 *******************************/

Figure 6. Sample Procedure P1 (Part 2 of 2)

Chapter 7. Stored Procedures 139


/******** START OF PL/I PROCEDURE P2 **************************/
/******** PROGRAM TEST12/CALLPROC *****************************/
/**************************************************************/

CALLPROC :PROC( PARM1,PARM2,PARM3,PARM4,PARM5,PARM6,PARM7,


PARM8,PARM9,PARM10,PARM11);
DCL SYSPRINT FILE STREAM OUTPUT EXTERNAL;
OPEN FILE(SYSPRINT);
DCL PARM1 CHAR(10);
DCL PARM2 FIXED BIN(31);
DCL PARM3 FIXED BIN(15);
DCL PARM4 BIN FLOAT(22);
DCL PARM5 BIN FLOAT(53);
DCL PARM6 FIXED DEC(10,5);
DCL PARM7 CHARACTER(10) VARYING;
DCL PARM8 CHAR(10); /* FOR DATE */
DCL PARM9 CHAR(8); /* FOR TIME */
DCL PARM10 CHAR(26); /* FOR TIMESTAMP */
DCL PARM11(10) FIXED BIN(15); /* Indicators */

/* PERFORM LOGIC - Variables can be set to other values for */


/* return to the calling program. */

END CALLPROC;

Figure 7. Sample Procedure P2

The next example shows a REXX procedure called from an ILE C program.

Assume a procedure is defined as follows:


EXEC SQL CREATE PROCEDURE REXXPROC
(IN PARM1 CHARACTER(20),
IN PARM2 INTEGER,
IN PARM3 DECIMAL(10,5),
IN PARM4 DOUBLE PRECISION,
IN PARM5 VARCHAR(10),
IN PARM6 GRAPHIC(4),
IN PARM7 VARGRAPHIC(10),
IN PARM8 DATE,
IN PARM9 TIME,
IN PARM10 TIMESTAMP)
EXTERNAL NAME 'TEST.CALLSRC(CALLREXX)'
LANGUAGE REXX GENERAL WITH NULLS

140 DB2 UDB for AS/400 SQL Programming V4R4


Example 2. Sample REXX Procedure Called From C Application
/**************************************************************/
/*********** START OF SQL C Application ***********************/

#include <decimal.h>
#include <stdio.h>
#include <string.h>
#include <wcstr.h>
/*-----------------------------------------------------------*/
exec sql include sqlca;
exec sql include sqlda;
/* ***********************************************************/
/* Declare host variable for the CALL statement */
/* ***********************************************************/
char parm1[20];
signed long int parm2;
decimal(10,5) parm3;
double parm4;
struct { short dlen;
char dat[10];
} parm5;
wchar_t parm6[4] = { 0xC1C1, 0xC2C2, 0xC3C3, 0x0000 };
struct { short dlen;
wchar_t dat[10];
} parm7 = {0x0009, 0xE2E2,0xE3E3,0xE4E4, 0xE5E5, 0xE6E6,
0xE7E7, 0xE8E8, 0xE9E9, 0xC1C1, 0x0000 };

char parm8[10];
char parm9[8];
char parm10[26];
main()
{

Figure 8. Sample REXX Procedure Called From C Application (Part 1 of 4)

Chapter 7. Stored Procedures 141


/* *************************************************************/
/* Call the procedure - on return from the CALL statement the */
/* SQLCODE should be 0. If the SQLCODE is non-zero, */
/* the procedure detected an error. */
/* *************************************************************/
strcpy(parm1,"TestingREXX");
parm2 = 12345;
parm3 = 5.5;
parm4 = 3e3;
parm5.dlen = 5;
strcpy(parm5.dat,"parm6");
strcpy(parm8,"1994-01-01");
strcpy(parm9,"13.01.00");
strcpy(parm10,"1994-01-01-13.01.00.000000");

EXEC SQL CALL REXXPROC (:parm1, :parm2,


:parm3,:parm4,
:parm5, :parm6,
:parm7,
:parm8, :parm9,
:parm10);

if (strncpy(SQLSTATE,"00000",5))
{
/* handle error or warning returned on CALL */
:
}
:
}

/****** END OF SQL C APPLICATION ************************************/


/**********************************************************************/

Figure 8. Sample REXX Procedure Called From C Application (Part 2 of 4)

142 DB2 UDB for AS/400 SQL Programming V4R4


/**********************************************************************/
/****** START OF REXX MEMBER TEST/CALLSRC CALLREXX ********************/
/**********************************************************************/
/* REXX source member TEST/CALLSRC CALLREXX */
/* Note the extra parameter being passed for the indicator*/
/* array. */
/* */
/* ACCEPT THE FOLLOWING INPUT VARIABLES SET TO THE */
/* SPECIFIED VALUES : */
/* AR1 CHAR(20) = 'TestingREXX' */
/* AR2 INTEGER = 12345 */
/* AR3 DECIMAL(10,5) = 5.5 */
/* AR4 DOUBLE PRECISION = 3e3 */
/* AR5 VARCHAR(10) = 'parm6' */
/* AR6 GRAPHIC = G'C1C1C2C2C3C3' */
/* AR7 VARGRAPHIC = */
/* G'E2E2E3E3E4E4E5E5E6E6E7E7E8E8E9E9EAEA' */
/* AR8 DATE = '1994-01-01' */
/* AR9 TIME = '13.01.00' */
/* AR10 TIMESTAMP = */
/* '1994-01-01-13.01.00.000000' */
/* AR11 INDICATOR ARRAY = +0+0+0+0+0+0+0+0+0+0 */

/**********************************************************/
/* Parse the arguments into individual parameters */
/**********************************************************/
parse arg ar1 ar2 ar3 ar4 ar5 ar6 ar7 ar8 ar9 ar10 ar11

/**********************************************************/
/* Verify that the values are as expected */
/**********************************************************/
if ar1<>"'TestingREXX'" then signal ar1tag
if ar2<>12345 then signal ar2tag
if ar3<>5.5 then signal ar3tag
if ar4<>3e3 then signal ar4tag
if ar5<>"'parm6'" then signal ar5tag
if ar6 <>"G'AABBCC'" then signal ar6tag
if ar7 <>"G'SSTTUUVVWWXXYYZZAA'" then ,
signal ar7tag
if ar8 <> "'1994-01-01'" then signal ar8tag
if ar9 <> "'13.01.00'" then signal ar9tag
if ar10 <> "'1994-01-01-13.01.00.000000'" then signal ar10tag
if ar11 <> "+0+0+0+0+0+0+0+0+0+0" then signal ar11tag

Figure 8. Sample REXX Procedure Called From C Application (Part 3 of 4)

Chapter 7. Stored Procedures 143


/************************************************************/
/* Perform other processing as necessary .. */
/************************************************************/
:
/************************************************************/
/* Indicate the call was successful by exiting with a */
/* return code of 0 */
/************************************************************/
exit(0)

ar1tag:
say "ar1 did not match" ar1
exit(1)
ar2tag:
say "ar2 did not match" ar2
exit(1)
:
:

/************ END OF REXX MEMBER **********************************/

Figure 8. Sample REXX Procedure Called From C Application (Part 4 of 4)

144 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 8. Using the Object-Relational Capabilities
This chapter discusses the object-oriented capabilities of DB2.
v Why Use the DB2 Object Extensions?
v DB2 Approach to Supporting Objects
v Using Large Objects (LOBs)
v User-Defined Functions (UDF)
v User-defined Distinct Types (UDT)
v Synergy Between UDTs, UDFs, and LOBs

One of the most important recent developments in modern programming language


technology is object-orientation. Object orientation is the notion that entities in the
application domain can be modeled as independent objects that are related to one
another by means of classification. Object-orientation lets you capture the
similarities and differences among objects in your application domain and group
those objects together into related types. Objects of the same type behave in the
same way because they share the same set of type-specific functions. These
functions reflect the behavior of your objects in the application domain.

Why Use the DB2 Object Extensions?


| With the object extensions of DB2, you can incorporate object-oriented (OO)
| concepts and methodologies into your relational database. You accomplish this by
| extending it with richer sets of types and functions. With these extensions, you can
| store instances of object-oriented data types in columns of tables, and operate on
| them by means of functions in SQL statements. In addition, you can make the
| semantic behavior of stored objects an important resource that can be shared
| among all your applications by means of the database.

To incorporate object-orientation into your relational database systems, you can


define new types and functions of your own. These new types and functions should
reflect the semantics of the objects in your application domain. Some of the data
objects you want to model may be large and complex (for example, text, voice,
image, and financial data). Therefore, you may also need mechanisms for the
storage and manipulation of large objects. User-defined Distinct types (UDTs),
user-defined functions (UDFs), and Large Objects (LOBs) are the mechanisms that
are provided by DB2. With DB2, you can now define new types and functions of
your own to store and manipulate application objects within the database.

As described in subsequent sections, there is an important synergy among these


object-oriented features. You can model a complex object in the application domain
as a UDT. The UDT may in turn be internally represented as a LOB. In turn, the
UDT’s behavior may be implemented in terms of UDFs. This section shows you
how to use LOBs along with the steps that are required to define UDTs and UDFs.
You will also learn how UDTs, UDFs, and LOBs can better represent the objects in
your application and thus work together.

Note: The use of the DB2 object-oriented mechanisms (UDTs, UDFs, and LOBs) is
not restricted to the support of object-oriented applications. Just as the C++
programming language implements all sorts of non-object-oriented
applications, the object-oriented mechanisms provided by DB2 can also
support all kinds of non-object-oriented applications. UDTs, UDFs, and LOBs
are general-purpose mechanisms that can be used to model any database

© Copyright IBM Corp. 1997, 1999 145


application. For this reason, these DB2 object extensions offer extensive
support for both non-traditional, that is, object-oriented applications, in
addition to improving support for traditional ones.

DB2 Approach to Supporting Objects


The object extensions of DB2 enable you to realize the benefits of object
technology while building on the strengths of relational technology. In a relational
system, data types describe the data stored in columns of tables where the
instances (or objects) of these data types are stored. Operations on these instances
are supported by means of operators or functions that can be invoked anywhere
that expressions are allowed.

| The DB2 approach to support object extensions fits exactly into the relational
| paradigm. UDTs are data types that you define. UDT’s, like built-in types, can be
| used to describe the data that is stored in columns of tables. UDFs are functions
| that you define. UDFs, like built-in functions or operators, support the manipulation
| of UDT instances. Thus, UDT instances are stored in columns of tables and
| manipulated by UDFs in SQL queries. UDTs can be internally represented in
| different ways. LOBs are just one example of this.

Using Large Objects (LOBs)


The VARCHAR and VARGRAPHIC data types have a limit of 32K bytes of storage.
While this may be sufficient for small to medium size text data, applications often
need to store large text documents. They may also need to store a wide variety of
additional data types such as audio, video, drawings, mixed text and graphics, and
images. DB2 provides three data types to store these data objects as strings of up
to fifteen (15) megabytes (MB) in size. The three data types are: Binary Large
OBjects (BLOBs), single-byte Character Large OBjects (CLOBs), and Double-Byte
Character Large OBjects (DBCLOBs).

Along with storing large objects (LOBs), you will also need a method to refer to,
use, and modify each LOB in the database. Each DB2 table may have a large
amount of associated LOB data. Although a single row containing one or more LOB
values cannot exceed 15 megabytes, a table may contain nearly 256 gigabytes of
LOB data. The content of the LOB column of a particular row at any point in time
has a large object value.

You can refer to and manipulate LOBs using host variables just as you would any
other data type. However, host variables use the client memory buffer which may
not be large enough to hold LOB values. Other means are necessary to manipulate
these large values. Locators are useful to identify and manipulate a large object
value at the database server and for extracting pieces of the LOB value. File
reference variables are useful for physically moving a large object value (or a large
part of it) to and from the client.

The subsections that follow discuss the topics that are introduced above in more
detail.

146 DB2 UDB for AS/400 SQL Programming V4R4


Understanding Large Object Data Types (BLOB, CLOB, DBCLOB)
| Large object data types store data ranging in size from zero bytes to 15 megabytes.

The three large object data types have the following definitions:
v Character Large OBjects (CLOBs) — A character string made up of single-byte
characters with an associated code page. This data type is best for holding
text-oriented information where the amount of information could grow beyond the
limits of a regular VARCHAR data type (upper limit of 32K bytes). Code page
conversion of the information is supported as well as compatibility with the other
character types.
| v Double-Byte Character Large OBjects (DBCLOBs) — A character string made up
| of double-byte characters with an associated code page. This data type is best
| for holding text-oriented information where double-byte character sets are used.
| Again, code page conversion of the information is supported as well as
| compatibility with the other double-byte character types.
v Binary Large OBjects (BLOBs) — A binary string made up of bytes with no
associated code page. This data type may be the most useful because it can
store binary data. Therefore, it is a perfect source type for use by User-defined
Distinct Types (UDTs). UDTs using BLOBs as the source type are created to
store image, voice, graphical, and other types of business or application-specific
data. For more information on UDTs, see “User-defined Distinct Types (UDT)” on
page 169.

Understanding Large Object Locators


Conceptually, LOB locators represent a simple idea that has been around for a
while; use a small, easily managed value to refer to a much larger value.
Specifically, a LOB locator is a 4-byte value stored in a host variable that a program
uses to refer to a LOB value (or LOB expression) held in the database system.
Using a LOB locator, a program can manipulate the LOB value as if the LOB value
was stored in a regular host variable. When you use the LOB locator, there is no
need to transport the LOB value from the server to the application (and possibly
back again).

The LOB locator is associated with a LOB value or LOB expression, not a row or
physical storage location in the database. Therefore, after selecting a LOB value
into a locator, you cannot perform an operation on the original row(s) or tables(s)
that would have any effect on the value referenced by the locator. The value
associated with the locator is valid until the unit of work ends, or the locator is
explicitly freed, whichever comes first. The FREE LOCATOR statement releases a
locator from its associated value. In a similar way, a commit or roll-back operation
frees all LOB locators associated with the transaction.

LOB locators can also be passed between DB2 and UDFs. Within the UDF, those
functions that work on LOB data are available to manipulate the LOB values using
LOB locators.

When selecting a LOB value, you have three options.


v Select the entire LOB value into a host variable. The entire LOB value is copied
into the host variable.
| v Select the LOB value into a LOB locator. The LOB value remains on the server;
| it is not copied to the host variable.

Chapter 8. Using the Object-Relational Capabilities 147


v Select the entire LOB value into a file reference variable. The LOB value is
moved to an Integrated File System (IFS) file.

The use of the LOB value within the program can help the programmer determine
which method is best. If the LOB value is very large and is needed only as an input
value for one or more subsequent SQL statements, keep the value in a locator.

| If the program needs the entire LOB value regardless of the size, then there is no
| choice but to transfer the LOB. Even in this case, there are still three options
| available to you. You can select the entire value into a regular or file reference host
| variable. You may also select the LOB value into a locator and read it piecemeal
| from the locator into a regular host variable, as suggested in the following example.

Example: Using a Locator to Work With a CLOB Value


In this example, the application program retrieves a locator for a LOB value; then it
uses the locator to extract the data from the LOB value. Using this method, the
program allocates only enough storage for one piece of LOB data (the size is
determined by the program). In addition, the program needs to issue only one fetch
call using the cursor.

How the Sample LOBLOC Program Works


1. Declare host variables. The BEGIN DECLARE SECTION and END DECLARE
SECTION statements delimit the host variable declarations. Host variables are
prefixed with a colon (:) when referenced in an SQL statement. CLOB
LOCATOR host variables are declared.
| 2. Fetch the LOB value into the locator host variable. A CURSOR and FETCH
| routine is used to obtain the location of a LOB field in the database to a locator
| host variable.
3. Free the LOB LOCATORS. The LOB LOCATORS used in this example are
freed, releasing the locators from their previously associated values.

The CHECKERR macro/function is an error checking utility which is external to the


program. The location of this error checking utility depends on the programming
language that is used:
C check_error is redefined as CHECKERR and is located in the util.c
file.

148 DB2 UDB for AS/400 SQL Programming V4R4


C Sample: LOBLOC.SQC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
EXEC SQL INCLUDE SQLCA;

#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0) return 1;


int main(int argc, char *argv[]) {

#ifdef DB2MAC
char * bufptr;
#endif

EXEC SQL BEGIN DECLARE SECTION; „1…


char number[7];
long deptInfoBeginLoc;
long deptInfoEndLoc;
SQL TYPE IS CLOB_LOCATOR resume;
SQL TYPE IS CLOB_LOCATOR deptBuffer;
short lobind;
char buffer[1000]="";
char userid[9];
char passwd[19];
EXEC SQL END DECLARE SECTION;

printf( "Sample C program: LOBLOC\n" );


if (argc == 1) {
EXEC SQL CONNECT TO sample;
CHECKERR ("CONNECT TO SAMPLE");
}
else if (argc == 3) {
strcpy (userid, argv[1]);
strcpy (passwd, argv[2]);
EXEC SQL CONNECT TO sample USER :userid USING :passwd;
CHECKERR ("CONNECT TO SAMPLE");
}
else {
printf ("\nUSAGE: lobloc [userid passwd]\n\n");
return 1;
} /* endif */

/* Employee A10030 is not included in the following select, because


the lobeval program manipulates the record for A10030 so that it is
not compatible with lobloc */

EXEC SQL DECLARE c1 CURSOR FOR


SELECT empno, resume FROM emp_resume WHERE resume_format='ascii'
AND empno <> 'A00130';

EXEC SQL OPEN c1;


CHECKERR ("OPEN CURSOR");

do {
EXEC SQL FETCH c1 INTO :number, :resume :lobind; „2…
if (SQLCODE != 0) break;
if (lobind < 0) {
printf ("NULL LOB indicated\n");
} else {
/* EVALUATE the LOB LOCATOR */
/* Locate the beginning of "Department Information" section */
EXEC SQL VALUES (POSSTR(:resume, 'Department Information'))
INTO :deptInfoBeginLoc;
CHECKERR ("VALUES1");

/* Locate the beginning of "Education" section (end of "Dept.Info" */


EXEC SQL VALUES (POSSTR(:resume, 'Education'))
INTO :deptInfoEndLoc;
CHECKERR ("VALUES2");
/* Obtain ONLY the "Department Information" section by using SUBSTR */
EXEC SQL VALUES(SUBSTR(:resume, :deptInfoBeginLoc,
:deptInfoEndLoc - :deptInfoBeginLoc)) INTO :deptBuffer;
CHECKERR ("VALUES3");
/* Append the "Department Information" section to the :buffer var. */
EXEC SQL VALUES(:buffer || :deptBuffer) INTO :buffer;
CHECKERR ("VALUES4");
} /* endif */
} while ( 1 );

#ifdef DB2MAC
/* Need to convert the newline character for the Mac */
bufptr = &(buffer[0]);
while ( *bufptr != '\0' ) {
if ( *bufptr == 0x0A ) *bufptr = 0x0D;
bufptr++;
}
#endif

printf ("%s\n",buffer);

EXEC SQL FREE LOCATOR :resume, :deptBuffer; „3…

Chapter 8. Using the Object-Relational Capabilities 149


CHECKERR ("FREE LOCATOR");

EXEC SQL CLOSE c1;


CHECKERR ("CLOSE CURSOR");
EXEC SQL CONNECT RESET;
CHECKERR ("CONNECT RESET");
return 0;
}
/* end of program : LOBLOC.SQC */

COBOL Sample: LOBLOC.SQB


Identification Division.
Program-ID. "lobloc".

Data Division.
Working-Storage Section.
copy "sqlenv.cbl".
copy "sql.cbl".
copy "sqlca.cbl".
EXEC SQL BEGIN DECLARE SECTION END-EXEC. „1…
01 userid pic x(8).
01 passwd.
49 passwd-length pic s9(4) comp-5 value 0.
49 passwd-name pic x(18).
01 empnum pic x(6).
01 di-begin-loc pic s9(9) comp-5.
01 di-end-loc pic s9(9) comp-5.
01 resume USAGE IS SQL TYPE IS CLOB-LOCATOR.
01 di-buffer USAGE IS SQL TYPE IS CLOB-LOCATOR.
01 lobind pic s9(4) comp-5.
01 buffer USAGE IS SQL TYPE IS CLOB(1K).
EXEC SQL END DECLARE SECTION END-EXEC.

77 errloc pic x(80).


Procedure Division.
Main Section.
display "Sample COBOL program: LOBLOC".
* Get database connection information.
display "Enter your user id (default none): "
with no advancing.
accept userid.

if userid = spaces
EXEC SQL CONNECT TO sample END-EXEC
else
display "Enter your password : " with no advancing
accept passwd-name.

* Passwords in a CONNECT statement must be entered in a VARCHAR


* format with the length of the input string.
inspect passwd-name tallying passwd-length for characters
before initial " ".
EXEC SQL CONNECT TO sample USER :userid USING :passwd
END-EXEC.
move "CONNECT TO" to errloc.
call "checkerr" using SQLCA errloc.

* Employee A10030 is not included in the following select, because


* the lobeval program manipulates the record for A10030 so that it is
* not compatible with lobloc
EXEC SQL DECLARE c1 CURSOR FOR
SELECT empno, resume FROM emp_resume
WHERE resume_format = 'ascii'
AND empno <> 'A00130' END-EXEC.

EXEC SQL OPEN c1 END-EXEC.


move "OPEN CURSOR" to errloc.
call "checkerr" using SQLCA errloc.

Move 0 to buffer-length.
perform Fetch-Loop thru End-Fetch-Loop
until SQLCODE not equal 0.
* display contents of the buffer.
display buffer-data(1:buffer-length).

EXEC SQL FREE LOCATOR :resume, :di-buffer END-EXEC. „3…


move "FREE LOCATOR" to errloc.
call "checkerr" using SQLCA errloc.

EXEC SQL CLOSE c1 END-EXEC.


move "CLOSE CURSOR" to errloc.
call "checkerr" using SQLCA errloc.

EXEC SQL CONNECT RESET END-EXEC.


move "CONNECT RESET" to errloc.
call "checkerr" using SQLCA errloc.
End-Main.

150 DB2 UDB for AS/400 SQL Programming V4R4


go to End-Prog.

Fetch-Loop Section.
EXEC SQL FETCH c1 INTO :empnum, :resume :lobind „2…
END-EXEC.
if SQLCODE not equal 0
go to End-Fetch-Loop.
* check to see if the host variable indicator returns NULL.
if lobind less than 0 go to NULL-lob-indicated.
* Value exists. Evaluate the LOB locator.
* Locate the beginning of "Department Information" section.
EXEC SQL VALUES (POSSTR(:resume, 'Department Information'))
INTO :di-begin-loc END-EXEC.
move "VALUES1" to errloc.
call "checkerr" using SQLCA errloc.

* Locate the beginning of "Education" section (end of Dept.Info)


EXEC SQL VALUES (POSSTR(:resume, 'Education'))
INTO :di-end-loc END-EXEC.
move "VALUES2" to errloc.
call "checkerr" using SQLCA errloc.
subtract di-begin-loc from di-end-loc.

* Obtain ONLY the "Department Information" section by using SUBSTR


EXEC SQL VALUES (SUBSTR(:resume, :di-begin-loc,
:di-end-loc))
INTO :di-buffer END-EXEC.
move "VALUES3" to errloc.
call "checkerr" using SQLCA errloc.

* Append the "Department Information" section to the :buffer var


EXEC SQL VALUES (:buffer || :di-buffer) INTO :buffer
END-EXEC.
move "VALUES4" to errloc.
call "checkerr" using SQLCA errloc.

go to End-Fetch-Loop.

NULL-lob-indicated.
display "NULL LOB indicated".
End-Fetch-Loop. exit.

End-Prog.
stop run.

Indicator Variables and LOB Locators


For normal host variables in an application program, when selecting a NULL value
into a host variable, a negative value is assigned to the indicator variable signifying
that the value is NULL. In the case of LOB locators, however, the meaning of
indicator variables is slightly different. Since a locator host variable itself can never
be NULL, a negative indicator variable value indicates that the LOB value
represented by the LOB locator is NULL. The NULL information is kept local to the
client using the indicator variable value — the server does not track NULL values
with valid locators.

LOB File Reference Variables


File reference variables are similar to host variables except they are used to
transfer data to and from IFS files (not to and from memory buffers). A file reference
variable represents (rather than contains) the file, just as a LOB locator represents
(rather than contains) the LOB value. Database queries, updates, and inserts may
use file reference variables to store, or to retrieve, single LOB values.

For very large objects, files are natural containers. It is likely that most LOBs begin
as data stored in files on the client before they are moved to the database on the
server. The use of file reference variables assists in moving LOB data. Programs
use file reference variables to transfer LOB data from the IFS file directly to the
database engine. To carry out the movement of LOB data, the application does not
have to write utility routines to read and write files using host variables.

Chapter 8. Using the Object-Relational Capabilities 151


Note: The file referenced by the file reference variable must be accessible from
(but not necessarily resident on) the system on which the program runs. For
a stored procedure, this would be the server.

A file reference variable has a data type of BLOB, CLOB, or DBCLOB. It is used
either as the source of data (input) or as the target of data (output). The file
reference variable may have a relative file name or a complete path name of the file
(the latter is advised). The file name length is specified within the application
program. The data length portion of the file reference variable is unused during
input. During output, the data length is set by the application requestor code to the
length of the new data that is written to the file.

| When using file reference variables there are different options on both input and
| output. You must choose an action for the file by setting the file_options field in
| the file reference variable structure. Choices for assignment to the field covering
| both input and output values are shown below.

Values (shown for C) and options when using input file reference variables are as
follows:
| v SQL_FILE_READ (Regular file) — This option has a value of 2. This is a file that
| can be open, read, and closed. DB2 determines the length of the data in the file
| (in bytes) when opening the file. DB2 then returns the length through the
| data_length field of the file reference variable structure. (The value for COBOL is
| SQL-FILE-READ.)

Values and options when using output file reference variables are as follows:
| v SQL_FILE_CREATE (New file) — This option has a value of 8. This option
| creates a new file. Should the file already exist, an error message is returned.
| (The value for COBOL is SQL-FILE-CREATE.)
| v SQL_FILE_OVERWRITE (Overwrite file) — This option has a value of 16. This
| option creates a new file if none already exists. If the file already exists, the new
| data overwrites the data in the file. (The value for COBOL is
| SQL-FILE-OVERWRITE.)
| v SQL_FILE_APPEND (Append file) — This option has a value of 32. This option
| has the output appended to the file, if it exists. Otherwise, it creates a new file.
| (The value for COBOL is SQL-FILE-APPEND.)

Note: If a LOB file reference variable is used in an OPEN statement, do not delete
the file associated with the LOB file reference variable until the cursor is
closed.

For more information about integrated file system, see Integrated File System
| Introduction.

Example: Extracting a Document To a File


This program example shows how CLOB elements can be retrieved from a table
into an external file.

How the Sample LOBFILE Program Works


1. Declare host variables. The BEGIN DECLARE SECTION and END DECLARE
SECTION statements delimit the host variable declarations. Host variables are
prefixed with a colon (:) when referenced in an SQL statement. A CLOB FILE
REFERENCE host variable is declared.

152 DB2 UDB for AS/400 SQL Programming V4R4


| 2. CLOB FILE REFERENCE host variable is set up. The attributes of the FILE
| REFERENCE are set up. A file name without a fully declared path is, by default,
| placed in the user’s current directory. If the pathname does not begin with the
| forward slash (/) character, it is not qualified.
| 3. Select into the CLOB FILE REFERENCE host variable. The data from the
| resume field is selected into the filename that is referenced by the host variable.

The CHECKERR macro/function is an error checking utility which is external to the


program. The location of this error checking utility depends upon the programming
language used:
C check_error is redefined as CHECKERR and is located in the util.c
file.
COBOL CHECKERR is an external program named checkerr.cbl

C Sample: LOBFILE.SQC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sql.h>
#include "util.h"

EXEC SQL INCLUDE SQLCA;

#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0) return 1;

int main(int argc, char *argv[]) {

EXEC SQL BEGIN DECLARE SECTION; „1…


SQL TYPE IS CLOB_FILE resume;
short lobind;
char userid[9];
char passwd[19];
EXEC SQL END DECLARE SECTION;

printf( "Sample C program: LOBFILE\n" );


if (argc == 1) {
EXEC SQL CONNECT TO sample;
CHECKERR ("CONNECT TO SAMPLE");
}
else if (argc == 3) {
strcpy (userid, argv[1]);
strcpy (passwd, argv[2]);
EXEC SQL CONNECT TO sample USER :userid USING :passwd;
CHECKERR ("CONNECT TO SAMPLE");
}
else {
printf ("\nUSAGE: lobfile [userid passwd]\n\n");
return 1;
} /* endif */

strcpy (resume.name, "RESUME.TXT"); „2…


resume.name_length = strlen("RESUME.TXT");
resume.file_options = SQL_FILE_OVERWRITE;

EXEC SQL SELECT resume INTO :resume :lobind FROM emp_resume „3…
WHERE resume_format='ascii' AND empno='000130';

if (lobind < 0) {
printf ("NULL LOB indicated \n");
} else {
printf ("Resume for EMPNO 000130 is in file : RESUME.TXT\n");
} /* endif */
EXEC SQL CONNECT RESET;
CHECKERR ("CONNECT RESET");
return 0;
}
/* end of program : LOBFILE.SQC */

COBOL Sample: LOBFILE.SQB


Identification Division.
Program-ID. "lobfile".

Data Division.
Working-Storage Section.
copy "sqlenv.cbl".
copy "sql.cbl".
copy "sqlca.cbl".
EXEC SQL BEGIN DECLARE SECTION END-EXEC. „1…

Chapter 8. Using the Object-Relational Capabilities 153


01 userid pic x(8).
01 passwd.
49 passwd-length pic s9(4) comp-5 value 0.
49 passwd-name pic x(18).
01 resume USAGE IS SQL TYPE IS CLOB-FILE.
01 lobind pic s9(4) comp-5.
EXEC SQL END DECLARE SECTION END-EXEC.

77 errloc pic x(80).

Procedure Division.
Main Section.
display "Sample COBOL program: LOBFILE".
* Get database connection information.
display "Enter your user id (default none): "
with no advancing.
accept userid.

if userid = spaces
EXEC SQL CONNECT TO sample END-EXEC
else
display "Enter your password : " with no advancing
accept passwd-name.
* Passwords in a CONNECT statement must be entered in a VARCHAR
* format with the length of the input string.
inspect passwd-name tallying passwd-length for characters
before initial " ".

EXEC SQL CONNECT TO sample USER :userid USING :passwd


END-EXEC.
move "CONNECT TO" to errloc.
call "checkerr" using SQLCA errloc.

move "RESUME.TXT" to resume-NAME. „2…


move 10 to resume-NAME-LENGTH.
move SQL-FILE-OVERWRITE to resume-FILE-OPTIONS.

EXEC SQL SELECT resume INTO :resume :lobind „3…


FROM emp_resume
WHERE resume_format = 'ascii'
AND empno = '000130' END-EXEC.
if lobind less than 0 go to NULL-LOB-indicated.
display "Resume for EMPNO 000130 is in file : RESUME.TXT".
go to End-Main.

NULL-LOB-indicated.
display "NULL LOB indicated".

End-Main.
EXEC SQL CONNECT RESET END-EXEC.
move "CONNECT RESET" to errloc.
call "checkerr" using SQLCA errloc.
End-Prog.
stop run.

Example: Inserting Data Into a CLOB Column


Inthe path description of the following C program segment:
v userid represents the directory for one of your users.
v dirname represents a subdirectory name of “userid”.
v filnam.1 can become the name of one of your documents that you wish to insert
into the table.
v clobtab is the name of the table with the CLOB data type.

| The following example shows how to insert data from a regular file referenced by
| :hv_text_file into a CLOB column:
| strcpy(hv_text_file.name, "/home/userid/dirname/filnam.1");
| hv_text_file.name_length = strlen("/home/userid/dirname/filnam.1");
| hv_text_file.file_options = SQL_FILE_READ; /* this is a 'regular' file */
|
| EXEC SQL INSERT INTO CLOBTAB
| VALUES(:hv_text_file);

154 DB2 UDB for AS/400 SQL Programming V4R4


| Display Layout of LOB Columns
| When a row of data from a table holding LOB columns is displayed using CL
| commands such as Display Physical File Member (DSPPFM), the LOB data stored
| in that row will not be displayed. Instead, the Database will show a special value for
| the LOB columns. The layout of this special value is as follows:
| v 13 to 28 bytes of hex zeros.
| v 16 bytes beginning with *POINTER and followed by blanks.
| The number of bytes in the first portion of the value is set to the number needed to
| 16 byte boundary align the second part of the value.

| For example, say you have a table that holds three columns: ColumnOne Char(10),
| ColumnTwo CLOB(40K), and ColumnThree BLOB(10M). If you were to issue a
| DSPPFM of this table, each row of data would look as follows.
| v For ColumnOne: 10 bytes filled with character data.
| v For ColumnTwo: 22 bytes filled with hex zeros and 16 bytes filled with
| ’*POINTER ’.
| v For ColumnThree: 16 bytes filled with hex zeros and 16 bytes filled with
| ’*POINTER ’.
| The full set of commands that display LOB columns in this way is:
| v Display Physical File Member (DSPPFM)
| v Copy File (CPYF) when the value *PRINT is specified for the TOFILE keyword
| v Display Journal (DSPJRN)
| v Retrieve Journal Entry (RTVJRNE)
| v Receive Journal Entry (RCVJRNE) when the values *TYPE1, *TYPE2, *TYPE3
| and *TYPE4 are specified for the ENTFMT keyword.

| Journal Entry Layout of LOB Columns


| Two commands return a buffer that gives the user addressability to LOB data that
| had been journaled:
| v Receive Journal Entry (RCVJRNE) CL command, when the value *TYPEPTR is
| specified for the ENTFMT keyword
| v Retrieve Journal Entries (QjoRetrieveJournalEntries) API
| The layout of the LOB columns in these entries is as follows:
| v 0 to 15 bytes of hex zeros
| v 1 byte of system information set to ’00’x
| v 4 bytes holding the length of the LOB data addressed by the pointer, below
| v 8 bytes of hex zeros
| v 16 bytes holding a pointer to the LOB data stored in the Journal Entry.
| The first part of this layout is intended to 16 byte boundary align the pointer to the
| LOB data. The number of bytes in this area depends on the length of the columns
| that proceed the LOB column. Refer to the section above on the Display Layout of
| LOB Columns for an example of how the length of this first part is calculated.

| For more information on the Journal handling of LOB columns, refer to the ″Working
| with Journal Entries, Journals and Journal Receivers″ chapter of the Backup and
| Recovery book.

Chapter 8. Using the Object-Relational Capabilities 155


User-Defined Functions (UDF)
A user-defined function is a mechanism with which you can write your own
extensions to SQL. The built-in functions supplied with DB2 are a useful set of
functions, but they may not satisfy all of your requirements. Thus, you may need to
extend SQL for the following reasons:
v Customization.
The function specific to your application does not exist in DB2. Whether the
function is a simple transformation, a trivial calculation, or a complicated
multivariate analysis, you can probably use a UDF to do the job.
v Flexibility.
The DB2 built-in function does not quite permit the variations that you wish to
include in your application.
v Standardization.
Many of the programs at your site implement the same basic set of functions, but
there are minor differences in all the implementations. Thus, you are unsure
about the consistency of the results you receive. If you correctly implement these
functions once, in a UDF, then all these programs can use the same
implementation directly in SQL and provide consistent results.
v Object-relational support.
As discussed in “User-defined Distinct Types (UDT)” on page 169, UDTs can be
very useful in extending the capability and increasing the safety of DB2. UDFs
act as the methods for UDTs, by providing behavior and encapsulating the types.

| In addition, SQL UDFs provide the support to manipulate Large Objects and
| DataLink types. While the database provides several built-in functions which are
| useful in working with these datatypes, SQL UDFs provide a way for users to
| further manipulate and enhance the capabilities of the database (to the
| specialization required) in this area.

Why Use UDFs?


In writing DB2 applications, you have a choice when implementing desired actions
or operations:
v As a UDF
v As a subroutine or function in your application.

Although it appears easier to implement new operations as subroutines or functions


in your application, you should still consider:
v Re-use.
| If the new operation is something of which other users or programs at your site
| can take advantage, then UDFs can help to reuse it. In addition, the function can
| be invoked directly in SQL wherever an expression can be used by any user of
| the database. The database will take care of many data type promotions of the
| function arguments automatically. For example, with DECIMAL to DOUBLE, the
| database will allow your function to be applied to different, but compatible data
| types.
| It may seem easier to implement your new function as a normal function. (You
| would not have to define the function to DB2.) If you did this, you would have to
| inform all other interested application developers, and package the function
| effectively for their use. However, this process ignores the interactive users like

156 DB2 UDB for AS/400 SQL Programming V4R4


| those who normally use the Command Line Processor (CLP) to access the
| database. However, functions written for use only within programs ignores those
| (interactive) users who do not have associated programs. This includes
| commands such as STRSQL, STRQM, and RUNSQLSTM, in addition to many
| clients such as ODBC, JDBC, etc. CLP users cannot use your function unless it
| is a UDF in the database. This also applies to any other tools that use SQL (such
| as Visualizer), that do not get recompiled.
v Performance.
| In certain cases, invoking the UDF directly from the database engine instead of
| from your application can have a considerable performance advantage. You willl
| notice this advantage when the function may be used in the qualification of data
| for further processing. These cases occur when the function is used in record
| selection processing. Consider a simple scenario where you want to process
| some data. You can meet some selection criteria which can be expressed as a
| function SELECTION_CRITERIA(). Your application could issue the following select
| statement:
| SELECT A, B, C FROM T

| When it receives each row, it runs SELECTION_CRITERIA against the data to decide
| if it is interested in processing the data further. Here, every row of table T must
| be passed back to the application. But, if SELECTION_CRITERIA() is implemented
| as a UDF, your application can issue the following statement:
| SELECT C FROM T WHERE SELECTION_CRITERIA(A,B)=1

| In this case, only the rows and column of interest are passed across the interface
| between the application and the database.

| Another case where a UDF can offer a performance benefit is when dealing with
| Large Objects (LOB). Suppose you have a function that extracts some
| information from a value of one of the LOB types. You can perform this extraction
| right on the database server and pass only the extracted value back to the
| application. This is more efficient than passing the entire LOB value back to the
| application and then performing the extraction. The performance value of
| packaging this function as a UDF could be enormous, depending on the
| particular situation. (Note that you can also extract a portion of a LOB by using a
| LOB locator. See “Indicator Variables and LOB Locators” on page 151 for an
| example of a similar scenario.)
v Object Orientation.
| You can implement the behavior of a user-defined distinct type (UDT), also called
| distinct type, using a UDF. For more information on UDTs, see “User-defined
| Distinct Types (UDT)” on page 169. For additional details on UDTs and the
| important concept of castability discussed herein, see the CREATE DISTINCT
| TYPE statement in the DB2 UDB for AS/400 SQL Reference. When you create a
| distinct type, you are automatically provided cast functions between the distinct
| type and its source type. You may also be provided comparison operators such
| as =, >, <, and so on, depending on the source type. You have to provide any
| additional behavior yourself. It is best to keep the behavior of a distinct type in
| the database where all of the users of the distinct type can easily access it. You
| can use UDFs, therefore, as the implementation mechanism.
| For example, suppose that you have a BOAT distinct type, defined over a one
| megabyte BLOB. The type create statement:
| CREATE DISTINCT TYPE BOAT AS BLOB(1MEG)

Chapter 8. Using the Object-Relational Capabilities 157


| The BLOB contains the various nautical specifications, and some drawings. You
| may wish to compare sizes of boats. However, with a distinct type defined over a
| BLOB source type, you do not get the comparison operations automatically
| generated for you. You can implement a BOAT_COMPARE function which
| decides if one boat is bigger than another based on a measure that you choose.
| These could be: displacement, length over all, metric tonnage, or another
| calculation based on the BOAT object. You create the BOAT_COMPARE function
| as follows:
| CREATE SQL FUNCTION BOAT_COMPARE (BOAT, BOAT) RETURNS INTEGER ...

| If your function returns:


| – 1 the first BOAT is bigger
| – 2 the second is bigger and
| – 0 they are equal.
| You could use this function in your SQL code to compare boats. Suppose you
| create the following tables:
| CREATE TABLE BOATS_INVENTORY (
| BOAT_ID CHAR(5),
| BOAT_TYPE VARCHAR(25),
| DESIGNER VARCHAR(40),
| OWNER VARCHAR(40),
| DESIGN_DATE DATE,
| SPEC BOAT,
| ... )
|
| CREATE TABLE MY_BOATS (
| BOAT_ID CHAR(5),
| BOAT_TYPE VARCHAR(25),
| DESIGNER VARCHAR(40),
| DESIGN_DATE DATE,
| ACQUIRE_DATE DATE,
| ACQUIRE_PRICE CANADIAN_DOLLAR,
| CURR_APPRAISL CANADIAN_DOLLAR,
| SPEC BOAT,
| ... )

| You can execute the following SQL SELECT statement:


| SELECT INV.BOAT_ID, INV.BOAT_TYPE, INV.DESIGNER,
| INV.OWNER, INV.DESIGN_DATE
| FROM BOATS_INVENTORY INV, MY_BOATS MY
| WHERE MY.BOAT_ID = '19GCC'
| AND BOAT_COMPARE(INV.SPEC, MY.SPEC) = 1
| AND INV.DESIGNER = MY.DESIGNER

| This simple example returns all the boats from BOATS_INVENTORY from the
| same designer that are bigger than a particular boat in MY_BOATS. Note that
| the example only passes the rows of interest back to the application because the
| comparison occurs in the database server. In fact, it completely avoids passing
| any values of data type BOAT. This is a significant improvement in storage and
| performance as BOAT is based on a one megabyte BLOB data type.

UDF Concepts
The following is a discussion of the important concepts you need to know prior to
coding UDFs:

Function Name
| v Full name of a function.

158 DB2 UDB for AS/400 SQL Programming V4R4


| The full name of a function using *SQL naming is <schema-name>.<function-
| name>.
| The full name of a function in *SYS naming is <schema-name>/<function-name>.
| Function names cannot be qualified using *SYS naming in DML statements.
| You can use this full name anywhere you refer to a function. For example:
| QGPL.SNOWBLOWER_SIZE SMITH.FOO QSYS2.SUBSTR QSYS2.FLOOR

| However, you may also omit the <schema-name>., in which case, DB2 must
| determine the function to which you are referring. For example:
| SNOWBLOWER_SIZE FOO SUBSTR FLOOR
| v Path
| The concept of path is central to DB2’s resolution of unqualified references that
| occur when schema-name is not specified. For the use of path in DDL statements
| that refer to functions, see the description of the corresponding CREATE
| FUNCTION statement in the DB2 UDB for AS/400 SQL Reference. The path is
| an ordered list of schema names. It provides a set of schemas for resolving
| unqualified references to UDFs as well as UDTs. In cases where a function
| reference matches functions in more than one schema in the path, the order of
| the schemas in the path is used to resolve this match. The path is established by
| means of the SQLPATH option on the precompile and bind commands for static
| SQL. The path is set by the SET PATH statement for dynamic SQL. When the
| first SQL statement that runs in an activation group runs with SQL naming, the
| path has the following default value:
| "QSYS","QSYS2","<ID>"

| This applies to both static and dynamic SQL, where <ID> represents the current
| statement authorization ID.

| When the first SQL statement in an activation group runs with system naming,
| the default path is *LIBL.
| v Overloaded function names.
| Function names can be overloaded, which means that multiple functions, even in
| the same schema, can have the same name. Two functions cannot, however,
| have the same signature, which can be defined to be the qualified function name
| concatenated with the defined data types of all the function parameters in the
| order in which they are defined. For an example of an overloaded function, see
| “Example: BLOB String Search” on page 162. See the DB2 UDB for AS/400 SQL
| Reference book for more information on signature and function resolution.
| v Function resolution.
| It is the function resolution algorithm that takes into account the facts of
| overloading and function path to choose the best fit for every function reference,
| whether it is a qualified or an unqualified reference. All functions, even built-in
| functions, are processed through the function selection algorithm.
| v Types of function.
| There are several types of functions:
| – Built-in. These are functions provided by and shipped with the database.
| SUBSTR() is an example.
| – System-generated. These are functions implicitly generated by the database
| engine when a DISTINCT TYPE is created. These functions provide casting
| operations between the DISTINCT TYPE and its base type.
| – User-defined. These are functions created by users and registered to the
| database.

Chapter 8. Using the Object-Relational Capabilities 159


| In addition, each function can be further classified as a scalar or column function.
| A scalar function returns a single value answer each time it is called. For
| example, the built-in function SUBSTR() is a scalar function, as are many built-in
| functions. System-generated functions are always scalar functions. Scalar UDFs
| can either be external (coded in a programming language such as C, or in
| SQL—an SQL function), or sourced (using the implementation of an existing
| function).

| A column function receives a set of like values (a column of data) and returns a
| single value answer from this set of values. These are also called aggregating
| functions in DB2. Some built-in functions are column functions. An example of a
| column function is the built-in function AVG(). An external UDF cannot be defined
| as a column function. However, a sourced UDF is defined to be a column
| function if it is sourced on one of the built-in column functions. The latter is useful
| for distinct types. For example, if a distinct type SHOESIZE exists that is defined
| with base type INTEGER, you could define a UDF, AVG(SHOESIZE), as a column
| function sourced on the existing built-in column function, AVG(INTEGER).

| The concept of path, the SET PATH statement, and the function resolution algorithm
| are discussed in detail in the DB2 UDB for AS/400 SQL Reference. The SQLPATH
| precompile option is discussed in the command appendix.

Implementing UDFs
There are three types of UDFs: sourced, external, and SQL. The implementation of
each type is considerably different.
v Sourced UDFs. These are simply functions registered to the database that
themselves reference another function. They, in effect, map the sourced function.
As such, nothing more is required in implementing these functions than
registering them to the database using the CREATE FUNCTION statement.
v External functions. These are references to programs and service programs
written in a high level language such as C, COBOL, or RPG. Once the function is
registered to the database, the database will invoke the program or service
program whenever the function is referenced in a DML statement. As such,
external UDFs require that the UDF writer, besides knowing the high level
language and how to develop code in it, must understand the interface between
the program and the database. See “Chapter 9. Writing User-Defined Functions
(UDFs)” on page 185 for more information on writing external functions.
v SQL UDFs. SQL UDFs are functions written entirely in the SQL language. Their
’code’ is actually SQL statements embedded within the CREATE FUNCTION
statement itself. SQL UDFs provide several advantages:
– They are written in SQL, making them quite portable.
– Defining the interface between the database and the function is by use of SQL
declares, with no need to worry about details of actual parameter passing.
– They allow the passing of large objects, datalinks, and UDTs as parameters,
and subsequent manipulation of them in the function itself. More information
about SQL functions can be found in “Chapter 9. Writing User-Defined
Functions (UDFs)” on page 185.
1. Registering the UDF with DB2. Regardless of which type of UDF is being
created, they all need to be registered to the database using the CREATE
FUNCTION statement. In the case of source functions, this registration step
does everything necessary to define the function to the database. For SQL
UDFs, the CREATE FUNCTION statement contains everything necessary to

160 DB2 UDB for AS/400 SQL Programming V4R4


define the function as well, except that the syntax of the CREATE statement is
much more complex (contains actual SQL executable code). For external UDFs,
the CREATE FUNCTION statement only registers the function to the database;
the supporting code that actually implements the function must be written
separately. See “Registering UDFs” for more information.
2. Debugging the UDF. See “Chapter 9. Writing User-Defined Functions (UDFs)”
on page 185.

| After these steps are successfully completed, your UDF is ready for use in data
| manipulation language (DML) or data definition language (DDL) statements such as
| CREATE VIEW.

| Registering UDFs
| A UDF must be registered in the database before the function can be recognized
| and used by the database. You can register a UDF using the CREATE FUNCTION
| statement. You can find detailed explanations for this statement and its options in
| the DB2 UDB for AS/400 SQL Reference.

| The statement allows you to specify the language and name of the program, along
| with options such as DETERMINISTIC, ALLOW PARALLEL, and RETURN NULLS
| ON NULL INPUT. These options help to more specifically identify to the database
| the intention of the function and how calls to the database can be optimized.

| You should register the UDF to DB2 after you have written and completely tested
| the actual code. It is possible to define the UDF prior to actually writing it. However,
| to avoid any problems with running your UDF, you are encouraged to write and test
| it extensively before registering it. For information on testing your UDF, see
| “Chapter 9. Writing User-Defined Functions (UDFs)” on page 185.

Examples of Registering UDFs


| The examples which follow illustrate a variety of typical situations where UDFs can
| be registered. The examples include:
| v Example: Exponentiation
| v Example: String Search
| v Example: String Search over UDT
| v Example: External Function with UDT Parameter
| v Example: AVG over a UDT
| v Example: Counting

| Example: Exponentiation
| Suppose you have written an external UDF to perform exponentiation of floating
| point values, and wish to register it in the MATH schema.
| CREATE FUNCTION MATH.EXPON (DOUBLE, DOUBLE)
| RETURNS DOUBLE
| EXTERNAL NAME 'MYLIB/MYPGM(MYENTRY)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| NO SQL

Chapter 8. Using the Object-Relational Capabilities 161


| DETERMINISTIC
| NO EXTERNAL ACTION
| RETURNS NULL ON NULL INPUT
| ALLOW PARALLEL

| In this example, the system uses the RETURNS NULL ON NULL INPUT default
| value. This is desirable since you want the result to be NULL if either argument is
| NULL. Since you do not require a scratchpad and no final call is necessary, the NO
| SCRATCHPAD and NO FINAL CALL default values are used. As there is no reason
| why EXPON cannot be parallel, the ALLOW PARALLEL value is specified.

Example: String Search


Your associate, Willie, has written a UDF to look for the existence of a given short
string, passed as an argument, within a given CLOB value, which is also passed as
an argument. The UDF returns the position of the string within the CLOB if it finds
the string, or zero if it does not.

Additionally, Willie has written the function to return a FLOAT result. Suppose you
know that when it is used in SQL, it should always return an INTEGER. You can
create the following function:
CREATE FUNCTION FINDSTRING (CLOB(500K), VARCHAR(200))
RETURNS INTEGER
CAST FROM FLOAT
SPECIFIC "willie_find_feb95"
EXTERNAL NAME 'MYLIB/MYPGM(FINDSTR)'
LANGUAGE C
PARAMETER STYLE DB2SQL
NO SQL
DETERMINISTIC
NO EXTERNAL ACTION
RETURNS NULL ON NULL INPUT

| Note that a CAST FROM clause is used to specify that the UDF body really returns
| a FLOAT value but you want to cast this to INTEGER before returning the value to
| the statement which used the UDF. As discussed in the DB2 UDB for AS/400 SQL
| Reference, the INTEGER built-in function can perform this cast for you. Also, you
| wish to provide your own specific name for the function and later reference it in
| DDL (see “Example: String Search over UDT” on page 163). Because the UDF was
| not written to handle NULL values, you use the RETURNS NULL ON NULL INPUT.
| And because there is no scratchpad, you use the NO SCRATCHPAD and NO
| FINAL CALL default values. As there is no reason why FINDSTRING cannot be
| parallel, the ALLOW PARALLELISM default value is used.

Example: BLOB String Search


| Because you want this function to work on BLOBs as well as on CLOBs, you define
| another FINDSTRING taking BLOB as the first parameter:
| CREATE FUNCTION FINDSTRING (BLOB(500K), VARCHAR(200))
| RETURNS INTEGER
| CAST FROM FLOAT
| SPECIFIC "willie_fblob_feb95"
| EXTERNAL NAME 'MYLIB/MYPGM(FINDSTR)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| NO SQL
| DETERMINISTIC
| NO EXTERNAL ACTION

162 DB2 UDB for AS/400 SQL Programming V4R4


| This example illustrates overloading of the UDF name, and shows that multiple
UDFs can share the same body. Note that although a BLOB cannot be assigned to
a CLOB, the same source code can be used. There is no programming problem in
the above example as the programming interface for BLOB and CLOB between
DB2 and UDF is the same; length followed by data. DB2 does not check if the UDF
using a particular function body is in any way consistent with any other UDF using
the same body.

Example: String Search over UDT


This example is a continuation of the previous example. Say you are satisfied with
the FINDSTRING functions from “Example: BLOB String Search” on page 162, but
now you have defined a distinct type BOAT with source type BLOB. You also want
FINDSTRING to operate on values having data type BOAT, so you create another
FINDSTRING function. This function is sourced on the FINDSTRING which
operates on BLOB values in “Example: BLOB String Search” on page 162. Note the
further overloading of FINDSTRING in this example:
CREATE FUNCTION FINDSTRING (BOAT, VARCHAR(200))
RETURNS INT
SPECIFIC "slick_fboat_mar95"
SOURCE SPECIFIC "willie_fblob_feb95"

Note that this FINDSTRING function has a different signature from the
FINDSTRING functions in “Example: BLOB String Search” on page 162, so there is
no problem overloading the name. You wish to provide your own specific name for
possible later reference in DDL. Because you are using the SOURCE clause, you
cannot use the EXTERNAL NAME clause or any of the related keywords specifying
function attributes. These attributes are taken from the source function. Finally,
observe that in identifying the source function you are using the specific function
name explicitly provided in “Example: BLOB String Search” on page 162. Because
this is an unqualified reference, the schema in which this source function resides
must be in the function path, or the reference will not be resolved.

Example: External Function with UDT Parameter


You have written another UDF to take a BOAT and examine its design attributes
and generate a cost for the boat in Canadian dollars. Even though internally, the
labor cost may be priced in German marks, or Japanese yen, or US dollars, this
function needs to generate the cost to build the boat in the required currency,
Canadian dollars. This means it has to get current exchange rate information from
the exchange_rate file, managed outside of DB2, and the answer depends on what
it finds in this file. This makes the function NOT DETERMINISTIC.
CREATE FUNCTION BOAT_COST (BOAT)
RETURNS INTEGER
EXTERNAL NAME 'MYLIB/COSTS(BOATCOST)'
LANGUAGE C
PARAMETER STYLE DB2SQL
NO SQL
NOT DETERMINISTIC
NO EXTERNAL ACTION

| Observe that CAST FROM and SPECIFIC are not specified, but that NOT
| DETERMINISTIC is specified.

Chapter 8. Using the Object-Relational Capabilities 163


Example: AVG over a UDT
| This example implements the AVG column function over the CANADIAN_DOLLAR
| distinct type. See “Example: Money” on page 171 for the definition of
| CANADIAN_DOLLAR. Strong typing prevents you from using the built-in AVG
| function on a distinct type. It turns out that the source type for CANADIAN_DOLLAR
| was DECIMAL, and so you implement the AVG by sourcing it on the
| AVG(DECIMAL) built-in function. The ability to do this depends on being able to
| cast from DECIMAL to CANADIAN_DOLLAR and vice versa, but since DECIMAL is
| the source type for CANADIAN_DOLLAR you know these casts will work.
| CREATE FUNCTION AVG (CANADIAN_DOLLAR)
| RETURNS CANADIAN_DOLLAR
| SOURCE "QSYS2".AVG(DECIMAL(9,2))

| Note that in the SOURCE clause you have qualified the function name, just in case
| there might be some other AVG function lurking in your SQL path.

| Example: Counting
| Your simple counting function returns a 1 the first time and increments the result by
| one each time it is called. This function takes no SQL arguments, and by definition
| it is a NOT DETERMINISTIC function since its answer varies from call to call. It
| uses the scratchpad to save the last value returned, and each time it is invoked it
| increments this value and returns it.
| CREATE FUNCTION COUNTER ()
| RETURNS INT
| EXTERNAL NAME 'MYLIB/MYFUNCS(CTR)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| NO SQL
| NOT DETERMINISTIC
| NOT FENCED
| SCRATCHPAD 4
| DISALLOW PARALLEL

| Note that no parameter definitions are provided, just empty parentheses. The above
| function specifies SCRATCHPAD, and uses the default specification of NO FINAL
| CALL. In this case, the size of the scratchpad is set to only 4 bytes, which is
| sufficient for a counter. Since the COUNTER function requires that a single
| scratchpad be used to operate properly, DISALLOW PARALLEL is added to prevent
| DB2 from operating it in parallel.

Using UDFs
Scalar and column UDFs can be invoked within an SQL statement almost
everywhere that an expression is valid. There are a few restrictions of UDF usage,
however:
v UDFs and system generated functions cannot be specified in check constraints.
Check constraints also cannot contain references to the built-in functions
DLVALUE, DLURLPATH, DLURLPATHONLY, DLURLSCHEME,
DLURLCOMPLETE, or DLURLSERVER.
v External UDFs, SQL UDFS and the built-in functions DLVALUE, DLURLPATH,
DLURLPATHONLY, DLURLSCHEME, DLURLCOMPLETE, and DLURLSERVER
cannot be referenced in an ORDER BY or GROUP BY clause, unless the SQL
statement is read-only and allows temporary processing (ALWCPYDTA(*YES) or
(*OPTIMIZE).

164 DB2 UDB for AS/400 SQL Programming V4R4


The DB2 UDB for AS/400 SQL Reference discusses all these contexts in detail.
The discussion and examples used in this section focus on relatively simple
SELECT statement contexts, but note that their use is not restricted to these
contexts.

Refer to “UDF Concepts” on page 158 for a summary of the use and importance of
the path and the function resolution algorithm. You can find the details for both of
these concepts in the DB2 UDB for AS/400 SQL Reference. The resolution of any
Data Manipulation Language (DML) reference to a function uses the function
resolution algorithm, so it is important to understand how it works.

Referring to Functions
Each reference to a function, whether it is a UDF, or a built-in function, contains the
following syntax:

ÊÊ function_name ( ) ÊÍ
ALL ,
DISTINCT
· expression

| In the above, function_name can be either an unqualified or a qualified function


| name. Note that when using the *SYS naming convention, functions cannot be
| qualified. The arguments can number from 0 to 90, and are expressions which may
| contain:
| v A column name, qualified or unqualified
| v A constant
| v A host variable
| v A special register
| v A parameter marker with a CAST function
| v An expression
| v A function

| The position of the arguments is important and must conform to the function
| definition for the semantics to be correct. Both the position of the arguments and
| the function definition must conform to the function body itself. DB2 does not
| attempt to shuffle arguments to better match a function definition, and DB2 does not
| attempt to determine the semantics of the individual function parameters.

Examples of Function Invocations


| Some valid examples of function invocations are:
| AVG(FLOAT_COLUMN)
| BLOOP(COLUMN1)
| BLOOP(FLOAT_COLUMN + CAST(? AS INTEGER))
| BLOOP(:hostvar :indicvar)
| BRIAN.PARSE(CONCAT(CHAR_COLUMN,USER, 1, 0, 0, 1)
| CTR()
| FLOOR(FLOAT_COLUMN)
| PABLO.BLOOP(A+B)
| PABLO.BLOOP(:hostvar)
| "search_schema"(CURRENT PATH, 'GENE')
| SUBSTR(COLUMN2,8,3)

Chapter 8. Using the Object-Relational Capabilities 165


| QSYS2.FLOOR(AVG(EMP.SALARY))
| QSYS2.AVG(QSYS2.FLOOR(EMP.SALARY))
| QSYS2.SUBSTR(COLUMN2,11,LENGTH(COLUMN3))

| Using Parameter Markers in Functions


An important restriction involves parameter markers; you cannot simply code the
following:
BLOOP(?)

As the function selection logic does not know what data type the argument may turn
out to be, it cannot resolve the reference. You can use the CAST specification to
provide a type for the parameter marker, for example INTEGER, and then the
function selection logic can proceed:
BLOOP(CAST(? AS INTEGER))

Using Qualified Function Reference


If you use a qualified function reference, you restrict DB2’s search for a matching
function to that schema. For example, you have the following statement:
SELECT PABLO.BLOOP(COLUMN1) FROM T

Only the BLOOP functions in schema PABLO are considered. It does not matter
that user SERGE has defined a BLOOP function, or whether or not there is a
built-in BLOOP function. Now suppose that user PABLO has defined two BLOOP
functions in his schema:
CREATE FUNCTION BLOOP (INTEGER) RETURNS ...
CREATE FUNCTION BLOOP (DOUBLE) RETURNS ...

BLOOP is thus overloaded within the PABLO schema, and the function selection
algorithm would choose the best BLOOP, depending on the data type of the
argument, column1. In this case, both of the PABLO.BLOOPs take numeric
arguments, and if column1 is not one of the numeric types, the statement will fail.
On the other hand if column1 is either SMALLINT or INTEGER, function selection
will resolve to the first BLOOP, while if column1 is DECIMAL or DOUBLE, the
second BLOOP will be chosen.

Several points about this example:


1. It illustrates argument promotion. The first BLOOP is defined with an INTEGER
parameter, yet you can pass it a SMALLINT argument. The function selection
algorithm supports promotions among the built-in data types (for details, see the
DB2 UDB for AS/400 SQL Reference) and DB2 performs the appropriate data
value conversions.
2. If for some reason you want to invoke the second BLOOP with a SMALLINT or
INTEGER argument, you have to take an explicit action in your statement as
follows:
SELECT PABLO.BLOOP(DOUBLE(COLUMN1)) FROM T
3. Alternatively, if you want to invoke the first BLOOP with a DECIMAL or DOUBLE
argument, you have your choice of explicit actions, depending on your exact
intent:
| SELECT PABLO.BLOOP(INTEGER(COLUMN1)) FROM T
| SELECT PABLO.BLOOP(FLOOR(COLUMN1)) FROM T

| You should investigate these other functions in the DB2 UDB for AS/400 SQL
| Reference. The INTEGER function is a built-in function in the QSYS2 schema.

166 DB2 UDB for AS/400 SQL Programming V4R4


Using Unqualified Function Reference
| If, instead of a qualified function reference, you use an unqualified function
| reference, DB2’s search for a matching function normally uses the function path to
| qualify the reference. In the case of the DROP FUNCTION or COMMENT ON
| FUNCTION functions, the reference is qualified using the current authorization ID, if
| they are unqualified for *SQL naming, or *LIBL for *SYS naming. Thus, it is
| important that you know what your function path is, and what, if any, conflicting
| functions exist in the schemas of your current function path. For example, suppose
| you are PABLO and your static SQL statement is as follows, where COLUMN1 is data
| type INTEGER:
| SELECT BLOOP(COLUMN1) FROM T

| You have created the two BLOOP functions cited in “Using Qualified Function
| Reference” on page 166, and you want and expect one of them to be chosen. If the
| following default function path is used, the first BLOOP is chosen (since column1 is
| INTEGER), if there is no conflicting BLOOP in QSYS or QSYS2:
| "QSYS","QSYS2","PABLO"

| However, suppose you have forgotten that you are using a script for precompiling
and binding which you previously wrote for another purpose. In this script, you
explicitly coded your SQLPATH parameter to specify the following function path for
another reason that does not apply to your current work:
"KATHY","QSYS","QSYS2","PABLO"

If Kathy has written a BLOOP function for her own purposes, the function selection
could very well resolve to Kathy’s function, and your statement would execute
without error. You are not notified because DB2 assumes that you know what you
are doing. It becomes your responsibility to identify the incorrect output from your
statement and make the required correction.

Summary of Function References


For both qualified and unqualified function references, the function selection
algorithm looks at all the applicable functions, both built-in and user-defined, that
have:
v The given name
v The same number of defined parameters as arguments in the function reference
v Each parameter identical to or promotable from the type of the corresponding
argument.
(Applicable functions means functions in the named schema for a qualified
reference, or functions in the schemas of the function path for an unqualified
reference.) The algorithm looks for an exact match, or failing that, a best match
among these functions. The current function path is used, in the case of an
unqualified reference only, as the deciding factor if two identically good matches are
found in different schemas. The details of the algorithm can be found in the DB2
UDB for AS/400 SQL Reference.

An interesting feature, illustrated by the examples at the end of “Using Qualified


Function Reference” on page 166, is the fact that function references can be
nested, even references to the same function. This is generally true for built-in
functions as well as UDFs; however, there are some limitations when column
functions are involved.

Chapter 8. Using the Object-Relational Capabilities 167


Refining an earlier example:
CREATE FUNCTION BLOOP (INTEGER) RETURNS INTEGER ...
CREATE FUNCTION BLOOP (DOUBLE) RETURNS INTEGER ...

Now consider the following DML statement:


SELECT BLOOP( BLOOP(COLUMN1)) FROM T

If column1 is a DECIMAL or DOUBLE column, the inner BLOOP reference resolves


to the second BLOOP defined above. Because this BLOOP returns an INTEGER,
the outer BLOOP resolves to the first BLOOP.

Alternatively, if column1 is a SMALLINT or INTEGER column, the inner bloop


reference resolves to the first BLOOP defined above. Because this BLOOP returns
an INTEGER, the outer BLOOP also resolves to the first BLOOP. In this case, you
are seeing nested references to the same function.

A few additional points important for function references are:


v You can define a function with the name of one of the SQL operators. For
example, suppose you can attach some meaning to the "+" operator for values
which have distinct type BOAT. You can define the following UDF:
CREATE FUNCTION "+" (BOAT, BOAT) RETURNS ...

Then you can write the following valid SQL statement:


SELECT "+"(BOAT_COL1, BOAT_COL2)
FROM BIG_BOATS
WHERE BOAT_OWNER = 'Nelson Mattos'

Note that you are not permitted to overload the built-in conditional operators such
as >, =, LIKE, IN, and so on, in this way.
v The function selection algorithm does not consider the context of the reference in
resolving to a particular function. Look at these BLOOP functions, modified a bit
from before:
CREATE FUNCTION BLOOP (INTEGER) RETURNS INTEGER ...
CREATE FUNCTION BLOOP (DOUBLE) RETURNS CHAR(10)...

Now suppose you write the following SELECT statement:


SELECT 'ABCDEFG' CONCAT BLOOP(SMALLINT_COL) FROM T

Because the best match, resolved using the SMALLINT argument, is the first
BLOOP defined above, the second operand of the CONCAT resolves to data
type INTEGER. The statement fails because CONCAT demands string
arguments. If the first BLOOP was not present, the other BLOOP would be
chosen and the statement execution would be successful.
| v UDFs can be defined with parameters or results having any of the LOB types:
| BLOB, CLOB, or DBCLOB. DB2 will materialize the entire LOB value in storage
| before invoking such a function, even if the source of the value is a LOB locator
| host variable. For example, consider the following fragment of a C language
| application:
| EXEC SQL BEGIN DECLARE SECTION;
| SQL TYPE IS CLOB(150K) clob150K ; /* LOB host var */
| SQL TYPE IS CLOB_LOCATOR clob_locator1; /* LOB locator host var */
| char string[40]; /* string host var */
| EXEC SQL END DECLARE SECTION;

168 DB2 UDB for AS/400 SQL Programming V4R4


| Either host variable :clob150K or :clob_locator1 is valid as an argument for a
| function whose corresponding parameter is defined as CLOB(500K). Thus,
| referring to the FINDSTRING defined in “Example: String Search” on page 162,
| both of the following are valid in the program:
| ... SELECT FINDSTRING (:clob150K, :string) FROM ...
| ... SELECT FINDSTRING (:clob_locator1, :string) FROM ...
| v Non-SQL UDF parameters or results which have one of the LOB types can be
| created with the AS LOCATOR modifier. In this case, the entire LOB value is not
| materialized prior to invocation. Instead, a LOB LOCATOR is passed to the UDF.
| You can also use this capability on UDF parameters or results which have a
| distinct type that is based on a LOB. This capability is limited to non-SQL UDFs.
| Note that the argument to such a function can be any LOB value of the defined
| type; it does not have to be a host variable defined as one of the LOCATOR
| types. The use of host variable locators as arguments is completely unrelated to
| the use of AS LOCATOR in UDF parameters and result definitions.
v UDFs can be defined with distinct types as parameters or as the result. (Earlier
examples have illustrated this.) DB2 will pass the value to the UDF in the format
of the source data type of the distinct type.
Distinct type values which originate in a host variable and which are used as
arguments to a UDF which has its corresponding parameter defined as a distinct
type, must be explicitly cast to the distinct type by the user. There is no host
language type for distinct types. DB2’s strong typing necessitates this. Otherwise
your results may be ambiguous. So, consider the BOAT distinct type which is
defined over a BLOB, and consider the BOAT_COST UDF from “Example:
External Function with UDT Parameter” on page 163, which takes an object of
type BOAT as its argument. In the following fragment of a C language
application, the host variable :ship holds the BLOB value that is to passed to the
BOAT_COST function:
EXEC SQL BEGIN DECLARE SECTION;
SQL TYPE IS BLOB(150K) ship;
EXEC SQL END DECLARE SECTION;

Both of the following statements correctly resolve to the BOAT_COST function,


because both cast the :ship host variable to type BOAT:
... SELECT BOAT_COST (BOAT(:ship)) FROM ...
... SELECT BOAT_COST (CAST(:ship AS BOAT)) FROM ...

If there are multiple BOAT distinct types in the database, or BOAT UDFs in other
schema, you must exercise care with your function path. Otherwise your results
may be ambiguous.

User-defined Distinct Types (UDT)


Enabling you to define new data types to DB2 gives you considerable power and
extends your capabilities with the built-in data types. You are no longer restricted to
using system-supplied built-in data types to model your businesses and capture the
semantics of your data. A user-defined distinct type is the DB2 mechanism you can
use for this purpose.

Why Use UDTs?


There are several benefits associated with UDTs:
1. Extensibility.

Chapter 8. Using the Object-Relational Capabilities 169


By defining new types, you can indefinitely increase the set of types provided by
DB2 to support your applications.
2. Flexibility.
You can specify any semantics and behavior for your new type by using
user-defined functions (UDFs) to augment the diversity of the types available in
the system.
3. Consistent behavior.
Strong typing insures that your UDTs will behave appropriately. It guarantees
that only functions defined on your UDT can be applied to instances of the UDT.
4. Encapsulation.
The behavior of your UDTs is restricted by the functions and operators that can
be applied on them. This provides flexibility in the implementation since running
applications do not depend on the internal representation that you chose for
your type.
5. Extensible behavior.
The definition of user-defined functions on types can augment the functionality
provided to manipulate your UDT at any time. (See “User-Defined Functions
(UDF)” on page 156)
6. Performance.
Distinct types are highly integrated into the database manager. Because distinct
types are internally represented the same way as built-in data types, they share
the same efficient code used to implement built-in functions, comparison
operators, indexes, etc. for built-in data types.
7. Foundation for object-oriented extensions.
UDTs are the foundation for most object-oriented features. They represent the
most important step towards object-oriented extensions.

Defining a UDT
UDTs, like other objects such as tables, indexes, and UDFs, need to be defined
with a CREATE statement.

Use the CREATE DISTINCT TYPE statement to define your new UDT. Detailed
explanations for the statement syntax and all its options are found in the DB2 UDB
for AS/400 SQL Reference.

| For the CREATE DISTINCT TYPE statement, note that:


| 1. The name of the new UDT can be a qualified or an unqualified name.
| 2. The source type of the UDT is the type used by DB2 to internally represent the
| UDT. For this reason, it must be a built-in data type. Previously defined UDTs
| cannot be used as source types of other UDTs.
As part of a UDT definition, DB2 always generates cast functions to:
v Cast from the UDT to the source type, using the standard name of the source
type. For example, if you create a distinct type based on FLOAT, the cast
function called DOUBLE is created.
v Cast from the source type to the UDT. See the DB2 UDB for AS/400 SQL
Reference for a discussion of when additional casts to the UDTs are generated.
These functions are important for the manipulation of UDTs in queries.

170 DB2 UDB for AS/400 SQL Programming V4R4


Resolving Unqualified UDTs
The function path is used to resolve any references to an unqualified type name or
function, except if the type name or function is
v Created
v Dropped
v Commented on.
For information on how unqualified function references are resolved, see “Using
Qualified Function Reference” on page 166.

Examples of Using CREATE DISTINCT TYPE


The following are examples of using CREATE DISTINCT TYPE:
v Example: Money
v Example: Resume

Example: Money
Suppose you are writing applications that need to handle different currencies and
wish to ensure that DB2 does not allow these currencies to be compared or
manipulated directly with one another in queries. Remember that conversions are
necessary whenever you want to compare values of different currencies. So you
define as many UDTs as you need; one for each currency that you may need to
represent:
| CREATE DISTINCT TYPE US_DOLLAR AS DECIMAL (9,2)
| CREATE DISTINCT TYPE CANADIAN_DOLLAR AS DECIMAL (9,2)
| CREATE DISTINCT TYPE GERMAN_MARK AS DECIMAL (9,2)

| Example: Resume
| Suppose you would like to keep the form filled by applicants to your company in a
| DB2 table and you are going to use functions to extract the information from these
| forms. Because these functions cannot be applied to regular character strings
| (because they are certainly not able to find the information they are supposed to
| return), you define a UDT to represent the filled forms:
| CREATE DISTINCT TYPE PERSONAL.APPLICATION_FORM AS CLOB(32K)

| Defining Tables with UDTs


After you have defined several UDTs, you can start defining tables with columns
whose types are UDTs. Following are examples using CREATE TABLE:
v Example: Sales
v Example: Application Forms

Example: Sales
Suppose you want to define tables to keep your company’s sales in different
countries as follows:
CREATE TABLE US_SALES
(PRODUCT_ITEM INTEGER,
MONTH INTEGER CHECK (MONTH BETWEEN 1 AND 12),
YEAR INTEGER CHECK (YEAR > 1985),
TOTAL US_DOLLAR)

Chapter 8. Using the Object-Relational Capabilities 171


CREATE TABLE CANADIAN_SALES
(PRODUCT_ITEM INTEGER,
MONTH INTEGER CHECK (MONTH BETWEEN 1 AND 12),
YEAR INTEGER CHECK (YEAR > 1985),
TOTAL CANADIAN_DOLLAR)

CREATE TABLE GERMAN_SALES


(PRODUCT_ITEM INTEGER,
MONTH INTEGER CHECK (MONTH BETWEEN 1 AND 12),
YEAR INTEGER CHECK (YEAR > 1985),
TOTAL GERMAN_MARK)

The UDTs in the above examples are created using the same CREATE DISTINCT
TYPE statements in “Example: Money” on page 171. Note that the above examples
use check constraints. For information on check constraints see the DB2 UDB for
AS/400 SQL Reference.

Example: Application Forms


Suppose you need to define a table where you keep the forms filled out by
applicants as follows:
| CREATE TABLE APPLICATIONS
| (ID INTEGER,
| NAME VARCHAR (30),
| APPLICATION_DATE DATE,
| FORM PERSONAL.APPLICATION_FORM)

| You have fully qualified the UDT name because its qualifier is not the same as your
| authorization ID and you have not changed the default function path. Remember
| that whenever type and function names are not fully qualified, DB2 searches
| through the schemas listed in the current function path and looks for a type or
| function name matching the given unqualified name.

| .

Manipulating UDTs
One of the most important concepts associated with UDTs is strong typing. Strong
typing guarantees that only functions and operators defined on the UDT can be
applied to its instances.

Strong typing is important to ensure that the instances of your UDTs are correct.
For example, if you have defined a function to convert US dollars to Canadian
dollars according to the current exchange rate, you do not want this same function
to be used to convert German marks to Canadian dollars because it will certainly
return the wrong amount.

As a consequence of strong typing, DB2 does not allow you to write queries that
compare, for example, UDT instances with instances of the UDT source type. For
the same reason, DB2 will not let you apply functions defined on other types to
UDTs. If you want to compare instances of UDTs with instances of another type,
you have to cast the instances of one or the other type. In the same sense, you
have to cast the UDT instance to the type of the parameter of a function that is not
defined on a UDT if you want to apply this function to a UDT instance.

172 DB2 UDB for AS/400 SQL Programming V4R4


Examples of Manipulating UDTs
The following are examples of manipulating UDTs:
v Example: Comparisons Between UDTs and Constants
v Example: Casting Between UDTs
v Example: Comparisons Involving UDTs
v Example: Sourced UDFs Involving UDTs
v Example: Assignments Involving UDTs
v Example: Assignments in Dynamic SQL
v Example: Assignments Involving Different UDTs
v Example: Use of UDTs in UNION

Example: Comparisons Between UDTs and Constants


Suppose you want to know which products sold more than US $100 000.00 in the
US in the month of July, 1992 (7/92).
SELECT PRODUCT_ITEM
FROM US_SALES
WHERE TOTAL > US_DOLLAR (100000)
AND month = 7
AND year = 1992

Because you cannot compare US dollars with instances of the source type of US
dollars (that is, DECIMAL) directly, you have used the cast function provided by
DB2 to cast from DECIMAL to US dollars. You can also use the other cast function
provided by DB2 (that is, the one to cast from US dollars to DECIMAL) and cast the
column total to DECIMAL. Either way you decide to cast, from or to the UDT, you
can use the cast specification notation to perform the casting, or the functional
notation. That is, you could have written the above query as:
SELECT PRODUCT_ITEM
FROM US_SALES
WHERE TOTAL > CAST (100000 AS us_dollar)
AND MONTH = 7
AND YEAR = 1992

Example: Casting Between UDTs


Suppose you want to define a UDF that converts Canadian dollars to U.S. dollars.
Suppose you can obtain the current exchange rate from a file managed outside of
DB2. You would then define a UDF that obtains a value in Canadian dollars,
accesses the exchange rate file, and returns the corresponding amount in U.S.
dollars.

At first glance, such a UDF may appear easy to write. However, not all C compilers
support DECIMAL values. The UDTs representing different currencies have been
defined as DECIMAL. Your UDF will need to receive and return DOUBLE values,
since this is the only data type provided by C that allows the representation of a
DECIMAL value without losing the decimal precision. Thus, your UDF should be
defined as follows:
| CREATE FUNCTION CDN_TO_US_DOUBLE(DOUBLE) RETURNS DOUBLE
| EXTERNAL NAME 'MYLIB/CURRENCIES(C_CDN_US)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| NO SQL
| NOT DETERMINISTIC

Chapter 8. Using the Object-Relational Capabilities 173


| The exchange rate between Canadian and U.S. dollars may change between two
invocations of the UDF, so you declare it as NOT DETERMINISTIC.

The question now is, how do you pass Canadian dollars to this UDF and get U.S.
dollars from it? The Canadian dollars must be cast to DECIMAL values. The
DECIMAL values must be cast to DOUBLE. You also need to have the returned
DOUBLE value cast to DECIMAL and the DECIMAL value cast to U.S. dollars.

Such casts are performed automatically by DB2 anytime you define sourced UDFs,
whose parameter and return type do not exactly match the parameter and return
type of the source function. Therefore, you need to define two sourced UDFs. The
first brings the DOUBLE values to a DECIMAL representation. The second brings
the DECIMAL values to the UDT. That is, you define the following:
CREATE FUNCTION CDN_TO_US_DEC (DECIMAL(9,2)) RETURNS DECIMAL(9,2)
SOURCE CDN_TO_US_DOUBLE (DOUBLE)

CREATE FUNCTION US_DOLLAR (CANADIAN_DOLLAR) RETURNS US_DOLLAR


SOURCE CDN_TO_US_DEC (DECIMAL())

Note that an invocation of the US_DOLLAR function as in US_DOLLAR(C1), where C1 is


a column whose type is Canadian dollars, has the same effect as invoking:
US_DOLLAR (DECIMAL(CDN_TO_US_DOUBLE (DOUBLE (DECIMAL (C1)))))

That is, C1 (in Canadian dollars) is cast to decimal which in turn is cast to a double
value that is passed to the CDN_TO_US_DOUBLE function. This function accesses the
exchange rate file and returns a double value (representing the amount in U.S.
dollars) that is cast to decimal, and then to U.S. dollars.

A function to convert German marks to U.S. dollars would be similar to the example
above:
| CREATE FUNCTION GERMAN_TO_US_DOUBLE(DOUBLE)
| RETURNS DOUBLE
| EXTERNAL NAME 'MYLIB/CURRENCIES(C_GER_US)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| NO SQL
| NOT DETERMINISTIC
|
| CREATE FUNCTION GERMAN_TO_US_DEC (DECIMAL(9,2))
| RETURNS DECIMAL(9,2)
| SOURCE GERMAN_TO_US_DOUBLE(DOUBLE)
|
| CREATE FUNCTION US_DOLLAR(GERMAN_MARK) RETURNS US_DOLLAR
| SOURCE GERMAN_TO_US_DEC (DECIMAL())

Example: Comparisons Involving UDTs


Suppose you want to know which products sold more in the US than in Canada and
Germany for the month of March, 1989 (3/89):
SELECT US.PRODUCT_ITEM, US.TOTAL
FROM US_SALES AS US, CANADIAN_SALES AS CDN, GERMAN_SALES AS GERMAN
WHERE US.PRODUCT_ITEM = CDN.PRODUCT_ITEM
AND US.PRODUCT_ITEM = GERMAN.PRODUCT_ITEM
AND US.TOTAL > US_DOLLAR (CDN.TOTAL)
AND US.TOTAL > US_DOLLAR (GERMAN.TOTAL)
AND US.MONTH = 3
AND US.YEAR = 1989

174 DB2 UDB for AS/400 SQL Programming V4R4


AND CDN.MONTH = 3
AND CDN.YEAR = 1989
AND GERMAN.MONTH = 3
AND GERMAN.YEAR = 1989

Because you cannot directly compare US dollars with Canadian dollars or German
Marks, you use the UDF to cast the amount in Canadian dollars to US dollars, and
the UDF to cast the amount in German Marks to US dollars. You cannot cast them
all to DECIMAL and compare the converted DECIMAL values because the amounts
are not monetarily comparable. That is, the amounts are not in the same currency.

Example: Sourced UDFs Involving UDTs


Suppose you have defined a sourced UDF on the built-in SUM function to support
SUM on German Marks:
CREATE FUNCTION SUM (GERMAN_MARKS)
RETURNS GERMAN_MARKS
SOURCE SYSIBM.SUM (DECIMAL())

You want to know the total of sales in Germany for each product in the year of
1994. You would like to obtain the total sales in US dollars:
SELECT PRODUCT_ITEM, US_DOLLAR (SUM (TOTAL))
FROM GERMAN_SALES
WHERE YEAR = 1994
GROUP BY PRODUCT_ITEM

You could not write SUM (us_dollar (total)), unless you had defined a SUM
function on US dollar in a manner similar to the above.

Example: Assignments Involving UDTs


Suppose you want to store the form filled by a new applicant into the database. You
have defined a host variable containing the character string value used to represent
the filled form:
EXEC SQL BEGIN DECLARE SECTION;
SQL TYPE IS CLOB(32K) hv_form;
EXEC SQL END DECLARE SECTION;

/* Code to fill hv_form */

INSERT INTO APPLICATIONS


VALUES (134523, 'Peter Holland', CURRENT DATE, :hv_form)

You do not explicitly invoke the cast function to convert the character string to the
UDT personal.application_form . This is because DB2 lets you assign instances
of the source type of a UDT to targets having that UDT.

Example: Assignments in Dynamic SQL


If you want to use the same statement given in “Example: Assignments Involving
UDTs” in dynamic SQL, you can use parameter markers as follows:
EXEC SQL BEGIN DECLARE SECTION;
long id;
char name[30];
SQL TYPE IS CLOB(32K) form;
char command[80];
EXEC SQL END DECLARE SECTION;

/* Code to fill host variables */

Chapter 8. Using the Object-Relational Capabilities 175


strcpy(command,"INSERT INTO APPLICATIONS VALUES");
strcat(command,"(?, ?, CURRENT DATE, ?)");

EXEC SQL PREPARE APP_INSERT FROM :command;


EXEC SQL EXECUTE APP_INSERT USING :id, :name, :form;

You made use of DB2’s cast specification to tell DB2 that the type of the parameter
marker is CLOB(32K), a type that is assignable to the UDT column. Remember that
you cannot declare a host variable of a UDT type, since host languages do not
support UDTs. Therefore, you cannot specify that the type of a parameter marker is
a UDT.

Example: Assignments Involving Different UDTs


Suppose you have defined two sourced UDFs on the built-in SUM function to
support SUM on US and Canadian dollars, similar to the UDF sourced on German
Marks in “Example: Sourced UDFs Involving UDTs” on page 175:

CREATE FUNCTION SUM (CANADIAN_DOLLAR)


RETURNS CANADIAN_DOLLAR
SOURCE SYSIBM.SUM (DECIMAL())

CREATE FUNCTION SUM (US_DOLLAR)


RETURNS US_DOLLAR
SOURCE SYSIBM.SUM (DECIMAL())

Now suppose your supervisor requests that you maintain the annual total sales in
US dollars of each product and in each country, in separate tables:

CREATE TABLE US_SALES_94


(PRODUCT_ITEM INTEGER,
TOTAL US_DOLLAR)

CREATE TABLE GERMAN_SALES_94


(PRODUCT_ITEM INTEGER,
TOTAL US_DOLLAR)

CREATE TABLE CANADIAN_SALES_94


(PRODUCT_ITEM INTEGER,
TOTAL US_DOLLAR)

INSERT INTO US_SALES_94


SELECT PRODUCT_ITEM, SUM (TOTAL)
FROM US_SALES
WHERE YEAR = 1994
GROUP BY PRODUCT_ITEM

INSERT INTO GERMAN_SALES_94


SELECT PRODUCT_ITEM, US_DOLLAR (SUM (TOTAL))
FROM GERMAN_SALES
WHERE YEAR = 1994
GROUP BY PRODUCT_ITEM

INSERT INTO CANADIAN_SALES_94


SELECT PRODUCT_ITEM, US_DOLLAR (SUM (TOTAL))
FROM CANADIAN_SALES
WHERE YEAR = 1994
GROUP BY PRODUCT_ITEM

176 DB2 UDB for AS/400 SQL Programming V4R4


You explicitly cast the amounts in Canadian dollars and German Marks to US
dollars since different UDTs are not directly assignable to each other. You cannot
use the cast specification syntax because UDTs can only be cast to their own
source type.

Example: Use of UDTs in UNION


Suppose you would like to provide your American users with a view containing all
the sales of every product of your company:
CREATE VIEW ALL_SALES AS
SELECT PRODUCT_ITEM, MONTH, YEAR, TOTAL
FROM US_SALES
UNION
SELECT PRODUCT_ITEM, MONTH, YEAR, US_DOLLAR (TOTAL)
FROM CANADIAN_SALES
UNION
SELECT PRODUCT_ITEM, MONTH, YEAR, US_DOLLAR (TOTAL)
FROM GERMAN_SALES

You cast Canadian dollars to US dollars and German Marks to US dollars because
UDTs are union compatible only with the same UDT. You must use the functional
notation to cast between UDTs since the cast specification only lets you cast
between UDTs and their source types.

Synergy Between UDTs, UDFs, and LOBs


In previous sections, you learned how to define and use the individual DB2 object
extensions (UDTs, UDFs, and LOBs). However, as you will see in this section, there
is a lot of synergy between these three object extensions.

Combining UDTs, UDFs, and LOBs


According to the concept of object-orientation, similar objects in the application
domain are grouped into related types. Each of these types have a name, an
internal representation, and behavior. By using UDTs, you can tell DB2 the name of
your new type and how it is internally represented. A LOB is one of the possible
internal representations for your new type and is the most suitable representation
for large, complex structures. By using UDFs, you can define the behavior of the
new type. Consequently, there is an important synergy between UDTs, UDFs, and
LOBs. An application type with a complex data structure and behavior is modeled
as a UDT that is internally represented as a LOB, with its behavior implemented by
UDFs. The rules governing the semantic integrity of your application type will be
represented as constraints and triggers. To have better control and organization of
your related UDTs and UDFs, you should keep them in the same schema.

Examples of Complex Applications


The following examples show how you can use UDTs, UDFs, and LOBs together in
complex applications:
Example: Defining the UDT and UDFs
Example: Exploiting LOB Function to Populate the Database
Example: Exploiting UDFs to Query Instances of UDTs
Example: Exploiting LOB Locators to Manipulate UDT Instances

Chapter 8. Using the Object-Relational Capabilities 177


Example: Defining the UDT and UDFs
Suppose you would like to keep the electronic mail (e-mail) sent to your company in
DB2 tables. Ignoring any issues of privacy, you plan to write queries over such
e-mail to find out their subject, how often your e-mail service is used to receive
customer orders, and so on. E-mail can be quite large, and it has a complex
internal structure (a sender, a receiver, the subject, date, and the e-mail content).
Therefore, you decide to represent the e-mail by means of a UDT whose source
type is a large object. You define a set of UDFs on your e-mail type, such as
functions to extract the subject of the e-mail, the sender, the date, and so on. You
also define functions that can perform searches on the content of the e-mail. You do
the above using the following CREATE statements:
| CREATE DISTINCT TYPE E_MAIL AS BLOB (1M)
|
| CREATE FUNCTION SUBJECT (E_MAIL)
| RETURNS VARCHAR (200)
| EXTERNAL NAME 'LIB/PGM(SUBJECT)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| NO SQL
| DETERMINISTIC
| NO EXTERNAL ACTION
|
| CREATE FUNCTION SENDER (E_MAIL)
| RETURNS VARCHAR (200)
| EXTERNAL NAME 'LIB/PGM(SENDER)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| NO SQL
| DETERMINISTIC
| NO EXTERNAL ACTION
|
| CREATE FUNCTION RECEIVER (E_MAIL)
| RETURNS VARCHAR (200)
| EXTERNAL NAME 'LIB/PGM(RECEIVER)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| NO SQL
| DETERMINISTIC
| NO EXTERNAL ACTION
|
| CREATE FUNCTION SENDING_DATE (E_MAIL)
| RETURNS DATE CAST FROM VARCHAR(10)
| EXTERNAL NAME 'LIB/PGM(SENDING_DATE)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| NO SQL
| DETERMINISTIC
| NO EXTERNAL ACTION
|
| CREATE FUNCTION CONTENTS (E_MAIL)
| RETURNS BLOB (1M)
| EXTERNAL NAME 'LIB/PGM(CONTENTS)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| NO SQL
| DETERMINISTIC
| NO EXTERNAL ACTION
|
| CREATE FUNCTION CONTAINS (E_MAIL, VARCHAR (200))
| RETURNS INTEGER
| EXTERNAL NAME 'LIB/PGM(CONTAINS)'
| LANGUAGE C
| PARAMETER STYLE DB2SQL

178 DB2 UDB for AS/400 SQL Programming V4R4


| NO SQL
| DETERMINISTIC
| NO EXTERNAL ACTION
|
| CREATE TABLE ELECTRONIC_MAIL
| (ARRIVAL_TIMESTAMP TIMESTAMP,
| MESSAGE E_MAIL)

Example: Exploiting LOB Function to Populate the Database


Suppose you populate your table by transferring your e-mail that is maintained in
files into DB2. You would execute the following INSERT statement multiple times
with different values of the HV_EMAIL_FILE until you have stored all your e_mail
into DB2:
EXEC SQL BEGIN DECLARE SECTION
SQL TYPE IS BLOB_FILE HV_EMAIL_FILE;

EXEC SQL END DECLARE SECTION


strcpy (HV_EMAIL_FILE.NAME, "/u/mail/email/mbox");
HV_EMAIL_FILE.NAME_LENGTH = strlen(HV_EMAIL_FILE.NAME);
HV_EMAIL_FILE.FILE_OPTIONS = 2;

EXEC SQL INSERT INTO ELECTRONIC_MAIL


VALUES (CURRENT TIMESTAMP, :hv_email_file);

| All the function provided by DB2 LOB support is applicable to UDTs whose source
| type are LOBs. Therefore, you have used LOB file reference variables to assign the
| contents of the file into the UDT column. You have not used the cast function to
| convert values of BLOB type into your e-mail type. This is because DB2 let you
| assign values of the source type of a distinct type to targets to the distinct type.

Example: Exploiting UDFs to Query Instances of UDTs


Suppose you need to know how much e-mail was sent by a specific customer
regarding customer orders and you have the e-mail address of your customers in
the customers table.
SELECT COUNT (*)
FROM ELECTRONIC_MAIL AS EMAIL, CUSTOMERS
WHERE SUBJECT (EMAIL.MESSAGE) = 'customer order'
AND CUSTOMERS.EMAIL_ADDRESS = SENDER (EMAIL.MESSAGE)
AND CUSTOMERS.NAME = 'Customer X'

You have used the UDFs defined on the UDT in this SQL query since they are the
only means to manipulate the UDT. In this sense, your UDT e-mail is completely
encapsulated. That is, its internal representation and structure are hidden and can
only be manipulated by the defined UDFs. These UDFs know how to interpret the
data without the need to expose its representation.

Suppose you need to know the details of all the e-mail your company received in
1994 which had to do with the performance of your products in the marketplace.
SELECT SENDER (MESSAGE), SENDING_DATE (MESSAGE), SUBJECT (MESSAGE)
FROM ELECTRONIC_MAIL

WHERE CONTAINS (MESSAGE,

'"performance" AND "products" AND "marketplace"') = 1

You have used the contains UDF which is capable of analyzing the contents of the
message searching for relevant keywords or synonyms.

Chapter 8. Using the Object-Relational Capabilities 179


Example: Exploiting LOB Locators to Manipulate UDT Instances
Suppose you would like to obtain information about a specific e-mail without having
to transfer the entire e-mail into a host variable in your application program.
(Remember that an e-mail can be quite large.) Since your UDT is defined on a
LOB, you can use LOB locators for that purpose:
EXEC SQL BEGIN DECLARE SECTION
long hv_len;
char hv_subject[200];
char hv_sender[200];
char hv_buf[4096];
char hv_current_time[26];
SQL TYPE IS BLOB_LOCATOR hv_email_locator;
EXEC SQL END DECLARE SECTION

EXEC SQL SELECT MESSAGE


INTO :hv_email_locator
FROM ELECTRONIC MAIL
WHERE ARRIVAL_TIMESTAMP = :hv_current_time;

EXEC SQL VALUES (SUBJECT (E_MAIL(:hv_email_locator))


INTO :hv_subject;
.... code that checks if the subject of the e_mail is relevant ....
.... if the e_mail is relevant, then...............................

EXEC SQL VALUES (SENDER (CAST (:hv_email_locator AS E_MAIL)))


INTO :hv_sender;

Because your host variable is of type BLOB locator (the source type of the UDT),
you have explicitly converted the BLOB locator to your UDT, whenever it was used
as an argument of a UDF defined on the UDT.

Using DataLinks
The DataLink data type is one of the basic building blocks for extending the types
of data that can be stored in database files. The idea of a DataLink is that the
actual data stored in the column is only a pointer to the object. This object can be
anything, an image file, a voice recording, a text file, etc. The method used for
resolving to the object is to store a Uniform Resource Locator (URL). This means
that a row in a table can be used to contain information about the object in
traditional data types, and the object itself can be referenced using the DataLink
data type. The user can use new SQL scalar functions to get back the path to the
object and the server on which the object is stored. With the DataLink data type,
there is a fairly loose relationship between the row and the object. For instance,
deleting a row will sever the relationship to the object referenced by the DataLink,
but the object itself might not be deleted.

An SQL table created with a DataLink column can be used to hold information
about an object, without actually containing the object itself. This concept gives the
user much more flexibility in the types of data that can be managed using an SQL
table. If, for instance, the user has thousands of video clips stored in the integrated
file system of their AS/400, they may want to use an SQL table to contain
information about these video clips. But since the user already has the objects
stored in a directory, they simply want the SQL table to contain references to the
objects, not contain the actual bytes of storage. A good solution would be to use
DataLinks. The SQL table would use traditional SQL data types to contain
information about each clip, such as title, length, date, etc. But the clip itself would
be referenced using a DataLink column. Each row in the table would store a URL

180 DB2 UDB for AS/400 SQL Programming V4R4


for the object and an optional comment. Then an application that is working with the
clips can retrieve the URL using SQL interfaces, and then use a browser or other
playback software to work with the URL and display the video clip.

There are several advantages to using this technique:


v The integrated file system can store any type of stream file.
v The integrated file system can store extremely large objects, that would not fit
into a character column, or perhaps even a LOB column.
v The hierarchical nature of the integrated file system is well-suited to organizing
and working with the stream file objects.
v By leaving the bytes of the object outside the database and in the integrated file
system, applications can achieve better performance by allowing the SQL runtime
engine to handle queries and reports, and allowing the file system to handle
streaming of video, displaying images, text, etc.

Using DataLinks also gives control over the objects while they are in ″linked″ status.
A DataLink column can be created such that the referenced object cannot be
deleted, moved, or renamed while there is a row in the SQL table that references
that object. This object would be considered linked. Once the row containing that
reference is deleted, the object is unlinked. To understand this concept fully, one
should know the levels of control that can be specified when creating a DataLink
column. Refer to the SQL Reference for the exact syntax used when creating
DataLink columns.

NO LINK CONTROL
When a column is created with NO LINK CONTROL, there is no linking that takes
place when rows are added to the SQL table. The URL is verified to be syntactically
correct, but there is no check to make sure that the server is accessible, or that the
file even exists.

FILE LINK CONTROL (with File System Permissions)


When the DataLink column is created as FILE LINK CONTROL with file system
(FS) permissions, the system will verify that any DataLink value is a valid URL, with
a valid server name and file name. The file must exist at the time that row is being
inserted into the SQL table. When the object is found, it will be marked as linked.
This means that the object cannot be moved, deleted, or renamed during the time
that it is linked. Also, an object cannot be linked more than once. If the server name
portion of the URL specifies a remote system, that system must be accessible. If a
row containing a DataLink value is deleted, the object is unlinked. If a DataLink
value is updated to a different value, the old object is unlinked, and the new object
is linked.

The integrated file system is still responsible for managing permissions for the
linked object. The permissions are not modified during the link or unlink processes.
This option provides control of the object’s existence for the duration of time that it
is linked.

FILE LINK CONTROL (with Database Permissions)


When the DataLink column is create as FILE LINK CONTROL with database
permissions, the URL is verified, and all existing permissions to the object are
removed. The ownership of the object is changed to a special system-supplied user

Chapter 8. Using the Object-Relational Capabilities 181


profile. During the time that the object is linked, the only access to the object is by
obtaining the URL from the SQL table that has the object linked. This is handled by
using a special access token that is appended to the URL returned by SQL. Without
the access token, all attempts to access the object will fail with an authority
violation. If the URL with the access token is retrieved from the SQL table by
normal means (FETCH, SELECT INTO, etc.) the file system filter will validate the
access token and allow the access to the object.

This option provides the control of preventing updates to the linked object for users
trying to access the object by direct means. Since the only access to the object is
by obtaining the access token from an SQL operation, an administrator can
effectively control access to the linked objects by using the database permissions to
the SQL table that contains the DataLink column.

Commands Used for Working with DataLinks


Support for the DataLink data type can be broken down into 3 different
components:
1. The DB2 database support has a data type called DATALINK. This can be
specified on SQL statements such as CREATE TABLE and ALTER TABLE. The
column cannot have any default other than NULL. Access to the data must be
using SQL interfaces. This is because the DATALINK itself is not compatible
with any host variable type. SQL scalar functions can be used to retrieve the
DATALINK value in character form. There is a DLVALUE scalar function that
must be used in SQL to INSERT and UPDATE the values in the column.
2. The DataLink File Manager (DLFM) is the component that maintains the link
status for the files on a server, and keeps track of meta-data for each file. This
code handles linking, unlinking, and commitment control issues. An important
aspect of DataLinks is that the DLFM need not be on the same physical system
as the SQL table that contains the DataLink column. So an SQL table can link
an object that resides in either the same system’s integrated file system, or a
remote AS/400’s integrated file system.
3. The DataLink filter must be executed when the file system tries operations
against files that are in directories designated as containing linked objects. This
component determines if the file is linked, and optionally, if the user is
authorized to access the file. If the file name includes an access token, the
token will be verified. Since there is extra overhead in this filter process, it is
only executed when the accessed object exists in one of the directories within a
DataLink ″prefix’. See the discussion below on prefixes.

When working with DataLinks, there are several steps that must be taken to
properly configure the system:
v TCP/IP must be configured on any systems that are going to be used when
working with DataLinks. This would include the systems on which the SQL tables
with DataLink columns are going to be created, as well as the systems that will
contain the objects to be linked. In most cases, this will be the same system.
Since the URL that is used to reference the object contains a TCP/IP server
name, this name must be recognized by the system that is going to contain the
DataLink. The command CFGTCP can be used to configure the TCP/IP names,
or to register a TCP/IP name server.
v The system that contains the SQL tables must have the Relational Database
Directory updated to reflect the local database system, and any optional remote
systems. The command WRKRDBDIRE can be used to add or modify

182 DB2 UDB for AS/400 SQL Programming V4R4


information in this directory. For consistency, it is recommended that the same
names be used as the TCP/IP server name and the Relational Database name.
v The DLFM server must be started on any systems that will contain objects to be
linked. The command STRTCPSVR *DLFM can be used to start the DLFM
server. The DLFM server can be ended by using the CL command ENDTCPSVR
*DLFM.

Once the DLFM has been started, there are some steps needed to configure the
DLFM. These DLFM functions are available via an executable script that can be
entered from the QShell interface. To get to the interactive shell interface, use the
CL command QSH. This will bring up a command entry screen from which you can
enter the DLFM script commands. The script command dfmadmin -help can be
used to display help text and syntax diagrams. For the most commonly used
functions, CL commands have also been provided. Using the CL commands, most
or all of the DLFM configuration can be accomplished without using the script
interface. Depending on your preferences, you can choose to use either the script
commands from the QSH command entry screen or the CL commands from the CL
command entry screen.

Since these functions are meant for a system administrator or a database


administrator, they all require the *IOSYSCFG special authority.

Adding a prefix - A prefix is a path or directory that will contain objects to be linked.
When setting up the DLFM on a system, the administrator must add any prefixes
that will be used for DataLinks. The script command dfmadmin -add_prefix is used
to add prefixes. The CL command to add prefixes is ADDPFXDLFM.

For instance, on server TESTSYS1, there is a directory called /mydir/datalinks/ that


contains the objects that will be linked. The administrator uses the command
ADDPFXDLFM PREFIX((’/mydir/datalinks/’)) to add the prefix. Now links for URLs
such as:
http://TESTSYS1/mydir/datalinks/videos/file1.mpg

or

file://TESTSYS1/mydir/datalinks/text/story1.txt

would be valid since their path begins with a valid prefix.

It is also possible to remove a prefix using the script command dfmadmin


-del_prefix. This is not a commonly used function since it can only be executed if
there are no linked objects anywhere in the directory structure contained within the
prefix name.

Adding a Host Database - A host database is a relational database system from


which a link request originates. If the DLFM is on the same system as the SQL
tables that will contain the DataLinks, then only the local database name needs to
be added. If the DLFM will have link requests coming from remote systems, then all
of their names must be registered with the DLFM. The script command to add a
host database is dfmadmin -add_db and the CL command is ADDHDBDLFM. This
function also requires that the libraries containing the SQL tables also be registered.

For instance, on server TESTSYS1, where you have already added the
/mydir/datalinks/ prefix, you want SQL tables on the local system in either library

Chapter 8. Using the Object-Relational Capabilities 183


TESTDB or PRODDB to be allowed to link objects on this server. Use the following
command: ADDHDBDLFM HOSTDBLIB((TESTDB) (PRODDB))
HOSTDB(TESTSYS1)

Once the DLFM has been started, and the prefixes and host database names have
been registered, you can begin linking objects in the file system.

184 DB2 UDB for AS/400 SQL Programming V4R4


|
| Chapter 9. Writing User-Defined Functions (UDFs)
| User Defined Functions (UDFs) consist of three types: sourced, external, and SQL.
| Sourced function UDFs call other functions to perform the operation. SQL and
| external function UDFs require that you write and execute separate code. This
| chapter is about writing SQL and external functions. To write external and SQL
| functions, you need to do the following:
| v understand the “UDF runtime environment”
| v register the UDF, so that it is known to the database
| v write the function code to perform the function and pass the appropriate
| parameters
| v debug and test the function.
|
| UDF runtime environment
| There are several things to consider about the environment in which a UDF
| executes and the limitations of that environment. These factors should be
| considered carefully if you are contemplating writing complex function code for
| UDFs.

| Length of time that the UDF runs


| UDFs are invoked from within an SQL statement execution, which is normally a
| query operation that potentially runs against thousands of rows in a table. Because
| of this, the UDF needs to be invoked from a low level of the database.

| As a consequence of being invoked from such a low level, there are certain
| resources (locks and seizes) being held at the time the UDF is invoked and for the
| duration of the UDF execution. These resources are primarily locks on any tables
| and indexes involved in the SQL statement that is invoking the UDF. Due to these
| held resources, it is important that the UDF not perform operations that may take an
| extended period of time (minutes or hours). Because of the critical nature of holding
| resources for long periods of time, the database only waits for a certain period of
| time for the UDF to finish. If the UDF does not finish in the time allocated, the SQL
| statement will fail, which can be quite aggravating to the end user.

| The default UDF wait time used by the database should be more than sufficient to
| allow a normal UDF to run to completion. However, if you have a long running UDF
| and wish to increase the wait time, this can be done using the UDF_TIME_OUT
| option in the query INI file. See “Query Options File QAQQINI” on page 543 for
| more information on the INI file. Note, however, that there is a maximum time limit
| that the database will not exceed, regardless of the value specified for
| UDF_TIME_OUT.

| Since resources are held while the UDF is run, it is important that the UDF not
| operate on the same tables or indexes allocated for the original SQL statement or, if
| it does, that it does not perform an operation that conflicts with the one being
| performed in the SQL statement. Specifically, the UDF should not try to perform any
| insert, update or delete record operation on those tables.

© Copyright IBM Corp. 1997, 1999 185


| Threads considerations
| A UDF runs in the same job as the SQL statement that invoked it. However, the
| UDF runs in a system thread, separate from the thread that is running the SQL
| statement. For more information about threads, see Database considerations for
| multithreaded programming.

| Because the UDF runs in the same job as the SQL statement, it shares much of the
| same environment as the SQL statement. However, because it runs under a
| separate thread, the following threads considerations apply:
| v the UDF will conflict with thread level resources held by the SQL statement’s
| thread. Primarily, these are the table resources discussed above.
| v UDFs do not inherent any program adopted authority that may have been active
| at the time the SQL statement was invoked. UDF authority comes from either the
| authority associated with the UDF program itself or the authority of the user
| running the SQL statement.
| v the UDF cannot perform any operation that is blocked from being run in a
| secondary thread.
| v the UDF program must be created such that it either runs under a named
| activation group or in the activation group of its caller (ACTGRP parameter).
| Programs that specify ACTGRP(*NEW) will not be allowed to run as UDFs.

| Parallel processing
| A UDF can be defined to allow parallel processing. This means that the same UDF
| program can be running in multiple threads at the same time. Therefore, if ALLOW
| PARALLEL is specified for the UDF, ensure that it is thread safe. For more
| information about threads, see Database considerations for multithreaded
| programming.
|
| Writing function code
| Writing function code involves knowing how to write the SQL or external function to
| perform the function. It also involves understanding the interface between the
| database and the function code to define it correctly, and determining packaging
| options when creating the executable program.

| Writing UDFs as SQL functions


| SQL functions are UDFs that you have defined, written, and registered using the
| CREATE FUNCTION statement. As such, they are written using only the SQL
| language and their definition is completely contained within one (potentially large)
| CREATE FUNCTION statement.

| The CREATE FUNCTION statement for SQL functions follow the general flow of:
| CREATE FUNCTION function name(parameters) RETURNS return value
| LANGUAGE SQL
| BEGIN
| sql statements
| END

| For example, a function that returns a priority based on a date:

186 DB2 UDB for AS/400 SQL Programming V4R4


| CREATE FUNCTION PRIORITY(indate date) RETURNS CHAR(7)
| LANGUAGE SQL
| BEGIN
| RETURN(
| CASE
| WHEN indate>CURRENT DATE-3 DAYS THEN 'HIGH'
| WHEN indate>CURRENT DATE-7 DAYS THEN 'MEDIUM'
| ELSE 'LOW'
| END
| );
| END

| The function could then be invoked as:


| SELECT ORDERNBR, PRIORITY(ORDERDUEDATE) FROM ORDERS

| The creation of an SQL function causes the registration of the UDF, generates the
| executable code for the function, and defines to the database the details of how
| parameters are actually passed. Therefore, writing these functions is quite clean
| and provides less chance of introducing errors into the function.

| Writing UDFs as external functions


| You can also write the executable code of a UDF in a language other than SQL.
| While this method is slightly more cumbersome than an SQL function, it provides
| the flexibility for you to use whatever language is most effective for you. The
| executable code can be contained in either a program or service program.

| Passing arguments from DB2 to external functions


| DB2 provides the storage for all parameters passed to a UDF. Therefore,
| parameters are passed to the external function by address. This is the normal
| parameter passing method for programs. For service programs, ensure that the
| parameters are defined correctly in the function code.

| When defining and using the parameters in the UDF, care should be taken to
| ensure that no more storage is referenced for a given parameter than is defined for
| that parameter. The parameters are all stored in the same space and exceeding a
| given parameter’s storage space can overwrite another parameter’s value. This, in
| turn, can cause the function to see invalid input data or cause the value returned to
| the database to be invalid.

| There are four supported parameter styles available to external UDFs. For the most
| part, the styles differ in how many parameters are passed to the external program
| or service program.

| Parameter style SQL: The parameter style SQL conforms to the industry standard
| Structured Query Language (SQL). With parameter style SQL, the parameters are
| passed into the external program as follows (in the order specified):
|

| ÊÊ SQL-result Ê
|
· SQL-argument · SQL-argument-ind

Chapter 9. Writing User-Defined Functions (UDFs) 187


| Ê SQL-result-ind SQL-state function-name specific-name diagnostic-message ÊÍ

|
| SQL-argument
| This argument is set by DB2 before calling the UDF. This value repeats n
| times, where n is the number of arguments specified in the function
| reference. The value of each of these arguments is taken from the
| expression specified in the function invocation. It is expressed in the data
| type of the defined parameter in the create function statement. Note: These
| parameters are treated as input only; any changes to the parameter values
| made by the UDF are ignored by DB2.
| SQL-result
| This argument is set by the UDF before returning to DB2. The database
| provides the storage for the return value. Since the parameter is passed by
| address, the address is of the storage where the return value should be
| placed. The database provides as much storage as needed for the return
| value as defined on the CREATE FUNCTION statement. If the CAST
| FROM clause is used in the CREATE FUNCTION statement, DB2 assumes
| the UDF returns the value as defined in the CAST FROM clause, otherwise
| DB2 assumes the UDF returns the value as defined in the RETURNS
| clause.
| SQL-argument-ind
| This argument is set by DB2 before calling the UDF. It can be used by the
| UDF to determine if the corresponding SQL-argument is null or not. The nth
| SQL-argument-ind corresponds to the nth SQL-argument, described
| previously. Each indicator is defined as a two-byte signed integer. It is set to
| one of the following values:
| 0 The argument is present and not null.
| -1 The argument is null.

| If the function is defined with RETURNS NULL ON NULL INPUT, the UDF
| does not need to check for a null value. However, if it is defined with
| CALLS ON NULL INPUT, any argument can be NULL and the UDF should
| check for null input. Note: these parameters are treated as input only; any
| changes to the parameter values made by the UDF are ignored by DB2.
| SQL-result-ind
| This argument is set by the UDF before returning to DB2. The database
| provides the storage for the return value. The argument is defined as a
| two-byte signed integer. If set to a negative value, the database interprets
| the result of the function as null. If set to zero or a positive value, the
| database uses the value returned in SQL-result. The database provides the
| storage for the return value indicator. Since the parameter is passed by
| address, the address is of the storage where the indicator value should be
| placed.
| SQL-state
| This argument is a CHAR(5) value that represents the SQLSTATE.
| This parameter is passed in from the database set to '00000' and can be
| set by the function as a result state for the function. While normally the
| SQLSTATE is not set by the function, it can be used to signal an error or
| warning to the database as follows:
| 01Hxx The function code detected a warning situation. This results in an
| SQL warning, Here xx may be one of several possible strings.

188 DB2 UDB for AS/400 SQL Programming V4R4


| 38xxx The function code detected an error situation. It results in a SQL
| error. Here xxx may be one of several possible strings.

| See Appendix B for more information on valid SQLSTATEs that the function
| may use.
| function-name
| This argument is set by DB2 before calling the UDF. It is a VARCHAR(139)
| value that contains the name of the function on whose behalf the function
| code is being invoked.
| The form of the function name that is passed is:
| <schema-name>.<function-name>

| This parameter is useful when the function code is being used by multiple
| UDF definitions so that the code can distinguish which definition is being
| invoked. Note: This parameter is treated as input only; any changes to the
| parameter value made by the UDF are ignored by DB2.
| specific-name
| This argument is set by DB2 before calling the UDF. It is a VARCHAR(128)
| value that contains the specific name of the function on whose behalf the
| function code is being invoked.
| Like function-name, this parameter is useful when the function code is
| being used by multiple UDF definitions so that the code can distinguish
| which definition is being invoked. See the CREATE FUNCTION for more
| information about specific-name. Note: This parameter is treated as input
| only; any changes to the parameter value made by the UDF are ignored by
| DB2.
| diagnostic-message
| This argument is set by DB2 before calling the UDF. It is a VARCHAR(70)
| value that can be used by the UDF to send message text back when an
| SQLSTATE warning or error is signaled by the UDF.
| It is initialized by the database on input to the UDF and may be set by the
| UDF with descriptive information. Message text is ignored by DB2 unless
| the SQL-state parameter is set by the UDF.

| Parameter style DB2SQL: With the DB2SQL parameter style, the same
| parameters and same order of parameters are passed into the external program or
| service program as are passed in for parameter style SQL. However, DB2SQL
| allows additional optional parameters to be passed along as well. If more than one
| of the optional parameters below is specified in the UDF definition, they are passed
| to the UDF in the order defined below. Refer to parameter style SQL for the
| common parameters.

| ÊÊ SQL-result Ê
|
· SQL-argument · SQL-argument-ind

| Ê SQL-result-ind SQL-state function-name specific-name diagnostic-message Ê


|

Chapter 9. Writing User-Defined Functions (UDFs) 189


| Ê ÊÍ
scratchpad call-type dbinfo

|
| scratchpad
| This argument is set by DB2 before calling the UDF. It is only present if the
| CREATE FUNCTION statement for the UDF specified the SCRATCHPAD
| keyword. This argument is a structure with the following elements:
| v An INTEGER containing the length of the scratchpad.
| v The actual scratchpad, initialized to all binary 0’s by DB2 before the first
| call to the UDF.
| The scratchpad can be used by the UDF either as working storage or as
| persistent storage, since it is maintained across UDF invocations.
| call-type
| This argument is set by DB2 before calling the UDF. It is only present if the
| CREATE FUNCTION statement for the UDF specified the FINAL CALL
| keyword. It is an INTEGER value that contains one of the following values:
| -1 This is the first call to the UDF for this statement. A first call is a
| normal call in that all SQL argument values are passed.
| 0 This is a normal call. (All the normal input argument values are
| passed).
| 1 This is a final call. No SQL-argument or SQL-argument-ind values
| are passed. A UDF should not return any answer using the
| SQL-result or SQL-result-ind arguments. Both of these are ignored
| by DB2 upon return from the UDF. However, the UDF may set the
| SQL-state and diagnostic-message arguments. These arguments
| are handled in a way similar to other calls to the UDF.
| dbinfo This argument is set by DB2 before calling the UDF. It is only present if the
| CREATE FUNCTION statement for the UDF specifies the DBINFO keyword.
| The argument is a structure whose definition is contained in the sqludf
| include.

| Parameter Style GENERAL (or SIMPLE CALL): With parameter style GENERAL,
| the parameters are passed into the external service program just as they are
| specified in the CREATE FUNCTION statement. The format is:

ÊÊ SQL-result = func ( · ) ÊÍ
SQL-argument

|
| SQL-argument
| This argument is set by DB2 before calling the UDF. This value repeats n
| times, where n is the number of arguments specified in the function
| reference. The value of each of these arguments is taken from the
| expression specified in the function invocation. It is expressed in the data
| type of the defined parameter in the CREATE FUNCTION statement. Note:
| These parameters are treated as input only; any changes to the parameter
| values made by the UDF are ignored by DB2.

190 DB2 UDB for AS/400 SQL Programming V4R4


| SQL-result
| This value is returned by the UDF. DB2 copies the value into database
| storage. In order to return the value correctly, the function code must be a
| value-returning function. The database copies only as much of the value as
| defined for the return value as specified on the CREATE FUNCTION
| statement. If the CAST FROM clause is used in the CREATE FUNCTION
| statement, DB2 assumes the UDF returns the value as defined in the CAST
| FROM clause, otherwise DB2 assumes the UDF returns the value as
| defined in the RETURNS clause.
| In addition, in order to be returned correctly, the return value defined in the
| function code must be defined as a simple structure. For example, in C, to
| return an INTEGER, the function code would be defined as follows:
| typedef struct {
| int rtnint;
| } rtnval_t;
|
| rtnval_t func1()
| {
| rtnval_t rtnval;
| .
| .
| return(rtnval);
| };

| Note: The return value must be defined as a simple structure. If, instead,
| the function was defined as simply int func1(), the return value would not be
| available for DB2 to use.

| Because of the requirement that the function code be a value-returning


| function, any function code used for parameter style GENERAL must be
| created into a service program.

| Parameter Style GENERAL WITH NULLS: With parameter style GENERAL


| WITH NULLS, the parameters are passed into the service program as follows (in
| the order specified):

|
|
ÊÊ SQL-result = funcname ( · Ê
SQL-argument

| Ê SQL-result-ind ) ÊÍ
| SQL-argument-ind-array

|
| SQL-argument
| This argument is set by DB2 before calling the UDF. This value repeats n
| times, where n is the number of arguments specified in the function
| reference. The value of each of these arguments is taken from the
| expression specified in the function invocation. It is expressed in the data
| type of the defined parameter in the CREATE FUNCTION statement. Note:
| These parameters are treated as input only; any changes to the parameter
| values made by the UDF are ignored by DB2.
| SQL-argument-ind-array
| This argument is set by DB2 before calling the UDF. It can be used by the
| UDF to determine if one or moreSQL-arguments are null or not. It is an

Chapter 9. Writing User-Defined Functions (UDFs) 191


| array of two-byte signed integers (indicators). Thenth array argument
| corresponds corresponds to the nth SQL-argument. Each array entry is set
| to one of the following values:
| 0 The argument is present and not null.
| -1 The argument is null.

| The UDF should check for null input. Note: This parameter is treated as
| input only; any changes to the parameter value made by the UDF is
| ignored by DB2.
| SQL-result-ind
| This argument is set by the UDF before returning to DB2. The database
| provides the storage for the return value. The argument is defined as a
| two-byte signed integer. If set to a negative value, the database interprets
| the result of the function as null. If set to zero or a positive value, the
| database uses the value returned in SQL-result. The database provides the
| storage for the return value indicator. Since the parameter is passed by
| address, the address is of the storage where the indicator value should be
| placed.
| SQL-result
| This value is returned by the UDF. DB2 copies the value into database
| storage. In order to return the value correctly, the function code must be a
| value-returning function. The database copies only as much of the value as
| defined for the return value as specified on the CREATE FUNCTION
| statement. If the CAST FROM clause is used in the CREATE FUNCTION
| statement, DB2 assumes the UDF returns the value as defined in the CAST
| FROM clause, otherwise DB2 assumes the UDF returns the value as
| defined in the RETURNS clause.
| In order to be returned correctly, the return value defined in the function
| code must be defined as a simple structure. For example, in C, to return an
| INTEGER, the function code would be defined as follows:
| typedef struct {
| int rtnint;
| } rtnval_t;
|
| rtnval_t func1(short *parm1, short parmind[], short *rtnind)
| {
| rtnval_t rtnval;
| .
| .
| .
| return(rtnval);
| };

| Note: The return value must be defined as a simple structure. If, instead,
| the function was defined as simply int func1(...), the return value would not
| be available for DB2 to use.

| Because of the requirement that the function code be a value-returning


| function, any function code used for parameter style GENERAL WITH
| NULLS must be created into a service program.

192 DB2 UDB for AS/400 SQL Programming V4R4


|
| Examples of UDF code
| These examples show how to implement UDF code by using SQL functions and
| external functions.

| Example: Square of a number UDF


| Suppose that you wanted a function that returns the square of a number. The query
| statement is:
| SELECT SQUARE(myint) FROM mytable

| The following examples show how to define the UDF several different ways.
| v Using an SQL function
| CREATE FUNCTION SQUARE( inval INT) RETURNS INT
| LANGUAGE SQL
| BEGIN
| RETURN(inval*inval);
| END
| v Using an external function, parameter style SQL:
| The CREATE FUNCTION statement:
| CREATE FUNCTION SQUARE(INT) RETURNS INT CAST FROM FLOAT
| LANGUAGE C
| EXTERNAL NAME 'MYLIB/MATH(SQUARE)'
| DETERMINISTIC
| NO SQL
| NO EXTERNAL ACTION
| PARAMETER STYLE SQL
| ALLOW PARALLEL

| The code:
| void SQUARE(int *inval,
| double *outval,
| short *inind,
| short *outind,
| char *sqlstate,
| char *funcname,
| char *specname,
| char *msgtext)
| {
| if (*inind<0)
| *outind=-1;
| else
| {
| *outval=*inval;
| *outval=(*outval)*(*outval);
| *outind=0;
| }
| return;
| }

| To create the external service program so it can be debugged:


| CRTCMOD MODULE(mylib/square) DBGVIEW(*SOURCE)
| CRTSRVPGM SRVPGM(mylib/math) MODULE(mylib/square)
| EXPORT(*ALL) ACTGRP(*CALLER)
| v Using an external function, parameter style GENERAL:
| The CREATE FUNCTION statement:

Chapter 9. Writing User-Defined Functions (UDFs) 193


| CREATE FUNCTION SQUARE(INT) RETURNS INT CAST FROM FLOAT
| LANGUAGE C
| EXTERNAL NAME 'MYLIB/MATH(SQUARE)'
| DETERMINISTIC
| NO SQL
| NO EXTERNAL ACTION
| PARAMETER STYLE GENERAL
| ALLOW PARALLEL

| The code:
| typedef struct {
| double outf;
| } outval_t;
|
| outval_t SQUARE(int *inval)
| {
| outval_t outval;
| outval.outf=*inval;
| outval.outf=(outval.outf)*(outval.outf);
| return(outval);
| }

| To create the external service program so it can be debugged:


| CRTCMOD MODULE(mylib/square) DBGVIEW(*SOURCE)
|
| CRTSRVPGM SRVPGM(mylib/math) MODULE(mylib/square)
| EXPORT(*ALL) ACTGRP(*CALLER)

| Example: Counter
| Suppose you want to simply number the rows in your SELECT statement. So you
| write a UDF which increments and returns a counter. This example uses an
| external function with DB2 SQL parameter style and a scratchpad.
| CREATE FUNCTION COUNTER()
| RETURNS INT
| SCRATCHPAD
| NOT DETERMINISTIC
| NO SQL
| NO EXTERNAL ACTION
| LANGUAGE C
| PARAMETER STYLE DB2SQL
| EXTERNAL NAME 'MYLIB/MATH(ctr)'
| DISALLOW PARALLELISM;
|
| /* structure scr defines the passed scratchpad for the function "ctr" */
| struct scr {
| long len;
| long countr;
| char not_used[96];
| };
|
| void ctr (
| long *out, /* output answer (counter) */
| short *outnull, /* output NULL indicator */
| char *sqlstate, /* SQL STATE */
| char *funcname, /* function name */
| char *specname, /* specific function name */
| char *mesgtext, /* message text insert */
| struct scr *scratchptr) { /* scratch pad */
|
| *out = ++scratchptr->countr; /* increment counter & copy out */
| *outnull = 0;
| return;
| }
| /* end of UDF : ctr */

| For this UDF, observe that:


| v It has no input SQL arguments defined, but returns a value.
| v It appends the scratchpad input argument after the four standard trailing
| arguments, namely SQL-state, function-name, specific-name, and message-text.

194 DB2 UDB for AS/400 SQL Programming V4R4


| v It includes a structure definition to map the scratchpad which is passed.
| v No input parameters are defined. This agrees with the code.
| v SCRATCHPAD is coded, causing DB2 to allocate, properly initialize and pass the
| scratchpad argument.
| v You have specified it to be NOT DETERMINISTIC, because it depends on more
| than the SQL input arguments, (none in this case).
| v You have correctly specified DISALLOW PARALLELISM, because correct
| functioning of the UDF depends on a single scratchpad.

Chapter 9. Writing User-Defined Functions (UDFs) 195


196 DB2 UDB for AS/400 SQL Programming V4R4
|
Chapter 10. Dynamic SQL Applications
Dynamic SQL allows an application to define and run SQL statements at program
run time. An application that provides for dynamic SQL accepts as input (or builds)
an SQL statement in the form of a character string. The application does not need
to know what type of SQL statement it will run. The application:
v Builds or accepts as input an SQL statement
v Prepares the SQL statement for running
v Runs the statement
v Handles SQL return codes

Interactive SQL (described in Chapter 19. Using Interactive SQL) is an example of a


dynamic SQL program. SQL statements are processed and run dynamically by
interactive SQL.
Notes:
1. The run-time overhead is greater for statements processed using dynamic SQL
than for static SQL statements. The additional process is similar to that required
for precompiling, binding, and then running a program, instead of only running it.
Therefore, only applications requiring the flexibility of dynamic SQL should use
it. Other applications should access data from the database using normal
(static) SQL statements.
2. Programs that contain an EXECUTE or EXECUTE IMMEDIATE statement and
that use a FOR READ ONLY clause to make a cursor read-only experience
better performance because blocking is used to retrieve rows for the cursor.
The ALWBLK(*ALLREAD) CRTSQLxxx option will imply a FOR READ ONLY
declaration for all cursors that do not explicitly code FOR UPDATE OF or have
positioned deletes or updates that refer to the cursor. Cursors with an implied
FOR READ ONLY will benefit from the second item in this list.

Some dynamic SQL statements require use of address variables. RPG for AS/400
programs require the aid of PL/I, COBOL, C, or ILE RPG for AS/400 programs to
manage the address variables.

The examples in this chapter are PL/I examples. The following table shows all the
statements supported by DB2 UDB for AS/400 and indicates if they can be used in
a dynamic application.

Note: In the following table, the numbers in the Dynamic SQL column correspond
to the notes on the next page.
Table 22. List of SQL Statements Allowed in Dynamic Applications
SQL Statement Static SQL Dynamic SQL
ALTER TABLE Y Y
BEGIN DECLARE SECTION Y N
CALL Y Y
CLOSE Y N
COMMENT ON Y Y
COMMIT Y Y
CONNECT Y N
CREATE ALIAS Y Y

© Copyright IBM Corp. 1997, 1999 197


Table 22. List of SQL Statements Allowed in Dynamic Applications (continued)
SQL Statement Static SQL Dynamic SQL
CREATE COLLECTION Y Y
CREATE DISTINCT TYPE Y Y
CREATE FUNCTION Y Y
CREATE INDEX Y Y
CREATE PROCEDURE Y Y
CREATE SCHEMA N See Note 8.
CREATE TABLE Y Y
CREATE VIEW Y Y
DECLARE CURSOR Y See Note 4.
DECLARE PROCEDURE Y N
DECLARE STATEMENT Y N
DECLARE VARIABLE Y N
DELETE Y Y
DESCRIBE Y See Note 7.
DESCRIBE TABLE Y N
DISCONNECT Y N
DROP Y Y
END DECLARE SECTION Y N
EXECUTE Y See Note 1.
EXECUTE IMMEDIATE Y See Note 2.
FETCH Y N
FREE LOCATOR Y Y
GRANT Y Y
INCLUDE Y N
INSERT Y Y
LABEL ON Y Y
LOCK TABLE Y Y
OPEN Y N
PREPARE Y See Note 3.
RELEASE Y N
RENAME Y Y
REVOKE Y Y
ROLLBACK Y Y
SELECT INTO Y See Note 5.
SELECT statement Y See Note 6.
SET CONNECTION Y N
SET OPTION Y See Note 9.
SET PATH Y Y
SET RESULT SETS Y N
SET TRANSACTION Y Y

198 DB2 UDB for AS/400 SQL Programming V4R4


Table 22. List of SQL Statements Allowed in Dynamic Applications (continued)
SQL Statement Static SQL Dynamic SQL
SET variable Y N
UPDATE Y Y
VALUES INTO Y N
WHENEVER Y N

Notes:
1. Cannot be prepared, but used to run prepared SQL statements. The SQL
statement must be previously prepared by the PREPARE statement prior to
using the EXECUTE statement. See example for PREPARE under “Using the
PREPARE and EXECUTE Statements” on page 200.
2. Cannot be prepared, but used with dynamic statement strings that do not have
any ? parameter markers. The EXECUTE IMMEDIATE statement causes the
statement strings to be prepared and run dynamically at program run time. See
example for EXECUTE IMMEDIATE under “Processing Non-SELECT
statements”.
3. Cannot be prepared, but used to parse, optimize, and set up dynamic SELECT
statements prior to running. See example for PREPARE under “Processing
Non-SELECT statements”.
4. Cannot be prepared, but used to define the cursor for the associated dynamic
SELECT statement prior to running.
5. A SELECT INTO statement cannot be prepared or used in EXECUTE
IMMEDIATE.
6. Cannot be used with EXECUTE or EXECUTE IMMEDIATE but can be prepared
and used with OPEN.
7. Cannot be prepared, but used to return a description of a prepared statement.
8. Can only be run using the Run SQL Statements (RUNSQLSTM) command.
9. Can only be used when running a REXX procedure.

Designing and Running a Dynamic SQL Application


To issue a dynamic SQL statement, you must use the statement with either an
EXECUTE statement or an EXECUTE IMMEDIATE statement, because dynamic
SQL statements are not prepared at precompile time and therefore must be
prepared at run time. The EXECUTE IMMEDIATE statement causes the SQL
statement to be prepared and run dynamically at program run time.

There are two basic types of dynamic SQL statements: SELECT statements and
non-SELECT statements. Non-SELECT statements include such statements as
DELETE, INSERT, and UPDATE.

Client server applications that use interfaces such as ODBC typically use dynamic
SQL to access the database. For more information on developing client server
applications that use Client Access, see the Client Access for Windows 3.1 ODBC
User’s Guide.

Processing Non-SELECT statements


To build a dynamic SQL non-SELECT statement:

Chapter 10. Dynamic SQL Applications 199


1. Verify that the SQL statement you want to build is one that can be run
dynamically (see Table 22 on page 197).
2. Build the SQL statement. (Use Interactive SQL for an easy way to build, verify,
and run your SQL statement. See Chapter 19. Using Interactive SQL for more
information.)

To run a dynamic SQL non-SELECT statement:


1. Run the SQL statement using EXECUTE IMMEDIATE, or PREPARE the SQL
statement, then EXECUTE the prepared statement.
2. Handle any SQL return codes that might result.

The following is an example of an application running a dynamic SQL non-SELECT


statement (stmtstrg):
EXEC SQL
EXECUTE IMMEDIATE :stmtstrg;

CCSID of Dynamic SQL Statements


The SQL statement is normally a host variable. The CCSID of the host variable is
used as the CCSID of the statement text. In PL/I, it also can be a string expression.
In this case, the job CCSID is used as the CCSID of the statement text.

Dynamic SQL statements are processed using the CCSID of the statement text.
This affects variant characters the most. For example, the not sign (¬) is located at
'BA'X in CCSID 500. This means that if the CCSID of your statement text is 500,
SQL expects the not sign (¬) to be located at 'BA'X.

If the statement text CCSID is 65535, SQL processes variant characters as if they
had a CCSID of 37. This means that SQL looks for the not sign (¬) at '5F'X.

Using the PREPARE and EXECUTE Statements


If non-SELECT statements contain no parameter markers, they can be run
dynamically using the EXECUTE IMMEDIATE statement. However, if the
non-SELECT statements have parameter markers, they must be run using
PREPARE and EXECUTE.

The PREPARE statement prepares the non-SELECT statement (for example, the
DELETE statement) and gives it a name of your choosing. If DLYPRP (*YES) is
specified on the CRTSQLxxx command, the preparation is delayed until the first
time the statement is used in an EXECUTE or DESCRIBE statement, unless the
USING clause is specified on the PREPARE statement. In this instance, let us call it
S1. After the statement has been prepared, it can be run many times within the
same program, using different values for the parameter markers. The following
example is of a prepared statement being run multiple times:
DSTRING = 'DELETE FROM CORPDATA.EMPLOYEE WHERE EMPNO = ?';

/*The ? is a parameter marker which denotes


that this value is a host variable that is
to be substituted each time the statement is run.*/

EXEC SQL PREPARE S1 FROM :DSTRING;

/*DSTRING is the delete statement that the PREPARE statement is


naming S1.*/

200 DB2 UDB for AS/400 SQL Programming V4R4


DO UNTIL (EMP =0);
/*The application program reads a value for EMP from the
display station.*/
EXEC SQL
EXECUTE S1 USING :EMP;

END;

In routines similar to the example above, you must know the number of parameter
markers and their data types, because the host variables that provide the input data
are declared when the program is being written.

Note: All prepared statements that are associated with an application server are
destroyed whenever the connection to the application server ends.
Connections are ended by a CONNECT (Type 1) statement, a
DISCONNECT statement, or a RELEASE followed by a successful COMMIT.

Processing SELECT Statements and Using an SQLDA


There are two basic types of SELECT statements: fixed-list and varying-list.

To process a fixed-list SELECT statement, an SQLDA is not necessary.

To process a varying-list SELECT statement, you must first declare an SQLDA


structure. The SQLDA is a control block used to pass host variable input values
from an application program to SQL and to receive output values from SQL. In
addition, information about SELECT list expressions can be returned in a PREPARE
or DESCRIBE statement.

Fixed-List SELECT Statements


In dynamic SQL, fixed-list SELECT statements are those statements designed to
retrieve data of a predictable number and type. When using these statements, you
can anticipate and define host variables to accommodate the retrieved data, so that
an SQLDA is not necessary. Each successive FETCH returns the same number of
values as the last, and these values have the same data formats as those returned
for the last FETCH. You can specify host variables the same as you would for any
SQL application.

You can use fixed-list dynamic SELECT statements with any SQL-supported
application program.

To run fixed-list SELECT statements dynamically, your application must:


1. Place the input SQL statement into a host variable.
2. Issue a PREPARE statement to validate the dynamic SQL statement and put it
into a form that can be run. If DLYPRP (*YES) is specified on the CRTSQLxxx
command, the preparation is delayed until the first time the statement is used in
an EXECUTE or DESCRIBE statement, unless the USING clause is specified
on the PREPARE statement.
3. Declare a cursor for the statement name.
4. Open the cursor.
5. FETCH a row into a fixed list of variables (rather than into a descriptor area, as
you would if you were using a varying-list SELECT statement, described in the
following section, Varying-List Select-Statements).

Chapter 10. Dynamic SQL Applications 201


6. When end of data occurs, close the cursor.
7. Handle any SQL return codes that result.

For example:
MOVE 'SELECT EMPNO, LASTNAME FROM CORPDATA.EMPLOYEE WHERE EMPNO>?'
TO DSTRING.
EXEC SQL
PREPARE S2 FROM :DSTRING END-EXEC.

EXEC SQL
DECLARE C2 CURSOR FOR S2 END-EXEC.

EXEC SQL
OPEN C2 USING :EMP END-EXEC.

PERFORM FETCH-ROW UNTIL SQLCODE NOT=0.

EXEC SQL
CLOSE C2 END-EXEC.
STOP-RUN.
FETCH-ROW.
EXEC SQL
FETCH C2 INTO :EMP, :EMPNAME END-EXEC.

Note: Remember that because the SELECT statement, in this case, always returns
the same number and type of data items as previously run fixed-list SELECT
statements, you do not have to use the SQL descriptor area (SQLDA).

Varying-List Select-Statements
In dynamic SQL, varying-list SELECT statements are ones for which the number
and format of result columns to be returned are not predictable; that is, you do not
know how many variables you need, or what the data types are. Therefore, you
cannot define host variables in advance to accommodate the result columns
returned.

Note: In REXX, steps 5.b on page 203, 6 on page 203, and 7 on page 203 are not
applicable.

If your application accepts varying-list SELECT statements, your program has to:
1. Place the input SQL statement into a host variable.
2. Issue a PREPARE statement to validate the dynamic SQL statement and put it
into a form that can be run. If DLYPRP (*YES) is specified on the CRTSQLxxx
command, the preparation is delayed until the first time the statement is used
in an EXECUTE or DESCRIBE statement, unless the USING clause is
specified on the PREPARE statement.
3. Declare a cursor for the statement name.
4. Open the cursor (declared in step 3) that includes the name of the dynamic
SELECT statement.
5. Issue a DESCRIBE statement to request information from SQL about the type
and size of each column of the result table.
Notes:
a. You can also code the PREPARE statement with an INTO clause to
perform the functions of PREPARE and DESCRIBE with a single
statement.

202 DB2 UDB for AS/400 SQL Programming V4R4


b. If the SQLDA is not large enough to contain column descriptions for each
retrieved column, the program must determine how much space is needed,
get storage for that amount of space, build a new SQLDA, and reissue the
DESCRIBE statement.
6. Allocate the amount of storage needed to contain a row of retrieved data.
7. Put storage addresses into the SQLDA (SQL descriptor area) to tell SQL where
to put each item of retrieved data.
8. FETCH a row.
9. When end of data occurs, close the cursor.
10. Handle any SQL return codes that might result.

The SQL Descriptor Area (SQLDA)


You can use the SQLDA to pass information about an SQL statement between SQL
and your application.

The SQLDA is a collection of variables required for running the DESCRIBE and
DESCRIBE TABLE statements. It also can be used on the PREPARE, OPEN,
FETCH, CALL, and EXECUTE statements. An SQLDA is used with dynamic SQL. It
can be used in a DESCRIBE statement, changed with the addresses of host
variables, and then reused in a FETCH statement.

The meaning of the information in an SQLDA depends on its use. In PREPARE and
DESCRIBE, an SQLDA provides information to an application program about a
prepared statement. In DESCRIBE TABLE, the SQLDA provides information to an
application program about the columns in a table or view. In OPEN, EXECUTE,
CALL, and FETCH, an SQLDA provides information about host variables.

SQLDA is required for:


v DESCRIBE
v DESCRIBE TABLE

SQLDA is an option for:


v EXECUTE
v FETCH
v OPEN
v PREPARE
v CALL

If your application lets you have several cursors open at the same time, you can
code several SQLDAs, one for each dynamic SELECT statement. For more
information on SQLDA and SQLCA, see the DB2 UDB for AS/400 SQL Reference
book.

SQLDAs can be used in C, COBOL, PL/I, REXX, and RPG. Because RPG for
AS/400 does not provide a way to set pointers, pointers must be set outside the
RPG for AS/400 program by a PL/I, C, COBOL, or ILE RPG for AS/400 program.
Since the area used must be declared by the PL/I, C, COBOL, or ILE RPG for
AS/400 program, that program must call the RPG for AS/400 program.

Chapter 10. Dynamic SQL Applications 203


SQLDA Format
The SQLDA consists of four variables followed by an arbitrary number of
occurrences of a sequence of six variables collectively named SQLVAR.

Note: The SQLDA in REXX is different. For more information, see Chapter 17.
Coding SQL Statements in REXX Applications.
When an SQLDA is used in OPEN, FETCH, CALL, and EXECUTE, each
occurrence of SQLVAR describes a host variable.

The variables of SQLDA are as follows (variable names are in lowercase for C):
SQLDAID
SQLDAID is used for storage dumps. Byte 7 of SQLDAID is used to
indicate if there are extension SQL VARs used for LOBs or UDTs. It is a
string of 8 characters that have the value 'SQLDA' after the SQLDA that is
used in a PREPARE or DESCRIBE statement. It is not used for FETCH,
OPEN, CALL or EXECUTE.
| Byte 7 can be used to determine if more than one SQLVAR entry is needed
| for each column. This flag is set to a blank if there are not any LOBs or
| distinct types.
SQLDAID is not applicable in REXX.
SQLDABC
SQLDABC indicates the length of the SQLDA. It is a 4-byte integer that has
the value SQLN*LENGTH(SQLVAR) + 16 after the SQLDA is used in a
PREPARE or DESCRIBE statement. SQLDABC must have a value equal to
or greater than SQLN*LENGTH(SQLVAR) + 16 prior to use by FETCH,
OPEN, CALL, or EXECUTE.
SQLABC is not applicable in REXX.
SQLN SQLN is a 2-byte integer that specifies the total number of occurrences of
SQLVAR. It must be set prior to use by any SQL statement to a value
greater than or equal to 0.
SQLN is not applicable in REXX.
SQLD SQLD is a 2-byte integer that specifies the pertinent number of occurrences
of SQLVAR; that is, the number of host variables described by the SQLDA.
This field is set by SQL on a DESCRIBE or PREPARE statement. In other
statements, this field must be set prior to use to a value greater than or
equal to 0 and less than or equal to SQLN.
SQLVAR
The variables of SQLVAR are SQLTYPE, SQLLEN, SQLRES, SQLDATA,
SQLIND, and SQLNAME. These variables are set by SQL on a DESCRIBE
or PREPARE statement. In other statements, they must be set prior to use.
These variables are defined as follows:
SQLTYPE
SQLTYPE is a 2-byte integer that specifies the data type of the host
variable as shown in the table below. Odd values for SQLTYPE show that
the host variable has an associated indicator variable addressed by
SQLIND.
SQLLEN
SQLLEN is a 2-byte integer variable that specifies the length attributes of
the host variables shown in Figure 10-2.

204 DB2 UDB for AS/400 SQL Programming V4R4


Table 23. SQLTYPE and SQLLEN Values for PREPARE, DESCRIBE, FETCH, OPEN, CALL, or EXECUTE
For PREPARE and DESCRIBE For FETCH, OPEN, CALL, and EXECUTE
HOST VARIABLE DATA
SQLTYPE COLUMN DATA TYPE SQLLEN TYPE SQLLEN
384/385 Date 10 Fixed-length character Length attribute of
string representation of a the host variable
date
388/389 Time 8 Fixed-length character Length attribute of
string representation of a the host variable
time
392/393 Timestamp 26 Fixed-length character Length attribute of
string representation of a the host variable
timestamp
| 396/397 DataLink6 Length attribute of N/A N/A
| the column
400/401 N/A N/A NUL-terminated graphic Length attribute of
string the host variable
392/393 Timestamp 26 Fixed-length character Length attribute of
string representation of a the host variable
timestamp
| 404/405 BLOB 07 BLOB Not used.7
| 408/409 CLOB 07 CLOB Not used.7
| 412/413 DBCLOB 07 DBCLOB Not used.7
452/453 Fixed-length character Length attribute of Fixed-length character Length attribute of
string the column string the host variable
456/457 Long varying-length Length attribute of Long varying-length Length attribute of
character string the column character string the host variable
460/461 N/A N/A NUL-terminated character Length attribute of
string the host variable
464/465 Varying-length graphic Length attribute of Varying-length graphic Length attribute of
string the column string the host variable
468/469 Fixed-length graphic string Length attribute of Fixed-length graphic string Length attribute of
the column the host variable
472/473 Long varying-length Length attribute of Long graphic string Length attribute of
graphic string the column the host variable
476/477 N/A N/A PASCAL L-string Length attribute of
the host variable
480/481 Floating point 4 for single Floating point 4 for single
precision, 8 for precision, 8 for
double precision double precision
484/485 Packed decimal Precision in byte Packed decimal Precision in byte
1; scale in byte 2 1; scale in byte 2
488/489 Zoned decimal Precision in byte Zoned decimal Precision in byte
1; scale in byte 2 1; scale in byte 2
5
496/497 Large integer 4 Large integer 4
5
500/501 Small integer 2 Small integer 2
504/505 N/A N/A DISPLAY SIGN LEADING Precision in byte
SEPARATE 1; scale in byte 2

Chapter 10. Dynamic SQL Applications 205


Table 23. SQLTYPE and SQLLEN Values for PREPARE, DESCRIBE, FETCH, OPEN, CALL, or
EXECUTE (continued)
For PREPARE and DESCRIBE For FETCH, OPEN, CALL, and EXECUTE
HOST VARIABLE DATA
SQLTYPE COLUMN DATA TYPE SQLLEN TYPE SQLLEN
| 916/917 N/A N/A BLOB file reference 267
| variable
| 920/921 N/A N/A CLOB file reference 267
| variable
| 924/925 N/A N/A DBCLOB file reference 267
| variable
| 960/961 N/A N/A BLOB locator 4
| 964/965 N/A N/A CLOB locator 4
| 968/969 N/A N/A DBCLOB locator 4

SQLRES
SQLRES is a 12-byte reserved area for boundary alignment purposes. Note
that, in OS/400, pointers must be on a quad-word boundary.
SQLRES is not applicable in REXX.
SQLDATA
SQLDATA is a 16-byte pointer variable that specifies the address of the
host variables when the SQLDA is used on OPEN, FETCH, CALL, and
EXECUTE.
When the SQLDA is used on PREPARE and DESCRIBE, this area is
overlaid with the following information:
The CCSID of a character, date, time, timestamp, and graphic field is stored
in the third and fourth bytes of SQLDATA. For BIT data, the CCSID is
65535. In REXX, the CCSID is returned in the variable SQLCCSID.
SQLIND
SQLIND is a 16-byte pointer that specifies the address of a small integer
host variable that is used as an indication of null or not null when the
SQLDA is used on OPEN, FETCH, CALL, and EXECUTE. A negative value
indicates null and a non-negative indicates not null. This pointer is only
used if SQLTYPE contains an odd value.
When the SQLDA is used on PREPARE and DESCRIBE, this area is
reserved for future use.
SQLNAME
SQLNAME is a variable-length character variable with a maximum length of
30, which contains the name of selected column, label, or system column
name after a PREPARE or DESCRIBE. In OPEN, FETCH, EXECUTE, or
CALL, it can be used to pass the CCSID of character strings. CCSIDs can
be passed for character, graphic, date, time, and timestamp host variables.
The SQLNAME field in an SQLVAR array entry of an input SQLDA can be
set to specify the CCSID:

5. Binary numbers can be represented in the SQLDA as either lengths 2 or 4, or with the precision in byte 1 and the scale in byte 2.
If the first byte is greater than X’00’, it indicates precision and scale.
6. The DataLink datatype is only returned on DESCRIBE TABLE.
7. The len.sqllonglen field in the secondary SQLVAR contains the length attribute of the column.

206 DB2 UDB for AS/400 SQL Programming V4R4


Length of SQLNAME SQLNAME
Data Type Sub-type SQLNAME Bytes 1 & 2 Bytes 3 & 4
Character SBCS 8 X’0000’ CCSID
Character MIXED 8 X’0000’ CCSID
Character BIT 8 X’0000’ X’FFFF’
GRAPHIC not applicable 8 X’0000’ CCSID
Any other data not applicable not applicable not applicable not applicable
type

Note: It is important to remember that the SQLNAME field is only for


overriding the CCSID. Applications that use the defaults do not need
to pass CCSID information. If a CCSID is not passed, the default
CCSID for the job is used.

The default for graphic host variables is the associated double-byte CCSID
for the job CCSID. If an associated double-byte CCSID does not exist,
65535 is used.
| SQLVAR2
| The Extended SQLVAR structure. Extended SQLVARs are only needed (for
| all columns of the result) if the result includes any LOB or distinct type
| columns. For distinct types, they contain the distinct type name. For LOBs,
| they contain the length attribute of the host variable and a pointer to the
| buffer that contains the actual length. If locators are used to represent
| LOBs, these entries are not necessary. The number of Extended SQLVAR
| occurrences needed depends on the statement that the SQLDA was
| provided for and the data types of the columns or parameters being
| described. Byte 7 of SQLDAID is always set to the number of sets of
| SQLVARs necessary.
| If SQLD is not set to a sufficient number of SQLVAR occurrences:
| v SQLD is set to the total number of SQLVAR occurrences needed for all
| sets.
| v A +237 warning is returned in the SQLCODE field of the SQLCA if at
| least enough were specified for the Base SQLVAR Entries. The Base
| SQLVAR entries are returned, but no Extended SQLVARs are returned.
| v A +239 warning is returned in the SQLCODE field of the SQLCA if
| enough SQLVARs were not specified for even the Base SQLVAR Entries.
| No SQLVAR entries are returned.
| SQLLONGLEN
| SQLLONGLEN is part of the Extended SQLVAR. It is a 4-byte integer
| variable that specifies the length attributes of a LOB (BLOB, CLOB, or
| DBCLOB) host variable.
| SQLDATALEN
| SQLDATALEN is part of the Extended SQLVAR. It is a 16-byte pointer
| variable that specifies the address of the length of the host variable. It is
| used for LOB (BLOB, CLOB, and DBCLOB) host variables only. If this field
| is NULL, then the actual length is stored in the 4 bytes immediately before
| the start of the data, and SQLDATA points to the first byte of the field
| length. The actual length indicates the number of bytes for a BLOB or
| CLOB, and the number of characters for a DBCLOB.
| If this field is not NULL, it contains a pointer to a 4-byte long buffer that
| contains the actual length in bytes (even for DBCLOB) of the data in the
| buffer pointed to from the SQLDATA field in the matching base SQLVAR.

Chapter 10. Dynamic SQL Applications 207


| SQLDATATYPE_NAME
| SQLDATATYPE_NAME is part of the Extended SQLVAR. It is a
| variable-length character variable with a maximum length of 30. It is set to
| one of the following:
| v For a distinct type column, the database manager sets this to the fully
| qualified distinct type name.
| v If the qualified name is longer than 30 bytes, it is truncated.
| v For a label, the database manager sets this to the first 20 bytes of the
| label. For a column name, the database manager sets this to the column
| name.

| Example of a Select-Statement for Allocating Storage for SQLDA


The SELECT statement can be read from a display station or from a host variable,
or it can be developed within an application program. The following example shows
a SELECT statement read from a display station:
SELECT WORKDEPT, PHONENO FROM CORPDATA.EMPLOYEE
WHERE LASTNAME = 'PARKER'

Note: The SELECT statement has no INTO clause. Dynamic SELECT statements
must not have an INTO clause, even if they return only one row.

When the statement is read, it is assigned to a host variable. The host variable (for
example, named DSTRING) is then processed, using the PREPARE statement, as
shown:
EXEC SQL
PREPARE S1 FROM :DSTRING;

Allocating Storage
You can allocate storage for the SQLDA. (Allocating storage is not necessary in
REXX.) The techniques for acquiring storage are language dependent. The SQLDA
must be allocated on a 16-byte boundary. The SQLDA consists of a fixed-length
header, 16 bytes long. The header is followed by a varying-length array section
(SQLVAR), each element of which is 80 bytes in length. The amount of storage you
need to allocate depends on how many elements you want to have in the SQLVAR
array. Each column you select must have a corresponding SQLVAR array element.
Therefore, the number of columns listed in your SELECT statement determines how
many SQLVAR array elements you should allocate. Because SELECT statements
are specified at run time, however, it is impossible to know how many columns will
be accessed. Consequently, you must estimate the number of columns. Suppose, in
this example, that no more than 20 columns are ever expected to be accessed by a
single SELECT statement. This means that the SQLVAR array should have a
dimension of 20 (for an SQLDA size 20 x 80, or 1600, plus 16 for a total of 1616
bytes), because each item in the select-list must have a corresponding entry in
SQLVAR.

Having allocated what you estimated to be enough space for your SQLDA in the
SQLN field of the SQLDA, set an initial value equal to the number of SQLVAR array
elements. In the following example, set SQLN to 20:
Allocate space for an SQLDA of 1616 bytes on a quadword boundary
SQLN = 20;

Note: In PL/I the ALLOCATE statement is the only way to ensure the allocation of
a quadword boundary.

208 DB2 UDB for AS/400 SQL Programming V4R4


Having allocated storage, you can now issue a DESCRIBE statement.
EXEC SQL
DESCRIBE S1 INTO :SQLDA;

When the DESCRIBE statement is run, SQL places values in the SQLDA that
provide information about the select-list. The following Figure 9 shows the contents
of the SQLDA after the DESCRIBE is run:

SQLDA Size

SQLDA (8 bytes) 1616 SQLDA (4 bytes) 20 SQLN (2 bytes) 2 SQLD (2 bytes)

453 3 (reserved)

37
SQLVAR
Element 1 0
(80 bytes)
8 WORKDEPT

453 4 (reserved)

37
SQLVAR
Element 2 0
(80 bytes)
7 P H O N E N O

RV3W188-0

Figure 9. Contents of SQLDA after a DESCRIBE Is Run

SQLDAID is an identifier field initialized by SQL when a DESCRIBE is run.


SQLDABC is the byte count or size of the SQLDA. You can ignore these for now.

The example for running the SELECT statement for S1 is:


SELECT WORKDEPT, PHONENO
FROM CORPDATA.EMPLOYEE
WHERE LASTNAME = 'PARKER'

Your program might have to alter the SQLN value if the SQLDA is not large enough
to contain the described SQLVAR elements. For example, let the SELECT
statement contain 27 select-list expressions instead of the 20 or less that you
estimated. Because the SQLDA was only allocated with an SQLVAR dimension of
20 elements, SQL cannot describe the select-list, because the SQLVAR has too
many elements. SQL sets the SQLD to the actual number of columns specified by
the SELECT statement, and the remainder of the structure is ignored. Therefore,
after a DESCRIBE, you should compare the SQLN to the SQLD. If the value of
SQLD is greater than the value of SQLN, allocate a larger SQLDA based on the
value in SQLD, as follows:
EXEC SQL
DESCRIBE S1 INTO :SQLDA;
IF SQLN <= SQLD THEN
DO;

/*Allocate a larger SQLDA using the value of SQLD.*/


/*Reset SQLN to the larger value.*/

EXEC SQL
DESCRIBE S1 INTO :SQLDA;
END;

Chapter 10. Dynamic SQL Applications 209


If you use DESCRIBE on a non SELECT statement, SQL sets SQLD to 0.
Therefore, if your program is designed to process both SELECT and non SELECT
statements, you can describe each statement (after it is prepared) to determine
whether it is a SELECT statement. This sample routine is designed to process only
SELECT statements; the SQLD is not checked.

Your program must now analyze the elements of SQLVAR. Remember that each
element describes a single select-list expression. Consider again the SELECT
statement that is being processed:
SELECT WORKDEPT, PHONENO
FROM CORPDATA.EMPLOYEE
WHERE LASTNAME = 'PARKER'

The first item in the select-list is WORKDEPT. At the beginning of this section, we
identified that each SQLVAR element contains the fields SQLTYPE, SQLLEN,
SQLRES, SQLDATA, SQLIND, and SQLNAME. SQL returns, in the SQLTYPE field,
a code that describes the data type of the expressions and whether nulls are
applicable or not.

For example, SQL sets SQLTYPE to 453 in SQLVAR element 1 (see Figure 9 on
page 209). This specifies that WORKDEPT is a fixed-length character string
(CHAR) column and that nulls are permitted in the column.

SQL sets SQLLEN to the length of the column. Because the data type of
WORKDEPT is CHAR, SQL sets SQLLEN equal to the length of the character
string. For WORKDEPT, that length is 3. Therefore, when the SELECT statement is
later run, a storage area large enough to hold a CHAR(3) string is needed.

Because the data type of WORKDEPT is CHAR FOR SBCS DATA, the first 4 bytes
of SQLDATA were set to the CCSID of the character column (see Figure 9 on
page 209). The last field in an SQLVAR element is a varying-length character string
called SQLNAME. The first 2 bytes of SQLNAME contain the length of the
character data. The character data itself is usually the name of a column used in
the SELECT statement (WORKDEPT in the above example.) The exceptions to this
are select-list items that are unnamed, such as functions (for example,
SUM(SALARY)), expressions (for example, A+B−C), and constants. In these cases,
SQLNAME is an empty string. SQLNAME can also contain a label rather than a
name. One of the parameters associated with the PREPARE and DESCRIBE
statements is the USING clause. You can specify it this way:
EXEC SQL
DESCRIBE S1 INTO:SQLDA
USING LABELS;

If you specify NAMES (or omit the USING parameter entirely), only column names
are placed in the SQLNAME field. If you specify SYSTEM NAMES, only the system
column names are placed in the SQLNAME field. If you specify LABELS, only
labels associated with the columns listed in your SQL statement are entered here. If
you specify ANY, labels are placed in the SQLNAME field for those columns that
have labels; otherwise, the column names are entered. If you specify BOTH, names
and labels are both placed in the field with their corresponding lengths. If you
specify BOTH, however, you must remember to double the size of the SQLVAR
array because you are including twice the number of elements. If you specify ALL,
column names, labels, and system column names are placed in the field with their
corresponding lengths. If you specify ALL, remember to triple the size of the
SQLVAR array. If you specify ALL:
v Names, and labels are placed in the field with their corresponding lengths.

210 DB2 UDB for AS/400 SQL Programming V4R4


v The size of the SQLVAR array must triple because you are including the number
of elements.
For more information on the USING option and on column labels, see the DB2 UDB
for AS/400 SQL Reference book.

In the example, the second SQLVAR element contains the information for the
second column used in the select: PHONENO. The 453 code in SQLTYPE specifies
that PHONENO is a CHAR column. For a CHAR data type of length 4, SQL sets
SQLLEN to 4.

After analyzing the result of the DESCRIBE, you can allocate storage for variables
containing the result of the SELECT statement. For WORKDEPT, a character field
of length 3 must be allocated; for PHONENO, a character field of length 4 must be
allocated.

After the storage is allocated, you must set SQLDATA and SQLIND to point to the
appropriate areas. For each element of the SQLVAR array, SQLDATA points to the
place where the results are to be put. SQLIND points to the place where the null
indicator is to be put. The following figure shows what the structure looks like now:

SQLDA Size

S Q L D A 1616 20 2 FLDA: (CHAR(3))

453 3 (reserved)

Address of FLDA
SQLVAR
Element 1 Address of FLDAI FLDB: (CHAR(4))
(80 bytes) 8 WORKDEPT

453 4 (reserved) Indicator


Variables: (halfword)
Address of FLDB FLDAI: FLDBI:
SQLVAR
Element 2 Address of FLDBI
(80 bytes)
7 P H O N E N O

RV3W189-0

This is what was done so far:


EXEC SQL
INCLUDE SQLDA;
/*Read a statement into the DSTRING varying-length
character string host variable.*/
EXEC SQL
PREPARE S1 FROM :DSTRING;
/*Allocate an SQLDA of 1616 bytes.*/
SQLN =20;
EXEC SQL
DESCRIBE S1 INTO :SQLDA;
/*Analyze the results of the DESCRIBE.*/
/*Allocate storage to hold one row of
the result table.*/
/*Set SQLDATA and SQLIND for each column
of the result table.*/

Chapter 10. Dynamic SQL Applications 211


Using a Cursor
You are now ready to retrieve the SELECT statements results. Dynamically defined
SELECT statements must not have an INTO statement. Therefore, all dynamically
defined SELECT statements must use a cursor. Special forms of the DECLARE,
OPEN, and FETCH are used for dynamically defined SELECT statements.

The DECLARE statement for the example statement is:


EXEC SQL DECLARE C1 CURSOR FOR S1;

As you can see, the only difference is that the name of the prepared SELECT
statement (S1) is used instead of the SELECT statement itself. The actual retrieval
of result rows is made as follows:
EXEC SQL
OPEN C1;
EXEC SQL
FETCH C1 USING DESCRIPTOR :SQLDA;
DO WHILE (SQLCODE = 0);
/*Display ... the results pointed to by SQLDATA*/
END;
/*Display ('END OF LIST')*/
EXEC SQL
CLOSE C1;

The cursor is opened, and the result table is evaluated. Notice that there are no
input host variables needed for the example SELECT statement. The SELECT
result rows are then returned using FETCH. On the FETCH statement, there is no
list of output host variables. Rather, the FETCH statement tells SQL to return results
into areas described by the descriptor called SQLDA. The same SQLDA that was
set up by DESCRIBE is now being used for the output of the SELECT statement. In
particular, the results are returned into the storage areas pointed to by the
SQLDATA and SQLIND fields of the SQLVAR elements. The following figure shows
what the structure looks like after the FETCH statement has been processed.

SQLDA Size

S Q L D A 1616 20 2 FLDA: (CHAR(3))

453 3 (reserved) E11

Address of FLDA
SQLVAR
Element 1 Address of FLDAI FLDB: (CHAR(4))
(80 bytes) 8 WORKDEPT 4502

453 4 (reserved) Indicator


Variables: (halfword)
Address of FLDB FLDAI: FLDBI:
SQLVAR
Element 2 Address of FLDBI 0 0
(80 bytes)
7 P H O N E N O

RV3W190-0

The meaning of the SMALLINT pointed to by SQLIND is the same as any other
indicator variable:

212 DB2 UDB for AS/400 SQL Programming V4R4


0 Denotes that the returned value is not null.
<0 Denotes that the returned value is null.
>0 Denotes that the returned value was truncated because
the storage area furnished was not large enough.
The indicator variable contains the length before
truncation.

Note: Unless HOLD is specified, dynamic cursors are closed during COMMIT or
ROLLBACK.

Using Parameter Markers


In the example we are using, the SELECT statement that was dynamically run had
predictable parameters (input host variables) in the WHERE clause. In the example,
it was:
WHERE LASTNAME = 'PARKER'

If you want to run the same SELECT statement several times, using different values
for LASTNAME, you can use an SQL statement such as PREPARE or EXECUTE
(as described in “Using the PREPARE and EXECUTE Statements” on page 200)
like this:
SELECT WORKDEPT, PHONENO FROM CORPDATA.EMPLOYEE WHERE LASTNAME = ?

When your parameters are not predictable, your application cannot know the
number or types of the parameters until run time. You can arrange to receive this
information at the time your application is run, and by using a USING
DESCRIPTOR on the OPEN statement, you can substitute the values contained in
specific host variables for the parameter markers included in the WHERE clause of
the SELECT statement.

To code such a program, you need to use the OPEN statement with the USING
DESCRIPTOR clause. This SQL statement is used to not only open a cursor, but to
replace each parameter marker with the value of the corresponding host variable.
The descriptor name that you specify with this statement must identify an SQLDA
that contains a valid description of those host variables. This SQLDA, unlike those
previously described, is not used to return information on data items that are part of
a SELECT list. That is, it is not used as output from a DESCRIBE statement, but as
input to the OPEN statement. It provides information on host variables that are used
to replace parameter markers in the WHERE clause of the SELECT statement. It
gets this information from the application, which must be designed to place
appropriate values into the necessary fields of the SQLDA. The SQLDA is then
ready to be used as a source of information for SQL in the process of replacing
parameter markers with host variable data.

When you use the SQLDA for input to the OPEN statement with the USING
DESCRIPTOR clause, not all of its fields have to be filled in. Specifically, SQLDAID,
SQLRES, and SQLNAME can be left blank (SQLNAME (SQLCCSID in REXX) can
be set if a specific CCSID is needed.) Therefore, when you use this method for
replacing parameter markers with host variable values, you need to determine:
v How many ? parameter markers are there?
v What are the data types and attributes of these parameters markers (SQLTYPE,
SQLLEN, and SQLNAME)?
v Do you want an indicator variable?

Chapter 10. Dynamic SQL Applications 213


In addition, if the routine is to handle both SELECT and non SELECT statements,
you may want to determine what category of statement it is. (Alternatively, you can
write code to look for the SELECT keyword.)

If your application uses parameter markers, your program has to:


1. Read a statement into the DSTRING varying-length character string host
variable.
2. Determine the number of ? parameter markers.
3. Allocate an SQLDA of that size.
This is not applicable in REXX.
4. Set SQLN and SQLD to the number of ? parameter markers.
SQLN is not applicable in REXX.
5. Set SQLDABC equal to SQLN*LENGTH(SQLVAR) + 16.
This is not applicable in REXX.
6. For each ? parameter marker:
a. Determine the data types, lengths, and indicators.
b. Set SQLTYPE and SQLLEN.
c. Allocate storage to hold the input values (the ? values).
d. Set these values.
e. Set SQLDATA and SQLIND (if applicable) for each ? parameter marker.
f. If character variables are used, and they are in a CCSID other than the job
default CCSID, set SQLNAME (SQLCCSID in REXX) accordingly.
g. If graphic variables are used and they have a CCSID other than the
associated DBCS CCSID for the job CCSID, set the SQLNAME (SQLCCSID
in REXX) to that CCSID.
h. Issue the OPEN statement with a USING DESCRIPTOR clause to open
your cursor and substitute a host variable value for each of the parameter
markers.

The statement can then be processed normally.

214 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 11. Common Concepts and Rules for Using SQL with
Host Languages
This chapter describes some concepts and rules that are common to using SQL
statements in a host language that involve:
v Using host variables in SQL statements
v Handling SQL error and return codes
v Handling exception conditions with the WHENEVER statement

Using Host Variables in SQL Statements


When your program retrieves data, the values are put into data items defined by
your program and specified with the INTO clause of a SELECT INTO or FETCH
statement. The data items are called host variables.

A host variable is a field in your program that is specified in an SQL statement,


usually as the source or target for the value of a column. The host variable and
column must be data type compatible. Host variables may not be used to identify
SQL objects, such as tables or views, except in the DESCRIBE TABLE statement.

A host structure is a group of host variables used as the source or target for a set
of selected values (for example, the set of values for the columns of a row). A host
structure array is an array of host structures used in the multiple-row FETCH and
blocked INSERT statements.

Note: By using a host variable instead of a literal value in an SQL statement, you
give the application program the flexibility it needs to process different rows
in a table or view.

For example, instead of coding an actual department number in a WHERE clause,


you can use a host variable set to the department number you are currently
interested in.

Host variables are commonly used in SQL statements in these ways:


1. In a WHERE clause: You can use a host variable to specify a value in the
predicate of a search condition, or to replace a literal value in an expression.
For example, if you have defined a field called EMPID that contains an
employee number, you can retrieve the name of the employee whose number is
000110 with:
MOVE '000110' TO EMPID.
EXEC SQL
SELECT LASTNAME
INTO :PGM-LASTNAME
FROM CORPDATA.EMPLOYEE
WHERE EMPNO = :EMPID
END-EXEC.
2. As a receiving area for column values (named in an INTO clause): You can
use a host variable to specify a program data area that is to contain the column
values of a retrieved row. The INTO clause names one or more host variables
that you want to contain column values returned by SQL. For example, suppose
you are retrieving the EMPNO, LASTNAME, and WORKDEPT column values
from rows in the CORPDATA.EMPLOYEE table. You could define a host
variable in your program to hold each column, then name the host variables
with an INTO clause. For example:

© Copyright IBM Corp. 1997, 1999 215


EXEC SQL
SELECT EMPNO, LASTNAME, WORKDEPT
INTO :CBLEMPNO, :CBLNAME, :CBLDEPT
FROM CORPDATA.EMPLOYEE
WHERE EMPNO = :EMPID
END-EXEC.

In this example, the host variable CBLEMPNO receives the value from EMPNO,
CBLNAME receives the value from LASTNAME, and CBLDEPT receives the
value from WORKDEPT.
3. As a value in a SELECT clause: When specifying a list of items in the
SELECT clause, you are not restricted to the column names of tables and
views. Your program can return a set of column values intermixed with host
variable values and literal constants. For example:
MOVE '000220' TO PERSON.
EXEC SQL
SELECT "A", LASTNAME, SALARY, :RAISE,
SALARY + :RAISE
INTO :PROCESS, :PERSON-NAME, :EMP-SAL,
:EMP-RAISE, :EMP-TTL
FROM CORPDATA.EMPLOYEE
WHERE EMPNO = :PERSON
END-EXEC.

The results are:

PROCESS PERSON-NAME EMP-SAL EMP-RAISE EMP-TTL


A LUTZ 29840 4476 34316
4. As a value in other clauses of an SQL statement:
The SET clause in an UPDATE statement
The VALUES clause in an INSERT statement
The CALL statement

For more information on these statements, see the DB2 UDB for AS/400 SQL
Reference book.

Assignment Rules
SQL column values are set to (or assigned to) host variables during the running of
FETCH and SELECT INTO statements. SQL column values are set from (or
assigned from) host variables during the running of INSERT, UPDATE, and CALL
statements. All assignment operations observe the following rules:
v Numbers and strings are not compatible:
Numbers cannot be assigned to string columns or string host variables.
Strings cannot be assigned to numeric columns or numeric host variables.
v All character and DBCS graphic strings are compatible with UCS-2 graphic
columns if conversion is supported between the CCSIDs. All graphic strings are
compatible if the CCSIDs are compatible. All numeric values are compatible.
Conversions are performed by SQL whenever necessary. All character and
DBCS graphic strings are compatible with UCS-2 graphic columns for
assignment operations, if conversion is supported between the CCSIDs. For the
CALL statement, character and DBCS graphic parameters are compatible with
UCS-2 parameters if conversion is supported.
v A null value cannot be assigned to a host variable that does not have an
associated indicator variable.

216 DB2 UDB for AS/400 SQL Programming V4R4


v Different types of date/time values are not compatible. Dates are only compatible
with dates or string representations of dates; times are only compatible with
times or string representations of times; and timestamps are only compatible with
timestamps or string representations of timestamps.
A date can be assigned only to a date column, a character column, a
DBCS-open or DBCS-either column or variable, or a character variable 8. The
insert or update value of a date column must be a date or a string representation
of a date.
A time can be assigned only to a time column, a character column, a DBCS-open
or DBCS-either column or variable, or a character variable. The insert or update
value of a time column must be a time or a string representation of a time.
A timestamp can be assigned only to a timestamp column, a character column, a
DBCS-open or DBCS-either column or variable, or a character variable. The
insert or update value of a timestamp column must be a timestamp or a string
representation of a timestamp.

Rules for String Assignment


Rules regarding character string assignment are:
v When a string is assigned to a column, the length of the string value must not be
greater than the length attribute of the column. (Trailing blanks are normally
included in the length of the string. However, for string assignment trailing blanks
are not included in the length of the string.)
v When a MIXED character result column is assigned to a MIXED column, the
value of the MIXED character result column must be a valid MIXED character
string.
v When the value of a result column is assigned to a host variable and the string
value of the result column is longer than the length attribute of the host variable,
the string is truncated on the right by the necessary number of characters. If this
occurs, SQLWARN0 and SQLWARN1 (in the SQLCA) are set to W.
v When the value of a result column is assigned to a fixed-length host variable or
when the value of a host variable is assigned to a fixed-length CHAR result
column and the length of the string value is less than the length attribute of the
target, the string is padded on the right with the necessary number of blanks.
v When a MIXED character result column is truncated because the length of the
host variable into which it was being assigned was less than the length of the
string, the shift-in character at the end of the string is preserved. The result,
therefore, is still a valid MIXED character string.

Rules for CCSIDs


CCSIDs must be considered when you assign one character or graphic value to
another. This includes the assignment of host variables. The database manager
uses a common set of system services for converting SBCS data, DBCS data,
MIXED data, and graphic data.

The rules for CCSIDs are as follows:


v If the CCSID of the source matches the CCSID of the target, the value is
assigned without conversion.

8. A DBCS-open or DBCS-either column or variable is a variable that was declared in the host language by including the definition of
an externally described file. DBCS-open variables are also declared if the job CCSID indicates MIXED data, or the DECLARE
VARIABLE statement is used and a MIXED CCSID or the FOR MIXED DATA clause is specified. See DECLARE VARIABLE in the
DB2 UDB for AS/400 SQL Reference book.

Chapter 11. Common Concepts and Rules for Using SQL with Host Languages 217
v If the sub-type for the source or target is BIT, the value is assigned without
conversion.
v If the value is either null or an empty string, the value is assigned without
conversion.
v If conversion is not defined between specific CCSIDs, the value is not assigned
and an error message is issued.
v If conversion is defined and needed, the source value is converted to the CCSID
of the target before the assignment is performed.
For more information on CCSIDs, see the International Application Development
book.

Rules for Numeric Assignment


Rules regarding numeric assignment are:
v The whole part of a number may be altered when converting it to
floating-point. A single-precision floating-point field can only contain seven
decimal digits. Any whole part of a number that contains more than seven digits
is altered due to rounding. A double-precision floating point field can only contain
16 decimal digits. Any whole part of a number that contains more than 16 digits
is altered due to rounding.
v The whole part of a number is never truncated. If necessary, the fractional
part of a number is truncated. If the number, as converted, does not fit into the
target host variable or column, a negative SQLCODE is returned.
v Whenever a decimal, numeric, or binary number is assigned to a decimal,
numeric, or binary column or host variable, the number is converted, if
necessary, to the precision and scale of the target. The necessary number of
leading zeros is added or deleted; in the fractional part of the number, the
necessary number of trailing zeros is added, or the necessary number of trailing
digits is eliminated.
v When a binary or floating-point number is assigned to a decimal or numeric
column or host variable, the number is first converted to a temporary decimal or
numeric number and then converted, if necessary, to the precision and scale of
the target.
– When a halfword binary integer (SMALLINT) with 0 scale is converted to
decimal or numeric, the temporary result has a precision of 5 and a scale of
0.
– When a fullword binary integer (INTEGER) is converted to decimal or
numeric, the temporary result has a precision of 11 and a scale of 0.
– When a floating-point number is converted to decimal or numeric, the
temporary result has a precision of 31 and the maximum scale that allows the
whole part of the number to be represented without loss of either significance
or accuracy.

Rules for Date, Time, and Timestamp Assignment


When a date is assigned to a host variable, the date is converted to the string
representation specified by the DATFMT and DATSEP parameters of the
CRTSQLxxx command. Leading zeros are not omitted from any part of the date
representation. The host variable must be a fixed or variable-length character string
variable with a length of at least 10 bytes for *USA, *EUR, *JIS, or *ISO date
formats, 8 bytes for *MDY, *DMY, or *YMD date formats, or 6 bytes for the *JUL
date format. If the length is greater than 10, the string is padded on the right with
blanks. In ILE RPG, the host variable can also be a date variable.

218 DB2 UDB for AS/400 SQL Programming V4R4


When a time is assigned to a host variable, the time is converted to the string
representation by the TIMFMT and TIMSEP parameters of the CRTSQLxxx
command. Leading zeros are not omitted. The host variable must be a fixed or
variable-length character string variable. If the length of the host variable is greater
than the string representation of the time, the string is padded on the right with
blanks.
v If the *USA format is used, the length of the host variable must not be less than
8.
v If the *HMS, *ISO, *EUR, or *JIS format is used, the length of the host variable
must be at least 8 bytes if seconds are to be included, and 5 bytes if only hours
and minutes are needed. In this case, SQLWARN0 and SQLWARN1 (in the
SQLCA) are set to W, and if an indicator variable is specified, it is set to the
actual number of seconds truncated.

In ILE RPG, the host variable can also be a time variable.

When a timestamp is assigned to a host variable, the timestamp is converted to its


string representation. Leading zeros are not omitted from any part. The host
variable must be a fixed or variable-length character string variable with a length of
at least 19 bytes. If the length is less than 26, the host variable does not include all
the digits of the microseconds. If the length is greater than 26, the host variable is
padded on the right with blanks. In ILE RPG, the host variable can also be a
timestamp variable.

Indicator Variables
An indicator variable is a halfword integer variable used to indicate whether its
associated host variable has been assigned a null value:
v If the value for the result column is null, SQL puts a -1 in the indicator variable.
v If you do not use an indicator variable and the result column is a null value, a
negative SQLCODE is returned.
v If the value for the result column causes a data mapping error. SQL sets the
indicator variable to −2.

You can also use an indicator variable to verify that a retrieved string value has not
been truncated. If truncation occurs, the indicator variable contains a positive
integer that specifies the original length of the string.

When the database manager returns a value from a result column, you can test the
indicator variable. If the value of the indicator variable is less than zero, you know
the value of the results column is null. When the database manager returns a null
value, the host variable will be set to the default value for the result column.

You specify an indicator variable (preceded by a colon) immediately after the host
variable or immediately after the keyword INDICATOR. For example:
EXEC SQL
SELECT COUNT(*), AVG(SALARY)
INTO :PLICNT, :PLISAL:INDNULL
FROM CORPDATA.EMPLOYEE
WHERE EDLEVEL < 18
END-EXEC.

You can then test INDNULL to see if it contains a negative value. If it does, you
know SQL returned a null value.

Chapter 11. Common Concepts and Rules for Using SQL with Host Languages 219
Always test for NULL in a column by using the IS NULL predicate. For example:
WHERE expression IS NULL

Do not test for NULL in this way:


MOVE -1 TO HUIND.
EXEC SQL...WHERE column-name = :HUI :HUIND

The EQUAL predicate will always be evaluated as false when it compares a null
value. The result of this example will select no rows.

Used with Host Structures


You can also specify an indicator structure (defined as an array of halfword
integer variables) to support a host structure. If the results column values returned
to a host structure can be null, you can add an indicator structure name to the host
structure name. This allows SQL to notify your program about each null value
returned to a host variable in the host structure.

For example, in COBOL:


01 SAL-REC.
10 MIN-SAL PIC S9(6)V99 USAGE COMP-3.
10 AVG-SAL PIC S9(6)V99 USAGE COMP-3.
10 MAX-SAL PIC S9(6)V99 USAGE COMP-3.
01 SALTABLE.
02 SALIND PIC S9999 USAGE COMP-4 OCCURS 3 TIMES.
01 EDUC-LEVEL PIC S9999 COMP-4.
...
MOVE 20 TO EDUC-LEVEL.
...
EXEC SQL
SELECT MIN(SALARY), AVG(SALARY), MAX(SALARY)
INTO :SAL-REC:SALIND
FROM CORPDATA.EMPLOYEE
WHERE EDLEVEL>:EDUC-LEVEL
END-EXEC.

In this example, SALIND is an array containing 3 values, each of which can be


tested for a negative value. If, for example, SALIND(1) contains a negative value,
then the corresponding host variable in the host structure (that is, MIN-SAL) is not
changed for the selected row.

In the above example, SQL selects the column values of the row into a host
structure. Therefore, you must use a corresponding structure for the indicator
variables to determine which (if any) selected column values are null.

Used to Set Null Values


You can use an indicator variable to set a null value in a column. When processing
UPDATE or INSERT statements, SQL checks the indicator variable (if it exists). If it
contains a negative value, the column value is set to null. If it contains a value
greater than -1, the associated host variable contains a value for the column.

For example, you can specify that a value be put in a column (using an INSERT or
UPDATE statement), but you may not be sure that the value was specified with the
input data. To provide the capability to set a column to a null value, you can write
the following statement:

220 DB2 UDB for AS/400 SQL Programming V4R4


EXEC SQL
UPDATE CORPDATA.EMPLOYEE
SET PHONENO = :NEWPHONE:PHONEIND
WHERE EMPNO = :EMPID
END-EXEC.

When NEWPHONE contains other than a null value, set PHONEIND to zero by
preceding the statement with:
MOVE 0 to PHONEIND.

Otherwise, to tell SQL that NEWPHONE contains a null value, set PHONEIND to a
negative value, as follows:
MOVE -1 TO PHONEIND.

Handling SQL Error Return Codes


When an SQL statement is processed in your program, SQL places a return code in
the SQLCODE and SQLSTATE fields. The return codes indicate the success or
failure of the running of your statement. If SQL encounters an error while
processing the statement, the SQLCODE is a negative number and
SUBSTR(SQLSTATE,1,2) is not '00', '01', or '02'. If SQL encounters an exception
but valid condition while processing your statement, the SQLCODE is a positive
number and SUBSTR(SQLSTATE,1,2) is '01' or '02'. If your SQL statement is
processed without encountering an error or warning condition, the SQLCODE is
zero and the SQLSTATE is '00000'.

Note: There are situations when a zero SQLCODE is returned to your program and
the result might not be satisfactory. For example, if a value was truncated as
a result of running your program, the SQLCODE returned to your program is
zero. However, one of the SQL warning flags (SQLWARN1) indicates
truncation. In this case, the SQLSTATE is not '00000'.

Attention: If you do not test for negative SQLCODEs or specify a WHENEVER


SQLERROR statement, your program will continue to the next statement.
Continuing to run after an error can produce unpredictable results.

The main purpose for SQLSTATE is to provide common return codes for common
return conditions among the different IBM relational database systems. SQLSTATEs
are particularly useful when handling problems with distributed database operations.
For more information, see the DB2 UDB for AS/400 SQL Reference book.

Because the SQLCA is a valuable problem-diagnosis tool, it is a good idea to


include in your application programs the instructions necessary to display some of
the information contained in the SQLCA. Especially important are the following
SQLCA fields:
SQLCODE Return code.
SQLSTATE Return code.
SQLERRD(3) The number of rows updated, inserted, or deleted
by SQL.
SQLWARN0 If set to W, at least one of the SQL warning flags
(SQLWARN1 through SQLWARNA) is set.

Chapter 11. Common Concepts and Rules for Using SQL with Host Languages 221
For more information about the SQLCA, see Appendix B, “SQL Communication
Area” in the DB2 UDB for AS/400 SQL Reference book. For a listing of DB2 UDB
for AS/400 SQLCODEs and SQLSTATEs, see Appendix B.

Handling Exception Conditions with the WHENEVER Statement


The WHENEVER statement causes SQL to check the SQLSTATE and SQLCODE
and continue processing your program, or branch to another area in your program if
an error, exception, or warning exists as a result of running an SQL statement. An
exception condition handling subroutine (part of your program) can then examine
the SQLCODE or SQLSTATE field to take an action specific to the error or
exception situation.

Note: The WHENEVER statement is not allowed in REXX procedures. For


information on handling exception conditions in REXX, see Chapter 17.
Coding SQL Statements in REXX Applications.

The WHENEVER statement allows you to specify what you want to do whenever a
general condition is true. You can specify more than one WHENEVER statement for
the same condition. When you do this, the first WHENEVER statement applies to all
subsequent SQL statements in the source program until another WHENEVER
statement is specified.

The WHENEVER statement looks like this:


EXEC SQL
WHENEVER condition action
END-EXEC.

There are three conditions you can specify:


SQLWARNING Specify SQLWARNING to indicate what you want
done when SQLWARN0 = W or SQLCODE
contains a positive value other than 100
(SUBSTR(SQLSTATE,1,2) =’01’).

Note: SQLWARN0 could be set for several


different reasons. For example, if the value
of a column was truncated when it was
moved into a host variable, your program
might not regard this as an error.
SQLERROR Specify SQLERROR to indicate what you want
done when an error code is returned as the result
of an SQL statement (SQLCODE < 0)
(SUBSTR(SQLSTATE,1,2) > ’02’).
NOT FOUND Specify NOT FOUND to indicate what you want
done when an SQLCODE of +100 and a
SQLSTATE of '02000' is returned because:
v After a single-row SELECT is issued or after the
first FETCH is issued for a cursor, the data the
program specifies does not exist.
v After a subsequent FETCH, no more rows
satisfying the cursor select-statement are left to
retrieve.

222 DB2 UDB for AS/400 SQL Programming V4R4


v After an UPDATE, a DELETE, or an INSERT, no
row meets the search condition.

You can also specify the action you want taken:


CONTINUE This causes your program to continue to the next
statement.
GO TO label This causes your program to branch to an area in
the program. The label for that area may be
preceded with a colon. The WHENEVER ... GO TO
statement:
v Must be a section name or an unqualified
paragraph name in COBOL
v Is a label in PL/I and C
v Is the label of a TAG in RPG

For example, if you are retrieving rows using a cursor, you expect that SQL will
eventually be unable to find another row when the FETCH statement is issued. To
prepare for this situation, specify a WHENEVER NOT FOUND GO TO ... statement
to cause SQL to branch to a place in the program where you issue a CLOSE
statement in order to close the cursor properly.

Note: A WHENEVER statement affects all subsequent source SQL statements until
another WHENEVER is encountered.

In other words, all SQL statements coded between two WHENEVER statements (or
following the first, if there is only one) are governed by the first WHENEVER
statement, regardless of the path the program takes.

Because of this, the WHENEVER statement must precede the first SQL statement it
is to affect. If the WHENEVER follows the SQL statement, the branch is not taken
on the basis of the value of the SQLCODE and SQLSTATE set by that SQL
statement. However, if your program checks the SQLCODE or SQLSTATE directly,
the check must be done after the SQL statement is run.

The WHENEVER statement does not provide a CALL to a subroutine option. For
this reason, you might want to examine the SQLCODE or SQLSTATE value after
each SQL statement is run and call a subroutine, rather than use a WHENEVER
statement.

Chapter 11. Common Concepts and Rules for Using SQL with Host Languages 223
224 DB2 UDB for AS/400 SQL Programming V4R4
Chapter 12. Coding SQL Statements in C and C++
Applications
This chapter describes the unique application and coding requirements for
embedding SQL statements in a C or C++ program. C program refers to ILE C for
AS/400 programs. C++ program refers to ILE C++ programs or programs that are
created with the VisualAge C++ for AS/400 compiler. This chapter also defines the
requirements for host structures and host variables.

A detailed sample C program, showing how SQL statements can be used, is


provided in Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements.

Defining the SQL Communications Area


A C or C++ program that contains SQL statements must include one or both of the
following:
v An SQLCODE variable declared as long SQLCODE
v An SQLSTATE variable declared as char SQLSTATE[6]

Or,
v An SQLCA (which contains an SQLCODE and SQLSTATE variable).
The SQLCODE and SQLSTATE values are set by the database manager after each
SQL statement is executed. An application can check the SQLCODE or SQLSTATE
value to determine whether the last SQL statement was successful.

You can code the SQLCA in a C or C++ program either directly or by using the SQL
INCLUDE statement. Using the SQL INCLUDE statement requests the inclusion of
a standard declaration:
EXEC SQL INCLUDE SQLCA ;

A standard declaration includes both a structure definition and a static data area
named 'sqlca'.

The SQLCODE, SQLSTATE, and SQLCA variables must appear before any
executable statements. The scope of the declaration must include the scope of all
SQL statements in the program.

The included C and C++ source statements for the SQLCA are:
#ifndef SQLCODE
struct sqlca {
unsigned char sqlcaid[8];
long sqlcabc;
long sqlcode;
short sqlerrml;
unsigned char sqlerrmc[70];
unsigned char sqlerrp[8];
long sqlerrd[6];
unsigned char sqlwarn[11];
unsigned char sqlstate[5];
};
#define SQLCODE sqlca.sqlcode
#define SQLWARN0 sqlca.sqlwarn[0]
#define SQLWARN1 sqlca.sqlwarn[1]
#define SQLWARN2 sqlca.sqlwarn[2]
#define SQLWARN3 sqlca.sqlwarn[3]

© Copyright IBM Corp. 1997, 1999 225


#define SQLWARN4 sqlca.sqlwarn[4]
#define SQLWARN5 sqlca.sqlwarn[5]
#define SQLWARN6 sqlca.sqlwarn[6]
#define SQLWARN7 sqlca.sqlwarn[7]
#define SQLWARN8 sqlca.sqlwarn[8]
#define SQLWARN9 sqlca.sqlwarn[9]
#define SQLWARNA sqlca.sqlwarn[10]
#define SQLSTATE sqlca.sqlstate
#endif
struct sqlca sqlca;

When a declare for SQLCODE is found in the program and the precompiler
provides the SQLCA, SQLCADE replaces SQLCODE. When a declare for
SQLSTATE is found in the program and the precompiler provides the SQLCA,
SQLSTOTE replaces SQLSTATE.

Note: Many SQL error messages contain message data that is of varying length.
The lengths of these data fields are embedded in the value of the SQLCA
sqlerrmc field. Because of these lengths, printing the value of sqlerrmc from
a C or C++ program might give unpredictable results.

For more information on SQLCA, see Appendix B, “SQL Communication Area” in


the DB2 UDB for AS/400 SQL Reference book.

Defining SQL Descriptor Areas


The following statements require an SQLDA:
EXECUTE...USING DESCRIPTOR descriptor-name
FETCH...USING DESCRIPTOR descriptor-name
OPEN...USING DESCRIPTOR descriptor-name
DESCRIBE statement-name INTO descriptor-name
DESCRIBE TABLE host-variable INTO descriptor-name
PREPARE statement-name INTO descriptor-name
CALL...USING DESCRIPTOR descriptor-name

Unlike the SQLCA, more than one SQLDA can be in the program, and an SQLDA
can have any valid name. You can code an SQLDA in a C or C++ program either
directly or by using the SQL INCLUDE statement. Using the SQL INCLUDE
statement requests the inclusion of a standard SQLDA declaration:
EXEC SQL INCLUDE SQLDA;

A standard declaration includes only a structure definition with the name ’sqlda’.

C and C++ declarations that are included for the SQLDA are:
#ifndef SQLDASIZE
struct sqlda {
unsigned char sqldaid[8];
long sqldabc;
short sqln;
short sqld;
struct sqlvar {
short sqltype;
short sqllen;
unsigned char *sqldata;
short *sqlind;
struct sqlname {

226 DB2 UDB for AS/400 SQL Programming V4R4


short length;
unsigned char data[30];
} sqlname;
} sqlvar[1];
};
#define SQLDASIZE(n) (sizeof(struct sqlda) + (n-1)* sizeof(struct sqlvar))
#endif

One benefit from using the INCLUDE SQLDA SQL statement is that you also get
the following macro definition:
#define SQLDASIZE(n) (sizeof(struct sqlda) + (n-1)* sizeof(struc sqlvar))

This macro makes it easy to allocate storage for an SQLDA with a specified number
of SQLVAR elements. In the following example, the SQLDASIZE macro is used to
allocate storage for an SQLDA with 20 SQLVAR elements.
#include <stdlib.h>
EXEC SQL INCLUDE SQLDA;

struct sqlda *mydaptr;


short numvars = 20;
.
.
mydaptr = (struct sqlda *) malloc(SQLDASIZE(numvars));
mydaptr->sqln = 20;

When you have declared an SQLDA as a pointer, you must reference it exactly as
declared when you use it in an SQL statement, just as you would for a host variable
that was declared as a pointer. To avoid compiler errors, the type of the value that
is assigned to the sqldata field of the SQLDA must be a pointer of unsigned
character. This helps avoid compiler errors. The type casting is only necessary for
the EXECUTE, OPEN, CALL, and FETCH statements where the application
program is passing the address of the host variables in the program. For example,
if you declared a pointer to an SQLDA called mydaptr, you would use it in a
PREPARE statement as:
EXEC SQL PREPARE mysname INTO :*mydaptr FROM :mysqlstring;

SQLDA declarations can appear wherever a structure definition is allowed. Normal


C scope rules apply.

Dynamic SQL is an advanced programming technique described in Chapter 10.


Dynamic SQL Applications. With dynamic SQL, your program can develop and then
run SQL statements while the program is running. A SELECT statement with a
variable SELECT list (that is a list of the data to be returned as part of the query)
that runs dynamically requires an SQL descriptor area (SQLDA). This is because
you will not know in advance how many or what type of variables to allocate in
order to receive the results of the SELECT.

For more information on the SQLDA, see the DB2 UDB for AS/400 SQL Reference
book.

Embedding SQL Statements


An SQL statement can be placed wherever a C or C++ statement that can be run
can be placed.

Chapter 12. Coding SQL Statements in C and C++ Applications 227


Each SQL statement must begin with EXEC SQL and end with a semicolon (;). The
EXEC SQL keywords must be on one line. The remaining part of the SQL
statement can be on more than one line.

Example: An UPDATE statement coded in a C or C++ program might be coded in


the following way:
EXEC SQL
UPDATE DEPARTMENT
SET MGRNO = :MGR_NUM
WHERE DEPTNO = :INT_DEPT ;

Comments
In addition to using SQL comments (--), you can include C comments (/*...*/) within
embedded SQL statements whenever a blank is allowed, except between the
keywords EXEC and SQL. Comments can span any number of lines. You cannot
nest comments. You can use single-line comments (comments that start with //) in
C++, but you cannot use them in C.

Continuation for SQL Statements


SQL statements can be contained on one or more lines. You can split an SQL
statement wherever a blank can appear. The backslash (\) can be used to continue
a string constant or delimited identifier.

Constants containing DBCS data may be continued across multiple lines in two
ways:
v If the character at the right margin of the continued line is a shift-in and the
character at the left margin of the continuation line is a shift-out, then the shift
characters located at the left and right margin are removed.
This SQL statement has a valid graphic constant of
G’<AABBCCDDEEFFGGHHIIJJKK>’. The redundant shifts at the margin are
removed.
*...+....1....+....2....+....3....+....4....+....5....+....6....+....7....*....8
EXEC SQL SELECT * FROM GRAPHTAB WHERE GRAPHCOL = G'<AABBCCDDEEFFGGHH>
<IIJJKK>';

v If you are not using the default margins of 1 and 80, it is possible to place the
shift characters outside of the margins. For this example, assume the margins
are 5 and 75. This SQL statement has a valid graphic constant of
G’<AABBCCDDEEFFGGHHIIJJKK>’.
*...(....1....+....2....+....3....+....4....+....5....+....6....+....7....)....8
EXEC SQL SELECT * FROM GRAPHTAB WHERE GRAPHCOL = G'<AABBCCDD>
<EEFFGGHHIIJJKK>';

Including Code
You can include SQL statements, C, or C++ statements by embedding the following
SQL statement in the source code:
EXEC SQL INCLUDE member-name;

You cannot use C and C++ #include statements to include SQL statements or
declarations of C or C++ host variables that are referred to in SQL statements.

228 DB2 UDB for AS/400 SQL Programming V4R4


Margins
You must code SQL statements within the margins that are specified by the
MARGINS parameter on the CRTSQLCI, CRTSQLCPPI, or CVTSQLCPP
command. If EXEC SQL does not start within the specified margins, the SQL
precompiler does not recognize the SQL statement. For more information about
CRTSQLCI, CRTSQLCPPI, and CVTSQLCPP, see Appendix D. DB2 UDB for
AS/400 CL Command Descriptions.

Names
You can use any valid C or C++ variable name for a host variable. It is subject to
the following restrictions:

Do not use host variable names or external entry names that begin with 'SQL',
'RDI', or 'DSN' in any combination of uppercase or lowercase letters. These names
are reserved for the database manager. The length of host variable names is limited
to 64.

NULLs and NULs


C, C++, and SQL use the word null, but for different meanings. The C and C++
languages have a null character (NUL), a null pointer (NULL), and a null statement
(just a semicolon). The C NUL is a single character that compares equal to 0. The
C NULL is a special reserved pointer value that does not point to any valid data
object. The SQL null value is a special value that is distinct from all nonnull values
and denotes the absence of a (non-null) value.

Statement Labels
Executable SQL statements can be preceded with a label.

Preprocessor Sequence
You must run the SQL preprocessor before the C or C++ preprocessor. You cannot
use C or C++ preprocessor directives within SQL statements.

Trigraphs
Some characters from the C and C++ character set are not available on all
keyboards. You can enter these characters into a C or C++ source program by
using a sequence of three characters that is called a trigraph. The following trigraph
sequences are supported within host variable declarations:
v ??( left bracket
v ??) right bracket
v ??< left brace
v ??> right brace
v ??= pound
v ??/ backslash

Chapter 12. Coding SQL Statements in C and C++ Applications 229


WHENEVER Statement
The target for the GOTO clause in an SQL WHENEVER statement must be within
the scope of any SQL statements affected by the WHENEVER statement.

Using Host Variables


All host variables used in SQL statements must be explicitly declared. A host
variable used in an SQL statement must be declared prior to the first use of the
host variable in an SQL statement.

In C, the C statements that are used to define the host variables should be
preceded by a BEGIN DECLARE SECTION statement and followed by an END
DECLARE SECTION statement. If a BEGIN DECLARE SECTION and END
DECLARE SECTION are specified, all host variable declarations used in SQL
statements must be between the BEGIN DECLARE SECTION and the END
DECLARE SECTION statements.

In C++, the C++ statements that are used to define the host variables must be
preceded by a BEGIN DECLARE SECTION statement and followed by an END
DECLARE SECTION statement. You cannot use any variable that is not between
the BEGIN DECLARE SECTION statement and the END DECLARE SECTION
statement as a host variable.

All host variables within an SQL statement must be preceded by a colon (:).

The names of host variables must be unique within the program, even if the host
variables are in different blocks or procedures.

An SQL statement that uses a host variable must be within the scope of the
statement in which the variable was declared.

Host variables cannot be union elements.

Declaring Host Variables


The C and C++ precompilers recognize only a subset of valid C and C++
declarations as valid host variable declarations.

Numeric Host Variables


The following figure shows the syntax for valid numeric host variable declarations.

230 DB2 UDB for AS/400 SQL Programming V4R4


Numeric

ÊÊ Ê
auto const
extern volatile
static

Ê float Ê
double
decimal ( precision )
, scale
long
signed short int

Ê · variable-name ; ÊÍ
= expression

Notes:
1. Precision and scale must be integer constants. Precision may be in the range
from 1 to 31. Scale may be in the range from 0 to the precision.
2. If using the decimal data type, the header file decimal.h must be included.

Character Host Variables


There are three valid forms for character host variables:
v Single-character form
v NUL-terminated character form
v VARCHAR structured form

All character types are treated as unsigned.

Single-Character Form

ÊÊ char Ê
auto const unsigned
extern volatile signed
static

Ê · variable-name ; ÊÍ
[ 1 ] = expression

Chapter 12. Coding SQL Statements in C and C++ Applications 231


NUL-Terminated Character Form

ÊÊ char Ê
auto const unsigned
extern volatile signed
static

Ê · variable-name [ length ] ; ÊÍ
= expression

Notes:
1. The length must be an integer constant that is greater than 1 and not greater
than 32741.
2. If the *CNULRQD option is specified on the CRTSQLCI, CRTSQLCPPI, or
CVTSQLCPP command, the input host variables must contain the
NUL-terminator. Output host variables are padded with blanks, and the last
character is the NUL-terminator. If the output host variable is too small to
contain both the data and the NUL-terminator, the following actions are taken:
v The data is truncated
v The last character is the NUL-terminator
v SQLWARN1 is set to ’W’
3. If the *NOCNULRQD option is specified on the CRTSQLCI, CRTSQLCPPI, or
CVTSQLCPP command, the input variables do not need to contain the
NUL-terminator.
The following applies to output host variables.
v If the host variable is large enough to contain the data and the
NUL-terminator, then the following actions are taken:
– The data is returned, but the data is not padded with blanks
– The NUL-terminator immediately follows the data
v If the host variable is large enough to contain the data but not the
NUL-terminator, then the following actions are taken:
– The data is returned
– A NUL-terminator is not returned
– SQLWARN1 is set to ’N’
v If the host variable is not large enough to contain the data, the following
actions are taken:
– The data is truncated
– A NUL-terminator is not returned
– SQLWARN1 is set to ’W’

232 DB2 UDB for AS/400 SQL Programming V4R4


VARCHAR Structured Form

ÊÊ struct { Ê
auto const _Packed tag
extern volatile
static

Ê short var-1 ; char var-2 [ length ] ; } Ê


signed int unsigned
signed

Ê · variable-name ; ÊÍ
= { expression , expression }

Notes:
1. length must be an integer constant that is greater than 0 and not greater than
32740.
2. var-1 and var-2 must be simple variable references and cannot be used
individually as integer and character host variables.
3. The struct tag can be used to define other data areas, but these cannot be used
as host variables.
4. The VARCHAR structured form should be used for bit data that may contain the
NULL character. The VARCHAR structured form will not be ended using the
nul-terminator.

Example:
EXEC SQL BEGIN DECLARE SECTION;

/* valid declaration of host variable vstring */

struct VARCHAR {
short len;
char s[10];
} vstring;

/* invalid declaration of host variable wstring */

struct VARCHAR wstring;

Graphic host variables


There are three valid forms for graphic host variables:
v Single-graphic form
v NUL-terminated graphic form
v VARGRAPHIC structured form

Chapter 12. Coding SQL Statements in C and C++ Applications 233


Single-Graphic Form

ÊÊ wchar_t Ê
auto const
extern volatile
static

Ê · variable-name ; ÊÍ
= expression

NUL-Terminated Graphic Form

ÊÊ wchar_t Ê
auto const
extern volatile
static

Ê · variable-name [ length ] ; ÊÍ
= expression

Notes:
1. length must be an integer constant that is greater than 1 and not greater than
16371.
2. If the *CNULRQD option is specified on the CRTSQLCI, CRTSQLCPPI, or
CVTSQLCPP command, then input host variables must contain the graphic
NUL-terminator (/0/0). Output host variables are padded with DBCS blanks, and
the last character is the graphic NUL-terminator. If the output host variable is too
small to contain both the data and the NUL-terminator, the following actions are
taken:
v The data is truncated
v The last character is the graphic NUL-terminator
v SQLWARN1 is set to ’W’

If the *NOCNULRQD option is specified on the CRTSQLCI, CRTSQLCPPI, or


CVTSQLCPP command, the input host variables do not need to contain the
graphic NUL-terminator. The following is true for output host variables.
v If the host variable is large enough to contain the data and the graphic
NUL-terminator, the following actions are taken:
– The data is returned, but is not padded with DBCS blanks
– The graphic NUL-terminator immediately follows the data

234 DB2 UDB for AS/400 SQL Programming V4R4


v If the host variable is large enough to contain the data but not the graphic
NUL-terminator, the following actions are taken:
– The data is returned
– A graphic NUL-terminator is not returned
– SQLWARN1 is set to ’N’
v If the host variable is not large enough to contain the data, the following
actions are taken:
– The data is truncated
– A graphic NUL-terminator is not returned
– SQLWARN1 is set to ’W’

VARGRAPHIC Structured Form

ÊÊ struct { Ê
auto const _Packed tag
extern volatile
static

Ê short var-1 ; wchar_t var-2 [ length ] ; } Ê


signed int

Ê · variable-name ; ÊÍ
= { expression , expression }

Notes:
1. length must be an integer constant that is greater than 0 and not greater than
16370.
2. var-1 and var-2 must be simple variable references and cannot be used as host
variables.
3. The struct tag can be used to define other data areas, but these cannot be used
as host variables.

Example:
EXEC SQL BEGIN DECLARE SECTION;

/* valid declaration of host variable graphic string */

struct VARGRAPH {
short len;
wchar_t s[10];
} vstring;

/* invalid declaration of host variable wstring */

struct VARGRAPH wstring;

Chapter 12. Coding SQL Statements in C and C++ Applications 235


| LOB Host Variables
|

| LOB Host Variable

| ÊÊ SQL TYPE IS BLOB Ê


| auto const CLOB
extern volatile DBCLOB
static

| Ê ( lob-length ) Ê
| K
M

| ,
|
Ê · variable-name ; ÊÍ
= { init-len,″init-data″ }
= SQL_BLOB_INIT(″init-data″)
= SQL_CLOB_INIT(″init-data″)
= SQL_DBCLOB_INIT(″init-data″)

||
|

| Notes:
| 1. The SQL TYPE IS clause is needed in order to distinguish the three LOB-types
| from each other so that type-checking and function resolution can be carried
| out for LOB-type host variables that are passed to functions.
| 2. For BLOB and CLOB, 1 <= lob-length <= 15,728,640
| 3. For DBCLOB, 1 <= lob-length <= 7,864,320
| 4. SQL TYPE IS, BLOB, CLOB, DBCLOB, K, M can be in mixed case.
| 5. The maximum length allowed for the initialization string is 32,766 bytes.
| 6. The initialization length, init-len, must be a numeric constant (that is, it cannot
| include K, M, or G).
| 7. A length for the LOB must be specified; that is, the following declaration is not
| permitted
| SQL TYPE IS BLOB my_blob;
| 8. If the LOB is not initialized within the declaration, then no initialization will be
| done within the precompiler generated code.
| 9. The precompiler generates a structure tag which can be used to cast to the
| host variables type.
| 10. LOB Host Variables can be declared in host structures and host structure
| arrays.
| 11. Pointers to LOB Host Variables can be declared, with the same rules and
| restrictions as for pointers to other host variable types.
| 12. CCSID processing for LOB Host Variables will be the same as the processing
| for other character and graphic host variable types.
| 13. If a DBCLOB is initialized, it is the user’s responsibility to prefix the string with
| an ’L’ (indicating a wide-character string).

| BLOB Example

236 DB2 UDB for AS/400 SQL Programming V4R4


| The following declaration:
| static SQL TYPE IS BLOB(128K)
| my_blob=SQL_BLOB_INIT("mydata");

| Results in the generation of the following structure:


| static struct my_blob_t {
| unsigned long length;
| char data[131072];
| } my_blob=SQL_BLOB_INIT("my_data");

| CLOB Example

| The following declaration:


| auto SQL TYPE IS CLOB(128K) var1, var2 = {10, "data2data2"};

| Results in the generation of the following structure:


| auto struct var1_t {
| unsigned long length;
| char data[131072];
| } var1, var2 = {10, "data2data2"};

| DBCLOB Example

| The following declaration:


| auto SQL TYPE IS DBCLOB(128K) my_dbclob;

| Results in the generation of the following structure:


| auto struct my_dbclob_t {
| unsigned long length;
| wchar_t data[131072];
| } my_dbclob;

| LOB Locators
|

| LOB Locator

| ÊÊ SQL TYPE IS BLOB_LOCATOR Ê


| auto const CLOB_LOCATOR
extern volatile DBCLOB_LOCATOR
static

| ,
|
Ê · variable-name ; ÊÍ
= init-value

||
|

| Notes:
| 1. SQL TYPE IS, BLOB_LOCATOR, CLOB_LOCATOR, DBCLOB_LOCATOR can
| be in mixed case.
| 2. init-value permits the initialization of pointer locator variables. Other types of
| initialization will have no meaning.
| 3. LOB Locators can be declared in host structures and host structure arrays.

Chapter 12. Coding SQL Statements in C and C++ Applications 237


| 4. Pointers to LOB Locators can be declared, with the same rules and restrictions
| as for pointers to other host variable types.

| CLOB Locator Example

| The following declaration:


| static SQL TYPE IS CLOB_LOCATOR my_locator;

| Results in the generation of the following structure:


| static long int unsigned my_locator;

| BLOB and DBCLOB locators have similar syntax.

| LOB File Reference Variables


|

| LOB File Reference Variable

| ÊÊ SQL TYPE IS BLOB_FILE Ê


| auto const CLOB_FILE
extern volatile DBCLOB_FILE
static

| ,
|
Ê · variable-name ; ÊÍ
= init-value

||
|

| Notes:
| 1. SQL TYPE IS, BLOB_FILE, CLOB_FILE, DBCLOB_FILE can be in mixed case.
| 2. LOB File Reference Variables can be declared as part of a host structure.
| 3. Pointers to LOB File Reference Variables can be declared, with the same rules
| and restrictions as for pointers to other host variable types.

| CLOB File Reference Example

| The following declaration:


| static SQL TYPE IS CLOB_FILE my_file;

| Results in the generation of the following structure:


| static struct {
| unsigned long name_length;
| unsigned long data_length;
| unsigned long file_options;
| char name[255];
| } my_file;

| BLOB and DBCLOB file reference variables have similar syntax.

| The pre-compiler will generate declarations for the following file option constants:
| v SQL_FILE_READ (2)
| v SQL_FILE_CREATE (8)

238 DB2 UDB for AS/400 SQL Programming V4R4


| v SQL_FILE_OVERWRITE (16)
| v SQL_FILE_APPEND (32)
|
Using Host Structures
In C and C++ programs, you can define a host structure, which is a named set of
elementary C or C++ variables. Host structures have a maximum of two levels,
even though the host structure might itself occur within a multilevel structure. An
exception is the declaration of a varying-length string, which requires another
structure.

A host structure name can be a group name whose subordinate levels name
elementary C or C++ variables. For example:
struct {
struct {
char c1;
char c2;
} b_st;
} a_st;

In this example, b_st is the name of a host structure consisting of the elementary
items c1 and c2.

You can use the structure name as a shorthand notation for a list of scalars, but
only for a two-level structure. You can qualify a host variable with a structure name
(for example, structure.field). Host structures are limited to two levels. (For example,
in the above host structure example, the a_st cannot be referred to in SQL.) A
structure cannot contain an intermediate level structure. In the previous example,
a_st could not be used as a host variable or referred to in an SQL statement. A host
structure for SQL data has two levels and can be thought of as a named set of host
variables. After the host structure is defined, you can refer to it in an SQL statement
instead of listing the several host variables (that is, the names of the host variables
that make up the host structure).

For example, you can retrieve all column values from selected rows of the table
CORPDATA.EMPLOYEE with:
struct { char empno[7];
struct { short int firstname_len;
char firstname_text[12];
} firstname;
char midint,
struct { short int lastname_len;
char lastname_text[15];
} lastname;
char workdept[4];
} pemp1;
.....
strcpy("000220",pemp1.empno);
.....
exec sql
select *
into :pemp1
from corpdata.employee
where empno=:pemp1.empno;

Notice that in the declaration of pemp1, two varying-length string elements are
included in the structure: firstname and lastname.

Chapter 12. Coding SQL Statements in C and C++ Applications 239


Host Structure Declarations
The following figure shows the valid syntax for host structure declarations.

Host Structures

ÊÊ struct { Ê
auto const _Packed tag
extern volatile
static

Ê · float · var-1 ; } Ê
double
decimal ( precision )
, scale
long
signed short int
varchar-structure
vargraphic-structure
,

char · var-2 ;
signed [ length ]
unsigned
,

wchar_t · var-5 ;
[ length ]

Ê · variable-name ; ÊÍ
= expression

varchar-structure:

struct { short var-3 ; Ê


tag signed int signed
unsigned

Ê char var-4 [ length ] ; }

vargraphic-structure:

struct { short Ê
tag signed int

Ê var-6 ; wchar_t var-7 [ length ] ; }

Note:

240 DB2 UDB for AS/400 SQL Programming V4R4


1. For details on declaring numeric, character, and graphic host variables,
see the notes under numeric host variables, character host variables,
and graphic host variables.
2. A structure of a short int followed by either a char or wchar_t array is
always interpreted by the SQL C and C++ compilers as either a
VARCHAR or VARGRAPHIC structure.

Host Structure Indicator Array


The following figure shows the valid syntax for host structure indicator array
declarations.

Host Structure Indicator Array

ÊÊ short Ê
auto const signed int
extern volatile
static

Ê · variable-name [ dimension ] ; ÊÍ
= expression

Note: Dimension must be an integer constant between 1 and 32767.

Using Arrays of Host Structures


In C and C++ programs, you can define a host structure array that has the
dimension attribute. Host structure arrays have a maximum of two levels, even
though the array might occur within a multiple-level structure. Another structure is
not needed if a varying-length character string or a varying-length graphic string is
not used.

In this example,
struct {
_Packed struct{
char c1_var[20];
short c2_var;
} b_array[10];
} a_struct;

the following are true:


v All of the members in b_array must be valid variable declarations.
v The _Packed attribute must be specified for the struct tag.
v b_array is the name of an array of host structures containing the members
c1_var and c2_var.
v b_array may only be used on the blocked forms of FETCH and INSERT
statements.

Chapter 12. Coding SQL Statements in C and C++ Applications 241


v c1_var and c2_var are not valid host variables in any SQL statement.
v A structure cannot contain an intermediate level structure.
For example, you can retrieve 10 rows from the cursor with:
_Packed struct {char first_initial;
char middle_initial;
_Packed struct {short lastname_len;
char lastname_data[15];
} lastname;
double total_salary;
} employee_rec[10];
struct { short inds[4];
} employee_inds[10];
...
EXEC SQL DECLARE C1 CURSOR FOR
SELECT SUBSTR(FIRSTNME,1,1), MIDINIT, LASTNAME,
SALARY+BONUS+COMM
FROM CORPDATA.EMPLOYEE;
EXEC SQL OPEN C1;
EXEC SQL FETCH C1 FOR 10 ROWS INTO :employee_rec:employee_inds;
...

Host Structure Array


The following figure shows the valid syntax for host structure array declarations.

242 DB2 UDB for AS/400 SQL Programming V4R4


Host Structure Array

ÊÊ _Packed struct { Ê
auto const tag
extern volatile
static

Ê · float · var-1 ; } Ê
double
decimal ( precision )
, scale
long
signed short int
varchar-structure
vargraphic-structure
,

char · var-2 ;
signed [ length ]
unsigned
,

wchar_t · var-5 ;
[ length ]

Ê · variable-name [ dimension ] ; ÊÍ
= expression

varchar-structure:

_Packed struct { short var-3 ; Ê


tag signed int signed
unsigned

Ê char var-4 [ length ] ; }

vargraphic-structure:

_Packed struct { short var-6 ; Ê


tag signed int

Ê wchar_t var-7 [ length ] ; }

Notes:
1. For details on declaring numeric, character, and graphic host variables, see the
notes under numeric-host variables, character-host, and graphic-host variables.
2. The struct tag can be used to define other data areas, but these cannot be used
as host variables.

Chapter 12. Coding SQL Statements in C and C++ Applications 243


3. Dimension must be an integer constant between 1 and 32767.

Host Structure Array Indicator Structure


The following figure shows the valid syntax for host structure array indicator
structure declarations.

Host Structure Array Indicator Structure

ÊÊ struct { Ê
auto const _Packed tag
extern volatile
static

Ê short var-1 [ dimension-1 ] ; } Ê


signed int

Ê · variable-name [ dimension-2 ] ; ÊÍ
= expression

Notes:
1. The struct tag can be used to define other data areas, but they cannot be used
as host variables.
2. dimension-1 and dimension-2 must both be integer constants between 1 and
32767.

Using Pointer Data Types


You can also declare host variables that are pointers to the supported C and C++
data types, with the following restrictions:
v If a host variable is declared as a pointer, then that host variable must be
declared with asterisks followed by a host variable. The following examples are
all valid:
short *mynum; /* Ptr to an integer */
long **mynumptr; /* Ptr to a ptr to a long integer */
char *mychar; /* Ptr to a single character */
char(*mychara)[20] /* Ptr to a char array of 20 bytes */
struct { /* Ptr to a variable char array of 30 */
short mylen; /* bytes. */
char mydata[30];
} *myvarchar;

Note: Parentheses are only allowed when declaring a pointer to a


NUL-terminated character array, in which case they are required. If the
parentheses were not used, you would be declaring an array of pointers
rather than the desired pointer to an array. For example:

244 DB2 UDB for AS/400 SQL Programming V4R4


char (*a)[10]; /* pointer to a null-terminated char array */
char *a[10]; /* pointer to an array of pointers */

v If a host variable is declared as a pointer, then no other host variable can be


declared with that same name within the same source file. For example, the
second declaration below would be invalid:
char *mychar; /* This declaration is valid */
char mychar; /* But this one is invalid */

v When a host variable is referenced within an SQL statement, that host variable
must be referenced exactly as declared, with the exception of pointers to
NUL-terminated character arrays. For example, the following declaration required
parentheses:
char (*mychara)[20]; /* ptr to char array of 20 bytes */

However, the parentheses are not allowed when the host variable is referenced
in an SQL statement, such as a SELECT:
EXEC SQL SELECT name INTO :*mychara FROM mytable;
v Only the asterisk can be used as an operator over a host variable name.
v The maximum length of a host variable name is affected by the number of
asterisks specified, as these asterisks are considered part of the name.
v Pointers to structures are not usable as host variables except for variable
character structures. Also, pointer fields in structures are not usable as host
variables.
v SQL requires that all specified storage for based host variables be allocated. If
the storage is not allocated, unpredictable results can occur.

Using ILE C for AS/400 External File Descriptions


You can use the C or C++ #pragma mapinc directive with the #include directive to
include external file descriptions in your program. When used with SQL, only a
particular format of the #pragma mapinc directive is recognized by the SQL
precompiler. If all of the required elements are not specified, the precompiler
ignores the directive and does not generate host variable structures. The required
elements are:
v Include name
v Externally described file name
v Format name or a list of format names
v Options
v Conversion options
The library name, union name, conversion options, and prefix name are optional.
Although typedef statements coded by the user are not recognized by the
precompiler, those created by the #pragma mapinc and #include directives are
recognized. SQL supports input, output, both, and key values for the options
parameter. For the conversion options, the supported values are D, p, z, _P, and
1BYTE_CHAR. These options may be specified in any order except that both D and
p can not be specified. Unions declared using the typedef union created by the
#pragma mapinc and #include directive cannot be used as host variables in SQL
statements; the members of the unions can be used. Structures that contain the
typedef structure cannot be used in SQL statements; the structure declared using
the typedef can be used.

Chapter 12. Coding SQL Statements in C and C++ Applications 245


To retrieve the definition of the sample table DEPARTMENT described in
Appendix A. DB2 UDB for AS/400 Sample Tables, you can code the following:
#pragma mapinc ("dept","CORPDATA/DEPARTMENT(*ALL)","both")
#include "dept"
CORPDATA_DEPARTMENT_DEPARTMENT_both_t Dept_Structure;

A host structure named Dept_Structure is defined with the following elements:


DEPTNO, DEPTNAME, MGRNO, and ADMRDEPT. These field names can be used
as host variables in SQL statements.

Note: DATE, TIME, and TIMESTAMP columns generate character host variable
definitions. They are treated by SQL with the same comparison and
assignment rules as a DATE, TIME, and TIMESTAMP column. For example,
a date host variable can only compared against a DATE column or a
character string which is a valid representation of a date.

If the GRAPHIC or VARGRAPHIC column has a UCS-2 CCSID, the


generated host variable will have the UCS-2 CCSID assigned to it.

Although zoned, binary (with non-zero scale fields), and optionally decimal
are mapped to character fields in ILE C for AS/400, SQL will treat these
fields as numeric. By using the extended program model (EPM) routines, you
can manipulate these fields to convert zoned and packed decimal data. For
more information, see the ILE C for AS/400 Language Reference book.

Determining Equivalent SQL and C or C++ Data Types


The precompiler determines the base SQLTYPE and SQLLEN of host variables
based on the following table. If a host variable appears with an indicator variable,
the SQLTYPE is the base SQLTYPE plus one.
Table 24. C or C++ Declarations Mapped to Typical SQL Data Types
SQLTYPE of Host SQLLEN of Host
C or C++ Data Type Variable Variable SQL Data Type
short int 500 2 SMALLINT
long int 496 4 INTEGER
decimal(p,s) 484 p in byte 1, s in byte DECIMAL (p,s)
2
float 480 4 FLOAT (single
precision)
double 480 8 FLOAT (double
precision)
single-character form 452 1 CHAR(1)
NUL-terminated 460 length VARCHAR (length -
character form 1)
VARCHAR structured 448 length VARCHAR (length)
form where length <
255
VARCHAR structure 456 length VARCHAR(length)
form where length >
254
single-graphic form 468 1 GRAPHIC(1)

246 DB2 UDB for AS/400 SQL Programming V4R4


Table 24. C or C++ Declarations Mapped to Typical SQL Data Types (continued)
SQLTYPE of Host SQLLEN of Host
C or C++ Data Type Variable Variable SQL Data Type
NUL-terminated 400 length VARGRAPHIC (length
single-graphic form - 1)
VARGRAPHIC 464 length VARGRAPHIC
structured form where (length)
length < 128
VARGRAPHIC 472 length VARGRAPHIC
structured form where (length)
length > 127

You can use the following table to determine the C or C++ data type that is
equivalent to a given SQL data type.
Table 25. SQL Data Types Mapped to Typical C or C++ Declarations
SQL Data Type C or C++ Data Type Notes
SMALLINT short int
INTEGER long int
DECIMAL(p,s) decimal(p,s) p is a positive integer from 1
to 31, and s is a positive
integer from 0 to 31.
NUMERIC(p,s) or nonzero No exact equivalent Use decimal(p,s).
scale binary
FLOAT (single precision) float
FLOAT (double precision) double
CHAR(1) single-character form
CHAR(n) No exact equivalent If n>1, use NUL-terminated
character form
VARCHAR(n) NUL-terminated character If data can contain character
form NULs (\0), use VARCHAR
structured form. Allow at least
n+1 to accommodate the
NUL-terminator.

n is a positive integer. The


maximum value of n is
32740.
VARCHAR structured form The maximum value of n is
32740.
BLOB None Use SQL TYPE IS to declare
a BLOB in C or C++.
CLOB None Use SQL TYPE IS to declare
a CLOB in C or C++.
GRAPHIC (1) single-graphic form
GRAPHIC (n) No exact equivalent If n > 1, use NUL-terminated
graphic form.

Chapter 12. Coding SQL Statements in C and C++ Applications 247


Table 25. SQL Data Types Mapped to Typical C or C++ Declarations (continued)
SQL Data Type C or C++ Data Type Notes
VARGRAPHIC(n) NUL-terminated graphic form If data can contain graphic
NUL values (/0/0), use
VARGRAPHIC structured
form. Allow at least n + 1 to
accommodate the
NUL-terminator.

n is a positive integer. The


maximum value of n is
16370.
VARGRAPHIC structured n is a positive integer. The
form maximum value of n is
16370.
DBCLOB None Use SQL TYPE IS to declare
a DBCLOB in C or C++.
DATE NUL-terminated character If the format is *USA, *ISO,
form *JIS, or *EUR, allow at least
11 characters to
accommodate the
NUL-terminator. If the format
is *MDY, *YMD, or *DMY,
allow at least 9 characters to
accommodate the
NUL-terminator. If the format
is *JUL, allow at least 7
characters to accommodate
the NUL-terminator.
VARCHAR structured form If the format is *USA, *ISO,
*JIS, or *EUR, allow at least
10 characters. If the format is
*MDY, *YMD, or *DMY, allow
at least 8 characters. If the
format is *JUL, allow at least
6 characters.
TIME NUL-terminated character Allow at least 7 characters (9
form to include seconds) to
accommodate the
NUL-terminator.
VARCHAR structured form Allow at least 6 characters; 8
to include seconds.
TIMESTAMP NUL-terminated character Allow at least 20 characters
form (27 to include microseconds
at full precision) to
accommodate the
NUL-terminator. If n is less
than 27, truncation occurs on
the microseconds part.
VARCHAR structured form Allow at least 19 characters.
To include microseconds at
full precision, allow 26
characters. If the number of
characters is less than 26,
truncation occurs on the
microseconds part.

248 DB2 UDB for AS/400 SQL Programming V4R4


Table 25. SQL Data Types Mapped to Typical C or C++ Declarations (continued)
SQL Data Type C or C++ Data Type Notes
DATALINK Not supported

Notes on C and C++ Variable Declaration and Usage


Apostrophes and quotation marks have different meanings in C, C++, and SQL. C
and C++ use quotation marks to delimit string constants and apostrophes to delimit
character constants. SQL does not have this distinction, but uses quotation marks
for delimited identifiers and uses apostrophes to delimit character string constants.
Character data in SQL is distinct from integer data.

Using Indicator Variables


An indicator variable is a two-byte integer (short int). You can also specify an
indicator structure (defined as an array of halfword integer variables) to support a
host structure. On retrieval, an indicator variable is used to show if its associated
host variable has been assigned a null value. On assignment to a column, a
negative indicator variable is used to indicate that a null value should be assigned.

See DB2 UDB for AS/400 SQL Reference book for more information on the use of
indicator variables.

Indicator variables are declared in the same way as host variables. The
declarations of the two can be mixed in any way that seems appropriate to you.

Example:

Given the statement:


EXEC SQL FETCH CLS_CURSOR INTO :ClsCd,
:Day :DayInd,
:Bgn :BgnInd,
:End :EndInd;

Variables can be declared as follows:


EXEC SQL BEGIN DECLARE SECTION;
char ClsCd[8];
char Bgn[9];
char End[9];
short Day, DayInd, BgnInd, EndInd;
EXEC SQL END DECLARE SECTION;

Chapter 12. Coding SQL Statements in C and C++ Applications 249


250 DB2 UDB for AS/400 SQL Programming V4R4
Chapter 13. Coding SQL Statements in COBOL Applications
The AS/400 system supports more than one COBOL compiler. The DB2 UDB Query
Manager and SQL Development Kit licensed program only supports the COBOL for
AS/400 and ILE COBOL for AS/400 languages. This chapter describes the unique
application and coding requirements for embedding SQL statements in a COBOL
program. Requirements for host structures and host variables are defined.

A detailed sample COBOL program, showing how SQL statements can be used, is
provided in Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements.

Defining the SQL Communications Area


A COBOL program that contains SQL statements must include one or both of the
following:
v An SQLCODE variable declared as PICTURE S9(9) BINARY, PICTURE S9(9)
COMP-4, or PICTURE S9(9) COMP.
v An SQLSTATE variable declared as PICTURE X(5)

Or,
v An SQLCA (which contains an SQLCODE and SQLSTATE variable).

The SQLCODE and SQLSTATE values are set by the database manager after each
SQL statement is executed. An application can check the SQLCODE or SQLSTATE
value to determine whether the last SQL statement was successful.

The SQLCA can be coded in a COBOL program either directly or by using the SQL
INCLUDE statement. Using the SQL INCLUDE statement requests the inclusion of
a standard declaration:
EXEC SQL INCLUDE SQLCA END-EXEC.

The SQLCODE, SQLSTATE, and SQLCA variable declarations must appear in the
WORKING-STORAGE SECTION or LINKAGE SECTION of your program and can
be placed wherever a record description entry can be specified in those sections.

When you use the INCLUDE statement, the SQL COBOL precompiler includes
COBOL source statements for the SQLCA:
01 SQLCA.
05 SQLCAID PIC X(8).
05 SQLCABC PIC S9(9) BINARY.
05 SQLCODE PIC S9(9) BINARY.
05 SQLERRM.
49 SQLERRML PIC S9(4) BINARY.
49 SQLERRMC PIC X(70).
05 SQLERRP PIC X(8).
05 SQLERRD OCCURS 6 TIMES
PIC S9(9) BINARY.
05 SQLWARN.
10 SQLWARN0 PIC X.
10 SQLWARN1 PIC X.
10 SQLWARN2 PIC X.
10 SQLWARN3 PIC X.
10 SQLWARN4 PIC X.
10 SQLWARN5 PIC X.
10 SQLWARN6 PIC X.
10 SQLWARN7 PIC X.

© Copyright IBM Corp. 1997, 1999 251


10 SQLWARN8 PIC X.
10 SQLWARN9 PIC X.
10 SQLWARNA PIC X.
05 SQLSTATE PIC X(5).

For ILE COBOL for AS/400, the SQLCA is declared using the GLOBAL clause.
SQLCODE is replaced with SQLCADE when a declare for SQLCODE is found in
the program and the SQLCA is provided by the precompiler. SQLSTATE is replaced
with SQLSTOTE when a declare for SQLSTATE is found in the program and the
SQLCA is provided by the precompiler.

For more information on SQLCA, see Appendix B, “SQL Communication Area” in


the DB2 UDB for AS/400 SQL Reference book.

Defining SQL Descriptor Areas


The following statements require an SQLDA:
EXECUTE...USING DESCRIPTOR descriptor-name
FETCH...USING DESCRIPTOR descriptor-name
OPEN...USING DESCRIPTOR descriptor-name
CALL...USING DESCRIPTOR descriptor-name
DESCRIBE statement-name INTO descriptor-name
DESCRIBE TABLE host-variable INTO descriptor-name
PREPARE statement-name INTO descriptor-name

Unlike the SQLCA, there can be more than one SQLDA in a program. The SQLDA
can have any valid name. An SQLDA can be coded in a COBOL program directly or
added with the INCLUDE statement. Using the SQL INCLUDE statement requests
the inclusion of a standard SQLDA declaration:
EXEC SQL INCLUDE SQLDA END-EXEC.

The COBOL declarations included for the SQLDA are:

1 SQLDA.
05 SQLDAID PIC X(8).
05 SQLDABC PIC S9(9) BINARY.
05 SQLN PIC S9(4) BINARY.
05 SQLD PIC S9(4) BINARY.
05 SQLVAR OCCURS 0 TO 409 TIMES DEPENDING ON SQLD.
10 SQLTYPE PIC S9(4) BINARY.
10 SQLLEN PIC S9(4) BINARY.
10 FILLER REDEFINES SQLLEN.
15 SQLPRECISION PIC X.
15 SQLSCALE PIC X.
10 SQLRES PIC X(12).
10 SQLDATA POINTER.
10 SQLIND POINTER.
10 SQLNAME.
49 SQLNAMEL PIC S9(4) BINARY.
49 SQLNAMEC PIC X(30).

Figure 10. INCLUDE SQLDA Declarations for COBOL

SQLDA declarations must appear in the WORKING-STORAGE SECTION or


LINKAGE SECTION of your program and can be placed wherever a record

252 DB2 UDB for AS/400 SQL Programming V4R4


description entry can be specified in those sections. For ILE COBOL for AS/400, the
SQLDA is declared using the GLOBAL clause.

Dynamic SQL is an advanced programming technique described in Chapter 10.


Dynamic SQL Applications. With dynamic SQL, your program can develop and then
run SQL statements while the program is running. A SELECT statement with a
variable SELECT list (that is, a list of the data to be returned as part of the query)
that runs dynamically requires an SQL descriptor area (SQLDA). This is because
you cannot know in advance how many or what type of variables to allocate in
order to receive the results of the SELECT.

For more information, refer to the DB2 UDB for AS/400 SQL Reference book.

Embedding SQL Statements


SQL statements can be coded in COBOL program sections as follows:

SQL Statement Program Section


BEGIN DECLARE SECTION WORKING-STORAGE SECTION or
LINKAGE SECTION
END DECLARE SECTION
DECLARE VARIABLE
DECLARE STATEMENT
INCLUDE SQLCA WORKING-STORAGE SECTION or
INCLUDE SQLDA LINKAGE SECTION
INCLUDE member-name DATA DIVISION or PROCEDURE DIVISION
Other PROCEDURE DIVISION

Each SQL statement in a COBOL program must begin with EXEC SQL and end
with END-EXEC. If the SQL statement appears between two COBOL statements,
the period is optional and might not be appropriate. The EXEC SQL keywords must
appear all on one line, but the remainder of the statement can appear on the next
and subsequent lines.

Example:

An UPDATE statement coded in a COBOL program might be coded as follows:


EXEC SQL
UPDATE DEPARTMENT
SET MGRNO = :MGR-NUM
WHERE DEPTNO = :INT-DEPT
END-EXEC.

Comments
In addition to SQL comments (--), you can include COBOL comment lines (* or / in
column 7) within embedded SQL statements except between the keywords EXEC
and SQL. COBOL debugging lines (D in column 7) are treated as comment lines by
the precompiler.

Continuation for SQL Statements


The line continuation rules for SQL statements are the same as those for other
COBOL statements, except that EXEC SQL must be specified within one line.

Chapter 13. Coding SQL Statements in COBOL Applications 253


If you continue a string constant from one line to the next, the first nonblank
character in the next line must be either an apostrophe or a quotation mark. If you
continue a delimited identifier from one line to the next, the first nonblank character
in the next line must be either an apostrophe or a quotation mark.

Constants containing DBCS data can be continued across multiple lines by placing
the shift-in character in column 72 of the continued line and the shift-out after the
first string delimiter of the continuation line.

This SQL statement has a valid graphic constant of


G’<AABBCCDDEEFFGGHHIIJJKK>’. The redundant shifts are removed.
*...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
EXEC SQL
SELECT * FROM GRAPHTAB WHERE GRAPHCOL = G'<AABB>
- '<CCDDEEFFGGHHIIJJKK>'
END-EXEC.

Including Code
SQL statements or COBOL host variable declaration statements can be included by
embedding the following SQL statement at the point in the source code where the
statements are to be embedded:
EXEC SQL INCLUDE member-name END-EXEC.

COBOL COPY statements cannot be used to include SQL statements or


declarations of COBOL host variables that are referenced in SQL statements.

Margins
Code SQL statements in columns 12 through 72. If EXEC SQL starts before the
specified margin (that is, before column 12), the SQL precompiler will not recognize
the statement.

Sequence Numbers
The source statements generated by the SQL precompiler are generated with the
same sequence number as the SQL statement.

Names
Any valid COBOL variable name can be used for a host variable and is subject to
the following restrictions:

Do not use host variable names or external entry names that begin with 'SQL',
'RDI', or 'DSN'. These names are reserved for the database manager.

COBOL Compile-Time Options


The COBOL PROCESS statement can be used to specify the compile-time options
for the COBOL compiler. Although the PROCESS statement will be recognized by
the COBOL compiler when it is called by the precompiler to create the program; the
SQL precompiler itself does not recognize the PROCESS statement. Therefore,
options that affect the syntax of the COBOL source such as APOST and QUOTE

254 DB2 UDB for AS/400 SQL Programming V4R4


should not be specified in the PROCESS statement. Instead *APOST and *QUOTE
should be specified in the OPTION parameter of the CRTSQLCBL and
CRTSQLCBLI commands.

Statement Labels
Executable SQL statements in the PROCEDURE DIVISION can be preceded by a
paragraph name.

WHENEVER Statement
The target for the GOTO clause in an SQL WHENEVER statement must be a
section name or unqualified paragraph name in the PROCEDURE DIVISION.

Multiple source programs


The SQL COBOL precompiler does not support precompiling multiple source
programs separated with the PROCESS statement.

Using Host Variables


All host variables used in SQL statements must be explicitly declared. A host
variable used in an SQL statement must be declared prior to the first use of the
host variable in an SQL statement.

The COBOL statements that are used to define the host variables should be
preceded by a BEGIN DECLARE SECTION statement and followed by an END
DECLARE SECTION statement. If a BEGIN DECLARE SECTION and END
DECLARE SECTION are specified, all host variable declarations used in SQL
statements must be between the BEGIN DECLARE SECTION and the END
DECLARE SECTION statements.

All host variables within an SQL statement must be preceded by a colon (:).

Host variables cannot be records or elements.

To accommodate using dashes within a COBOL host variable name, blanks must
precede and follow a minus sign.

Declaring Host Variables


The COBOL precompiler only recognizes a subset of valid COBOL declarations as
valid host variable declarations.

Numeric Host Variables


The following figure shows the syntax for valid integer host variable declarations.

Chapter 13. Coding SQL Statements in COBOL Applications 255


INTEGER and SMALLINT

ÊÊ 01 variable-name PICTURE picture-string Ê


77 PIC IS
level-1

Ê BINARY Ê
USAGE COMPUTATIONAL-4
IS COMP-4

Ê . ÊÍ
VALUE numeric-constant
IS

Notes:
1. BINARY, COMPUTATIONAL-4, and COMP-4 are equivalent. A portable
application should code BINARY, because COMPUTATIONAL-4 and COMP-4
are IBM extensions that are not supported in ISO/ANSI COBOL. The
picture-string associated with these types must have the form S9(i)V9(d) (or
S9...9V9...9, with i and d instances of 9). i + d must be less than or equal to 9.
2. level-1 indicates a COBOL level between 2 and 48.

The following figure shows the syntax for valid decimal host variable declarations.

DECIMAL

ÊÊ 01 variable-name PICTURE picture-string Ê


77 PIC IS
level-1

Ê PACKED-DECIMAL Ê
USAGE COMPUTATIONAL-3
IS COMP-3
COMPUTATIONAL
COMP

Ê . ÊÍ
VALUE numeric-constant
IS

Notes:
1. PACKED-DECIMAL, COMPUTATIONAL-3, and COMP-3 are equivalent. A
portable application should code PACKED-DECIMAL, because
COMPUTATIONAL-3 and COMP-3 are IBM extensions that are not supported in

256 DB2 UDB for AS/400 SQL Programming V4R4


ISO/ANS COBOL. The picture-string associated with these types must have the
form S9(i)V9(d) (or S9...9V9...9, with i and d instances of 9). i + d must be less
than or equal to 18.
2. COMPUTATIONAL and COMP are equivalent. The picture strings associated
with these and the data types they represent are product specific. Therefore,
COMP and COMPUTATIONAL should not be used in a portable application. In
the COBOL for AS/400 program, the picture-string associated with these types
must have the form S9(i)V9(d) (or S9...9V9...9, with i and d instances of 9). i + d
must be less than or equal to 18.
3. level-1 indicates a COBOL level between 2 and 48.

The following figure shows the syntax for valid numeric host variable declarations.

Numeric

ÊÊ 01 variable-name PICTURE picture-string Ê


77 PIC IS
level-1

Ê Ê
DISPLAY
USAGE display clause
IS

Ê . ÊÍ
VALUE numeric-constant
IS

display clause:

SIGN LEADING SEPARATE


DISPLAY IS CHARACTER

Notes:
1. The picture-string associated with SIGN LEADING SEPARATE and DISPLAY
must have the form S9(i)V9(d) (or S9...9V9...9, with i and d instances of 9). i + d
must be less than or equal to 18.
2. level-1 indicates a COBOL level between 2 and 48.

Floating Point Host Variables


The following figure shows the syntax for valid floating point host variable
declarations. Floating point host variables are only supported for ILE COBOL for
AS/400.

Chapter 13. Coding SQL Statements in COBOL Applications 257


Floating-point

ÊÊ 01 variable-name COMPUTATIONAL-1 Ê
77 USAGE COMP-1
level-1 IS COMPUTATIONAL-2
COMP-2

Ê . ÊÍ
VALUE numeric-constant
IS

Notes:
1. COMPUTATIONAL-1 and COMP-1 are equivalent. COMPUTATIONAL-2 and
COMP-2 are equivalent.
2. level-1 indicates a COBOL level between 2 and 48.

Character Host Variables


There are two valid forms of character host variables:
v Fixed-Length Strings
v Varying-Length Strings

Fixed-Length Character Strings

ÊÊ 01 variable-name PICTURE picture-string Ê


77 PIC IS
level-1

Ê Ê
DISPLAY VALUE string-constant
USAGE IS
IS

Ê . ÊÍ

Notes:
1. The picture string associated with these forms must be X(m) (or XXX...X, with m
instance of X) with 1 ≤ m ≤ 32 766.
2. level-1 indicates a COBOL level between 2 and 48.

258 DB2 UDB for AS/400 SQL Programming V4R4


Varying-Length Character Strings

ÊÊ 01 variable-name . 49 var-1 PICTURE Ê


level-1 PIC

Ê picture-string-1 BINARY Ê
IS USAGE COMPUTATIONAL-4
IS COMP-4

Ê . 49 var-2 PICTURE Ê
VALUE numeric-constant PIC
IS

Ê picture-string-2 Ê
IS DISPLAY
USAGE
IS

Ê . ÊÍ
VALUE string-constant
IS

Notes:
1. The picture-string-1 associated with these forms must be S9(m) or S9...9 with m
instances of 9. m must be from 1 to 4.
Note that the database manager will use the full size of the S9(m) variable even
though COBOL on the AS/400 only recognizes values up to the specified
precision. This can cause data truncation errors when COBOL statements are
being run and may effectively limit the maximum length of variable-length
character strings to the specified precision.
2. The picture-string-2 associated with these forms must be either X(m), or XX...X,
with m instances of X, and with 1 ≤ m ≤ 32 740.
3. var-1 and var-2 cannot be used as host variables.
4. level-1 indicates a COBOL level between 2 and 48.

Graphic Host Variables


Graphic host variables are only supported in ILE COBOL for AS/400.

There are two valid forms of graphic host variables:


v Fixed-Length Graphic Strings
v Varying-Length Graphic Strings

Chapter 13. Coding SQL Statements in COBOL Applications 259


Fixed-Length Graphic Strings

ÊÊ 01 variable-name PICTURE picture-string Ê


77 PIC IS
level-1

Ê Ê
DISPLAY-1 VALUE string-constant
USAGE IS
IS

Ê . ÊÍ

Notes:
1. The picture string associated with these forms must be G(m) (or GGG...G, with
m instance of G) or N(m) (or NNN...N, with m instance of N) with 1 ≤ m ≤ 16
383.
2. level-1 indicates a COBOL level between 2 and 48.

Varying-Length Graphic Strings

ÊÊ 01 variable-name . 49 var-1 PICTURE Ê


level-1 PIC

Ê picture-string-1 BINARY Ê
IS USAGE COMPUTATIONAL-4
IS COMP-4

Ê . 49 var-2 PICTURE Ê
VALUE numeric-constant PIC
IS

Ê picture-string-2 Ê
IS DISPLAY-1
USAGE
IS

Ê . ÊÍ
VALUE string-constant
IS

Notes:
1. The picture-string-1 associated with these forms must be S9(m) or S9...9 with m
instances of 9. m must be from 1 to 4.

260 DB2 UDB for AS/400 SQL Programming V4R4


Note that the database manager will use the full size of the S9(m) variable even
though COBOL on the AS/400 only recognizes values up to the specified
precision. This can cause data truncation errors when COBOL statements are
being run and may effectively limit the maximum length of variable-length
graphic strings to the specified precision.
2. The picture-string-2 associated with these forms must be G(m), GG...G with m
instances of G, N(m), or NN...N with m instances of N, and with 1 ≤ m ≤ 16 370.
3. var-1 and var-2 cannot be used as host variables.
4. level-1 indicates a COBOL level between 2 and 48.

| LOB Host Variables


| LOB host variables are only supported in ILE COBOL for AS/400.
|

| LOB Host Variables

| ÊÊ 01 variable-name SQL TYPE IS BLOB Ê


| USAGE CLOB
IS DBCLOB

| Ê ( lob-length ) . ÊÍ
| K
M

||
|

| Notes:
| 1. For BLOB and CLOB, 1 <= lob-length <= 15,728,640
| 2. For DBCLOB, 1 <= lob-length <= 7,864,320
| 3. SQL TYPE IS, BLOB, CLOB, DBCLOB can be in mixed case.
| 4. LOB Host Variables can be declared in host structures.

| BLOB Example

| The following declaration:


| 01 MY-BLOB SQL TYPE IS BLOB(16384).

| Results in the generation of the following structure:


| 01 MY-BLOB.
| 49 MY-BLOB-LENGTH PIC 9(9) BINARY.
| 49 MY-BLOB-DATA PIC X(16384).

| CLOB Example

| The following declaration:


| 01 MY-CLOB SQL TYPE IS CLOB(16384).

| Results in the generation of the following structure:


| 01 MY-CLOB.
| 49 MY-CLOB-LENGTH PIC 9(9) BINARY.
| 49 MY-CLOB-DATA PIC X(16384).

Chapter 13. Coding SQL Statements in COBOL Applications 261


| DBCLOB Example

| The following declaration:


| 01MY-DBCLOB SQL TYPE IS DBCLOB(8192).

| Results in the generation of the following structure:


| 01 MY-DBCLOB.
| 49 MY-DBCLOB-LENGTH PIC 9(9) BINARY.
| 49 MY-DBCLOB-DATA PIC G(8192) DISPLAY-1.

| LOB Locators
| LOB locators are only supported in ILE COBOL for AS/400.
|

| LOB Locator

| ÊÊ 01 variable-name Ê
| USAGE
IS

| Ê SQL TYPE IS BLOB-LOCATOR . ÊÍ


| CLOB-LOCATOR
DBCLOB-LOCATOR

||
|

| Notes:
| 1. SQL TYPE IS, BLOB-LOCATOR, CLOB-LOCATOR, DBCLOB-LOCATOR can be
| in mixed case.
| 2. LOB Locators cannot be initialized in the SQL TYPE IS statement.
| 3. LOB Locators can be declared as a part of a host structure.

| BLOB Example

| The following declaration:


| 01 MY-LOCATOR SQL TYPE IS BLOB_LOCATOR.

| Results in the generation of the following structure:


| 01 MY-LOCATOR PIC 9(9) BINARY.

| CLOB and DBCLOB locators have similar syntax.

| LOB File Reference Variables


| LOB variables are only supported in ILE COBOL for AS/400.

262 DB2 UDB for AS/400 SQL Programming V4R4


|

| LOB File Reference Variable

| ÊÊ 01 variable-name SQL TYPE IS BLOB-FILE Ê


| USAGE CLOB-FILE
IS DBCLOB-FILE

| Ê . ÊÍ
|
||
|

| Notes:
| 1. SQL TYPE IS, BLOB-FILE, CLOB-FILE, DBCLOB-FILE can be in mixed case.
| 2. LOB File Reference Variables can be declared as part of a host structure.

| BLOB Example

| The following declaration:


| 01 MY-FILE SQL TYPE IS BLOB-FILE.

| Results in the generation of the following structure:


| 01 MY-FILE.
| 49 MY-FILE-NAME-LENGTH PIC S9(9) COMP-5.
| 49 MY-FILE-DATA-LENGTH PIC S9(9) COMP-5.
| 49 MY-FILE-FILE-OPTIONS PIC S9(9) COMP-5.
| 49 MY-FILE-NAME PIC X(255).

| CLOB and DBCLOB file reference variables have similar syntax.

| The pre-compiler will generate declarations for the following file option constants:
| v SQL-FILE-READ (2)
| v SQL-FILE-CREATE (8)
| v SQL-FILE-OVERWRITE (16)
| v SQL-FILE-APPEND (32)

| Datetime Host Variables


| The following figure shows the syntax for valid date, time, and timestamp host
| variable declarations. Datetime host variables are supported only for ILE COBOL for
| AS/400.
|

| Datetime Host Variable

| ÊÊ 01 variable-name FORMAT DATE Ê


| 77 OF TIME IS
level-1 TIMESTAMP

| Ê format-options ÊÍ
|
||
|

Chapter 13. Coding SQL Statements in COBOL Applications 263


| Notes:
| 1. level-1 indicates a COBOL level between 2 and 48.
| 2. format-options indicates valid datetime options that are supported by the
| COBOL compiler. See the ILE COBOL for AS/400 Reference, SC09-2539-01
| book for details.
|
Using Host Structures
A host structure is a named set of host variables that is defined in your program’s
DATA DIVISION. Host structures have a maximum of two levels, even though the
host structure might itself occur within a multilevel structure. An exception is the
declaration of a varying-length character string, which requires another level that
must be level 49.

A host structure name can be a group name whose subordinate levels name basic
data items. For example:
01 A
02 B
03 C1 PICTURE ...
03 C2 PICTURE ...

In this example, B is the name of a host structure consisting of the basic items C1
and C2.

When writing an SQL statement using a qualified host variable name (for example,
to identify a field within a structure), use the name of the structure followed by a
period and the name of the field (that is, PL/I style). For example, specify B.C1
rather than C1 OF B or C1 IN B. However, PL/I style applies only to qualified
names within SQL statements; you cannot use this technique for writing qualified
names in COBOL statements.

A host structure is considered complete if any of the following items are found:
v A COBOL item that must begin in area A
v Any SQL statement (except SQL INCLUDE)

After the host structure is defined, you can refer to it in an SQL statement instead of
listing the several host variables (that is, the names of the data items that comprise
the host structure).

For example, you can retrieve all column values from selected rows of the table
CORPDATA.EMPLOYEE with:
01 PEMPL.
10 EMPNO PIC X(6).
10 FIRSTNME.
49 FIRSTNME-LEN PIC S9(4) USAGE BINARY.
49 FIRSTNME-TEXT PIC X(12).
10 MIDINIT PIC X(1).
10 LASTNAME.
49 LASTNAME-LEN PIC S9(4) USAGE BINARY.
49 LASTNAME-TEXT PIC X(15).
10 WORKDEPT PIC X(3).
...
MOVE "000220" TO EMPNO.
...
EXEC SQL
SELECT *

264 DB2 UDB for AS/400 SQL Programming V4R4


INTO :PEMPL
FROM CORPDATA.EMPLOYEE
WHERE EMPNO = :EMPNO
END-EXEC.

Notice that in the declaration of PEMPL, two varying-length string elements are
included in the structure: FIRSTNME and LASTNAME.

Host Structure
The following figure shows the syntax for the valid host structure.

Chapter 13. Coding SQL Statements in COBOL Applications 265


Host Structure

ÊÊ level-1 variable-name . Ê

Ê · level-2 var-1 PICTURE picture-string usage-clause . ÊÍ


PIC IS
floating-point .
. varchar-string .
. vargraphic-string .
datetime .

floating-point:

COMPUTATIONAL-1 VALUE constant


USAGE COMP-1 IS
IS COMPUTATIONAL-2
COMP-2

usage-clause:

BINARY VALUE constant


USAGE COMPUTATIONAL-4 IS
IS COMP-4
PACKED-DECIMAL
COMPUTATIONAL-3
COMP-3
COMPUTATIONAL
COMP
DISPLAY
display-clause
DISPLAY-1

display-clause:

SIGN LEADING SEPARATE


DISPLAY IS CHARACTER

266 DB2 UDB for AS/400 SQL Programming V4R4


Host Structure (continued)

varchar-string:

49 var-2 PICTURE picture-string-1 BINARY Ê


PIC IS USAGE COMPUTATIONAL-4
IS COMP-4

Ê . 49 var-3 PICTURE picture-string-2 Ê


VALUE numeric-constant PIC IS
IS

Ê
DISPLAY VALUE constant
USAGE IS
IS

vargraphic-string:

49 var-2 PICTURE picture-string-1 BINARY Ê


PIC IS USAGE COMPUTATIONAL-4
IS COMP-4

Ê . 49 var-3 PICTURE picture-string-2 Ê


VALUE numeric-constant PIC IS
IS

Ê
DISPLAY-1 VALUE constant
USAGE IS
IS

datetime:

variable-name FORMAT DATE format-options


OF TIME IS
TIMESTAMP

Notes:
1. level-1 indicates a COBOL level between 1 and 47.
2. level-2 indicates a COBOL level between 2 and 48 where level-2 > level-1.
3. Graphic host variables and floating-point host variables are only supported for
ILE COBOL for AS/400.
4. For details on declaring numeric, character, and graphic host variables, see the
notes under numeric-host variables, character-host variables, and graphic-host
variables.
5. format-options indicates valid datetime options that are supported by the
COBOL compiler. See the ILE COBOL for AS/400 Reference, SC09-2539-01
book for details.

Chapter 13. Coding SQL Statements in COBOL Applications 267


Host Structure Indicator Array
The following figure shows the syntax for valid indicator array declarations.

Host Structure Indicator Array

ÊÊ level-1 variable-name PICTURE picture-string Ê


PIC IS

Ê BINARY OCCURS dimension Ê


USAGE COMPUTATIONAL-4 TIMES
IS COMP-4

Ê . ÊÍ
VALUE constant
IS

Notes:
1. Dimension must be an integer between 1 and 32767.
2. level-1 must be an integer between 2 and 48.
3. BINARY, COMPUTATIONAL-4, and COMP-4 are equivalent. A portable
application should code BINARY, because COMPUTATIONAL-4 and COMP-4
are IBM extensions that are not supported in ISO/ANSI COBOL. The
picture-string associated with these types must have the form S9(i) (or S9...9,
with i instances of 9). i must be less than or equal to 4.

Using Host Structure Arrays


A host structure array is a named set of host variables that is defined in the
program’s Data Division and has an OCCURS clause. Host structure arrays have a
maximum of two levels, even though the host structure can occur within a multiple
level structure. A varying-length string requires another level, level 49. A host
structure array name can be a group name whose subordinate levels name basic
data items.

Inthese examples, the following are true:


v All members in B-ARRAY must be valid.
v B-ARRAY cannot be qualified.
v B-ARRAY can only be used on the blocked form of the FETCH and INSERT
statements.
v B-ARRAY is the name of an array of host structures containing items C1-VAR
and C2-VAR.
v The SYNCHRONIZED attribute must not be specified.
v C1-VAR and C2-VAR are not valid host variables in any SQL statement. A
structure cannot contain an intermediate level structure.

268 DB2 UDB for AS/400 SQL Programming V4R4


01 A-STRUCT.
02 B-ARRAY OCCURS 10 TIMES.
03 C1-VAR PIC X(20).
03 C2-VAR PIC S9(4).

To retrieve 10 rows from the CORPDATA.DEPARTMENT table, use the following


example:
01 TABLE-1.
02 DEPT OCCURS 10 TIMES.
05 DEPTNO PIC X(3).
05 DEPTNAME.
49 DEPTNAME-LEN PIC S9(4) BINARY.
49 DEPTNAME-TEXT PIC X(29).
05 MGRNO PIC X(6).
05 ADMRDEPT PIC X(3).
01 TABLE-2.
02 IND-ARRAY OCCURS 10 TIMES.
05 INDS PIC S9(4) BINARY OCCURS 4 TIMES.
....
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT *
FROM CORPDATA.DEPARTMENT
END-EXEC.
....
EXEC SQL
FETCH C1 FOR 10 ROWS INTO :DEPT :IND-ARRAY
END-EXEC.

Host Structure Array


The following figures show the syntax for valid host structure array declarations.

Chapter 13. Coding SQL Statements in COBOL Applications 269


Host Structure Array

ÊÊ level-1 variable-name OCCURS dimension . Ê


TIMES

Ê · level-2 var-1 PICTURE picture-string-1 usage-clause . ÊÍ


PIC IS
floating-point .
. varchar-string .
. vargraphic-string .
datetime .

floating-point:

COMPUTATIONAL-1 VALUE constant


USAGE COMP-1 IS
IS COMPUTATIONAL-2
COMP-2

usage-clause:

BINARY VALUE constant


USAGE COMPUTATIONAL-4 IS
IS COMP-4
PACKED-DECIMAL
COMPUTATIONAL-3
COMP-3
COMPUTATIONAL
COMP
DISPLAY
display-clause
DISPLAY-1

display-clause:

SIGN LEADING SEPARATE


DISPLAY IS CHARACTER

270 DB2 UDB for AS/400 SQL Programming V4R4


Host Structure Array (continued)

varchar-string:

49 var-2 PICTURE picture-string-2 BINARY Ê


PIC IS USAGE COMPUTATIONAL-4
IS COMP-4

Ê . 49 var-3 PICTURE picture-string-3 Ê


VALUE numeric-constant PIC IS
IS

Ê
DISPLAY VALUE constant
USAGE IS
IS

vargraphic-string:

49 var-2 PICTURE picture-string-2 BINARY Ê


PIC IS USAGE COMPUTATIONAL-4
IS COMP-4

Ê . 49 var-3 PICTURE picture-string-3 Ê


VALUE numeric-constant PIC IS
IS

Ê
DISPLAY-1 VALUE constant
USAGE IS
IS

datetime:

variable-name FORMAT DATE format-options


OF TIME IS
TIMESTAMP

Notes:
1. level-1 indicates a COBOL level between 2 and 47.
2. level-2 indicates a COBOL level between 3 and 48 where level-2 > level-1.
3. Graphic host variables and floating-point host variables are only supported for
ILE COBOL for AS/400.
4. For details on declaring numeric, character, and graphic host variables, see the
notes under numeric-host variables, character-host variables, and graphic-host
variables.
5. Dimension must be an integer constant between 1 and 32767.
6. format-options indicates valid datetime options that are supported by the
COBOL compiler. See the ILE COBOL for AS/400 Reference, SC09-2539-01
book for details.

Chapter 13. Coding SQL Statements in COBOL Applications 271


Host Array Indicator Structure
This figure shows the valid syntax for host structure array indicators.

Host Structure Array Indicator Structure

ÊÊ level-1 variable-name OCCURS dimension . Ê


TIMES

Ê level-2 var-1 PICTURE picture-string Ê


PIC IS

Ê BINARY Ê
USAGE COMPUTATIONAL-4 VALUE constant
IS COMP-4 IS

Ê . ÊÍ

Notes:
1. level-1 indicates a COBOL level between 2 and 48.
2. level-2 indicates a COBOL level between 3 and 48 where level-2 > level-1.
3. Dimension must be an integer constant between 1 and 32767.
4. BINARY, COMPUTATIONAL-4, and COMP-4 are equivalent. A portable
application should code BINARY, because COMPUTATIONAL-4 and COMP-4
are IBM extensions that are not supported in ISO/ANSI COBOL. The
picture-string associated with these types must have the form S9(i) (or S9...9,
with i instances of 9). i must be less than or equal to 4.

Using External File Descriptions


SQL uses the COPY DD-format-name, COPY DD-ALL-FORMATS, COPY
DDS-format-name, COPY DDR-format-name, COPY DDR-ALL-FORMATS, COPY
DDSR-format-name, COPY DDS-ALL-FORMATS, and COPY DDSR-ALL-
FORMATS to retrieve host variables from the file definitions. If the REPLACING
option is specified, only complete name replacing is done. Var-1 is compared
against the format name and the field name. If they are equal, var-2 is used as the
| new name.

| Note: You cannot retrieve host variables from file definitions that have field names
| which are COBOL reserved words. You must place the COPY DDx-format
| statement within a COBOL host structure.

| To retrieve the definition of the sample table DEPARTMENT described in


Appendix A. DB2 UDB for AS/400 Sample Tables, you can code the following:
01 DEPARTMENT-STRUCTURE.
COPY DDS-ALL-FORMATS OF DEPARTMENT.

A host structure named DEPARTMENT-STRUCTURE is defined with an 05 level


field named DEPARTMENT-RECORD that contains four 06 level fields named

272 DB2 UDB for AS/400 SQL Programming V4R4


DEPTNO, DEPTNAME, MGRNO, and ADMRDEPT. These field names can be used
as host variables in SQL statements. For more information on the COBOL COPY
verb, see the COBOL/400 User’s Guide book and the ILE COBOL for AS/400
Reference book.

Using External File Descriptions for Host Structure Arrays


Because COBOL creates an extra level when including externally described data,
the OCCURS clause must be placed on the preceding 04 level. The structure
cannot contain any additional declares at the 05 level.

If the file contains fields that are generated as FILLER, the structure cannot be
used as a host structure array.

For device files, if INDARA was not specified and the file contains indicators, the
declaration cannot be used as a host structure array. The indicator area is included
in the generated structure and causes the storage for records to not be contiguous.

For example, the following shows how to use COPY–DDS to generate a host
structure array and fetch 10 rows into the host structure array:
01 DEPT.
04 DEPT-ARRAY OCCURS 10 TIMES.
COPY DDS-ALL-FORMATS OF DEPARTMENT.
:

EXEC SQL DECLARE C1 CURSOR FOR


SELECT * FROM CORPDATA.DEPARTMENT
END EXEC.

EXEC SQL OPEN C1


END-EXEC.

EXEC SQL FETCH C1 FOR 10 ROWS INTO :DEPARTMENT


END-EXEC.

Note: DATE, TIME, and TIMESTAMP columns will generate character host variable
definitions that are treated by SQL with the same comparison and
assignment rules as the DATE, TIME, or TIMESTAMP column. For example,
a date host variable can only be compared against a DATE column or a
character string which is a valid representation of a date.

Although GRAPHIC and VARGRAPHIC are mapped to character variables in


COBOL for AS/400, SQL considers these GRAPHIC and VARGRAPHIC
variables. If the GRAPHIC or VARGRAPHIC column has a UCS-2 CCSID,
the generated host variable will have the UCS-2 CCSID assigned to it.

Chapter 13. Coding SQL Statements in COBOL Applications 273


Determining Equivalent SQL and COBOL Data Types
The precompiler determines the base SQLTYPE and SQLLEN of host variables
based on the following table. If a host variable appears with an indicator variable,
the SQLTYPE is the base SQLTYPE plus one.
Table 26. COBOL Declarations Mapped to Typical SQL Data Types
SQLTYPE of SQLLEN of Host
COBOL Data Type Host Variable Variable SQL Data Type
S9(i)V9(d) COMP-3 or S9(i)V9(d) 484 i+d in byte 1, d in DECIMAL(i+d,d)
COMP or S9(i)V9(d) byte 2
PACKED-DECIMAL
S9(i)V9(d) DISPLAY SIGN 504 i+d in byte 1, d in No exact
LEADING SEPARATE byte 2 equivalent use
DECIMAL(i+d,d)
or NUMERIC
(i+d,d)
S9(i)V9(d)DISPLAY 488 i+d in byte 1, d in NUMERIC(i+d,d)
byte 2
S9(i) BINARY or S9(i) COMP-4 500 2 SMALLINT
where i is from 1 to 4
S9(i) BINARY or S9(i) COMP-4 496 4 INTEGER
where i is from 5 to 9
S9(i)V9(d) BINARY or S9(i)V9(d) 500 i+d in byte 1, d in No exact
COMP-4 where i+d ≤ 4 byte 2 equivalent use
DECIMAL(i+d,d)
or NUMERIC
(i+d,d)
S9(i)V9(d) BINARY or S9(i)V9(d) 496 i+d in byte 1, d in No exact
COMP-4 where 4 < i+d ≤ 9 byte 2 equivalent use
DECIMAL(i+d,d)
or NUMERIC
(i+d,d)
COMP-1 480 4 FLOAT(single
precision)
COMP-2 480 8 FLOAT(double
precision)
Fixed-length character data 452 m CHAR(m)
Varying-length character data 448 m VARCHAR(m)
where m < 255
Varying-length character data 456 m VARCHAR(m)
where m > 254
Fixed-length graphic data 468 m GRAPHIC(m)
Varying-length graphic data where 464 m VARGRAPHIC(m)
m < 128
Varying-length graphic data where 472 m VARGRAPHIC(m)
m > 127
| DATE 384 DATE
| TIME 388 TIME
| TIMESTAMP 392 26 TIMESTAMP

274 DB2 UDB for AS/400 SQL Programming V4R4


The following table can be used to determine the COBOL data type that is
equivalent to a given SQL data type.
Table 27. SQL Data Types Mapped to Typical COBOL Declarations
SQL Data Type COBOL Data Type Notes
SMALLINT S9(m) COMP-4 m is from 1 to 4
INTEGER S9(m) COMP-4 m is from 5 to 9
DECIMAL(p,s) If p<19: S9(p-s)V9(s) p is precision; s is scale.
PACKED-DECIMAL or 0<=s<=p<=18. If s=0, use
S9(p-s)V9(s) COMP or S9(p) or S9(p)V. If s=p, use
S9(p-s)V9(s) COMP-3 If SV9(s).
p>18: Not supported
NUMERIC(p,s) If p<19: S9(p-s)V9(s) p is precision; s is scale.
DISPLAY If p>18: Not 0<=s<=p<=18. If s=0, use
supported S9(p) or S9(p)V. If s=p, use
SV9(s).
FLOAT(single precision) COMP-1 for ILE COBOL for
AS/400. Not supported for
COBOL for AS/400.
FLOAT(double precision) COMP-2 for ILE COBOL for
AS/400. Not supported for
COBOL for AS/400.
CHAR(n) Fixed-length character string 32766≥n≥1
VARCHAR(n) Varying-length character 32740≥n≥1
string
BLOB None Use SQL TYPE IS to declare
a BLOB. For ILE COBOL for
AS/400. Not supported for
COBOL for AS/400.
CLOB None Use SQL TYPE IS to declare
a CLOB. For ILE COBOL for
AS/400. Not supported for
COBOL for AS/400.
GRAPHIC(n) Fixed-length graphic string for 16383≥n≥1
ILE COBOL for AS/400. Not
supported for COBOL for
AS/400.
VARGRAPHIC(n) Varying-length graphic string 16370≥n≥1
for ILE COBOL for AS/400.
Not supported for COBOL for
AS/400.
DBCLOB None Use SQL TYPE IS to declare
a DBCLOB. For ILE COBOL
for AS/400. Not supported for
COBOL for AS/400.
DATE If the format is *USA, *JIS,
Fixed-length
*EUR, or *ISO, allow at least
character string
10 characters. If the format is
*YMD, *DMY, or *MDY, allow
at least 8 characters. If the
or DATE (for ILE format is *JUL, allow at least
COBOL for AS/400) 6 characters.

Chapter 13. Coding SQL Statements in COBOL Applications 275


Table 27. SQL Data Types Mapped to Typical COBOL Declarations (continued)
SQL Data Type COBOL Data Type Notes
TIME Allow at least 6 characters; 8
Fixed-length
to include seconds.
character string

or TIME (for ILE


COBOL for AS/400)

TIMESTAMP n must be at least 19. To


Fixed-length
include microseconds at full
character string
precision, n must be 26. If n
is less than 26, truncation
occurs on the microseconds
or TIMESTAMP (for part.
ILE COBOL for
AS/400)

DATALINK Not supported

Notes on COBOL Variable Declaration and Usage


Any level 77 data description entry can be followed by one or more REDEFINES
entries. However, the names in these entries cannot be used in SQL statements.

Unpredictable results may occur when a structure contains levels defined below a
FILLER item.

The COBOL declarations for SMALLINT and INTEGER data types are expressed
as a number of decimal digits. The database manager uses the full size of the
integers and can place larger values in the host variable than would be allowed in
the specified number of digits in the COBOL declaration. However, this can cause
data truncation or size errors when COBOL statements are being run. Ensure that
the size of numbers in your application is within the declared number of digits.

Using Indicator Variables


An indicator variable is a two-byte integer (PIC S9(m) USAGE BINARY, where m is
from 1 to 4). You can also specify an indicator structure (defined as an array of
halfword integer variables) to support a host structure. On retrieval, an indicator
variable is used to show whether its associated host variable has been assigned a
null value. On assignment to a column, a negative indicator variable is used to
indicate that a null value should be assigned.

See DB2 UDB for AS/400 SQL Reference for more information on the use of
indicator variables.

Indicator variables are declared in the same way as host variables, and the
declarations of the two can be mixed in any way that seems appropriate to the
programmer.

Example:

Given the statement:

276 DB2 UDB for AS/400 SQL Programming V4R4


EXEC SQL FETCH CLS_CURSOR INTO :CLS-CD,
:NUMDAY :NUMDAY-IND,
:BGN :BGN-IND,
:ENDCLS :ENDCLS-IND
END-EXEC.

The variables can be declared as follows:


EXEC SQL BEGIN DECLARE SECTION END-EXEC.
77 CLS-CD PIC X(7).
77 NUMDAY PIC S9(4) BINARY.
77 BGN PIC X(8).
77 ENDCLS PIC X(8).
77 NUMDAY-IND PIC S9(4) BINARY.
77 BGN-IND PIC S9(4) BINARY.
77 ENDCLS-IND PIC S9(4) BINARY.
EXEC SQL END DECLARE SECTION END-EXEC.

Chapter 13. Coding SQL Statements in COBOL Applications 277


278 DB2 UDB for AS/400 SQL Programming V4R4
Chapter 14. Coding SQL Statements in PL/I Applications
This chapter describes the unique application and coding requirements for
embedding SQL statements in an AS/400 PL/I program. Requirements for host
structures and host variables are defined.

A detailed sample PL/I program, showing how SQL statements can be used, is
provided in Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements.

Defining the SQL Communications Area


A PL/I program that contains SQL statements must include one or both of the
following:
v An SQLCODE variable declared as FIXED BINARY(31)
v An SQLSTATE variable declared as CHAR(5)

Or,
v An SQLCA (which contains an SQLCODE and SQLSTATE variable).

The SQLCODE and SQLSTATE values are set by the database manager after each
SQL statement is executed. An application can check the SQLCODE or SQLSTATE
value to determine whether the last SQL statement was successful.

The SQLCA can be coded in a PL/I program either directly or by using the SQL
INCLUDE statement. Using the SQL INCLUDE statement requests the inclusion of
a standard SQLCA declaration:
EXEC SQL INCLUDE SQLCA ;

The scope of the SQLCODE, SQLSTATE, and SQLCA variables must include the
scope of all SQL statements in the program.

The included PL/I source statements for the SQLCA are:


DCL 1 SQLCA,
2 SQLCAID CHAR(8),
2 SQLCABC FIXED(31) BINARY,
2 SQLCODE FIXED(31) BINARY,
2 SQLERRM CHAR(70) VAR,
2 SQLERRP CHAR(8),
2 SQLERRD(6) FIXED(31) BINARY,
2 SQLWARN,
3 SQLWARN0 CHAR(1),
3 SQLWARN1 CHAR(1),
3 SQLWARN2 CHAR(1),
3 SQLWARN3 CHAR(1),
3 SQLWARN4 CHAR(1),
3 SQLWARN5 CHAR(1),
3 SQLWARN6 CHAR(1),
3 SQLWARN7 CHAR(1),
3 SQLWARN8 CHAR(1),
3 SQLWARN9 CHAR(1),
3 SQLWARNA CHAR(1),
2 SQLSTATE CHAR(5);

© Copyright IBM Corp. 1997, 1999 279


SQLCODE is replaced with SQLCADE when a declare for SQLCODE is found in
the program and the SQLCA is provided by the precompiler. SQLSTATE is replaced
with SQLSTOTE when a declare for SQLSTATE is found in the program and the
SQLCA is provided by the precompiler.

For more information on SQLCA, see Appendix B, “SQL Communication Area” in


the DB2 UDB for AS/400 SQL Reference book.

Defining SQL Descriptor Areas


The following statements require an SQLDA:
EXECUTE...USING DESCRIPTOR descriptor-name
FETCH...USING DESCRIPTOR descriptor-name
OPEN...USING DESCRIPTOR descriptor-name
CALL...USING DESCRIPTOR descriptor-name
DESCRIBE statement-name INTO descriptor-name
DESCRIBE TABLE host-variable INTO descriptor-name
PREPARE statement-name INTO descriptor-name
Unlike the SQLCA, there can be more than one SQLDA in a program, and an
SQLDA can have any valid name. An SQLDA can be coded in a PL/I program
either program directly or by using the SQL INCLUDE statement. Using the SQL
INCLUDE statement requests the inclusion of a standard SQLDA declaration:
EXEC SQL INCLUDE SQLDA ;

The included PL/I source statements for the SQLDA are:


DCL 1 SQLDA BASED(SQLDAPTR),
2 SQLDAID CHAR(8),
2 SQLDABC FIXED(31) BINARY,
2 SQLN FIXED(15) BINARY,
2 SQLD FIXED(15) BINARY,
2 SQLVAR(99),
3 SQLTYPE FIXED(15) BINARY,
3 SQLLEN FIXED(15) BINARY,
3 SQLRES CHAR(12),
3 SQLDATA PTR,
3 SQLIND PTR,
3 SQLNAME CHAR(30) VAR;
DCL SQLDAPTR PTR;

Dynamic SQL is an advanced programming technique described in Chapter 10.


Dynamic SQL Applications. With dynamic SQL, your program can develop and then
run SQL statements while the program is running. A SELECT statement with a
variable SELECT list (that is, a list of the data to be returned as part of the query)
that runs dynamically requires an SQL descriptor area (SQLDA). This is because
you cannot know in advance how many or what type of variables to allocate in
order to receive the results of the SELECT.

For more information on SQLDA, see the DB2 UDB for AS/400 SQL Reference
book.

Embedding SQL Statements


The first statement of the PL/I program must be a PROCEDURE statement.

280 DB2 UDB for AS/400 SQL Programming V4R4


SQL statements can be coded in a PL/I program wherever executable statements
can appear.

Each SQL statement in a PL/I program must begin with EXEC SQL and end with a
semicolon (;). The key words EXEC SQL must appear all on one line, but the
remainder of the statement can appear on the next and subsequent lines.

Example
An UPDATE statement coded in a PL/I program might be coded as follows:
EXEC SQL UPDATE DEPARTMENT
SET MGRNO = :MGR_NUM
WHERE DEPTNO = :INT_DEPT ;

Comments
In addition to SQL comments (--), you can include PL/I comments (/*...*/) in
embedded SQL statements wherever a blank is allowed, except between the
keywords EXEC and SQL.

Continuation for SQL Statements


The line continuation rules for SQL statements are the same as those for other PL/I
statements, except that EXEC SQL must be specified within one line.

Constants containing DBCS data can be continued across multiple lines by placing
the shift-in and shift-out characters outside of the margins. This example assumes
margins of 2 and 72. This SQL statement has a valid graphic constant of
G’<AABBCCDDEEFFGGHHIIJJKK>’.
*(..+....1....+....2....+....3....+....4....+....5....+....6....+....7.)..
EXEC SQL SELECT * FROM GRAPHTAB WHERE GRAPHCOL = G'<AABBCCDD>
<EEFFGGHHIIJJKK>';

Including Code
SQL statements or PL/I host variable declaration statements can be included by
placing the following SQL statement at the point in the source code where the
statements are to be embedded:
EXEC SQL INCLUDE member-name ;

No PL/I preprocessor directives are permitted within SQL statements. PL/I


%INCLUDE statements cannot be used to include SQL statements or declarations
of PL/I host variables that are referenced in SQL statements.

Margins
Code SQL statements within the margins specified by the MARGINS parameter on
the CRTSQLPLI command. If EXEC SQL does not start within the specified
margins, the SQL precompiler will not recognize the SQL statement. For more
information about the CRTSQLPLI command, see Appendix D. DB2 UDB for
AS/400 CL Command Descriptions.

Chapter 14. Coding SQL Statements in PL/I Applications 281


Names
Any valid PL/I variable name can be used for a host variable and is subject to the
following restrictions:

Do not use host variable names or external entry names that begin with 'SQL',
'RDI', or 'DSN'. These names are reserved for the database manager.

Statement Labels
All executable SQL statements, like PL/I statements, can have a label prefix.

WHENEVER Statement
The target for the GOTO clause in an SQL WHENEVER statement must be a label
in the PL/I source code and must be within the scope of any SQL statements
affected by the WHENEVER statement.

Using Host Variables


All host variables used in SQL statements must be explicitly declared.

The PL/I statements that are used to define the host variables should be preceded
by a BEGIN DECLARE SECTION statement and followed by an END DECLARE
SECTION statement. If a BEGIN DECLARE SECTION and END DECLARE
SECTION are specified, all host variable declarations used in SQL statements must
be between the BEGIN DECLARE SECTION and the END DECLARE SECTION
statements.

All host variables within an SQL statement must be preceded by a colon (:).

The names of host variables must be unique within the program, even if the host
variables are in different blocks or procedures.

An SQL statement that uses a host variable must be within the scope of the
statement in which the variable was declared.

Host variables must be scalar variables. They cannot be elements of an array.

Declaring Host Variables


The PL/I precompilers only recognize a subset of valid PL/I declarations as valid
host variable declarations.

Only the names and data attributes of the variables are used by the precompilers;
the alignment, scope, and storage attributes are ignored. Even though alignment,
scope, and storage are ignored, there are some restrictions on their use that, if
ignored, may result in problems when compiling PL/I source code that is created by
the precompiler. These restrictions are:
v A declaration with the EXTERNAL scope attribute and the STATIC storage
attribute must also have the INITIAL storage attribute.
v If the BASED storage attribute is coded, it must be followed by a PL/I
element-locator-expression.

282 DB2 UDB for AS/400 SQL Programming V4R4


Numeric-Host Variables
The following figure shows the syntax for valid scalar numeric-host variable
declarations.

Numeric

ÊÊ DECLARE variable-name Ê
DCL ,

( · variable-name )

Ê BINARY FIXED Ê
BIN ( precision )
FLOAT
( precision )
DECIMAL FIXED
DEC ( precision )
,scale
FLOAT
( precision )
PICTURE picture-string

Ê ; ÊÍ
Alignment and/or Scope and/or Storage

Notes:
1. (BINARY, BIN, DECIMAL, or DEC) and (FIXED or FLOAT) and (precision, scale)
can be specified in any order.
2. A picture-string in the form ’9...9V9...R’ indicates a numeric host variable. The R
is required. The optional V indicates the implied decimal point.
3. A picture-string in the form ’S9...9V9...9’ indicates a sign leading separate host
variable. The S is required. The optional V indicates the implied decimal point.

Character-Host Variables
The following figure shows the syntax for valid scalar character-host variables.

Chapter 14. Coding SQL Statements in PL/I Applications 283


Character

ÊÊ DECLARE variable-name CHARACTER Ê


DCL , CHAR

( · variable-name )

Ê Ê
( length ) VARYING
VAR

Ê ; ÊÍ
Alignment and/or Scope and/or Storage

Notes:
1. Length must be an integer constant not greater than 32766 if VARYING or VAR
is not specified.
2. If VARYING or VAR is specified, length must be a constant no greater than
32740.

| LOB Host Variables


| The following figure shows the syntax for valid LOB host variables.
|

| LOB

| ÊÊ DECLARE variable-name SQL TYPE IS BLOB Ê


| DCL , CLOB

( · variable-name )

| Ê ( lob-length ) Ê
| K

| Ê ; ÊÍ
| Alignment and/or Scope and/or Storage

||
|

| Notes:
| 1. The SQL TYPE IS clause is needed in order to distinguish the three LOB-types
| from each other so that type-checking and function resolution can be carried out
| for LOB-type host variables that are passed to functions.
| 2. For BLOB and CLOB, 1 <= lob-length <= 32,766
| 3. SQL TYPE IS, BLOB, CLOB can be in mixed case.
| 4. LOB Host Variables can be declared in host structures.

284 DB2 UDB for AS/400 SQL Programming V4R4


| BLOB Example:

| The following declaration:


| DCL MY_BLOB SQL TYPE IS BLOB(16384);

| Results in the generation of the following structure:


| DCL 1 MY_BLOB,
| 3 MY_BLOB_LENGTH BINARY FIXED (31),
| 3 MY_BLOB_DATA CHARACTER (16384);

| CLOB Example:

| The following declaration:


| DCL MY_CLOB SQL TYPE IS CLOB(16384);

| Results in the generation of the following structure:


| DCL 1 MY_CLOB,
| 3 MY_CLOB_LENGTH BINARY FIXED (31),
| 3 MY_CLOB_DATA CHARACTER (16384);

| LOB Locators
| The following figure shows the syntax for valid LOB locators.
|

| LOB locator

| ÊÊ DECLARE variable-name Ê
| DCL ,

( · variable-name )

| Ê SQL TYPE IS BLOB_LOCATOR Ê


| CLOB_LOCATOR
DBCLOB_LOCATOR

| Ê ; ÊÍ
| Alignment and/or Scope and/or Storage

||
|

| Notes:
| 1. SQL TYPE IS, BLOB_LOCATOR, CLOB_LOCATOR, DBCLOB_LOCATOR can
| be in mixed case.
| 2. LOB Locators can be declared as part of a host structure.

| CLOB Example:

| The following declaration:


| DCL MY_LOCATOR SQL TYPE IS CLOB_LOCATOR;

| Results in the generation of the following structure:


| DCL MY_LOCATOR BINARY FIXED(32);

Chapter 14. Coding SQL Statements in PL/I Applications 285


| BLOB and DBCLOB locators have similar syntax.

| LOB File Reference Variables


| The following figure shows the syntax for valid LOB file reference variables.
|

| LOB file reference variable

| ÊÊ DECLARE variable-name Ê
| DCL ,

( · variable-name )

| Ê SQL TYPE IS BLOB_FILE Ê


| CLOB_FILE
DBCLOB_FILE

| Ê ; ÊÍ
| Alignment and/or Scope and/or Storage

||
|

| Notes:
| 1. SQL TYPE IS, BLOB_LOCATOR, CLOB_LOCATOR, DBCLOB_LOCATOR can
| be in mixed case.
| 2. LOB File Reference Variables can be declared as part of a host structure.

| CLOB Example:

| The following declaration:


| DCL MY_FILE SQL TYPE IS CLOB_FILE;

| Results in the generation of the following structure:


| DCL 1 MY_FILE,
| 3 MY_FILE_NAME_LENGTH BINARY FIXED(32),
| 3 MY_FILE_DATA_LENGTH BINARY FIXED(32),
| 3 MY_FILE_FILE_OPTIONS BINARY FIXED(32),
| 3 MY_FILE_NAME CHAR(255);

| BLOB and DBCLOB locators have similar syntax.

| The pre-compiler will generate declarations for the following file option constants:
| v SQL_FILE_READ (2)
| v SQL_FILE_CREATE (8)
| v SQL_FILE_OVERWRITE (16)
| v SQL_FILE_APPEND (32)
|
Using Host Structures
In PL/I programs, you can define a host structure, which is a named set of
elementary PL/I variables. A host structure name can be a group name whose
subordinate levels name elementary PL/I variables. For example:

286 DB2 UDB for AS/400 SQL Programming V4R4


DCL 1 A,
2 B,
3 C1 CHAR(...),
3 C2 CHAR(...);

In this example, B is the name of a host structure consisting of the elementary


items C1 and C2.

You can use the structure name as shorthand notation for a list of scalars. You can
qualify a host variable with a structure name (for example, STRUCTURE.FIELD).
Host structures are limited to two levels. (For example, in the above host structure
example, the A cannot be referred to in SQL.) A structure cannot contain an
intermediate level structure. In the previous example, A could not be used as a host
variable or referred to in an SQL statement. However, B is the first level structure. B
can be referred to in an SQL statement. A host structure for SQL data is two levels
deep and can be thought of as a named set of host variables. After the host
structure is defined, you can refer to it in an SQL statement instead of listing the
several host variables (that is, the names of the host variables that make up the
host structure).

For example, you can retrieve all column values from selected rows of the table
CORPDATA.EMPLOYEE with:
DCL 1 PEMPL,
5 EMPNO CHAR(6),
5 FIRSTNME CHAR(12) VAR,
5 MIDINIT CHAR(1),
5 LASTNAME CHAR(15) VAR,
5 WORKDEPT CHAR(3);
...
EMPID = '000220';
...
EXEC SQL
SELECT *
INTO :PEMPL
FROM CORPDATA.EMPLOYEE
WHERE EMPNO = :EMPID;

Host Structures
The following figure shows the syntax for valid host structure declarations.

Chapter 14. Coding SQL Statements in PL/I Applications 287


Host Structures

ÊÊ DECLARE 1 variable-name , Ê
DCL Scope and/or storage
level-1 variable-name ,

Ê · level-2 var-1 data-types ; ÊÍ


,

( · var-2 )

data-types:

BINARY FIXED
BIN FLOAT ( precision ) UNALIGNED
DECIMAL FIXED
DEC ( precision )
, scale
FLOAT
( precision ) UNALIGNED
PICTURE picture-string
CHARACTER
CHAR ( length ) VARYING
VAR ALIGNED

Notes:
1. Level-1 indicates that there is an intermediate level structure.
2. Level-1 must be an integer constant between 1 and 254.
3. Level-2 must be an integer constant between 2 and 255.
4. For details on declaring numeric and character host variables, see the notes
under numeric-host variables and character-host variables.

Host Structure Indicator Arrays


The following figure shows the syntax for valid indicator arrays.

288 DB2 UDB for AS/400 SQL Programming V4R4


Host Structure Indicator Array

ÊÊ DECLARE variable-name ( dimension ) Ê


DCL ,

( · variable-name ( dimension ) )

Ê BINARY FIXED Ê
BIN ( precision )

Ê ; ÊÍ
Alignment and/or scope and/or storage

Note: Dimension must be an integer constant between 1 and 32766.

Using Host Structure Arrays


In PL/I programs, you can define a host structure array. In these examples, the
following are true:
v B_ARRAY is the name of a host structure array that contains the items C1_VAR
and C2_VAR.
v B_ARRAY cannot be qualified.
v B_ARRAY can only be used with the blocked forms of the FETCH and INSERT
statements.
v All items in B_ARRAY must be valid host variables.
v C1_VAR and C2_VAR are not valid host variables in any SQL statement. A
structure cannot contain an intermediate level structure. A_STRUCT cannot
contain the dimension attribute.
DCL 1 A_STRUCT,
2 B_ARRAY(10),
3 C1_VAR CHAR(20),
3 C2_FIXED BIN(15) UNALIGNED;

To retrieve 10 rows from the CORPDATA.DEPARTMENT table, do the following:

DCL 1 DEPT(10),
5 DEPTPNO CHAR(3),
5 DEPTNAME CHAR(29) VAR,
5 MGRNO CHAR(6),
5 ADMRDEPT CHAR (3);
DCL 1 IND_ARRAY(10),
5 INDS(4) FIXED BIN(15);
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT *
FROM CORPDATA.DEPARTMENT;

EXEC SQL
FETCH C1 FOR 10 ROWS INTO :DEPT :IND_ARRAY;

Chapter 14. Coding SQL Statements in PL/I Applications 289


Host Structure Array
The following syntax diagram shows the syntax for valid structure array
declarations.

Host Structure Array

ÊÊ DECLARE 1 variable-name ( dimension ) , Ê


DCL Scope and/or storage
level-1 variable-name ,

Ê · level-2 var-1 data-types ; ÊÍ


,

( · var-2 )

data-types:

BINARY FIXED UNALIGNED


BIN FLOAT ( precision )
DECIMAL FIXED
DEC ( precision )
, scale
FLOAT UNALIGNED
( precision )
PICTURE picture-string
CHARACTER
CHAR ( length ) VARYING
VAR

Notes:
1. Level-1 indicates that there is an intermediate level structure.
2. Level-1 must be an integer constant between 1 and 254.
3. Level-2 must be an integer constant between 2 and 255.
4. For details on declaring numeric and character host variables, see the notes
under numeric-host variables and character-host variables.
5. Dimension must be an integer constant between 1 and 32767.

Host Structure Array Indicator


The following figure shows the syntax diagram for valid host structure array
indicator structure declarations.

290 DB2 UDB for AS/400 SQL Programming V4R4


Host Structure Array Indicator Structure

ÊÊ DECLARE 1 variable-name ( dimension ) , Ê


DCL Scope and/or storage
level-1 variable-name ,

Ê level-2 identifier ( dimension-2 ) BINARY FIXED ; ÊÍ


BIN ( precision )

Notes:
1. Level-1 indicates that there is an intermediate level structure.
2. Level-1 must be an integer constant between 1 and 254.
3. Level-2 must be an integer constant between 2 and 255.
4. Dimension-1 and dimension-2 must be integer constants between 1 and 32767.

Using External File Descriptions


You can use the PL/I %INCLUDE directive to include the definitions of externally
described files in a source program. When used with SQL, only a particular format
of the %INCLUDE directive is recognized by the SQL precompiler. That directive
format must have the following three elements or parameter values, otherwise the
precompiler ignores the directive. The required elements are file name, format
name, and element type. There are two optional elements supported by the SQL
precompiler: prefix name and COMMA.

The structure is ended normally by the last data element of the record or key
structure. However, if in the %INCLUDE directive the COMMA element is specified,
then the structure is not ended. For more information about the %INCLUDE
directive, see the PL/I Reference Summary book, SX09-1290, and the PL/I User’s
Guide and Reference book, SC09-1825.

To include the definition of the sample table DEPARTMENT described in


Appendix A. DB2 UDB for AS/400 Sample Tables, you can code:
DCL 1 TDEPT_STRUCTURE,
%INCLUDE DEPARTMENT(DEPARTMENT,RECORD);

In the above example, a host structure named TDEPT_STRUCTURE would be


defined having four fields. The fields would be DEPTNO, DEPTNAME, MGRNO,
and ADMRDEPT.

For device files, if INDARA was not specified and the file contains indicators, the
declaration cannot be used as a host structure array. The indicator area is included
in the generated structure and causes the storage to not be contiguous.

DCL 1 DEPT_REC(10),
%INCLUDE DEPARTMENT(DEPARTMENT,RECORD);
:

EXEC SQL DECLARE C1 CURSOR FOR


SELECT * FROM CORPDATA.DEPARTMENT;

EXEC SQL OPEN C1;

Chapter 14. Coding SQL Statements in PL/I Applications 291


EXEC SQL FETCH C1 FOR 10 ROWS INTO :DEPT_REC;

Note: DATE, TIME, and TIMESTAMP columns will generate host variable
definitions that are treated by SQL with the same comparison and
assignment rules as a DATE, TIME, and TIMESTAMP column. For example,
a date host variable can only be compared with a DATE column or a
character string that is a valid representation of a date.

Although decimal and zoned fields with precision greater than 15 and binary with
nonzero scale fields are mapped to character field variables in PL/I, SQL considers
these fields to be numeric.

Although GRAPHIC and VARGRAPHIC are mapped to character variables in PL/I,


SQL considers these to be GRAPHIC and VARGRAPHIC host variables. If the
GRAPHIC or VARGRAPHIC column has a UCS-2 CCSID, the generated host
variable will have the UCS-2 CCSID assigned to it.

Determining Equivalent SQL and PL/I Data Types


The precompiler determines the base SQLTYPE and SQLLEN of host variables
based on the following table. If a host variable appears with an indicator variable,
the SQLTYPE is the base SQLTYPE plus one.
Table 28. PL/I Declarations Mapped to Typical SQL Data Types
SQLTYPE of SQLLEN of Host
PL/I Data Type Host Variable Variable SQL Data Type
BIN FIXED(p) where p is in the 500 2 SMALLINT
range 1 to 15
BIN FIXED(p) where p is in the 496 4 INTEGER
range 16 to 31
DEC FIXED(p,s) 484 p in byte 1, s in DECIMAL(p,s)
byte 2
BIN FLOAT(p) p is in the range 1 480 4 FLOAT (single
to 24 precision)
BIN FLOAT(p) p is in the range 25 480 8 FLOAT (double
to 53 precision)
DEC FLOAT(m) m is in the range 1 480 4 FLOAT (single
to 7 precision)
DEC FLOAT(m) m is in the range 8 480 8 FLOAT (double
to 16 precision)
PICTURE picture string (numeric) 488 p in byte 1, s in NUMERIC (p,s)
byte 2
PICTURE picture string (sign 504 p in byte 1, s in No exact
leading separate) byte 2 equivalent, use
NUMERIC(p,s).
CHAR(n) 452 n CHAR(n)
CHAR(n) VARYING where n <255 448 n VARCHAR(n)
CHAR(n) varying where n > 254 456 n VARCHAR(n)

292 DB2 UDB for AS/400 SQL Programming V4R4


The following table can be used to determine the PL/I data type that is equivalent to
a given SQL data type.
Table 29. SQL Data Types Mapped to Typical PL/I Declarations
SQL Data Type PL/I Equivalent Explanatory Notes
SMALLINT BIN FIXED(p) p is a positive integer from 1
to 15.
INTEGER BIN FIXED(p) p is a positive integer from 16
to 31.
DECIMAL(p,s) or DEC FIXED(p) or DEC s (the scale factor) and p (the
NUMERIC(p,s) FIXED(p,s) or PICTURE precision) are positive
picture-string integers. p is a positive
integer from 1 to 31. s is a
positive integer from 0 to p.
FLOAT (single precision) BIN FLOAT(p) or DEC p is a positive integer from 1
FLOAT(m) to 24.

m is a positive integer from 1


to 7.
FLOAT (double precision) BIN FLOAT(p) or DEC p is a positive integer from 25
FLOAT(m) to 53.

m is a positive integer from 8


to 16.
CHAR(n) CHAR(n) n is a positive integer from 1
to 32766.
VARCHAR(n) CHAR(n) VAR n is a positive integer from 1
to 32740.
BLOB None Use SQL TYPE IS to declare
a BLOB.
CLOB None Use SQL TYPE IS to declare
a CLOB.
GRAPHIC(n) Not supported Not supported.
VARGRAPHIC(n) Not supported Not supported.
DBCLOB None Use SQL TYPE IS to declare
a DBCLOB.
DATE CHAR(n) If the format is *USA, *JIS,
*EUR, or *ISO, n must be at
least 10 characters. If the
format is *YMD, *DMY, or
*MDY, n must be at least 8
characters. If the format is
*JUL, n must be at least 6
characters.
TIME CHAR(n) n must be at least 6; to
include seconds, n must be at
least 8.
TIMESTAMP CHAR(n) n must be at least 19. To
include microseconds at full
precision, n must be 26; if n
is less than 26, truncation
occurs on the microseconds
part.

Chapter 14. Coding SQL Statements in PL/I Applications 293


Table 29. SQL Data Types Mapped to Typical PL/I Declarations (continued)
SQL Data Type PL/I Equivalent Explanatory Notes
DATALINK Not supported Not supported

Using Indicator Variables


An indicator variable is a two-byte integer (BIN FIXED(p), where p is 1 to 15). You
can also specify an indicator structure (defined as an array of halfword integer
variables) to support a host structure. On retrieval, an indicator variable is used to
show whether its associated host variable has been assigned a null value. On
assignment to a column, a negative indicator variable is used to indicate that a null
value should be assigned.

See DB2 UDB for AS/400 SQL Reference book for more information about using
indicator variables.

Indicator variables are declared in the same way as host variables and the
declarations of the two can be mixed in any way that seems appropriate to the
programmer.

Example:

Given the statement:


EXEC SQL FETCH CLS_CURSOR INTO :CLS_CD,
:DAY :DAY_IND,
:BGN :BGN_IND,
:END :END_IND;

Variables can be declared as follows:


EXEC SQL BEGIN DECLARE SECTION;
DCL CLS_CD CHAR(7);
DCL DAY BIN FIXED(15);
DCL BGN CHAR(8);
DCL END CHAR(8);
DCL (DAY_IND, BGN_IND, END_IND) BIN FIXED(15);
EXEC SQL END DECLARE SECTION;

Differences in PL/I Because of Structure Parameter Passing


Techniques
The PL/I precompiler attempts to use the structure parameter passing technique, if
possible. This structure parameter passing technique provides better performance
for most PL/I programs using SQL. The precompiler generates code where each
host variable is a separate parameter when the following conditions are true:
v A PL/I %INCLUDE compiler directive is found that copies external text into the
source program.
v The data length of the host variables referred to in the statement is greater than
32703. Because SQL uses 64 bytes of the structure, 32703 + 64 = 32767, the
maximum length of a data structure.
v The PL/I precompiler estimates that it could possibly exceed the PL/I limit for
user-defined names.
v A sign leading separate host variable is found in the host variable list for the SQL
statement.

294 DB2 UDB for AS/400 SQL Programming V4R4


For more information on the structure parameter passing technique, see “Improving
Performance by Using Structure Parameter Passing Techniques” on page 472.

Chapter 14. Coding SQL Statements in PL/I Applications 295


296 DB2 UDB for AS/400 SQL Programming V4R4
Chapter 15. Coding SQL Statements in RPG for AS/400
Applications
The RPG for AS/400 licensed program supports both RPG II and RPG III programs.
SQL statements can only be used in RPG III programs. RPG II and AutoReport are
NOT supported. All referrals to RPG in this guide apply to RPG III or ILE RPG only.

This chapter describes the unique application and coding requirements for
embedding SQL statements in a RPG for AS/400 program. Requirements for host
variables are defined.

A detailed sample RPG for AS/400 program, showing how SQL statements can be
used, is provided in Appendix C. Sample Programs Using DB2 UDB for AS/400
Statements.

Defining the SQL Communications Area


The SQL precompiler automatically places the SQLCA in the input specifications of
the RPG for AS/400 program prior to the first calculation specification. INCLUDE
SQLCA should not be coded in the source program. If the source program specifies
INCLUDE SQLCA, the statement will be accepted, but it is redundant. The SQLCA,
as defined for RPG for AS/400:
ISQLCA DS SQL
I* SQL Communications area SQL
I 1 8 SQLAID SQL
I B 9 120SQLABC SQL
I B 13 160SQLCOD SQL
I B 17 180SQLERL SQL
I 19 88 SQLERM SQL
I 89 96 SQLERP SQL
I 97 120 SQLERR SQL
I B 97 1000SQLER1 SQL
I B 101 1040SQLER2 SQL
I B 105 1080SQLER3 SQL
I B 109 1120SQLER4 SQL
I B 113 1160SQLER5 SQL
I B 117 1200SQLER6 SQL
I 121 131 SQLWRN SQL
I 121 121 SQLWN0 SQL
I 122 122 SQLWN1 SQL
I 123 123 SQLWN2 SQL
I 124 124 SQLWN3 SQL
I 125 125 SQLWN4 SQL
I 126 126 SQLWN5 SQL
I 127 127 SQLWN6 SQL
I 128 128 SQLWN7 SQL
I 129 129 SQLWN8 SQL
I 130 130 SQLWN9 SQL
I 131 131 SQLWNA SQL
I 132 136 SQLSTT SQL
I* End of SQLCA SQL

Note: Variable names in RPG for AS/400 are limited to 6 characters. The standard
SQLCA names have been changed to a length of 6. RPG for AS/400 does
not have a way of defining arrays in a data structure without also defining
them in the extension specification. SQLERR is defined as character with
SQLER1 through 6 used as the names of the elements.

© Copyright IBM Corp. 1997, 1999 297


See the DB2 UDB for AS/400 SQL Reference book for more information.

Defining SQL Descriptor Areas


The following statements require an SQLDA:
EXECUTE...USING DESCRIPTOR descriptor-name
FETCH...USING DESCRIPTOR descriptor-name
OPEN...USING DESCRIPTOR descriptor-name
CALL...USING DESCRIPTOR descriptor-name
DESCRIBE statement-name INTO descriptor-name
DESCRIBE TABLE host-variable INTO descriptor-name
PREPARE statement-name INTO descriptor-name

Unlike the SQLCA, there can be more than one SQLDA in a program and an
SQLDA can have any valid name.

Dynamic SQL is an advanced programming technique described in Chapter 10.


Dynamic SQL Applications. With dynamic SQL, your program can develop and then
run SQL statements while the program is running. A SELECT statement with a
variable SELECT list (that is, a list of the data to be returned as part of the query)
that runs dynamically requires an SQL descriptor area (SQLDA). This is because
you cannot know in advance how many or what type of variables to allocate in
order to receive the results of the SELECT.

Because the SQLDA uses pointer variables which are not supported by RPG for
AS/400, an INCLUDE SQLDA statement cannot be specified in an RPG for AS/400
program. An SQLDA must be set up by a C, COBOL, PL/I, or ILE RPG program
and passed to the RPG program in order to use it.

Embedding SQL Statements


SQL statements coded in an RPG for AS/400 program must be placed in the
calculation section. This requires that a C be placed in position 6. SQL statements
can be placed in detail calculations, in total calculations, or in an RPG for AS/400
subroutine. The SQL statements are executed based on the logic of the RPG for
AS/400 statements.

The keywords EXEC SQL indicate the beginning of an SQL statement. EXEC SQL
must occupy positions 8 through 16 of the source statement, preceded by a / in
position 7. The SQL statement may start in position 17 and continue through
position 74.

The keyword END-EXEC ends the SQL statement. END-EXEC must occupy
positions 8 through 16 of the source statement, preceded by a slash (/) in position
7. Positions 17 through 74 must be blank.

Both uppercase and lowercase letters are acceptable in SQL statements.

Example
An UPDATE statement coded in an RPG for AS/400 program might be coded as
follows:

298 DB2 UDB for AS/400 SQL Programming V4R4


*...1....+....2....+....3....+....4....+....5....+....6....+....7...*
C/EXEC SQL UPDATE DEPARTMENT
C+ SET MANAGER = :MGRNUM
C+ WHERE DEPTNO = :INTDEP
C/END-EXEC

Comments
In addition to SQL comments (--), RPG for AS/400 comments can be included
within SQL statements wherever a blank is allowed, except between the keywords
EXEC and SQL. To embed an RPG for AS/400 comment within the SQL statement,
place an asterisk (*) in position 7.

Continuation for SQL Statements


When additional records are needed to contain the SQL statement, positions 9
through 74 can be used. Position 7 must be a + (plus sign), and position 8 must be
blank.

Constants containing DBCS data can be continued across multiple lines by placing
the shift-in character in position 75 of the continued line and placing the shift-out
character in position 8 of the continuation line. This SQL statement has a valid
graphic constant of G’<AABBCCDDEEFFGGHHIIJJKK>’.
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
C/EXEC SQL SELECT * FROM GRAPHTAB WHERE GRAPHCOL = G'<AABB>
C+<CCDDEEFFGGHHIIJJKK>'
C/END-EXEC

Including Code
SQL statements and RPG for AS/400 calculation specifications can be included by
embedding the SQL statement:
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
C/EXEC SQL INCLUDE member-name
C/END-EXEC

The /COPY statement can be used to include SQL statements or RPG for AS/400
specifications.

Sequence Numbers
The sequence numbers of the source statements generated by the SQL
precompiler are based on the *NOSEQSRC/*SEQSRC keywords of the OPTION
parameter on the CRTSQLRPG command. When *NOSEQSRC is specified, the
sequence number from the input source member is used. For *SEQSRC, the
sequence numbers start at 000001 and are incremented by 1.

Names
Any valid RPG variable name can be used for a host variable and is subject to the
following restrictions:

Do not use host variable names or external entry names that begin with 'SQ', 'SQL',
'RDI', or 'DSN'. These names are reserved for the database manager.

Chapter 15. Coding SQL Statements in RPG for AS/400 Applications 299
Statement Labels
A TAG statement can precede any SQL statement. Code the TAG statement on the
line preceding EXEC SQL.

WHENEVER Statement
The target for the GOTO clause must be the label of the TAG statement. The scope
rules for the GOTO/TAG must be observed.

Using Host Variables


| All host variables used in SQL statements must be explicitly declared. LOB host
| variables are not supported in RPG for AS/400.

SQL embedded in RPG for AS/400 does not use the SQL BEGIN DECLARE
SECTION and END DECLARE SECTION statements to identify host variables. Do
not put these statements in the source program.

All host variables within an SQL statement must be preceded by a colon (:).

The names of host variables must be unique within the program.

Declaring Host Variables


The SQL RPG for AS/400 precompiler only recognizes a subset of RPG for AS/400
declarations as valid host variable declarations.

All variables defined in RPG for AS/400 can be used in SQL statements, except for
the following:
Indicator field names (*INxx)
Tables
UDATE
UDAY
UMONTH
UYEAR
Look-ahead fields
Named constants

Fields used as host variables are passed to SQL, using the CALL/PARM functions
of RPG for AS/400. If a field cannot be used in the result field of the PARM, it
cannot be used as a host variable.

Using Host Structures


The RPG for AS/400 data structure name can be used as a host structure name if
subfields exist in the data structure. The use of the data structure name in an SQL
statement implies the list of subfield names making up the data structure.

When subfields are not present for the data structure, then the data structure name
is a host variable of character type. This allows character variables larger than 256,
because data structures can be up to 9999.

300 DB2 UDB for AS/400 SQL Programming V4R4


In the following example, BIGCHR is an RPG for AS/400 data structure without
subfields. SQL treats any referrals to BIGCHR as a character string with a length of
642.
*...1....+....2....+....3....+....4....+....5....+....6....+....7...*
IBIGCHR DS 642

In the next example, PEMPL is the name of the host structure consisting of the
subfields EMPNO, FIRSTN, MIDINT, LASTNAME, and DEPTNO. The referral to
PEMPL uses the subfields. For example, the first column of EMPLOYEE is placed
in EMPNO, the second column is placed in FIRSTN, and so on.
*...1....+....2....+....3....+....4....+....5....+....6....+....7. ..*
IPEMPL DS
I 01 06 EMPNO
I 07 18 FIRSTN
I 19 19 MIDINT
I 20 34 LASTNA
I 35 37 DEPTNO
...
C MOVE '000220' EMPNO
...
C/EXEC SQL
C+ SELECT * INTO :PEMPL
C+ FROM CORPDATA.EMPLOYEE
C+ WHERE EMPNO = :EMPNO
C/END-EXEC

When writing an SQL statement, referrals to subfields can be qualified. Use the
name of the data structure, followed by a period and the name of the subfield. For
example, PEMPL.MIDINT is the same as specifying only MIDINT.

Using Host Structure Arrays


A host structure array is defined as an occurrence data structure. An occurrence
data structure can be used on the SQL FETCH statement when fetching multiple
rows. In these examples, the following are true:
v All items in BARRAY must be valid host variables.
v All items in BARRAY must be contiguous. The first FROM position must be 1 and
there cannot be overlaps in the TO and FROM positions.
v For all statements other than the multiple-row FETCH and blocked INSERT, if an
occurrence data structure is used, the current occurrence is used. For the
multiple-row FETCH and blocked INSERT, the occurrence is set to 1.
*...1....+....2....+....3....+....4....+....5....+....6....+....7. ..*
IBARRAY DS 10
I 01 20 C1VAR
I B 21 220C2VAR

The following example uses a host structure array called DEPT and a multiple-row
FETCH statement to retrieve 10 rows from the DEPARTMENT table.
*...1....+....2....+....3....+....4....+....5....+....6....+....7...*
E INDS 4 4 0
IDEPT DS 10
I 01 03 DEPTNO
I 04 32 DEPTNM
I 33 38 MGRNO
I 39 41 ADMRD
IINDARR DS 10

Chapter 15. Coding SQL Statements in RPG for AS/400 Applications 301
I B 1 80INDS
...
C/EXEC SQL
C+ DECLARE C1 CURSOR FOR
C+ SELECT *
C+ FROM CORPDATA.DEPARTMENT
C/END-EXEC
C/EXEC SQL
C+ OPEN C1
C/END-EXEC
C/EXEC SQL
C+ FETCH C1 FOR 10 ROWS INTO :DEPT:INDARR
C/END-EXEC

Using External File Descriptions


The SQL precompiler processes the RPG for AS/400 source in much the same
manner as the ILE RPG for AS/400 compiler. This means that the precompiler
processes the /COPY statement for definitions of host variables. Field definitions for
externally described files are obtained and renamed, if different names are
specified. The external definition form of the data structure can be used to obtain a
copy of the column names to be used as host variables.

In the following example, the sample table DEPARTMENT is used as a file in an


ILE RPG for AS/400 program. The SQL precompiler retrieves the field (column)
definitions for DEPARTMENT for use as host variables.
*...1....+....2....+....3....+....4....+....5....+....6....+....7....*
FTDEPT IP E DISK
F TDEPT KRENAMEDEPTREC
IDEPTREC
I DEPTNAME DEPTN
I ADMRDEPT ADMRD

Note: Code an F-spec for a file in your RPG program only if you use RPG for
AS/400 statements to do I/O operations to the file. If you use only SQL
statements to do I/O operations to the file, you can include the external
definition by using an external data structure.

In the following example, the sample table is specified as an external data structure.
The SQL precompiler retrieves the field (column) definitions as subfields of the data
structure. Subfield names can be used as host variable names, and the data
structure name TDEPT can be used as a host structure name. The field names
must be changed because they are greater than six characters.
*...1....+....2....+....3....+....4....+....5....+....6....+....7....*
ITDEPT E DSDEPARTMENT
I DEPTNAME DEPTN
I ADMRDEPT ADMRD

Note: DATE, TIME, and TIMESTAMP columns will generate host variable
definitions which are treated by SQL with the same comparison and
assignment rules as a DATE, TIME, and TIMESTAMP column. For example,
a date host variable can only be compared against a DATE column or a
character string which is a valid representation of a date.

Although varying-length columns generate fixed-length character-host variable


definitions, to SQL they are varying-length character variables.

302 DB2 UDB for AS/400 SQL Programming V4R4


Although GRAPHIC and VARGRAPHIC columns are mapped to character variables
in RPG for AS/400, SQL considers these GRAPHIC and VARGRAPHIC variables. If
the GRAPHIC or VARGRAPHIC column has a UCS-2 CCSID, the generated host
variable will have the UCS-2 CCSID assigned to it.

External File Description Considerations for Host Structure Arrays


If the file contains floating-point fields, it cannot be used as a host structure array.
For device files, if INDARA was not specified and the file contains indicators, the
declaration is not used as a host structure array. The indicator area is included in
the structure that is generated and would cause the storage to not be contiguous.

In the following example, the DEPARTMENT table is included in the RPG for
AS/400 program and is used to declare a host structure array. A multiple-row
FETCH statement is then used to retrieve 10 rows into the host structure array.

*...1....+....2....+....3....+....4....+....5....+....6....*
ITDEPT E DSDEPARTMENT 10
I DEPARTMENT DEPTN
I ADMRDEPT ADMRD

...

C/EXEC SQL
C+ DECLARE C1 CURSOR FOR
C+ SELECT *
C+ FROM CORPDATA.DEPARTMENT
C/END-EXEC

...

C/EXEC SQL
C+ FETCH C1 FOR 10 ROWS INTO :TDEPT
C/END-EXEC

Determining Equivalent SQL and RPG for AS/400 Data Types


The precompiler determines the base SQLTYPE and SQLLEN of host variables
based on the following table. If a host variable appears with an indicator variable,
the SQLTYPE is the base SQLTYPE plus one.
Table 30. RPG for AS/400 Declarations Mapped to Typical SQL Data Types
RPG for
AS/400 Data Other RPG for SQLTYPE of SQLLEN of SQL Data
Type Col 43 Col 52 AS/400 Coding Host Variable Host Variable Type
Data Structure blank blank Length = n where n ≤ 452 n CHAR(n)
subfield 256
Data structure n/a n/a Length = n where n ≤ 452 n CHAR(n)
(without 9999
subfields)
Input field blank blank Length = n where n ≤ 452 n CHAR(n)
256
Calculation n/a blank Length = n where n ≤ 452 n CHAR(n)
result field 256
Data Structure B 0 Length = 2 500 2 SMALLINT
subfield

Chapter 15. Coding SQL Statements in RPG for AS/400 Applications 303
Table 30. RPG for AS/400 Declarations Mapped to Typical SQL Data Types (continued)
RPG for
AS/400 Data Other RPG for SQLTYPE of SQLLEN of SQL Data
Type Col 43 Col 52 AS/400 Coding Host Variable Host Variable Type
Data Structure B 0 Length = 4 496 4 INTEGER
subfield
Data Structure B 1-4 Length = 2 500 2 DECIMAL(4,s)
subfield where
s=column 52
Data Structure B 1-9 Length = 4 496 4 DECIMAL(9,s)
subfield where
s=column 52
Data Structure P 0 to 9 Length = n where n is 484 p in byte 1, s in DECIMAL(p,s)
subfield 1 to 16 byte 2 where p =
n*2-1 and s =
column 52
Input field P 0 to 9 Length = n where n is 484 p in byte 1, s in DECIMAL(p,s)
1 to 16 byte 2 where p =
n*2-1 and s =
column 52
Input field blank 0 to 9 Length = n where n is 484 p in byte 1, s in DECIMAL(p,s)
1 to 30 byte 2 where p = n
and s = column
52
Input field B 0 to 4 if n Length = 2 or 4 484 p in byte 1, s in DECIMAL(p,s)
= 2; 0 to 9 byte 2 where p=4 if
if n = 4 n=2 or 9 if n=4
and s = column
52
Calculation n/a 0 to 9 Length = n where n is 484 p in byte 1, s in DECIMAL(p,s)
result field 1 to 30 byte 2 where p = n
and s = column
52
Data Structure blank 0 to 9 Length = n where n is 488 p in byte 1, s in NUMERIC(p,s)
subfield 1 to 30 byte 2 where p = n
and s = column
52

The following table can be used to determine the RPG for AS/400 data type that is
equivalent to a given SQL data type.
Table 31. SQL Data Types Mapped to Typical RPG for AS/400 Declarations
SQL Data Type RPG for AS/400 Data Type Notes
SMALLINT Subfield of a data structure. B in position 43,
length must be 2 and 0 in position 52 of the
subfield specification.
INTEGER Subfield of a data structure. B in position 43,
length must be 4 and 0 in position 52 of the
subfield specification.

304 DB2 UDB for AS/400 SQL Programming V4R4


Table 31. SQL Data Types Mapped to Typical RPG for AS/400 Declarations (continued)
SQL Data Type RPG for AS/400 Data Type Notes
DECIMAL Subfield of a data structure. P in position 43 Maximum length of 16 (precision 30) and
and 0 through 9 in position 52 of the subfield maximum scale of 9.
specification.

OR

Defined as numeric and not a subfield of a


data structure.
NUMERIC Subfield of the data structure. Blank in Maximum length of 30 (precision 30) and
position 43 and 0 through 9 in position 52 of maximum scale of 9.
the subfield
FLOAT (single No exact equivalent Use one of the alternative numeric data types
precision) described above.
FLOAT (double No exact equivalent Use one of the alternative numeric data types
precision) described above.
CHAR(n) Subfield of a data structure or input field. n can be from 1 to 256.
Blank in positions 43 and 52 of the
specification.

OR

Calculation result field defined without decimal


places.
CHAR(n) Data structure name with no subfields in the n can be from 1 to 9999.
data structure.
VARCHAR(n) No exact equivalent Use a character host variable large enough to
contain the largest expected VARCHAR
value.
BLOB Not supported Not supported
CLOB Not supported Not supported
GRAPHIC(n) Not supported Not supported
VARGRAPHIC(n) Not supported Not supported
DBCLOB Not supported Not supported
DATE Subfield of a data structure. Blank in position If the format is *USA, *JIS, *EUR, or *ISO, the
52 of the subfield specification. length must be at least 10. If the format is
*YMD, *DMY, or *MDY, the length must be at
OR least 8. If the format is *JUL, the length must
be at least 6.
Field defined without decimal places.
TIME Subfield of a data structure. Blank in position Length must be at least 6; to include seconds,
52 of the subfield specification. length must be at least 8.

OR

Field defined without decimal places.


TIMESTAMP Subfield of a data structure. Blank in position Length must be at least 19. To include
52 of the subfield specification. microseconds at full precision, length must be
26. If length is less than 26, truncation occurs
OR on the microseconds part.

Field defined without decimal places.


DATALINK Not supported Not supported

Chapter 15. Coding SQL Statements in RPG for AS/400 Applications 305
Notes on RPG for AS/400 Variable Declaration and Usage
Assignment rules
RPG for AS/400 associates precision and scale with all numeric types. RPG for
AS/400 defines numeric operations, assuming the data is in packed format. This
means that operations involving binary variables include an implicit conversion to
packed format before the operation is performed (and back to binary, if necessary).
Data is aligned to the implied decimal point when SQL operations are performed.

Using Indicator Variables


An indicator variable is a two-byte integer (see the entry for the SMALLINT SQL
data type in Table 30 on page 303).

An indicator structure can be defined by declaring the variable as an array with an


element length of 4,0 and declaring the array name as a subfield of a data structure
with B in position 43. On retrieval, an indicator variable is used to show whether its
associated host variable has been assigned a null value. on assignment to a
column, a negative indicator variable is used to indicate that a null value should be
assigned.

See the DB2 UDB for AS/400 SQL Referencefor more information on the use of
indicator variables.

Indicator variables are declared in the same way as host variables and the
declarations of the two can be mixed in any way that seems appropriate to the
programmer.

Example
Given the statement:
*...1....+....2....+....3....+....4....+....5....+....6....+....7...*
C/EXEC SQL FETCH CLS_CURSOR INTO :CLSCD,
C+ :DAY :DAYIND,
C+ :BGN :BGNIND,
C+ :END :ENDIND
C/END-EXEC

variables can be declared as follows:


*...1....+....2....+....3....+....4....+....5....+....6....+....7...*
I DS
I 1 7 CLSCD
I B 8 90DAY
I B 10 110DAYIND
I 12 19 BGN
I B 20 210BGNIND
I 22 29 END
I B 30 310ENDIND

306 DB2 UDB for AS/400 SQL Programming V4R4


Differences in RPG for AS/400 Because of Structure Parameter
Passing Techniques
The SQL RPG for AS/400 precompiler attempts to use the structure parameter
passing technique, if possible. The precompiler generates code where each host
variable is a separate parameter when the following conditions are true:
v The data length of the host variables, referred to in the statement, is greater than
9935. Because SQL uses 64 bytes of the structure, 9935 + 64 = 9999, the
maximum length of a data structure.
v An indicator is specified on the statement where the length of the indexed
indicator name plus the required index value is greater than six characters. The
precompiler must generate an assignment statement for the indicator with the
indicator name in the result field that is limited to six characters (″INDIC,1″
requires seven characters).
v The length of a host variable is greater than 256. This can happen when a data
structure without subfields is used as a host variable, and its length exceeds 256.
Subfields cannot be defined with a length greater than 256.

For more information on the structure parameter passing technique, see “Improving
Performance by Using Structure Parameter Passing Techniques” on page 472.

Ending a Called RPG for AS/400 Program Correctly


SQL run time builds and maintains data areas (internal SQLDAs) for each SQL
statement which contains host variables. These internal SQLDAs are built the first
time the statement is run and then reused on subsequent executions of the
statement to increase performance. The internal SQLDAs can be reused as long as
there is at least one SQL program active. The SQL precompiler allocates static
storage used by SQL run time to manage the internal SQLDAs properly.

If an RPG for AS/400 program containing SQL is called from another program which
also contains SQL, the RPG for AS/400 program should not set the Last Record
(LR) indicator on. Setting the LR indicator on causes the static storage to be
re-initialized the next time the RPG for AS/400 program is run. Re-initializing the
static storage causes the internal SQLDAs to be rebuilt, thus causing a
performance degradation.

An RPG for AS/400 program containing SQL statements that is called by a program
that also contains SQL statements, should be ended one of two ways:
v By the RETRN statement
v By setting the RT indicator on.
This allows the internal SQLDAs to be used again and reduces the total run time.

Chapter 15. Coding SQL Statements in RPG for AS/400 Applications 307
308 DB2 UDB for AS/400 SQL Programming V4R4
Chapter 16. Coding SQL Statements in ILE RPG for AS/400
Applications
This chapter describes the unique application and coding requirements for
embedding SQL statements in an ILE RPG for AS/400 program. The coding
requirements for host variables are defined.

Defining the SQL Communications Area


The SQL precompiler automatically places the SQLCA in the definition
specifications of the ILE RPG for AS/400 program prior to the first calculation
specification. INCLUDE SQLCA should not be coded in the source program. If the
source program specifies INCLUDE SQLCA, the statement will be accepted, but it
is redundant. The SQLCA, as defined for ILE RPG for AS/400:
D* SQL Communications area
D SQLCA DS
D SQLAID 1 8A
D SQLABC 9 12B 0
D SQLCOD 13 16B 0
D SQLERL 17 18B 0
D SQLERM 19 88A
D SQLERP 89 96A
D SQLERRD 97 120B 0 DIM(6)
D SQLERR 97 120A
D SQLER1 97 100B 0
D SQLER2 101 104B 0
D SQLER3 105 108B 0
D SQLER4 109 112B 0
D SQLER5 113 116B 0
D SQLER6 117 120B 0
D SQLWRN 121 131A
D SQLWN0 121 121A
D SQLWN1 122 122A
D SQLWN2 123 123A
D SQLWN3 124 124A
D SQLWN4 125 125A
D SQLWN5 126 126A
D SQLWN6 127 127A
D SQLWN7 128 128A
D SQLWN8 129 129A
D SQLWN9 130 130A
D SQLWNA 131 131A
D SQLSTT 132 136A
D* End of SQLCA

Note: Variable names in RPG for AS/400 are limited to 6 characters. The standard
SQLCA names were changed to a length of 6 for RPG for AS/400. To
maintain compatibility with RPG for AS/400 programs which are converted to
ILE RPG for AS/400, the names for the SQLCA will remain as used with
RPG for AS/400. The SQLCA defined for the ILE RPG for AS/400 has added
the field SQLERRD which is defined as an array of six integers. SQLERRD
is defined to overlay the SQLERR definition.

© Copyright IBM Corp. 1997, 1999 309


Defining SQL Descriptor Areas
The following statements require an SQLDA:
EXECUTE...USING DESCRIPTOR descriptor-name
FETCH...USING DESCRIPTOR descriptor-name
OPEN...USING DESCRIPTOR descriptor-name
CALL...USING DESCRIPTOR descriptor-name
DESCRIBE statement-name INTO descriptor-name
DESCRIBE TABLE host-variable INTO descriptor-name
PREPARE statement-name INTO descriptor-name

Unlike the SQLCA, there can be more than one SQLDA in a program and an
SQLDA can have any valid name.

Dynamic SQL is an advanced programming technique described in the SQL


programmers guide. With dynamic SQL, your program can develop and then run
SQL statements while the program is running. A SELECT statement with a variable
SELECT list (that is, a list of the data to be returned as part of the query) that runs
dynamically requires an SQL descriptor area (SQLDA). This is because you cannot
know in advance how many or what type of variables to allocate in order to receive
the results of the SELECT.

An INCLUDE SQLDA statement can be specified in an ILE RPG for AS/400


program. The format of the statement is:
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8.
C/EXEC SQL INCLUDE SQLDA
C/END-EXEC

The INCLUDE SQLDA generates the following data structure.


D* SQL Descriptor area
D SQLDA DS
D SQLDAID 1 8A
D SQLDABC 9 12B 0
D SQLN 13 14B 0
D SQLD 15 16B 0
D SQL_VAR 80A DIM(SQL_NUM)
D 17 18B 0
D 19 20B 0
D 21 32A
D 33 48*
D 49 64*
D 65 66B 0
D 67 96A
D*
D SQLVAR DS
D SQLTYPE 1 2B 0
D SQLLEN 3 4B 0
D SQLRES 5 16A
D SQLDATA 17 32*
D SQLIND 33 48*
D SQLNAMELEN 49 50B 0
D SQLNAME 51 80A
D* End of SQLDA

The user is responsible for the definition of SQL_NUM. SQL_NUM must be defined
as a numeric constant with the dimension required for SQL_VAR.

310 DB2 UDB for AS/400 SQL Programming V4R4


Since ILE RPG for AS/400 does not support structures within arrays, the INCLUDE
SQLDA generates two data structures. The second data structure is used to
setup/reference the part of the SQLDA which contains the field descriptions.

To set the field descriptions of the SQLDA the program sets up the field description
in the subfields of SQLVAR and then does a MOVEA of SQLVAR to SQL_VAR,n
where n is the number of the field in the SQLDA. This is repeated until all the field
descriptions are set.

When the SQLDA field descriptions are to be referenced the user does a MOVEA of
SQL_VAR,n to SQLVAR where n is the number of the field description to be
processed.

Embedding SQL Statements


SQL statements coded in an ILE RPG for AS/400 program must be placed in the
calculation section. This requires that a C be placed in position 6. SQL statements
can be placed in detail calculations, in total calculations, or in an RPG subroutines.
The SQL statements are executed based on the logic of the RPG statements.

The keywords EXEC SQL indicate the beginning of an SQL statement. EXEC SQL
must occupy positions 8 through 16 of the source statement, preceded by a / in
position 7. The SQL statement may start in position 17 and continue through
position 80.

The keyword END-EXEC ends the SQL statement. END-EXEC must occupy
positions 8 through 16 of the source statement, preceded by a slash (/) in position
7. Positions 17 through 80 must be blank.

Both uppercase and lowercase letters are acceptable in SQL statements.

Example
An UPDATE statement coded in an ILE RPG for AS/400 program might be coded
as follows:
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8.
C/EXEC SQL UPDATE DEPARTMENT
C+ SET MANAGER = :MGRNUM
C+ WHERE DEPTNO = :INTDEP
C/END-EXEC

Comments
In addition to SQL comments (--), ILE RPG for AS/400 comments can be included
within SQL statements wherever SQL allows a blank character. To embed an ILE
RPG for AS/400 comment within the SQL statement, place an asterisk (*) in position
7.

Continuation for SQL Statements


When additional records are needed to contain the SQL statement, positions 9
through 80 can be used. Position 7 must be a + (plus sign), and position 8 must be
blank. Position 80 of the continued line is concatenated with position 9 of the
continuation line.

Chapter 16. Coding SQL Statements in ILE RPG for AS/400 Applications 311
Constants containing DBCS data can be continued across multiple lines by placing
the shift-in character in position 81 of the continued line and placing the shift-out
character in position 8 of the continuation line.

In this example the SQL statement has a valid graphic constant of


G’<AABBCCDDEEFFGGHHIIJJKK>’.

*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8.
C/EXEC SQL SELECT * FROM GRAPHTAB WHERE GRAPHCOL = G'<AABBCCDDEE>
C+<FFGGHHIIJJKK>'
C/END-EXEC

Including Code
SQL statements and RPG calculation specifications can be included by using the
SQL statement:
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
C/EXEC SQL INCLUDE member-name
C/END-EXEC

The RPG /COPY statement can be used to include SQL statements or RPG
specifications.

Sequence Numbers
The sequence numbers of the source statements generated by the SQL
precompiler are based on the *NOSEQSRC/*SEQSRC keywords of the OPTION
parameter on the CRTSQLRPGI command. When *NOSEQSRC is specified, the
sequence number from the input source member is used. For *SEQSRC, the
sequence numbers start at 000001 and are incremented by 1.

Names
Any valid ILE RPG for AS/400 variable name can be used for a host variable and is
subject to the following restrictions:

Do not use host variable names or external entry names that begin with the
characters 'SQ', 'SQL', 'RDI', or 'DSN'. These names are reserved for the database
manager. The length of host variable names is limited to 64.

Statement Labels
A TAG statement can precede any SQL statement. Code the TAG statement on the
line preceding EXEC SQL.

WHENEVER Statement
The target for the GOTO clause must be the label of the TAG statement. The scope
rules for the GOTO/TAG must be observed.

Using Host Variables


All host variables used in SQL statements must be explicitly declared.

312 DB2 UDB for AS/400 SQL Programming V4R4


SQL embedded in ILE RPG for AS/400 does not use the SQL BEGIN DECLARE
SECTION and END DECLARE SECTION statements to identify host variables. Do
not put these statements in the source program.

All host variables within an SQL statement must be preceded by a colon (:).

The names of host variables must be unique within the program, even if the host
variables are in different procedures.

An SQL statement that uses a host variable must be within the scope of the
statement in which the variable was declared.

Declaring Host Variables


The SQL ILE RPG for AS/400 precompiler only recognizes a subset of valid ILE
RPG for AS/400 declarations as valid host variable declarations.

All variables defined in ILE RPG for AS/400 can be used in SQL statements, except
for the following:
Pointer
Tables
UDATE
UDAY
UMONTH
UYEAR
Look-ahead fields
Named constants
Multiple dimension arrays
Definitions requiring the resolution of *SIZE or *ELEM
Definitions requiring the resolution of constants unless the constant is used in
OCCURS or DIM.

Fields used as host variables are passed to SQL, using the CALL/PARM functions
of ILE RPG for AS/400. If a field cannot be used in the result field of the PARM, it
cannot be used as a host variable.

Date and time host variables are always assigned to corresponding date and time
subfields in the structures generated by the SQL precompiler. The generated date
and time subfields are declared using the format and separator specified by the
DATFMT, DATSEP, TIMFMT, and TIMSEP parameters on the CRTSQLRPGI
command. Conversion from the user declared host variable format to the
precompile specified format occurs on assignment to and from the SQL generated
structure. If the DATFMT parameter value is a system format (*MDY, *YMD, *DMY,
or *JUL), then all input and output host variables must contain date values within
the range 1940-2039. If any date value is outside of this range, then the DATFMT
on the precompile must be specified as one of the IBM SQL formats of *ISO, *USA,
*EUR, or *JIS.

Chapter 16. Coding SQL Statements in ILE RPG for AS/400 Applications 313
Using Host Structures
The ILE RPG for AS/400 data structure name can be used as a host structure
name if subfields exist in the data structure. The use of the data structure name in
an SQL statement implies the list of subfield names making up the data structure.

When subfields are not present for the data structure, then the data structure name
is a host variable of character type. This allows character variables larger than 256.
While this support does not provide additional function since a field can be defined
with a maximum length of 32766 it is required for compatibility with RPG for AS/400
programs.

In the following example, BIGCHR is an ILE RPG for AS/400 data structure without
subfields. SQL treats any referrals to BIGCHR as a character string with a length of
642.
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
DBIGCHR DS 642

In the next example, PEMPL is the name of the host structure consisting of the
subfields EMPNO, FIRSTN, MIDINT, LASTNAME, and DEPTNO. The referral to
PEMPL uses the subfields. For example, the first column of
CORPDATA.EMPLOYEE is placed in EMPNO, the second column is placed in
FIRSTN, and so on.
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
DPEMPL DS
D EMPNO 01 06A
D FIRSTN 07 18A
D MIDINT 19 19A
D LASTNA 20 34A
D DEPTNO 35 37A

...
C MOVE '000220' EMPNO

...
C/EXEC SQL
C+ SELECT * INTO :PEMPL
C+ FROM CORPDATA.EMPLOYEE
C+ WHERE EMPNO = :EMPNO
C/END-EXEC

When writing an SQL statement, referrals to subfields can be qualified. Use the
name of the data structure, followed by a period and the name of the subfield. For
example, PEMPL.MIDINT is the same as specifying only MIDINT.

Using Host Structure Arrays


A host structure array is defined as an occurrence data structure. An occurrence
data structure can be used on the SQL FETCH or INSERT statement when
processing multiple rows. The following list of items must be considered when using
a data structure with multiple row blocking support.
v All subfields must be valid host variables.
v All subfields must be contiguous. The first FROM position must be 1 and there
cannot be overlaps in the TO and FROM positions.

314 DB2 UDB for AS/400 SQL Programming V4R4


v If the date and time format and separator of date and time subfields within the
host structure are not the same as the DATFMT, DATSEP, TIMFMT, and TIMSEP
parameters on the CRTSQLRPGI command, then the host structure array is not
usable.

For all statements, other than the blocked FETCH and blocked INSERT, if an
occurrence data structure is used, the current occurrence is used. For the blocked
FETCH and blocked INSERT, the occurrence is set to 1.

The following example uses a host structure array called DEPT and a blocked
FETCH statement to retrieve 10 rows from the DEPARTMENT table.
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
DDEPARTMENT DS OCCURS(10)
D DEPTNO 01 03A
D DEPTNM 04 32A
D MGRNO 33 38A
D ADMRD 39 41A

DIND_ARRAY DS OCCURS(10)
D INDS 4B 0 DIM(4)
...
C/EXEC SQL
C+ DECLARE C1 FOR
C+ SELECT *
C+ FROM CORPDATA.DEPARTMENT
C/END-EXEC
...

C/EXEC SQL
C+ FETCH C1 FOR 10 ROWS
C+ INTO :DEPARTMENT:IND_ARRAY
C/END-EXEC

Declaring LOB Host Variables

| LOB Host Variables


| BLOB Example

| The following declaration:


| D MYBLOB S SQLTYPE(BLOB:500)

| Results in the generation of the following structure:


| D MYBLOB DS
| D MYBLOB_LEN 10U
| D MYBLOB_DATA 500A

| CLOB Example

| The following declaration:


| D MYCLOB S SQLTYPE(CLOB:1000)

| Results in the generation of the following structure:


| D MYCLOB DS
| D MYCLOB_LEN 10U
| D MYCLOB_DATA 1000A

Chapter 16. Coding SQL Statements in ILE RPG for AS/400 Applications 315
| DBCLOB Example

| The following declaration:


| D MYDBCLOB S SQLTYPE(DBCLOB:400)

| Results in the generation of the following structure:


| D MYDBCLOB DS
| D MYDBCLOB_LEN 10U
| D MYDBCLOB_DATA 400G

| LOB Locators
| BLOB Example

| The following declaration:


| D MYBLOB S SQLTYPE(BLOB_LOCATOR)

| Results in the generation of the following structure:


| D MYBLOB S 10U

| CLOB and DBCLOB locators have similar syntax.

| LOB File Reference Variables


| BLOB Example

| The following declaration:


| D MYFILE S SQLTYPE(CLOB_FILE)

| Results in the generation of the following structure:


| D MY_FILE DS
| D MY_FILE_NL 10U
| D MY_FILE_DL 10U
| D MY_FILE_FO 10U
| D MY_FILE_NAME 255A

| BLOB and DBCLOB locators have similar syntax.

| The pre-compiler will generate declarations for the following file option constants:
| v SQFRD (2)
| v SQFCRT (8)
| v SQFOVR (16)
| v SQFAPP (32)
|
Using External File Descriptions
The SQL precompiler processes the ILE RPG for AS/400 source in much the same
manner as the ILE RPG for AS/400 compiler. This means that the precompiler
processes the /COPY statement for definitions of host variables. Field definitions for
externally described files are obtained and renamed, if different names are
specified. The external definition form of the data structure can be used to obtain a
copy of the column names to be used as host variables.

316 DB2 UDB for AS/400 SQL Programming V4R4


How date and time field definition are retrieved and processed by the SQL
precompiler depends on whether *NOCVTDT or *CVTDT is specified on the
OPTION parameter of the CRTSQLRPGI command. If *NOCVTDT is specified, then
date and time field definitions are retrieved including the format and separator. If
*CVTDT is specified, then the format and separator is ignored when date and time
field definitions are retrieved, and the precompiler assumes that the variable
declarations are date/time host variables in character format. *CVTDT is a
compatibility option for the RPG for AS/400 precompiler.

In the following example, the sample table DEPARTMENT is used as a file in an


ILE RPG for AS/400 program. The SQL precompiler retrieves the field (column)
definitions for DEPARTMENT for use as host variables.
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
FDEPARTMENTIP E DISK RENAME(ORIGREC:DEPTREC)

Note: Code an F-spec for a file in your ILE RPG for AS/400 program only if you
use ILE RPG for AS/400 statements to do I/O operations to the file. If you
use only SQL statements to do I/O operations to the file, you can include the
external definition of the file (table) by using an external data structure.

In the following example, the sample table is specified as an external data structure.
The SQL precompiler retrieves the field (column) definitions as subfields of the data
structure. Subfield names can be used as host variable names, and the data
structure name TDEPT can be used as a host structure name. The example shows
that the field names can be renamed if required by the program.
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
DTDEPT E DS EXTNAME(DEPARTMENT)
D DEPTN E EXTFLD(DEPTNAME)
D ADMRD E EXTFLD(ADMRDEPT)

If the GRAPHIC or VARGRAPHIC column has a UCS-2 CCSID, the generated host
variable will have the UCS-2 CCSID assigned to it.

External File Description Considerations for Host Structure Arrays


For device files, if INDARA was not specified and the file contains indicators, the
declaration is not used as a host structure array. The indicator area is included in
the structure that is generated and would cause the storage to be separated.

If OPTION(*NOCVTDT) is specified and the date and time format and separator of
date and time field definitions within the file are not the same as the DATFMT,
DATSEP, TIMFMT, and TIMSEP parameters on the CRTSQLRPGI command, then
the host structure array is not usable.

In the following example, the DEPARTMENT table is included in the ILE RPG for
AS/400 program and used to declare a host structure array. A blocked FETCH
statement is then used to retrieve 10 rows into the host structure array.
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
DDEPARTMENT E DS OCCURS(10)

...

C/EXEC SQL
C+ DECLARE C1 CURSOR FOR
C+ SELECT *
C+ FROM CORPDATA.DEPARTMENT

Chapter 16. Coding SQL Statements in ILE RPG for AS/400 Applications 317
C/END-EXEC

...

C/EXEC SQL
C+ FETCH C1 FOR 10 ROWS
C+ INTO :DEPARTMENT
C/END-EXEC

Determining Equivalent SQL and RPG Data Types


The precompiler will determine the base SQLTYPE and SQLLEN of host variables
according to the following table. If a host variable appears with an indicator variable,
the SQLTYPE is the base SQLTYPE plus one.
Table 32. ILE RPG for AS/400 Declarations Mapped to Typical SQL Data Types
SQLTYPE
RPG Data D spec Pos D spec Pos of Host SQLLEN of
Type 40 41,42 Other RPG Coding Variable Host Variable SQL Data Type
Data structure blank blank Length = n where n ≤ 452 n CHAR(n)
(without 32766
subfields)
Calculation n/a n/a Length = n where n ≤ 452 n CHAR(n)
result field (pos 32766 (pos 59-63)
69,70 = blank)
Definition A blank length=n where n is 1 448 n VARCHAR (n)
specification to 254. VARYING in
columns 44-80.
Definition A blank length=n where n > 456 n VARCHAR (n)
specification 254. VARYING in
columns 44-80
Definition B 0 Length ≤ 4 500 2 SMALLINT
specification
Definition I 0 Length = 5 500 2 SMALLINT
specification
Definition B 0 Length ≤ 9 and ≥ 5 496 4 INTEGER
specification
Definition I 0 Length = 10 496 4 INTEGER
specification
Definition B 1-4 Length = 2 500 2 DECIMAL(4,s)
specification s=col 41, 42
Definition B 1-9 Length = 4 496 4 DECIMAL(9,s)
specification s=col 41, 42
Definition P 0 to 30 Length = n where n is 484 p in byte 1, s in DECIMAL(p,s)
specification 1 to 16 byte 2 where p = n*2-1
and s = pos 41,
42
Definition F blank Length = 4 480 4 FLOAT (single
specification precision)
Definition F blank Length = 8 480 8 FLOAT (double
specification precision)

318 DB2 UDB for AS/400 SQL Programming V4R4


Table 32. ILE RPG for AS/400 Declarations Mapped to Typical SQL Data Types (continued)
SQLTYPE
RPG Data D spec Pos D spec Pos of Host SQLLEN of
Type 40 41,42 Other RPG Coding Variable Host Variable SQL Data Type
Definition blank 0 to 30 Length = n where n is 484 p in byte 1, s in DECIMAL(p,s)
specification 1 to 16 byte 2 where p = n*2-1
not a subfield and s = pos 41,
42
Input field (pos n/a n/a Length = n where n is 484 p in byte 1, s in DECIMAL(p,s)
36 = P) 1 to 16 (pos 37-46) byte 2 where p = n*2-1
and s = pos 47,
48
Input field (pos n/a n/a Length = n where n is 484 p in byte 1, s in DECIMAL(p,s)
36 = blank or 1 to 30 (pos 37-46) byte 2 where p = n and
S) s = pos 47, 48
Input field (pos n/a n/a Length = n where n is 484 p in byte 1, s in DECIMAL(p,s)
36 = B) 2 or 4 (pos 37-46) byte 2 where p=4 if n=2
or 9 if n=4 s =
pos 47, 48
Calculation n/a n/a Length = n where n is 484 p in byte 1, s in DECIMAL(p,s)
result field (pos 1 to 30 (pos 59-63) byte 2 where p = n and
69,70 ≠ blank) s = pos 64, 65
Data Structure blank 0 to 30 Length = n where n is 488 p in byte 1, s in NUMERIC(p,s)
subfield 1 to 30 byte 2 where p = n and
s = pos 41, 42
Definition S 0 to 30 Length = n where n is 488 p in byte 1, s in NUMERIC(p,s)
specification 1 to 30 byte 2 where p = n and
s = pos 41, 42
Input field (pos n/a n/a Length = n where n is 468 m GRAPHIC(m)
36 = G) 1 to 32766 (pos 37-46) where m = n/2 m
= (TO-FROM-1)/2
Definition G blank length=n where n is 1 464 n VARGRAPHIC
specification to 127. VARYING in (n)
columns 44-80.
Definition G blank length=n where n > 472 n VARGRAPHIC
specification 127. VARYING in (n)
columns 44-80.
Definition D blank Length = n where n is 384 n DATE (DATFMT,
specification 6, 8 or 10 DATSEP
specified in pos
44-80)
Input field (pos n/a n/a Length = n where n is 384 n DATE (format
36 = D) 6, 8, or 10 (pos 37-46) specified in pos
31-34)
Definition T blank Length = n where n is 388 n TIME (TIMFMT,
specification 8 TIMSEP specified
in pos 44-80)
Input field (pos n/a n/a Length = n where n is 388 n TIME (format
36 = T) 8 (pos 37-46) specified in pos
31-34)
Definition Z blank Length = n where n is 392 n TIMESTAMP
specification 26

Chapter 16. Coding SQL Statements in ILE RPG for AS/400 Applications 319
Table 32. ILE RPG for AS/400 Declarations Mapped to Typical SQL Data Types (continued)
SQLTYPE
RPG Data D spec Pos D spec Pos of Host SQLLEN of
Type 40 41,42 Other RPG Coding Variable Host Variable SQL Data Type
Input field (pos n/a n/a Length = n where n is 392 n TIMESTAMP
36 = Z) 26 (pos 37-46)

Notes:
1. In the first column the term ″definition specification″ includes data structure
subfields unless explicitly stated otherwise.
2. In definition specifications the length of binary fields (B in pos 40) is determined
by the following:
v FROM (pos 26-32) is not blank, then length = TO-FROM+1.
v FROM (pos 26-32) is blank, then length = 2 if pos 33-39 < 5, or length = 4 if
pos 33-39 > 4.
3. SQL will create the date/time subfield using the DATE/TIME format specified on
the CRTSQLRPGI command. The conversion to the host variable DATE/TIME
format will occur when the mapping is done between the host variables and the
SQL generated subfields.

The following table can be used to determine the RPG data type that is equivalent
to a given SQL data type.
Table 33. SQL Data Types Mapped to Typical RPG Declarations
SQL Data Type RPG Data Type Notes
SMALLINT Definition specification. I in position
40, length must be 5 and 0 in position
42.
OR

Definition specification. B in position


40, length must be ≤ 4 and 0 in
position 42.
INTEGER Definition specification. I in position
40, length must be 10 and 0 in
position 42.
OR

Definition specification. B in position


40, length must be ≤ 9 and ≥ 5 and 0
in position 42.
DECIMAL Definition specification. P in position Maximum length of 16 (precision 30)
40 or blank in position 40 for a and maximum scale of 30.
non-subfield, 0 through 30 in position
41,42.
OR

Defined as numeric on non-definition


specification.
NUMERIC Definition specification. S in position Maximum length of 30 (precision 30)
40 or blank in position 40 for a and maximum scale of 30.
subfield, 0 through 30 in position
41,42.
FLOAT (single precision) Definition specification. F in position
40, length must be 4.

320 DB2 UDB for AS/400 SQL Programming V4R4


Table 33. SQL Data Types Mapped to Typical RPG Declarations (continued)
SQL Data Type RPG Data Type Notes
FLOAT (double precision) Definition specification. F in position
40, length must be 8.
CHAR(n) Definition specification. A or blank in n can be from 1 to 32766.
positions 40 and blanks in position
41,42.
OR

Input field defined without decimal


places.
OR

Calculation result field defined without


decimal places.
CHAR(n) Data structure name with no subfields n can be from 1 to 32766.
in the data structure.
VARCHAR(n) Definition specification. A or blank in n can be from 1 to 32740.
position 40 and VARYING in positions
44-80.
BLOB Not supported Use SQL TYPE IS to declare a BLOB.
CLOB Not supported Use SQL TYPE IS to declare a CLOB.
GRAPHIC(n) Definition specification. G in position n can be 1 to 16383.
40.
OR

Input field defined with G in position


36.
VARGRAPHIC(n) Definition specification. G in position n can be from 1 to 16370.
40 and VARYING in positions 44-80.
DBCLOB Not supported Use SQL TYPE IS to declare a
DBCLOB.
DATE A character field If the format is *USA, *JIS, *EUR, or
OR *ISO, the length must be at least 10. If
the format is *YMD, *DMY, or *MDY,
Definition specification with a D in the length must be at least 8. If the
position 40. format is *JUL, the length must be at
OR least 6.

Input field defined with D in position


36.
TIME A character field Length must be at least 6; to include
OR seconds, length must be at least 8.

Definition specification with a T in


position 40.
OR

Input field defined with T in position


36.

Chapter 16. Coding SQL Statements in ILE RPG for AS/400 Applications 321
Table 33. SQL Data Types Mapped to Typical RPG Declarations (continued)
SQL Data Type RPG Data Type Notes
TIMESTAMP A character field Length must be at least 19; to include
OR microseconds, length must be at least
26. If length is less than 26, truncation
Definition specification with a Z in occurs on the microsecond part.
position 40.
OR

Input field defined with Z in position


36.
DATALINK Not supported

Notes on ILE/RPG 400 Variable Declaration and Usage


Assignment rules
ILE RPG for AS/400 associates precision and scale with all numeric types. ILE RPG
for AS/400 defines numeric operations, assuming the data is in packed format. This
means that operations involving binary variables include an implicit conversion to
packed format before the operation is performed (and back to binary, if necessary).
Data is aligned to the implied decimal point when SQL operations are performed.

Using Indicator Variables


An indicator variable is a binary field with length less then 5 (2 bytes).

An indicator array can be defined by declaring the variable element length of 4,0
and specifying the DIM on the definition specification.

On retrieval, an indicator variable is used to show if its associated host variable has
been assigned a null value. On assignment to a column, a negative indicator
variable is used to indicate that a null value should be assigned.

See the DB2 UDB for AS/400 SQL Reference book for more information on the use
of indicator variables.

Indicator variables are declared in the same way as host variables and the
declarations of the two can be mixed in any way that seems appropriate to the
programmer.

Example
Given the statement:
*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
C/EXEC SQL FETCH CLS_CURSOR INTO :CLSCD,
C+ :DAY :DAYIND,
C+ :BGN :BGNIND,
C+ :END :ENDIND
C/END-EXEC

variables can be declared as follows:


*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
D CLSCD S 7
D DAY S 2B 0

322 DB2 UDB for AS/400 SQL Programming V4R4


D DAYIND S 2B 0
D BGN S 8A
D BGNIND S 2B 0
D END S 8
D ENDIND S 2B 0

SQLDA Example of the SQLDA for a Multiple Row-Area Fetch


*...1....+....2....+....3....+....4....+....5....+....6....+....7....+....8.
C/EXEC SQL INCLUDE SQLDA
C/END-EXEC
DDEPARTMENT DS OCCURS(10)
D DEPTNO 01 03A
D DEPTNM 04 32A
D MGRNO 33 38A
D ADMRD 39 41A
...

DIND_ARRAY DS OCCURS(10)
D INDS 4B 0 DIM(4)
...
C* setup number of sqlda entries and length of the sqlda
C eval sqld = 4
C eval sqln = 4
C eval sqldabc = 336
C*
C* setup the first entry in the sqlda
C*
C eval sqltype = 453
C eval sqllen = 3
C eval sql_var(1) = sqlvar
C*
C* setup the second entry in the sqlda
C*
C eval sqltype = 453
C eval sqllen = 29
C eval sql_var(2) = sqlvar
...
C*
C* setup the forth entry in the sqlda
C*
C eval sqltype = 453
C eval sqllen = 3
C eval sql_var(4) = sqlvar

...
C/EXEC SQL
C+ DECLARE C1 FOR
C+ SELECT *
C+ FROM CORPDATA.DEPARTMENT
C/END-EXEC
...

C/EXEC SQL
C+ FETCH C1 FOR 10 ROWS
C+ USING DESCRIPTOR :SQLDA
C+ INTO :DEPARTMENT:IND_ARRAY
C/END-EXEC

Chapter 16. Coding SQL Statements in ILE RPG for AS/400 Applications 323
324 DB2 UDB for AS/400 SQL Programming V4R4
Chapter 17. Coding SQL Statements in REXX Applications
REXX procedures do not have to be preprocessed. At runtime, the REXX
interpreter passes statements that it does not understand to the current active
command environment for processing. The command environment can be changed
to *EXECSQL to send all unknown statements to the database manager in two
ways:
1. CMDENV parameter on the STRREXPRC CL command
2. address positional parameter on the ADDRESS REXX command

For more information on the STRREXPRC CL command or the ADDRESS REXX


command, see the REXX/400 Programmer’s Guide book.

Using the SQL Communications Area


The fields that make up the SQL Communications Area (SQLCA) are automatically
included by the SQL/REXX interface. An INCLUDE SQLCA statement is not
required and is not allowed. The SQLCODE and SQLSTATE fields of the SQLCA
contain SQL return codes. These values are set by the database manager after
each SQL statement is executed. An application can check the SQLCODE or
SQLSTATE value to determine whether the last SQL statement was successful.

The SQL/REXX interface uses the SQLCA in a manner consistent with the typical
SQL usage. However, the SQL/REXX interface maintains the fields of the SQLCA in
separate variables rather than in a contiguous data area. The variables that the
SQL/REXX interface maintains for the SQLCA are defined as follows:
SQLCODE The primary SQL return code.
SQLERRMC Error and warning message tokens.
SQLERRP Product code and, if there is an error, the name of
the module that returned the error.
SQLERRD.n Six variables (n is a number between 1 and 6)
containing diagnostic information.
SQLWARN.n Eleven variables (n is a number between 0 and 10)
containing warning flags.
SQLSTATE The alternate SQL return code.

Using SQL Descriptor Areas


The following statements require an SQLDA:
EXECUTE...USING DESCRIPTOR descriptor-name
FETCH...USING DESCRIPTOR descriptor-name
OPEN...USING DESCRIPTOR descriptor-name
CALL...USING DESCRIPTOR descriptor-name
DESCRIBE statement-name INTO descriptor-name
DESCRIBE TABLE host-variable INTO descriptor-name

Unlike the SQLCA, more than one SQLDA can be in a procedure, and an SQLDA
can have any valid name. Each SQLDA consists of a set of REXX variables with a
common stem, where the name of the stem is the descriptor-name from the

© Copyright IBM Corp. 1997, 1999 325


appropriate SQL statements. This must be a simple stem; that is, the stem itself
must not contain any periods. The SQL/REXX interface automatically provides the
fields of the SQLDA for each unique descriptor name. An INCLUDE SQLDA
statement is not required and is not allowed.

The SQL/REXX interface uses the SQLDA in a manner consistent with the typical
SQL usage. However, the SQL/REXX interface maintains the fields of the SQLDA in
separate variables rather than in a contiguous data area. See the DB2 UDB for
AS/400 SQL Reference book for more information on the SQLDA.

The following variables are returned to the application after a DESCRIBE, a


DESCRIBE TABLE, or a PREPARE INTO statement:
stem.n.SQLNAME
The name of the nth column in the result table.

The following variables must be provided by the application before an


EXECUTE...USING DESCRIPTOR, an OPEN...USING DESCRIPTOR, a
CALL...USING DESCRIPTOR, or a FETCH...USING DESCRIPTOR statement.
They are returned to the application after a DESCRIBE, a DESCRIBE TABLE, or a
PREPARE INTO statement:
stem.SQLD
Number of variable elements that the SQLDA actually contains.
stem.n.SQLTYPE
An integer representing the data type of the nth element (for example, the
first element is in stem.1.SQLTYPE).
The following data types are not allowed:
400/401 NUL-terminated graphic string
404/405 BLOB host variable
408/409 CLOB host variable
412/413 DBCLOB host variable
460/461 NUL-terminated character string
476/477 PASCAL L-string
496/497 Large integer (where scale is greater than 0)
500/501 Small integer (where scale is greater than 0)
504/505 DISPLAY SIGN LEADING SEPARATE
916/917 BLOB file reference variables
920/921 CLOB file reference variables
924/925 DBCLOB file reference variables
960/961 BLOB locator
964/965 CLOB locator
968/969 DBCLOB locator
stem.n.SQLLEN
If SQLTYPE does not indicate a DECIMAL or NUMERIC data type, the
maximum length of the data contained in stem.n.SQLDATA.

326 DB2 UDB for AS/400 SQL Programming V4R4


stem.n.SQLLEN.SQLPRECISION
If the data type is DECIMAL or NUMERIC, this contains the precision of the
number.
stem.n.SQLLEN.SQLSCALE
If the type is DECIMAL or NUMERIC, this contains the scale of the number.
stem.n.SQLCCSID
The CCSID of the nth column of the data.

The following variables must be provided by the application before an


EXECUTE...USING DESCRIPTOR or an OPEN...USING DESCRIPTOR statement,
and they are returned to the application after a FETCH...USING DESCRIPTOR
statement. They are not used after a DESCRIBE, a DESCRIBE TABLE, or a
PREPARE INTO statement:
stem.n.SQLDATA
This contains the input value supplied by the application, or the output
value fetched by SQL.
This value is converted to the attributes specified in SQLTYPE, SQLLEN,
SQLPRECISION, and SQLSCALE.
stem.n.SQLIND
If the input or output value is null, this is a negative number.

Embedding SQL Statements


An SQL statement can be placed anywhere a REXX command can be placed.

Each SQL statement in a REXX procedure must begin with EXECSQL (in any
combination of uppercase and lowercase letters), followed by either:
v The SQL statement enclosed in single or double quotes, or
v A REXX variable containing the statement. Note that a colon must not precede a
REXX variable when it contains an SQL statement.

For example:
EXECSQL “COMMIT”

is equivalent to:
rexxvar = “COMMIT”
EXECSQL rexxvar

The command follows normal REXX rules. For example, it can optionally be
followed by a semicolon (;) to allow a single line to contain more than one REXX
statement. REXX also permits command names to be included within single quotes,
for example:
'EXECSQL COMMIT'

Chapter 17. Coding SQL Statements in REXX Applications 327


The SQL/REXX interface supports the following SQL statements:

ALTER TABLE EXECUTE


CALL 10 EXECUTE IMMEDIATE
CLOSE FETCH 9
COMMENT ON GRANT
COMMIT INSERT 9, 10
CREATE ALIAS LABEL ON
CREATE COLLECTION LOCK TABLE
CREATE DISTINCT TYPE OPEN
CREATE FUNCTION PREPARE
CREATE INDEX RENAME
CREATE PROCEDURE REVOKE
CREATE TABLE ROLLBACK
CREATE VIEW SET OPTION 11
DECLARE CURSOR 10 SET PATH
DELETE 10 SET TRANSACTION
DESCRIBE SET variable 10
DESCRIBE TABLE UPDATE 10
DROP VALUES INTO 10

The following SQL statements are not supported by the SQL/REXX interface:

BEGIN DECLARE SECTION END DECLARE SECTION


CONNECT FREE LOCATOR
CREATE SCHEMA INCLUDE
DECLARE PROCEDURE RELEASE
DECLARE STATEMENT SELECT INTO
DECLARE VARIABLE SET CONNECTION
DISCONNECT SET RESULT SETS
WHENEVER12

Comments
Neither SQL comments (--) nor REXX comments are allowed in strings representing
SQL statements.

Continuation of SQL Statements


The string containing an SQL statement can be split into several strings on several
lines, separated by commas or concatenation operators, according to standard
REXX usage.

Including Code
Unlike the other host languages, support is not provided for including externally
defined statements.

9. The blocked form of this statement is not supported.


10. These statements cannot be executed directly if they contain host variables; they must be the object of a PREPARE and then an
EXECUTE.
11. The SET OPTION statement can be used in a REXX procedure to change some of the processing options used for running SQL
statements. These options include the commitment control level and date format. See the DB2 UDB for AS/400 SQL Reference
book for more information on the SET OPTION statement.
12. See “Handling Errors and Warnings” on page 329 for more information.

328 DB2 UDB for AS/400 SQL Programming V4R4


Margins
There are no special margin rules for the SQL/REXX interface.

Names
Any valid REXX name not ending in a period (.) can be used for a host variable.
The name must be 64 characters or less.

Variable names should not begin with the characters 'SQL', 'RDI', 'DSN', 'RXSQL',
or 'QRW'.

Nulls
Although the term null is used in both REXX and SQL, the term has different
meanings in the two languages. REXX has a null string (a string of length zero) and
a null clause (a clause consisting only of blanks and comments). The SQL null
value is a special value that is distinct from all non-null values and denotes the
absence of a (non-null) value.

Statement Labels
REXX command statements can be labeled as usual.

Handling Errors and Warnings


The WHENEVER statement is not supported by the SQL/REXX interface. Any of
the following may be used instead:
v A test of the REXX SQLCODE or SQLSTATE variables after each SQL statement
to detect error and warning conditions issued by the database manager, but not
for those issued by the SQL/REXX interface.
v A test of the REXX RC variable after each SQL statement to detect error and
warning conditions. Each use of the EXECSQL command sets the RC variable
to:
0 Statement completed successfully.
+10 A SQL warning occurred.
-10 An SQL error occurred
-100 An SQL/REXX interface error occurred.

This can be used to detect errors and warnings issued by either the database
manager or by the SQL/REXX interface.
v The SIGNAL ON ERROR and SIGNAL ON FAILURE facilities can be used to
detect errors (negative RC values), but not warnings.

Using Host Variables


| REXX does not provide for variable declarations. LOB host variables are not
| supported in REXX. New variables are recognized by their appearance in
| assignment statements. Therefore, there is no declare section, and the BEGIN
| DECLARE SECTION and END DECLARE SECTION statements are not supported.

Chapter 17. Coding SQL Statements in REXX Applications 329


All host variables within an SQL statement must be preceded by a colon (:).

The SQL/REXX interface performs substitution in compound variables before


passing statements to the database manager. For example:
a = 1
b = 2
EXECSQL 'OPEN c1 USING :x.a.b'

causes the contents of x.1.2 to be passed to SQL.

Determining Data Types of Input Host Variables


All data in REXX is in the form of strings. The data type of input host variables (that
is, host variables used in a 'USING host variable' clause in an EXECUTE or OPEN
statement) is inferred by the database manager at run time from the contents of the
variable according to Table 34.

These rules define either numeric, character, or graphic values. A numeric value
can be used as input to a numeric column of any type. A character value can be
used as input to a character column of any type, or to a date, time, or timestamp
column. A graphic value can be used as input to a graphic column of any type.
Table 34. Determining Data Types of Host Variables in REXX
SQL Type SQL Type
Host Variable Contents Assumed Data Type Code Description
Undefined Variable Variable for which a value None Data that is
has not been assigned not valid was
detected.
A string with leading and trailing apostrophes (’) or Varying-length character 448/449 VARCHAR(n)
quotation marks (″), which has length n after removing string
the two delimiters,

or a string with a leading X or x followed by an


apostrophe (’) or quotation mark (″), and a trailing
apostrophe (’) or quotation mark (″). The string has a
length of 2n after removing the X or x and the two
delimiters. Each remaining pair of characters is the
hexadecimal representation of a single character.

or a string of length n, which cannot be recognized as


character, numeric, or graphic through other rules in this
table

330 DB2 UDB for AS/400 SQL Programming V4R4


Table 34. Determining Data Types of Host Variables in REXX (continued)
SQL Type SQL Type
Host Variable Contents Assumed Data Type Code Description
A string with a leading and trailing apostrophe (’) or Varying-length graphic string 464/465 VARGRAPHIC(n)
quotation marks (″) preceded by: 13
v A string that starts with a G, g, N or n. This is followed
by an apostrophe or quote and a shift-out (x’0E’). This
is followed by n graphic characters, each 2 characters
long. The string must end with a shift-in (X’0F’) and an
apostrophe or quote (whichever the string started
with).
v A string with a leading GX, Gx, gX, or gx, followed by
an apostrophe or quote and a shift-out (x’0E’). This is
followed by n graphic characters, each 2 characters
long. The string must end with a shift-in (X’0F’) and an
apostrophe or quote (whichever the string started
with). The string has a length of 4n after removing the
GX and the delimiters. Each remaining group of 4
characters is the hexadecimal representation of a
single graphic character.
A number that is in scientific or engineering notation Floating point 480/481 FLOAT
(that is, followed immediately by an 'E' or 'e', an optional
plus or minus sign, and a series of digits). It can have a
leading plus or minus sign.
A number that includes a decimal point, but no Packed decimal 484/485 DECIMAL(m,n)
exponent,

or a number that does not include a decimal point or an


exponent and is greater than 2147483647 or smaller
than -2147483647.

It can have a leading plus or minus sign. m is the total


number of digits in the number. n is the number of digits
to the left of the decimal point (if any).
A number with neither decimal point nor exponent. It can Signed integers 496/497 INTEGER
have a leading plus or minus sign.

The Format of Output Host Variables


It is not necessary to determine the data type of an output host variable (that is, a
host variable used in an 'INTO host variable' clause in a FETCH statement). Output
values are assigned to host variables as follows:
v Character values are assigned without leading and trailing apostrophes.
v Graphic values are assigned without a leading G or apostrophe, without a trailing
apostrophe, and without shift-out and shift-in characters.
v Numeric values are translated into strings.
v Integer values do not retain any leading zeros. Negative values have a leading
minus sign.
v Decimal values retain leading and trailing zeros according to their precision and
scale. Negative values have a leading minus sign. Positive values do not have a
leading plus sign.

13. The byte immediately following the leading apostrophe is a X'0E' shift-out, and the byte immediately preceding the trailing
apostrophe is a X'0F' shift-in.

Chapter 17. Coding SQL Statements in REXX Applications 331


v Floating-point values are in scientific notation, with one digit to the left of the
decimal place. The 'E' is in uppercase.

Avoiding REXX Conversion


To guarantee that a string is not converted to a number or assumed to be of
graphic type, strings should be enclosed in the following: "'". Simply enclosing the
string in apostrophes does not work. For example:
stringvar = '100'

causes REXX to set the variable stringvar to the string of characters 100 (without
the apostrophes). This is evaluated by the SQL/REXX interface as the number 100,
and it is passed to SQL as such.

On the other hand,


stringvar = “'“100”'”

causes REXX to set the variable stringvar to the string of characters '100' (with the
apostrophes). This is evaluated by the SQL/REXX interface as the string 100, and it
is passed to SQL as such.

Using Indicator Variables


An indicator variable is an integer. On retrieval, an indicator variable is used to
show if its associated host variable was assigned a null value. On assignment to a
column, a negative indicator variable is used to indicate that a null value should be
assigned.

Unlike other languages, a valid value must be specified in the host variable even if
its associated indicator variable contains a negative value.

For more information on indicator variables see the DB2 UDB for AS/400 SQL
Reference book.

332 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 18. Preparing and Running a Program with SQL
Statements
This chapter describes some of the tasks for preparing and running an application
program. The tasks described are:
v Precompiling
v Compiling
v Binding
v Running

Basic Processes of the SQL Precompiler


You must precompile and compile an application program containing embedded
SQL statements before you can run it. 14 Precompiling of such programs is done by
the SQL precompiler. The SQL precompiler scans each statement of the application
program source and does the following:
v Looks for SQL statements and for the definition of host variable names.
The variable names and definitions are used to verify the SQL statements. You
can examine the listing after the SQL precompiler completes processing to see if
any errors occurred.
v Verifies that each SQL statement is valid and free of syntax errors. The
validation procedure supplies error messages in the output listing that help you
correct any errors that occur.
v Validates the SQL statements using the description in the database. During
the precompile, the SQL statements are checked for valid table, view, and
column names. If a specified table or view does not exist, or you are not
authorized to the table or view at the time of the precompile or compile, the
validation is done at run time. If the table or view does not exist at run time, an
error occurs.
Notes:
1. Overrides are processed when retrieving external definitions. For more
information, see the DB2 UDB for AS/400 Database Programming book, and
the Data Management book.
2. You need some authority (at least *OBJOPR) to any tables or views referred
to in the SQL statements in order to validate the SQL statements. The actual
authority required to process any SQL statement is checked at run time. For
more information on any SQL statement, see the DB2 UDB for AS/400 SQL
Reference book.
3. When the RDB parameter is specified on the CRTSQLxxx commands, the
precompiler accesses the specified relational database to obtain the table
and view descriptions.
v Prepares each SQL statement for compilation in the host language. For
most SQL statements, the SQL precompiler inserts a comment and a CALL
statement to one of the SQL interface modules:
– QSQROUTE
– QSQLOPEN
– QSQLCLSE

14. SQL statements in a REXX procedure are not precompiled and compiled.

© Copyright IBM Corp. 1997, 1999 333


– QSQLCMIT
For some SQL statements (for example, DECLARE statements), the SQL
precompiler produces no host language statement except a comment.
v Produces information about each precompiled SQL statement. The
information is stored internally in a temporary source file member, where it is
available for use during the bind process.

To get complete diagnostic information when you precompile, specify either of the
following:
v OPTION(*SOURCE *XREF) for CRTSQLxxx (where xxx=CBL, PLI, or RPG)
v OPTION(*XREF) OUTPUT(*PRINT) for CRTSQLxxx (where xxx=CI, CPPI, CBLI,
or RPGI) or for CVTSQLCPP

Input to the Precompiler


Application programming statements and embedded SQL statements are the
primary input to the SQL precompiler. In PL/I, C, and C++ programs, the SQL
statements must use the margins that are specified in the MARGINS parameter of
the CRTSQLPLI, CRTSQLCI, CRTSQLCPPI, and CVTSQLCPP commands.

The SQL precompiler assumes that the host language statements are syntactically
correct. If the host language statements are not syntactically correct, the
precompiler may not correctly identify SQL statements and host variable
declarations. There are limits on the forms of source statements that can be passed
through the precompiler. Literals and comments that are not accepted by the
application language compiler, can interfere with the precompiler source scanning
process and cause errors.

You can use the SQL INCLUDE statement to get secondary input from the file that
is specified by the INCFILE parameter of the CRTSQLxxx 15 and CVTSQLCPP
command. The SQL INCLUDE statement causes input to be read from the specified
member until it reaches the end of the member. The included member may not
contain other precompiler INCLUDE statements, but can contain both application
program and SQL statements.

Another preprocessor may process source statements before the SQL precompiler.
However, any preprocessor run before the SQL precompile must be able to pass
through SQL statements.

If mixed DBCS constants are specified in the application program source, the
source file must be a mixed CCSID.

You can specify many of the precompiler options in the input source member by
using the SQL SET OPTION statement. See the DB2 UDB for AS/400 SQL
Reference book for the SET OPTION syntax.

Source File CCSIDs


The SQL precompiler will read the source records by using the CCSID of the
source file. When processing SQL INCLUDE statements, the include source will be

15. The xxx in this command refers to the host language indicators: CBL for the COBOL for AS/400 language, CBLI for the ILE
COBOL for AS/400 language, PLI for the AS/400 PL/I language, CI for the ILE C for AS/400 language, RPG for the RPG for
AS/400 language, RPGI for the ILE RPG for AS/400 language, CPPI for the ILE C++/400 language.

334 DB2 UDB for AS/400 SQL Programming V4R4


converted to the CCSID of the original source file if necessary. If the include source
cannot be converted to the CCSID of the original source file, an error will occur.

The SQL precompiler will process SQL statements using the source CCSID. This
affects variant characters the most. For example, the not sign (¬) is located at 'BA'X
in CCSID 500. Prior to Version 2 Release 1.1, SQL looked for the not sign (¬) in the
location '5F'X in CCSID 37. This means that if the CCSID of your source file is 500,
SQL expects the not sign (¬) to be located at 'BA'X.

If the source file CCSID is 65535, SQL processes variant characters as if they had
a CCSID of 37. This means that SQL looks for the not sign (¬) at '5F'X.

Output from the Precompiler


The following sections describe the various kinds of output supplied by the
precompiler.

Listing
The output listing is sent to the printer file that is specified by the PRTFILE
parameter of the CRTSQLxxx or CVTSQLCPP command. The following items are
written to the printer file:
v Precompiler options
Options specified in the CRTSQLxxx or CVTSQLCPP command.
v Precompiler source
This output supplies precompiler source statements with the record numbers that
are assigned by the precompiler, if the listing option is in effect.
v Precompiler cross-reference
If *XREF was specified in the OPTION parameter, this output supplies a
cross-reference listing. The listing shows the precompiler record numbers of SQL
statements that contain the referred to host names and column names.
v Precompiler diagnostics
This output supplies diagnostic messages, showing the precompiler record
numbers of statements in error.
The output to the printer file will use a CCSID value of 65535. The data will not
be converted when it is written to the printer file.

Temporary Source File Members


Source statements processed by the precompiler are written to an output source file
that is specified on the CRTSQLxx or CVTSQLCPP command in the TOSRCFILE
parameter. The default file is QSQLTEMP (QSQLTEMP1 for ILE RPG for AS/400) in
the QTEMP library. In your precompiler-changed source code, SQL statements
have been converted to comments and calls to the SQL runtime. The name of the
output source file member is the same as the name specified in the PGM or OBJ
parameter of the CRTSQLxxx or CVTSQLCPP command. This member cannot be
changed before being used as input to the compiler. When SQL creates the output
source file, it uses the CCSID value of the source file as the CCSID value for the
new file.

If the precompile uses QSQLTEMP or QSQLTEMP1 in QTEMP, the file can be


moved to a permanent library after the precompile if you want to compile at a later
time. You cannot change the records of the source member, or the attempted
compile fails.

Chapter 18. Preparing and Running a Program with SQL Statements 335
The SQL precompiler uses the CRTSRCPF command to create the output source
file. If the defaults for this command have changed, then the results may be
unpredictable. If the source file is created by the user, not the SQL precompiler, the
file’s attributes may be different as well. It is recommended that the user allow SQL
to create the output source file. Once it has been created by SQL, it can be reused
on later precompiles.

Sample Precompiler Output


The precompiler output can provide information about your program source. To
generate the listing:
v For non-ILE precompilers, specify the *SOURCE (*SRC) and *XREF options on
the OPTION parameter of the CRTSQLxxx command.
v For ILE precompilers, specify OPTION(*XREF) and OUTPUT(*PRINT) on the
CRTSQLxxx or CVTSQLCPP command.

The format of the precompiler output is:

5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLTEST1 04/01/98 11:14:21 Page 1
Source type...............COBOL
Program name..............CORPDATA/CBLTEST1
Source file...............CORPDATA/SRC
Member....................CBLTEST1
To source file............QTEMP/QSQLTEMP
„1…Options...................*SRC *XREF *SQL
Target release............V4R4M0
INCLUDE file..............*LIBL/*SRCFILE
Commit....................*CHG
Allow copy of data........*YES
Close SQL cursor..........*ENDPGM
Allow blocking............*READ
Delay PREPARE.............*NO
Generation level..........10
Printer file..............*LIBL/QSYSPRT
Date format...............*JOB
Date separator............*JOB
Time format...............*HMS
Time separator ...........*JOB
Replace...................*YES
Relational database.......*LOCAL
User .....................*CURRENT
RDB connect method........*DUW
Default Collection........*NONE
Package name..............*PGMLIB/*PGM
Dynamic User Profile......*USER
User Profile..............*NAMING
Sort Sequence.............*JOB
Language ID...............*JOB
IBM SQL flagging..........*NOFLAG
ANS flagging..............*NONE
Text......................*SRCMBRTXT
Source file CCSID.........65535
Job CCSID.................65535
„2… Source member changed on 04/01/98 10:16:44

„1… A list of the options you specified when the SQL precompiler was called.
„2… The date the source member was last changed.

Figure 11. Sample COBOL Precompiler Output Format (Part 1 of 5)

336 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLTEST1 04/01/98 11:14:21 Page 2
„1…Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 „2… SEQNBR „3…Last Change

1 IDENTIFICATION DIVISION. 100


2 PROGRAM-ID. CBLTEST1. 200
3 ENVIRONMENT DIVISION. 300
4 CONFIGURATION SECTION. 400
5 SOURCE-COMPUTER. IBM-AS400. 500
6 OBJECT-COMPUTER. IBM-AS400. 600
7 INPUT-OUTPUT SECTION. 700
8 FILE-CONTROL. 800
9 SELECT OUTFILE, ASSIGN TO PRINTER-QPRINT, 900
10 FILE STATUS IS FSTAT. 1000
11 DATA DIVISION. 1100
12 FILE SECTION. 1200
13 FD OUTFILE 1300
14 DATA RECORD IS REC-1, 1400
15 LABEL RECORDS ARE OMITTED. 1500
16 01 REC-1. 1600
17 05 CC PIC X. 1700
18 05 DEPT-NO PIC X(3). 1800
19 05 FILLER PIC X(5). 1900
20 05 AVERAGE-EDUCATION-LEVEL PIC ZZZ. 2000
21 05 FILLER PIC X(5). 2100
22 05 AVERAGE-SALARY PIC ZZZZ9.99. 2200
23 01 ERROR-RECORD. 2300
24 05 CC PIC X. 2400
25 05 ERROR-CODE PIC S9(5). 2500
26 05 ERROR-MESSAGE PIC X(70). 2600
27 WORKING-STORAGE SECTION. 2700
28 EXEC SQL 2800
29 INCLUDE SQLCA 2900
30 END-EXEC. 3000
31 77 FSTAT PIC XX. 3100
32 01 AVG-RECORD. 3200
33 05 WORKDEPT PIC X(3). 3300
34 05 AVG-EDUC PIC S9(4) USAGE COMP-4. 3400
35 05 AVG-SALARY PIC S9(6)V99 COMP-3. 3500
36 PROCEDURE DIVISION. 3600
37 *************************************************************** 3700
38 * This program will get the average education level and the * 3800
39 * average salary by department. * 3900
40 *************************************************************** 4000
41 A000-MAIN-PROCEDURE. 4100
42 OPEN OUTPUT OUTFILE. 4200
43 *************************************************************** 4300
44 * Set-up WHENEVER statement to handle SQL errors. * 4400
45 *************************************************************** 4500
46 EXEC SQL 4600
47 WHENEVER SQLERROR GO TO B000-SQL-ERROR 4700
48 END-EXEC. 4800
49 *************************************************************** 4900
50 * Declare cursor * 5000
51 *************************************************************** 5100
52 EXEC SQL 5200
53 DECLARE CURS CURSOR FOR 5300
54 SELECT WORKDEPT, AVG(EDLEVEL), AVG(SALARY) 5400
55 FROM CORPDATA.EMPLOYEE 5500
56 GROUP BY WORKDEPT 5600
57 END-EXEC. 5700
58 *************************************************************** 5800
59 * Open cursor * 5900
60 *************************************************************** 6000
61 EXEC SQL 6100
62 OPEN CURS 6200
63 END-EXEC. 6300

„1… Record number assigned by the precompiler when it reads the source record. Record numbers are
used to identify the source record in error messages and SQL run-time processing.
„2… Sequence number taken from the source record. The sequence number is the number seen when
you use the source entry utility (SEU) to edit the source member.
„3… Date when the source record was last changed. If Last is blank, it indicates that the record has not
been changed since it was created.

Figure 11. Sample COBOL Precompiler Output Format (Part 2 of 5)

Chapter 18. Preparing and Running a Program with SQL Statements 337
5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLTEST1 04/01/98 11:14:21 Page 3
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
64 *************************************************************** 6400
65 * Fetch all result rows * 6500
66 *************************************************************** 6600
67 PERFORM A010-FETCH-PROCEDURE THROUGH A010-FETCH-EXIT 6700
68 UNTIL SQLCODE IS = 100. 6800
69 *************************************************************** 6900
70 * Close cursor * 7000
71 *************************************************************** 7100
72 EXEC SQL 7200
73 CLOSE CURS 7300
74 END-EXEC. 7400
75 CLOSE OUTFILE. 7500
76 STOP RUN. 7600
77 *************************************************************** 7700
78 * Fetch a row and move the information to the output record. * 7800
79 *************************************************************** 7900
80 A010-FETCH-PROCEDURE. 8000
81 MOVE SPACES TO REC-1. 8100
82 EXEC SQL 8200
83 FETCH CURS INTO :AVG-RECORD 8300
84 END-EXEC. 8400
85 IF SQLCODE IS = 0 8500
86 MOVE WORKDEPT TO DEPT-NO 8600
87 MOVE AVG-SALARY TO AVERAGE-SALARY 8700
88 MOVE AVG-EDUC TO AVERAGE-EDUCATION-LEVEL 8800
89 WRITE REC-1 AFTER ADVANCING 1 LINE. 8900
90 A010-FETCH-EXIT. 9000
91 EXIT. 9100
92 *************************************************************** 9200
93 * An SQL error occurred. Move the error number to the error * 9300
94 * record and stop running. * 9400
95 *************************************************************** 9500
96 B000-SQL-ERROR. 9600
97 MOVE SPACES TO ERROR-RECORD. 9700
98 MOVE SQLCODE TO ERROR-CODE. 9800
99 MOVE "AN SQL ERROR HAS OCCURRED" TO ERROR-MESSAGE. 9900
100 WRITE ERROR-RECORD AFTER ADVANCING 1 LINE. 10000
101 CLOSE OUTFILE. 10100
102 STOP RUN. 10200
* * * * * E N D O F S O U R C E * * * * *

Figure 11. Sample COBOL Precompiler Output Format (Part 3 of 5)

338 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLTEST1 04/01/98 11:14:21 Page 4
CROSS REFERENCE
„1… „2… „3…
Data Names Define Reference
AVERAGE-EDUCATION-LEVEL 20 IN REC-1
AVERAGE-SALARY 22 IN REC-1
AVG-EDUC 34 SMALL INTEGER PRECISION(4,0) IN AVG-RECORD
AVG-RECORD 32 STRUCTURE
83
AVG-SALARY 35 DECIMAL(8,2) IN AVG-RECORD
BIRTHDATE 55 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
BONUS 55 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
B000-SQL-ERROR **** LABEL
47
CC 17 CHARACTER(1) IN REC-1
CC 24 CHARACTER(1) IN ERROR-RECORD
COMM 55 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
CORPDATA **** „4… COLLECTION
„5… 55
CURS 53 CURSOR
62 73 83
DEPT-NO 18 CHARACTER(3) IN REC-1
EDLEVEL **** COLUMN
54
„6…
EDLEVEL 55 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMPLOYEE **** TABLE IN CORPDATA „7…
55
EMPNO 55 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
ERROR-CODE 25 NUMERIC(5,0) IN ERROR-RECORD
ERROR-MESSAGE 26 CHARACTER(70) IN ERROR-RECORD
ERROR-RECORD 23 STRUCTURE
FIRSTNME 55 VARCHAR(12) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
FSTAT 31 CHARACTER(2)
HIREDATE 55 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
JOB 55 CHARACTER(8) COLUMN IN CORPDATA.EMPLOYEE
LASTNAME 55 VARCHAR(15) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
MIDINIT 55 CHARACTER(1) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
PHONENO 55 CHARACTER(4) COLUMN IN CORPDATA.EMPLOYEE
REC-1 16
SALARY **** COLUMN
54
SALARY 55 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE

„1… Data names are the symbolic names used in source statements.
„2… The define column specifies the line number at which the name is defined. The line number is
generated by the SQL precompiler. **** means that the object was not defined or the precompiler
did not recognize the declarations.
„3… The reference column contains two types of information:
v What the symbolic name is defined as „4…
v The line numbers where the symbolic name occurs „5…

If the symbolic name refers to a valid host variable, the data-type „6… or data-structure „7… is also
noted.

Figure 11. Sample COBOL Precompiler Output Format (Part 4 of 5)

5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLTEST1 04/01/98 11:14:21 Page 5
CROSS REFERENCE
SEX 55 CHARACTER(1) COLUMN IN CORPDATA.EMPLOYEE
WORKDEPT 33 CHARACTER(3) IN AVG-RECORD
WORKDEPT **** COLUMN
54 56
WORKDEPT 55 CHARACTER(3) COLUMN IN CORPDATA.EMPLOYEE
No errors found in source
102 Source records processed
* * * * * E N D O F L I S T I N G * * * * *

Figure 11. Sample COBOL Precompiler Output Format (Part 5 of 5)

Chapter 18. Preparing and Running a Program with SQL Statements 339
Non-ILE Precompiler Commands
DB2 UDB Query Manager and SQL Development Kit includes non-ILE precompiler
commands for the following host languages: CRTSQLCBL (for COBOL for AS/400),
CRTSQLPLI (for AS/400 PL/I), and CRTSQLRPG (for RPG III, which is part of RPG
for AS/400). Some options only apply to certain languages. For example, the
options *APOST and *QUOTE are unique to COBOL. They are not included in the
commands for the other languages. Refer to “Appendix D. DB2 UDB for AS/400 CL
Command Descriptions” on page 645 for more information.

Compiling a Non-ILE Application Program


The SQL precompiler automatically calls the host language compiler after the
successful completion of a precompile, unless *NOGEN is specified. The
CRTxxxPGM command is run specifying the program name, source file name,
precompiler created source member name, text, and USRPRF.

Within these languages, the following parameters are passed:


v For COBOL, the *QUOTE or *APOST is passed on the CRTCBLPGM command.
v For RPG and COBOL, SAAFLAG (*FLAG) is passed on the CRTxxxPGM
command.
v For RPG and COBOL, the SRTSEQ and LANGID parameter from the
CRTSQLxxx command is specified on the CRTxxxPGM command.
v For RPG and COBOL, the CVTOPT (*DATETIME *VARCHAR) is always
specified on the CRTxxxPGM command.
v For COBOL and RPG, the TGTRLS parameter value from the CRTSQLxxx
command is specified on the CRTxxxPGM command. TGTRLS is not specified
on the CRTPLIPGM command. The program can be saved or restored to the
level specified on the TGTRLS parameter of the CRTSQLPLI command.
v For PL/I, the MARGINS are set in the temporary source file.
v For all languages, the REPLACE parameter from the CRTSQLxxx command is
specified on the CRTxxxPGM command.
If a package is created as part of the precompile process, the REPLACE
parameter value from the CRTSQLxxx command is specified on the
CRTSQLPKG command.
v For all languages, if USRPRF(*USER) or system naming (*SYS) with
USRPRF(*NAMING) is specified, then USRPRF(*USER) is specified on the
CRTxxxPGM command. If USRPRF(*OWNER) or SQL naming (*SQL) with
USRPRF(*NAMING) is specified, then USRPRF(*OWNER) is specified on the
CRTxxxPGM command.
Defaults are used for all other parameters with CRTxxxPGM commands.

You can interrupt the call to the host language compiler by specifying *NOGEN on
the OPTION parameter of the precompiler command. *NOGEN specifies that the
host language compiler will not be called. Using the object name in the CRTSQLxxx
command as the member name, the precompiler created the source member in the
output source file (specified as the TOSRCFILE parameter on the CRTSQLxxx
command). You now can explicitly call the host language compilers, specify the
source member in the output source file, and change the defaults. If the precompile
and compile were done as separate steps, the CRTSQLPKG command can be
used to create the SQL package for a distributed program.

340 DB2 UDB for AS/400 SQL Programming V4R4


Note: You must not change the source member in QTEMP/QSQLTEMP prior to
issuing the CRTxxxPGM command or the compile will fail.

ILE Precompiler Commands


In the DB2 UDB Query Manager and SQL Development Kit, the following ILE
precompiler commands exist: CRTSQLCI, CRTSQLCBLI, CRTSQLRPGI,
CRTSQLCPPI, and CVTSQLCPP. There is a precompiler command for each of the
host languages: ILE C for AS/400, ILE COBOL for AS/400, and ILE RPG for
AS/400. Separate commands, by language, let you specify the required parameters
and take the default for the remaining parameters. The defaults are applicable only
to the language you are using. For example, the options *APOST and *QUOTE are
unique to COBOL. They are not included in the commands for the other languages.
Refer to “Appendix D. DB2 UDB for AS/400 CL Command Descriptions” on page
645 for more information.

Compiling an ILE Application Program


The SQL precompiler automatically calls the host language compiler after the
successful completion of a precompile for the CRTSQLxxx commands, unless
*NOGEN is specified. If the *MODULE option is specified, the SQL precompiler
issues the CRTxxxMOD command to create the module. If the *PGM option is
specified, the SQL precompiler issues the CRTBNDxxx command to create the
program. If the *SRVPGM option is specified, the SQL precompiler issues the
CRTxxxMOD command to create the module, followed by the Create Service
Program (CRTSRVPGM) command to create the service program. The
CRTSQLCPPI command only create *MODULE objects. The CVTSQLCPP never
creates an object.

Within these languages, the following parameters are passed:


v If DBGVIEW(*SOURCE) is specified on the CRTSQLxxx command, then
DBGVIEW(*ALL) is specified on both the CRTxxxMOD and CRTBNDxxx
commands.
v If OUTPUT(*PRINT) is specified on the CRTSQLxxx command, it is passed on
both the CRTxxxMOD and CRTBNDxxx commands.
If OUTPUT(*NONE) is specified on the CRTSQLxxx command, it is not specified
on either the CRTxxxMOD command or the CRTBNDxxx command.
v The TGTRLS parameter value from the CRTSQLxxx command is specified on
the CRTxxxMOD, CRTBNDxxx, and Create Service Program (CRTSRVPGM)
commands.
v The REPLACE parameter value from the CRTSQLxxx command is specified on
the CRTxxxMOD, CRTBNDxxx, and CRTSRVPGM commands.
If a package is created as part of the precompile process, the REPLACE
parameter value from the CRTSQLxxx command is specified on the
CRTSQLPKG command.
v If OBJTYPE is either *PGM or *SRVPGM, and USRPRF(*USER) or system
naming (*SYS) with USRPRF(*NAMING) is specified, USRPRF(*USER) is
specified on the CRTBNDxxx or the CRTSRVPGM commands.
If OBJTYPE is either *PGM or *SRVPGM, and USRPRF(*OWNER) or SQL
naming (*SQL) with USRPRF(*NAMING) is specified, USRPRF(*OWNER) is
specified on the CRTBNDxxx or the CRTSRVPGM commands.
v For C and C++, the MARGINS are set in the temporary source file.

Chapter 18. Preparing and Running a Program with SQL Statements 341
v For COBOL, the *QUOTE or *APOST is passed on the CRTBNDCBL or the
CRTCBLMOD commands.
v FOR RPG and COBOL, the SRTSEQ and LANGID parameter from the
CRTSQLxxx command is specified on the CRTxxxMOD and CRTBNDxxx
commands.
| v For COBOL, CVTOPT(*VARCHAR *DATETIME *PICGGRAPHIC *FLOAT *DATE
| *TIME *TIMESTAMP) is always specified on the CRTCBLMOD and CRTBNDCBL
| commands.
v For RPG, if OPTION(*CVTDT) is specified, then CVTOPT(*DATETIME) is
specified on the CRTRPGMOD and CRTBNDRPG commands.

You can interrupt the call to the host language compiler by specifying *NOGEN on
the OPTION parameter of the precompiler command. *NOGEN specifies that the
host language compiler is not called. Using the specified program name in the
CRTSQLxxx command as the member name, the precompiler creates the source
member in the output source file (TOSRCFILE parameter). You can now explicitly
call the host language compilers, specify the source member in the output source
file, and change the defaults. If the precompile and compile were done as separate
steps, the CRTSQLPKG command can be used to create the SQL package for a
distributed program.

If the program or service program is created later, the USRPRF parameter may not
be set correctly on the CRTBNDxxx, Create Program (CRTPGM), or Create Service
Program (CRTSRVPGM) command. The SQL program runs predictably only after
the USRPRF parameter is corrected. If system naming is used, then the USRPRF
parameter must be set to *USER. If SQL naming is used, then the USRPRF
parameter must be set to *OWNER.

Precompiling for the VisualAge C++ for OS/400 Compiler


The SQL precompiler for VisualAge C++ for OS/400 is invoked using the
CVTSQLCPP CL command. This precompiler is different than the other language
precompilers since it does not have an option to generate the module or program
object. Since the precompiler runs on the AS/400 and the compiler runs on the
workstation, the two steps must be run independently.

The precompile and compile should be done following these steps:


| 1. Make sure both the base and option one are loaded for the product.
2. Make sure that the environment is set up to run the compiler and precompiler:
v Set EBCDIC/ASCII conversion for file extensions .h and .mbr in Client
Access.
v Map the AS/400 to a workstation drive. In this discussion, it is assumed that
the x drive is mapped to the AS/400 system.
v Ensure you have a connection established to the AS/400 using the following
command:
CTTCONN /h<as400name>
3. If your source is on the workstation, issue the following command:
CTTCRSQX myapp.sqx x mylib/myfile/myapp

This command copies myapp.sqx (your source) to the AS/400 into the
qsys.lib/mylib.lib/myfile.file/myapp.mbr directory. This is the same as the AS/400
file system MYLIB/MYFILE (MYAPP) member.

342 DB2 UDB for AS/400 SQL Programming V4R4


4. Run the SQL precompiler on the AS/400 for the source member. This is the
CVTSQLCPP CL command. You can also do this from the workstation by using
the CTTHCMD command.
5. Copy the output source file member containing the converted SQL to the
workstation:
CTTCRCPP mylib/mytosrcfile/myapp x myapp.cpp

This creates a file called myapp.cpp on the workstation.

Alternately, you can leave the source on the AS/400 and run the compiler
against it there.
6. Run the C++ compiler and create the final module or program. If the output
source member is still on the AS/400:
iccas /c x:\qsys.lib\mylib.lib\mytosrcfile.file\myapp.mbr

If the source member is on the workstation:


iccas -c myapp.cpp

Note that the program must be created on the AS/400 where the precompile
was run since there is some additional SQL information that was created by the
precompiler that is needed for the final executable object.

Interpreting Application Program Compile Errors


Attention: If you separate precompile and compile steps, and the source program
refers to externally described files, the referred to files must not be changed
between precompile and compile. Otherwise, results that are not predictable may
occur because the changes to the field definitions are not changed in the temporary
source member.

Examples of externally described files are:


v COPY DDS in COBOL
v %INCLUDE in PL/I
v #pragma mapinc and #include in C or C++
v Data structures in RPG

When the SQL precompiler does not recognize host variables, try compiling the
source. The compiler will not recognize the EXEC SQL statements, ignore these
errors. Verify that the compiler interprets the host variable declaration as defined by
the SQL precompiler for that language.

Error and Warning Messages during a Compile


The conditions described in the following paragraphs could produce an error or
warning message during an attempted compile process.

During a PL/I, C, or C++ Compile


If EXEC SQL starts before the left margin (as specified with the MARGINS
parameter, the default), the SQL precompiler will not recognize the statement as an
SQL statement. Consequently, it will be passed as is to the compiler.

Chapter 18. Preparing and Running a Program with SQL Statements 343
During a COBOL Compile
If EXEC SQL starts before column 12, the SQL precompiler will not recognize the
statement as an SQL statement. Consequently, it will be passed as is to the
compiler.

During an RPG Compile


If EXEC SQL is not coded in positions 8 through 16, and preceded with the ’/’
character in position 7, the SQL precompiler will not recognize the statement as an
SQL statement. Consequently, it will be passed as is to the compiler.

For more information, see the specific programming examples in Chapter 12.
Coding SQL Statements in C and C++ Applications, through Chapter 17. Coding
SQL Statements in REXX Applications.

Binding an Application
Before you can run your application program, a relationship between the program
and any specified tables and views must be established. This process is called
binding. The result of binding is an access plan.

The access plan is a control structure that describes the actions necessary to
satisfy each SQL request. An access plan contains information about the program
and about the data the program intends to use.

For a nondistributed SQL program, the access plan is stored in the program. For a
distributed SQL program (where the RDB parameter was specified on the
CRTSQLxxx or CVTSQLCPP commands), the access plan is stored in the SQL
package at the specified relational database.

SQL automatically attempts to bind and create access plans when the program
object is created. For non-ILE compiles, this occurs as the result of a successful
CRTxxxPGM. For ILE compiles, this occurs as the result of a successful
CRTBNDxxx, CRTPGM, or CRTSRVPGM command. If DB2 UDB for AS/400
detects at run time that an access plan is not valid (for example, the referenced
tables are in a different library) or detects that changes have occurred to the
database that may improve performance (for example, the addition of indexes), a
new access plan is automatically created. Binding does three things:
1. It revalidates the SQL statements using the description in the database.
During the bind process, the SQL statements are checked for valid table, view,
and column names. If a specified table or view does not exist at the time of the
precompile or compile, the validation is done at run time. If the table or view
does not exist at run time, a negative SQLCODE is returned.
2. It selects the index needed to access the data your program wants to
process. In selecting an index, table sizes, and other factors are considered,
when it builds an access plan. It considers all indexes available to access the
data and decides which ones (if any) to use when selecting a path to the data.
3. It attempts to build access plans. If all the SQL statements are valid, the bind
process then builds and stores access plans in the program.

If the characteristics of a table or view your program accesses have changed, the
access plan may no longer be valid. When you attempt to run a program that
contains an access plan that is not valid, the system automatically attempts to
rebuild the access plan. If the access plan cannot be rebuilt, a negative SQLCODE

344 DB2 UDB for AS/400 SQL Programming V4R4


is returned. In this case, you might have to change the program’s SQL statements
and reissue the CRTSQLxxx or CVTSQLCPP command to correct the situation.

For example, if a program contains an SQL statement that refers to COLUMNA in


TABLEA and the user deletes and recreates TABLEA so that COLUMNA no longer
exists, when you call the program, the automatic rebind will be unsuccessful
because COLUMNA no longer exists. In this case you must change the program
source and reissue the CRTSQLxxx command.

Program References
All collections, tables, views, SQL packages, and indexes referenced in SQL
statements in an SQL program are placed in the object information repository (OIR)
of the library when the program is created.

You can use the CL command Display Program References (DSPPGMREF) to


display all object references in the program. If the SQL naming convention is used,
the library name is stored in the OIR in one of three ways:
1. If the SQL name is fully qualified, the collection name is stored as the name
qualifier.
2. If the SQL name is not fully qualified and the DFTRDBCOL parameter is not
specified, the authorization ID of the statement is stored as the name qualifier.
3. If the SQL name is not fully qualified and the DFTRDBCOL parameter is
specified, the collection name specified on the DFTRDBCOL parameter is
stored as the name qualifier.
If the system naming convention is used, the library name is stored in the OIR in
one of three ways:
1. If the object name is fully qualified, the library name is stored as the name
qualifier.
2. If the object is not fully qualified and the DFTRDBCOL parameter is not
specified, *LIBL is stored.
3. If the SQL name is not fully qualified and the DFTRDBCOL parameter is
specified, the collection name specified on the DFTRDBCOL parameter is
stored as the name qualifier.

Displaying Precompiler Options


When the SQL application program is successfully compiled, the Display Module
(DSPMOD), the Display Program (DSPPGM), or the Display Service Program
(DSPSRVPGM) command can be used to determine some of the options that were
specified on the SQL precompile. This information may be needed when the source
of the program has to be changed. These same SQL precompiler options can then
be specified on the CRTSQLxxx or CVTSQLCPP command when the program is
compiled again.

The Print SQL Information (PRTSQLINF) command can also be used to determine
some of the options that were specified on the SQL precompile.

Chapter 18. Preparing and Running a Program with SQL Statements 345
Running a Program with Embedded SQL
Running a host language program with embedded SQL statements, after the
precompile and compile have been successfully done, is the same as running any
host program. Type:
CALL pgm-name

on the system command line. For more information on running programs, see the
| CL Programming book.

| Note: After installing a new release, users may encounter message CPF2218 in
| QHST using any Structured Query Language (SQL) program if the user does
| not have *CHANGE authority to the program. Once a user with *CHANGE
| authority calls the program, the access plan is updated and the message will
| be issued.

| OS/400 DDM Considerations


SQL does not support remote file access through DDM (distributed data
management) files. SQL does support remote access through DRDA (Distributed
Relational Database Architecture.)

Override Considerations
You can use overrides (specified by the OVRDBF command) to direct a reference
to a different table or view or to change certain operational characteristics of the
program or SQL Package. The following parameters are processed if an override is
specified:
TOFILE
MBR
SEQONLY
INHWRT
WAITRCD
All other override parameters are ignored. Overrides of statements in SQL
packages are accomplished by doing both of the following:
1. Specifying the OVRSCOPE(*JOB) parameter on the OVRDBF command
2. Sending the command to the application server by using the Submit Remote
Command (SBMRMTCMD) command

To override tables and views that are created with long names, you can create an
override using the system name that is associated with the table or view. When the
long name is specified in an SQL statement, the override is found using the
corresponding system name.

An alias is actually created as a DDM file. You can create an override that refers to
an alias name (DDM file). In this case, an SQL statement that refers to the file that
has the override actually uses the file to which the alias refers.

For more information on overrides, see the DB2 UDB for AS/400 Database
Programming book, and the Data Management book.

346 DB2 UDB for AS/400 SQL Programming V4R4


SQL Return Codes
A list of SQL return codes is provided in Appendix B. SQLCODEs and SQLSTATEs.

Chapter 18. Preparing and Running a Program with SQL Statements 347
348 DB2 UDB for AS/400 SQL Programming V4R4
Chapter 19. Using Interactive SQL
This chapter describes how to use interactive SQL to run SQL statements and use
the prompt function. Overview information and tips on using interactive SQL are
provided. If you want to learn how to use SQL, you should see Chapter 2. Getting
Started with SQL. Special considerations for using interactive SQL with a remote
connection are covered in “Accessing Remote Databases with Interactive SQL” on
page 359.

Basic Functions of Interactive SQL


Interactive SQL allows the programmer or database administrator to quickly and
easily define, update, delete, or look at data for testing, problem analysis, and
database maintenance. A programmer, using interactive SQL, can insert rows into a
table and test the SQL statements before running them in an application program. A
database administrator can use interactive SQL to grant or revoke privileges, create
or drop collections, tables, or views, or select information from system catalog
tables.

After an interactive SQL statement is run, a completion message or an error


message is displayed. In addition, status messages are normally displayed during
long-running statements.

You can see help on a message by positioning the cursor on the message and
pressing F1=Help.

The basic functions supplied by interactive SQL are:


v The statement entry function allows you to:
– Type in an interactive SQL statement and run it.
– Retrieve and edit statements.
– Prompt for SQL statements.
– Page through previous statements and messages.
– Call session services.
– Invoke list selection function.
– Exit interactive SQL.
v The prompt function allows you to type either a complete SQL statement or a
partial SQL statement, press F4=Prompt, and then be prompted for the syntax of
the statement. It also allows you to press F4 to get a menu of all SQL
statements. From this menu, you can select a statement and be prompted for the
syntax of the statement.
v The list selection function allows you to select from lists of your authorized
relational databases, collections, tables, views, columns, constraints, or SQL
packages.
The selections you make from the lists can be inserted into the SQL statement at
the cursor position.
v The session services function allows you to:
– Change session attributes.
– Print the current session.
– Remove all entries from the current session.

© Copyright IBM Corp. 1997, 1999 349


– Save the session in a source file.

Starting Interactive SQL


You can start using interactive SQL by typing STRSQL on an AS/400 command line.
For a complete description of the command and its parameters, see Appendix D.
DB2 UDB for AS/400 CL Command Descriptions.

The Enter SQL Statements display appears. This is the main interactive SQL
display. From this display, you can enter SQL statements and use:
v F4=prompt
v F13=Session services
v F16=Select collections
v F17=Select tables
v F18=Select columns
Enter SQL Statements

Type SQL statement, press Enter.


Current connection is to relational database rdjacque.
===>_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________

Bottom
F3=Exit F4=Prompt F6=Insert line F9=Retrieve F10=Copy line
F12=Cancel F13=Services F24=More keys

Press F24=More keys to view the remaining function keys.


_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________

Bottom

F14=Delete line F15=Split line F16=Select collections (libraries)


F17=Select tables F18=Select columns F24=More keys
(files) (fields)

Note: If you are using the system naming convention, the names in parentheses
appear instead of the names shown above.

An interactive session consists of:


v Parameter values you specified for the STRSQL command .
v SQL statements you entered in the session along with corresponding messages
that follow each SQL statement

350 DB2 UDB for AS/400 SQL Programming V4R4


v Values of any parameters you changed using the session services function
v List selections you have made

Interactive SQL supplies a unique session-ID consisting of your user ID and the
current work station ID. This session-ID concept allows multiple users with the
same user ID to use interactive SQL from more than one work station at the same
time. Also, more than one interactive SQL session can be run from the same work
station at the same time from the same user ID.

If an SQL session exists and is being re-entered, any parameters specified on the
STRSQL command are ignored. The parameters from the existing SQL session are
used.

Using Statement Entry Function


The statement entry function is the function you first enter when selecting
interactive SQL. You return to the statement entry function after processing each
interactive SQL statement.

In the statement entry function, you type or prompt for the entire SQL statement
and then submit it for processing by pressing the Enter key.

Typing Statements
The statement you type on the command line can be one or more lines long. You
cannot type comments for the SQL statement in interactive SQL. When the
statement has been processed, the statement and the resulting message are
moved upward on the display. You can then enter another statement.

If a statement is recognized by SQL but contains a syntax error, the statement and
the resulting text message (syntax error) are moved upward on the display. In the
input area, a copy of the statement is shown with the cursor positioned at the
syntax error. You can place the cursor on the message and press F1=Help for more
information about the error.

You can page through previous statements, commands, and messages. Press
F9=Retrieve with your cursor on a previous statement to place a copy of that
statement in the input area. If you need more room to type an SQL statement, page
down on the display.

Prompting
The prompt function helps you supply the necessary information for the syntax of
the statement you want to use. The prompt function can be used in any of the three
statement processing modes: *RUN, *VLD, and *SYN.

You have two options when using the prompter:


v Type the verb of the statement before pressing F4=Prompt.
The statement is parsed and the clauses that are completed are filled in on the
prompt displays.
If you type SELECT and press F4=Prompt, the following display appears:

Chapter 19. Using Interactive SQL 351


Specify SELECT Statement

Type SELECT statement information. Press F4 for a list.

FROM tables . . . . . . . . _____________________________________________


SELECT columns . . . . . . _____________________________________________
WHERE conditions . . . . . _____________________________________________
GROUP BY columns . . . . . _____________________________________________
HAVING conditions . . . . . _____________________________________________
ORDER BY columns . . . . . _____________________________________________
FOR UPDATE OF columns . . . _____________________________________________

Bottom
Type choices, press Enter.

DISTINCT rows in result table . . . . . . . . . N Y=Yes, N=No


UNION with another SELECT . . . . . . . . . . . N Y=Yes, N=No
Specify additional options . . . . . . . . . . . N Y=Yes, N=No

F3=Exit F4=Prompt F5=Refresh F6=Insert line F9=Specify subquery


F10=Copy line F12=Cancel F14=Delete line F15=Split line F24=More keys

v Press F4=Prompt before typing anything on the Enter SQL Statements display.
You are shown a list of statements. The list of statements varies and depends on
the current interactive SQL statement processing mode. For syntax check mode
with a language other than *NONE, the list includes all SQL statements. For run
and validate modes, only statements that can be run in interactive SQL are
shown. You can select the number of the statement you want to use. The system
prompts you for the statement you selected.
If you press F4=Prompt without typing anything, the following display appears:
Select SQL Statement

Select one of the following:

1. ALTER TABLE
2. CALL
3. COMMENT ON
4. COMMIT
5. CONNECT
6. CREATE ALIAS
7. CREATE COLLECTION
8. CREATE INDEX
9. CREATE PROCEDURE
10. CREATE TABLE
11. CREATE VIEW
12. DELETE
13. DISCONNECT
14. DROP ALIAS
More...
Selection
__

F3=Exit F12=Cancel

If you press F21=Display Statement on a prompt display, the prompter displays the
formatted SQL statement as it was filled in to that point.

When Enter is pressed within prompting, the statement that was built through the
prompt screens is inserted into the session. If the statement processing mode is
*RUN, the statement is run. The prompter remains in control if an error is
encountered.

352 DB2 UDB for AS/400 SQL Programming V4R4


Syntax Checking
The syntax of the SQL statement is checked when it enters the prompter. The
prompter does not accept a syntactically incorrect statement. You must correct the
syntax or remove the incorrect part of the statement or prompting will not be
allowed.

Statement processing mode


The statement processing mode can be selected on the Change Session Attributes
display. In *RUN (run) or *VLD (validate) mode, only statements that are allowed to
run in interactive SQL can be prompted. In *SYN (syntax check) mode, all SQL
statements are allowed. The statement is not actually run in *SYN or *VLD modes;
only the syntax and existence of objects are checked.

Subqueries
Subqueries can be selected on any display that has a WHERE or HAVING clause.
To see the subquery display, press F9=Specify subquery when the cursor is on a
WHERE or HAVING input line. A display appears that allows you to type in
subselect information. If the cursor is within the parentheses of the subquery when
F9 is pressed, the subquery information is filled in on the next display. If the cursor
is outside the parentheses of the subquery, the next display is blank. For more
information on subqueries, see “Using Subqueries” on page 84.

CREATE TABLE prompting


When prompting for CREATE TABLE, support is available for entering column
definitions individually. Place your cursor in the column definition section of the
display, and press F4=Prompt. A display that provides room for entering all the
information for one column definition is shown.

To enter a column name longer than 18 characters, press F20=Display entire name.
A window with enough space for a 30 character name will be displayed.

The editing keys, F6=Insert line, F10=Copy line, and F14=Delete line, can be used
to add and delete entries in the column definition list.

Entering DBCS Data


The rules for processing DBCS data across multiple lines are the same on the
Enter SQL Statements display and in the SQL prompter. Each line must contain the
same number of shift-in and shift-out characters. When processing a DBCS data
string that requires more than one line for entering, the extra shift-in and shift-out
characters are removed. If the last column on a line contains a shift-in and the first
column of the next line contains a shift-out, the shift-in and shift-out characters are
removed by the prompter when the two lines are assembled. If the last two columns
of a line contain a shift-in followed by a single-byte blank and the first column of the
next line contains a shift-out, the shift-in, blank, shift-out sequence is removed when
the two lines are assembled. This removal allows DBCS information to be read as
one continuous character string.

As an example, suppose the following WHERE condition were entered. The shift
characters are shown here at the beginning and end of the string sections on each
of the two lines.

Chapter 19. Using Interactive SQL 353


Specify SELECT Statement

Type SELECT statement information. Press F4 for a list.

FROM tables . . . . . . . . TABLE1_______________________________________


SELECT columns . . . . . . *____________________________________________
WHERE conditions . . . . . COL1 = '<AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQ>
<RRSS>'______________________________________
GROUP BY columns . . . . . _____________________________________________
HAVING conditions . . . . . _____________________________________________
ORDER BY columns . . . . . _____________________________________________
FOR UPDATE OF columns . . . _____________________________________________

When Enter is pressed, the character string is put together, removing the extra shift
characters. The statement would look like this on the Enter SQL Statements
display:
SELECT * FROM TABLE1 WHERE COL1 = '<AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSS>'

Using the List Selection Function


The list selection function is available by pressing F4 on certain prompt displays, or
F16, F17, or F18 on the Enter SQL Statements display. After pressing the function
key, you are given a list of authorized relational databases, collections, tables,
views, aliases, columns, constraints, procedures, parameters, or packages from
which to choose. If you request a list of tables, but you have not previously selected
a collection, you are asked to select a collection first.

On a list, you can select one or more items, numerically specifying the order in
which you want them to appear in the statement. When the list function is exited,
the selections you made are inserted at the position of the cursor on the display
you came from.

Always select the list you are primarily interested in. For example, if you want a list
of columns, but you believe that the columns you want are in a table not currently
selected, press F18=Select columns. Then, from the column list, press F17 to
change the table. If the table list were selected first, the table name would be
inserted into your statement. You would not have a choice for selecting columns.

You can request a list at any time while typing an SQL statement on the Enter SQL
Statements display. The selections you make from the lists are inserted on the
Enter SQL Statements display. They are inserted where the cursor is located in the
numeric order that you specified on the list display. Although the selected list
information is added for you, you must type the keywords for the statement.

The list function tries to provide qualifications that are necessary for the selected
columns, tables, and SQL packages. However, sometimes the list function cannot
determine the intent of the SQL statement. You need to review the SQL statement
and verify that the selected columns, tables, and SQL packages are properly
qualified.

Example of Using the List Selection Function


The following example shows you how to use the list function to build a SELECT
statement.

Assume you have:


v Just entered interactive SQL by typing STRSQL on an AS/400 command line.

354 DB2 UDB for AS/400 SQL Programming V4R4


v Made no list selections or entries.
v Selected *SQL for the naming convention.

Note: The example shows lists that are not on your AS/400 system. They are used
as an example only.

Begin using SQL statements:


1. Type SELECT on the first statement entry line.
2. Type FROM on the second statement entry line.
3. Leave the cursor positioned after FROM.
Enter SQL Statements

Type SQL statement, press Enter.


===> SELECT
FROM _

4. Press F17=Select tables to obtain a list of tables, because you want the table
name to follow FROM.
Instead of a list of tables appearing as you expected, a list of collections
appears (the Select and Sequence Collections display). You have just entered
the SQL session and have not selected a collection to work with.
5. Type a 1 in the Seq column next to YOURCOLL2 collection.
Select and Sequence Collections

Type sequence numbers (1-999) to select collections, press Enter.

Seq Collection Type Text


YOURCOLL1 SYS Company benefits
1 YOURCOLL2 SYS Employee personal data
YOURCOLL3 SYS Job classifications/requirements
YOURCOLL4 SYS Company insurances

6. Press Enter.
The Select and Sequence Tables display appears, showing the tables existing
in the YOURCOLL2 collection.
7. Type a 1 in the Seq column next to PEOPLE table.
Select and Sequence Tables

Type sequence numbers (1-999) to select tables, press Enter.

Seq Table Collection Type Text


EMPLCO YOURCOLL2 TAB Employee company data
1 PEOPLE YOURCOLL2 TAB Employee personal data
EMPLEXP YOURCOLL2 TAB Employee experience
EMPLEVL YOURCOLL2 TAB Employee evaluation reports
EMPLBEN YOURCOLL2 TAB Employee benefits record
EMPLMED YOURCOLL2 TAB Employee medical record
EMPLINVST YOURCOLL2 TAB Employee investments record

8. Press Enter.

Chapter 19. Using Interactive SQL 355


The Enter SQL Statements display appears again with the table name,
YOURCOLL2.PEOPLE, inserted after FROM. The table name is qualified by the
collection name in the *SQL naming convention.
Enter SQL Statements

Type SQL statement, press Enter.


===> SELECT
FROM YOURCOLL2.PEOPLE _

9. Position the cursor after SELECT.


10. Press F18=Select columns to obtain a list of columns, because you want the
column name to follow SELECT.
The Select and Sequence Columns display appears, showing the columns in
the PEOPLE table.
11. Type a 2 in the Seq column next to the NAME column.
12. Type a 1 in the Seq column next to the SOCSEC column.
Select and Sequence Columns

Type sequence numbers (1-999) to select columns, press Enter.

Seq Column Table Type Digits Length


2 NAME PEOPLE CHARACTER 6
EMPLNO PEOPLE CHARACTER 30
1 SOCSEC PEOPLE CHARACTER 11
STRADDR PEOPLE CHARACTER 30
CITY PEOPLE CHARACTER 20
ZIP PEOPLE CHARACTER 9
PHONE PEOPLE CHARACTER 20

13. Press Enter.


The Enter SQL Statements display appears again with SOCSEC, NAME appearing
after SELECT.
Enter SQL Statements

Type SQL statement, press Enter.


===> SELECT SOCSEC, NAME
FROM YOURCOLL2.PEOPLE

14. Press Enter.


The statement you created is now run.

Once you have used the list function, the values you selected remain in effect until
you change them or until you change the list of collections on the Change Session
Attributes display.

Session Services Description


The interactive SQL Session Services display is requested by pressing F13 on the
Enter SQL Statements display.

356 DB2 UDB for AS/400 SQL Programming V4R4


From this display you can change session attributes and print, clear, or save the
session to a source file.

Option 1 (Change session attributes) displays the Change Session Attributes


display, which allows you to select the current values that are in effect for your
interactive SQL session. The options shown on this display change based on the
statement processing option selected.

The following session attributes can be changed:


v Commitment control attributes.
v The statement processing control.
v The SELECT output device.
v The list of collections.
v The list type to select either all your system and SQL objects, or only your SQL
objects.
v The data refresh option when displaying data.
v The allow copy data option.
v The naming option.
v The programming language.
v The date format.
v The time format.
v The date separator.
v The time separator.
v The decimal point representation.
v The SQL string delimiter.
v The sort sequence.
v The language identifier.

Option 2 (Print current session) accesses the Change Printer display, which lets you
print the current session immediately and then continue working. You are prompted
for printer information. All the SQL statements you entered and all the messages
displayed are printed just as they appear on the Enter SQL Statements display.

Option 3 (Remove all entries from current session) lets you remove all the SQL
statements and messages from the Enter SQL Statements display and the session
history. You are prompted to ensure that you really want to delete the information.

Option 4 (Save session in source file) accesses the Change Source File display,
which lets you save the session in a source file. You are prompted for the source
file name. This function lets you embed the source file into a host language
program by using the source entry utility (SEU).

Note: Option 4 allows you to embed prototyped SQL statements in a high-level


language (HLL) program that uses SQL. The source file created by option 4
may be edited and used as the input source file for the Run SQL Statements
(RUNSQLSTM) command.

Exiting Interactive SQL


Pressing F3=Exit on the Enter SQL Statements display allows you to exit the
interactive SQL environment and do one of the following:

Chapter 19. Using Interactive SQL 357


1. Save and exit session. Leave interactive SQL. Your current session will be
saved and used the next time you start interactive SQL.
2. Exit without saving session. Leave interactive SQL without saving your session.
3. Resume session. Remain in interactive SQL and return to the Enter SQL
Statements display. The current session parameters remain in effect.
4. Save session in source file. Save the current session in a source file. The
Change Source File display is shown to allow you to select where to save the
session. You cannot recover and work with this session again in interactive
SQL.
Notes:
1. Option 4 allows you to embed prototype SQL statements in a high-level
language (HLL) program that uses SQL. Use the source entry utility (SEU) to
copy the statements into your program. The source file can also be edited and
used as the input source file for the Run SQL Statements (RUNSQLSTM)
command.
2. If rows have been changed and locks are currently being held for this unit of
work and you attempt to exit interactive SQL, a warning message is displayed.

Using an existing SQL Session


If you saved only one interactive SQL session by using option 1 (Save and exit
session) on the Exit Interactive SQL display, you may resume that session at any
workstation. However, if you use option 1 to save two or more sessions on different
workstations, interactive SQL will first attempt to resume a session that matches
your work station. If no matching sessions are available, then interactive SQL will
increase the scope of the search to include all sessions that belong to your user ID.
If no sessions for your user ID are available, the system will create a new session
for your user ID and current workstation.

For example, you saved a session on workstation 1 and saved another session on
workstation 2 and you are currently working at workstation 1. Interactive SQL will
first attempt to resume the session saved for workstation 1. If that session is
currently in use, interactive SQL will then attempt to resume the session that was
saved for workstation 2. If that session is also in use, then the system will create a
second session for workstation 1.

However, suppose you are working at workstation 3 and want to use the ISQL
session associated with workstation 2. You then may need to first delete the
session from workstation 1 by using option 2 (Exit without saving session) on the
Exit Interactive SQL display.

Recovering an SQL Session


If the previous SQL session ended abnormally, interactive SQL presents the
Recover SQL Session display at the start of the next session (when the next
STRSQL command is entered). From this display, you can either:
v Recover the old session by selecting option 1 (Attempt to resume existing SQL
session).
v Delete the old session and start a new session by selecting option 2 (Delete
existing SQL session and start a new session).

If you choose to delete the old session and continue with the new session, the
parameters you specified when you entered STRSQL are used. If you choose to

358 DB2 UDB for AS/400 SQL Programming V4R4


recover the old session, or are entering a previously saved session, the parameters
you specified when you entered STRSQL are ignored and the parameters from the
old session are used. A message is returned to indicate which parameters were
changed from the specified value to the old session value.

Accessing Remote Databases with Interactive SQL


In interactive SQL, you can communicate with a remote relational database by
using the SQL CONNECT statement. Interactive SQL uses the CONNECT (Type 2)
semantics (distributed unit of work) for CONNECT statements. Interactive SQL does
an implicit connect to the local RDB when starting an SQL session. When the
CONNECT statement is completed, a message shows the relational database
connection that was established. If starting a new session and COMMIT(*NONE)
was not specified, or if restoring a saved session and the commit level saved with
the session was not *NONE, the connection will be registered with commitment
control. This implicit connect and possible commitment control registration may
influence subsequent connections to remote databases. For further information, see
“Determining Connection Type” on page 567. It is recommended that prior to
connecting to the remote system:
v When connecting to an application server that does not support distributed unit of
work, a RELEASE ALL followed by a COMMIT be issued to end previous
connections, including the implicit connection to local.
v When connecting to a non-DB2 UDB for AS/400 application server, a RELEASE
ALL followed by a COMMIT be issued to end previous connections, including the
implicit connection to local, and change the commitment control level to at least
*CHG.

When you are connecting to a non-DB2 UDB for AS/400 application server, some
session attributes are changed to attributes that are supported by that application
server. The following table shows the attributes that change.
Table 35. Values Table
Session Attribute Original Value New Value
Date Format *YMD *ISO
*EUR
*DMY *USA
*USA
*MDY
*JUL
Time Format *HMS with a : separator *JIS
*HMS with any other *EUR
separator
Commitment Control *CHG, *CS Repeatable Read
*NONE
*ALL
Naming Convention *SYS *SQL
Allow Copy Data *NO, *YES *OPTIMIZE
Data Refresh *ALWAYS *FORWARD
Decimal Point *SYSVAL *PERIOD
Sort Sequence Any value other than *HEX *HEX

Chapter 19. Using Interactive SQL 359


Notes:
1. If connecting to an AS/400 system that is running a release prior to Version 2
Release 3, the sort sequence value changes to *HEX.
2. When connecting to a DB2/2 or DB2/6000 application server, the date and time
formats specified must be the same format.

After the connection is completed, a message is sent stating that the session
attributes have been changed. The changed session attributes can be displayed by
using the session services display. While interactive SQL is running, no other
connection can be established for the default activation group.

When connected to a remote system with interactive SQL, a statement processing


mode of syntax-only checks the syntax of the statement against the syntax
supported by the local system instead of the remote system. Similarly, the SQL
prompter and list support use the statement syntax and naming conventions
supported by the local system. The statement is run, however, on the remote
system. Because of differences in the level of SQL support between the two
systems, syntax errors may be found in the statement on the remote system at run
time.

Lists of collections and tables are available when you are connected to the local
relational database. Lists of columns are available only when you are connected to
a relational database manager that supports the DESCRIBE TABLE statement.

When you exit interactive SQL with connections that have pending changes or
connections that use protected conversations, the connections remain. If you do not
perform additional work over the connections, the connections are ended during the
next COMMIT or ROLLBACK operation. You can also end the connections by doing
a RELEASE ALL and a COMMIT before exiting interactive SQL.

Using interactive SQL for remote access to non-DB2 UDB for AS/400 application
servers can require some setup. For more information, see the Distributed
Database Programming book.

Note: In the output of a communications trace, there may be a reference to a


’CREATE TABLE XXX’ statement. This is used to determine package
existence; it is part of normal processing, and can be ignored.

360 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 20. Using the SQL Statement Processor
This section describes the SQL Statement processor. This processor is available
when you use the Run SQL Statements (RUNSQLSTM) command.

The SQL statement processor allows SQL statements to be executed from a source
member. The statements in the source member can be run repeatedly, or changed,
without compiling the source. This makes the setup of a database environment
easier. The statements that can be used with the SQL statement processor are:
v ALTER TABLE
v CALL
v COMMENT ON
v COMMIT
v CREATE ALIAS
v CREATE COLLECTION
| v CREATE DISTINCT TYPE
| v CREATE FUNCTION
v CREATE INDEX
v CREATE PROCEDURE
v CREATE SCHEMA
v CREATE TABLE
v CREATE VIEW
v DELETE
v DROP
v GRANT (Package Privileges)
v GRANT (Procedure Privileges)
v GRANT (Table Privileges)
v INSERT
v LABEL ON
v LOCK TABLE
v RENAME
v REVOKE (Package Privileges)
v REVOKE (Procedure Privileges)
v REVOKE (Table Privileges)
v ROLLBACK
| v SET PATH
v SET TRANSACTION
v UPDATE

In the source member, statements end with a semicolon and do not begin with
EXEC SQL. If the record length of the source member is longer than 80, only the
first 80 characters will be read. Comments in the source member can be either line
comments or block comments. Line comments begin with a double hyphen (−−) and
end at the end of the line. Block comments start with /* and can continue across
many lines until the next */ is reached. Block comments can be nested. Only SQL
statements and comments are allowed in the source file. The output listing and the
resulting messages for the SQL statements are sent to a print file. The default print
file is QSYSPRT.

© Copyright IBM Corp. 1997, 1999 361


To perform syntax checking only on all statements in the source member, specify
the PROCESS(*SYN) parameter on the RUNSQLSTM command.

Execution of Statements After Errors Occur


When a statement returns an error with a severity higher than the value specified
for the error level (ERRLVL) parameter of the RUNSQLSTM command, the
statement has failed. The rest of the statements in the source will be parsed to
check for syntax errors, but those statements will not be executed. Most SQL errors
have a severity of 30. If you want to continue processing after an SQL statement
fails, set the ERRLVL parameter of the RUNSQLSTM command to 30 or higher.

Commitment Control in the SQL Statement Processor


A commitment-control level is specified on the RUNSQLSTM command. If a
commitment-control level other than *NONE is specified, the SQL statements are
run under commitment control. If all of the statements successfully execute, a
COMMIT is done at the completion of the SQL statement processor. Otherwise, a
ROLLBACK is done. A statement is considered successful if its return code severity
is less than or equal to the value specified on the ERRLVL parameter of the
RUNSQLSTM command.

The SET TRANSACTION statement can be used within the source member to
override the level of commitment control specified on the RUNSQLSTM command.

Note: The job must be at a unit of work boundary to use the SQL statement
processor with commitment control.

Schemas in the SQL Statement Processor


The SQL statement processor supports the CREATE SCHEMA statement. This is a
complex statement that can be thought of as having two distinct sections. The first
section defines the collection for the schema. The second section contains DDL
statements that define the objects in the collection.

The first section can be written in one of two ways:


v CREATE SCHEMA collection-name
A collection is created using the specified collection name.
v CREATE SCHEMA AUTHORIZATION authorization-name
A collection is created using the authorization name as the collection name.
When the schema is run, the user must have authority to the user profile that is
named authorization-name.
The privileges held by the authorization-name of the statement must include:
– Authority to run the CREATE COLLECTION statement
– Authority to run each SQL statement within the CREATE SCHEMA

The second section of the CREATE SCHEMA statement can contain from zero to
any number of the following statements:
v COMMENT ON
| v CREATE DISTINCT TYPE
v CREATE TABLE

362 DB2 UDB for AS/400 SQL Programming V4R4


v CREATE VIEW
v CREATE INDEX
v CREATE ALIAS
| v GRANT (User-Defined Type Privileges)
v GRANT (Table Privileges)
v LABEL ON

These statements follow directly after the first section of the statement. The
statements and sections are not separated by semicolons. If other SQL statements
follow this schema definition, the last statement in the schema must be ended by a
semicolon.

All objects created or referenced in the second part of the schema statement must
be in the collection that was created for the schema. All unqualified references are
implicitly qualified by the collection that was created. All qualified references must
be qualified by the created collection.

Source Member Listing for the SQL Statement Processor

5769ST1 V4R4M0 990521 Run SQL Statements SCHEMA 04/01/98 15:35:18 Page 1
Source file...............CORPDATA/SRC
Member....................SCHEMA
Commit....................*NONE
Naming....................*SYS
Generation level..........10
Date format...............*JOB
Date separator............*JOB
Time format...............*HMS
Time separator ...........*JOB
Default Collection........*NONE
IBM SQL flagging..........*NOFLAG
ANS flagging..............*NONE
Decimal point.............*JOB
Sort Sequence.............*JOB
Language ID...............*JOB
Printer file..............*LIBL/QSYSPRT
Source file CCSID.........65535
Job CCSID.................0
Statement processing......*RUN
Allow copy of data........*OPTIMIZE
Allow blocking............*READ
Source member changed on 04/01/98 11:54:10

Figure 12. QSYSPRT listing for SQL statement processor (Part 1 of 3)

Chapter 20. Using the SQL Statement Processor 363


5769ST1 V4R4M0 990521 Run SQL Statements SCHEMA 04/01/98 15:35:18 Page 2
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
1
2 DROP COLLECTION DEPT;
3 DROP COLLECTION MANAGER;
4
5 CREATE SCHEMA DEPT
6 CREATE TABLE EMP (EMPNAME CHAR(50), EMPNBR INT)
7 -- EMP will be created in collection DEPT
8 CREATE INDEX EMPIND ON EMP(EMPNBR)
9 -- EMPIND will be created in DEPT
10 GRANT SELECT ON EMP TO PUBLIC; -- grant authority
11
12 INSERT INTO DEPT/EMP VALUES('JOHN SMITH', 1234);
13 /* table must be qualified since no
14 longer in the schema */
15
16 CREATE SCHEMA AUTHORIZATION MANAGER
17 -- this schema will use MANAGER's
18 -- user profile
19 CREATE TABLE EMP_SALARY (EMPNBR INT, SALARY DECIMAL(7,2),
20 LEVEL CHAR(10))
21 CREATE VIEW LEVEL AS SELECT EMPNBR, LEVEL
22 FROM EMP_SALARY
23 CREATE INDEX SALARYIND ON EMP_SALARY(EMPNBR,SALARY)
24
25 GRANT ALL ON LEVEL TO JONES GRANT SELECT ON EMP_SALARY TO CLERK
26 -- Two statements can be on the same line
* * * * * E N D O F S O U R C E * * * * *

Figure 12. QSYSPRT listing for SQL statement processor (Part 2 of 3)

5769ST1 V4R4M0 990521 Run SQL Statements SCHEMA 04/01/98 15:35:18 Page 3
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
MSG ID SEV RECORD TEXT
SQL7953 0 1 Position 1 Drop of DEPT in QSYS complete.
SQL7953 0 3 Position 3 Drop of MANAGER in QSYS complete.
SQL7952 0 5 Position 3 Collection DEPT created.
SQL7950 0 6 Position 8 Table EMP created in collection DEPT.
SQL7954 0 8 Position 8 Index EMPIND created on table EMP in DEPT.
SQL7966 0 10 Position 8 GRANT of authority to EMP in DEPT completed.
SQL7956 0 10 Position 40 1 rows inserted in EMP in DEPT.
SQL7952 0 13 Position 28 Collection
MANAGER created.
SQL7950 0 19 Position 9 Table EMP_SALARY created in collection
MANAGER.
SQL7951 0 21 Position 9 View LEVEL created in collection MANAGER.
SQL7954 0 23 Position 9 Index SALARYIND created on table EMP_SALARY
in MANAGER.
SQL7966 0 25 Position 9 GRANT of authority to LEVEL in MANAGER
completed.
SQL7966 0 25 Position 37 GRANT of authority to EMP_SALARY in MANAGER
completed.

Message Summary
Total Info Warning Error Severe Terminal
13 13 0 0 0 0
00 level severity errors found in source
* * * * * E N D O F L I S T I N G * * * * *

Figure 12. QSYSPRT listing for SQL statement processor (Part 3 of 3)

364 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 21. DB2 UDB for AS/400 Data Protection
This chapter describes the security plan for protecting SQL data from unauthorized
users and the methods for ensuring data integrity.

Security
All objects on the AS/400 system, including SQL objects, are managed by the
system security function. Users may authorize SQL objects through either the SQL
GRANT and REVOKE statements or the CL commands Edit Object Authority
(EDTOBJAUT), Grant Object Authority (GRTOBJAUT), and Revoke Object Authority
(RVKOBJAUT). For more information on system security and the use of the
GRTOBJAUT and RVKOBJAUT commands, see the Security - Reference book.

The SQL GRANT and REVOKE statements operate on SQL packages, SQL
procedures, tables, views, and the individual columns of tables and views.
Furthermore, SQL GRANT and REVOKE statements only grant private and public
authorities. In some cases, it is necessary to use EDTOBJAUT, GRTOBJAUT, and
RVKOBJAUT to authorize users to other objects, such as commands and programs.

For more information on the GRANT and REVOKE statements, see the DB2 UDB
for AS/400 SQL Reference book.

The authority checked for SQL statements depends on whether the statement is
static, dynamic, or being run interactively.

For static SQL statements:


v If the USRPRF value is *USER, the authority to run the SQL statement locally is
checked using the user profile of the user running the program. The authority to
run the SQL statement remotely is checked using the user profile at the
application server. *USER is the default for system (*SYS) naming.
v If the USRPRF value is *OWNER, the authority to run the SQL statement locally
is checked using the user profiles of the user running the program and of the
owner of the program. The authority to run the SQL statement remotely is
checked using the user profiles of the application server job and the owner of the
SQL package. The higher authority is the authority that is used. *OWNER is the
default for SQL (*SQL) naming.

For dynamic SQL statements:


v If the USRPRF value is *USER, the authority to run the SQL statement locally is
checked using the user profile of the person running the program. The authority
to run the SQL statement remotely is checked using the user profile of the
application server job.
v If the USRPRF value is *OWNER and DYNUSRPRF is *USER, the authority to
run the SQL statement locally is checked using the user profile of the person
running the program. The authority to run the SQL statement remotely is checked
using the user profile of the application server job.
v If the USRPRF value is *OWNER and DYNUSRPRF is *OWNER, the authority to
run the SQL statement locally is checked using the user profiles of the user
running the program and the owner of the program. The authority to run the SQL
statement remotely is checked using the user profiles of the application server
job and the owner of the SQL package. The highest authority is the authority that
is used. Because of security concerns, you should use the *OWNER parameter

© Copyright IBM Corp. 1997, 1999 365


value for DYNUSRPRF carefully. This option gives the access authority of the
owner program or package to those who run the program.

For interactive SQL statements, authority is checked against the authority of the
person processing the statement. Adopted authority is not used for interactive SQL
statements.

Authorization ID
The authorization ID identifies a unique user and is a user profile object on the
AS/400 system. Authorization IDs can be created using the system Create User
Profile (CRTUSRPRF) command.

Views
A view can prevent unauthorized users from having access to sensitive data. The
application program can access the data it needs in a table, without having access
to sensitive or restricted data in the table. A view can restrict access to particular
columns by not specifying those columns in the SELECT list (for example,
employee salaries). A view can also restrict access to particular rows in a table by
specifying a WHERE clause (for example, allowing access only to the rows
associated with a particular department number).

Auditing
DB2 UDB for AS/400 is designed to comply with the U.S. government C2 security
level. A key feature of that level is the ability to audit actions on the system. DB2
UDB for AS/400 uses the audit facilities managed by the system security function.
Auditing can be performed on an object level, user, or system level. The system
value QAUDCTL controls whether auditing is performed at the object or user level.
The Change User Audit (CHGUSRAUD) command and Change Object Audit
(CHGOBJAUD) command specify which users and objects are audited. The system
value QAUDLVL controls what types of actions are audited (for example,
authorization failures, creates, deletes, grants, revokes, etc.) For more information
on auditing see the Security - Reference book.

DB2 UDB for AS/400 can also audit row changes by using the DB2 UDB for AS/400
journal support.

In some cases, entries in the auditing journal will not be in the same order as they
occured. For example, a job that is running under commitment control deletes a
table, creates a new table with the same name as the one that was deleted, then
does a commit. This will be recorded in the auditing journal as a create followed by
a delete. This is because objects that are created are journalled immediately. An
object that is deleted under commitment control is hidden and not actually deleted
until a commit is done. Once the commit is done, the action is journaled.

Data Integrity
Data integrity protects data from being destroyed or changed by unauthorized
persons, system operation or hardware failures (such as physical damage to a
disk), programming errors, interruptions before a job is completed (such as a power
failure), or interference from running applications at the same time (such as
serialization problems). Data integrity is ensured by the following functions:

366 DB2 UDB for AS/400 SQL Programming V4R4


v Concurrency
v Journaling
v Commitment control
v Atomic operations
v Constraints
v Save/restore
v Damage tolerance
v Index recovery

The DB2 UDB for AS/400 Database Programming book and the Backup and
Recovery book contain more information about each of these functions.

Concurrency
Concurrency is the ability for multiple users to access and change data in the
same table or view at the same time without risk of losing data integrity. This ability
is automatically supplied by the DB2 UDB for AS/400 database manager. Locks are
implicitly acquired on tables and rows to protect concurrent users from changing the
same data at precisely the same time.

Typically, DB2 UDB for AS/400 will acquire locks on rows to ensure integrity.
However, some situations require DB2 UDB for AS/400 to acquire a more exclusive
table level lock instead of row locks. For more information see “Commitment
Control” on page 369.

| For example, an update (exclusive) lock on a row currently held by one cursor can
| be acquired by another cursor in the same program (or in a DELETE or UPDATE
| statement not associated with the cursor). This will prevent a positioned UPDATE or
| positioned DELETE statement that references the first cursor until another FETCH
| is performed. A read (shared no-update) lock on a row currently held by one cursor
| will not prevent another cursor in the same program (or DELETE or UPDATE
| statement) from acquiring a lock on the same row.

Default and user-specifiable lock-wait time-out values are supported. DB2 UDB for
AS/400 creates tables, views, and indexes with the default record wait time (60
seconds) and the default file wait time (*IMMED). This lock wait time is used for
DML statements. You can change these values by using the CL commands Change
Physical File (CHGPF), Change Logical File (CHGLF), and Override Database File
(OVRDBF).

The lock wait time used for all DDL statements and the LOCK TABLE statement, is
the job default wait time (DFTWAIT). You can change this value by using the CL
commands Change Job (CHGJOB) or Change Class (CHGCLS).

In the event that a large record wait time is specified, deadlock detection is
provided. For example, assume one job has an exclusive lock on row 1 and another
job has an exclusive lock on row 2. If the first job attempts to lock row 2, it will wait
because the second job is holding the lock. If the second job then attempts to lock
row 1, DB2 UDB for AS/400 will detect that the two jobs are in a deadlock and an
error will be returned to the second job.

Chapter 21. DB2 UDB for AS/400 Data Protection 367


You can explicitly prevent other users from using a table at the same time by using
the SQL LOCK TABLE statement, which is described in the DB2 UDB for AS/400
SQL Reference book. Using COMMIT(*RR) will also prevent other users from using
a table during a unit of work.

In order to improve performance, DB2 UDB for AS/400 will frequently leave the
open data path (ODP) open (for more information see “Chapter 25. Additional SQL
performance considerations” on page 459). This performance feature also leaves a
lock on tables referenced by the ODP, but does not leave any locks on rows. A lock
left on a table may prevent another job from performing an operation on that table.
In most cases, however, DB2 UDB for AS/400 will detect that other jobs are holding
locks and events will be signalled to those jobs. The event causes DB2 UDB for
AS/400 to close any ODPs (and release the table locks) that are associated with
that table and are currently only open for performance reasons. Note that the lock
wait time out must be large enough for the events to be signalled and the other jobs
to close the ODPs or an error will be returned.

Unless the LOCK TABLE statement is used to acquire table locks, or either
COMMIT(*ALL) or COMMIT(*RR) is used, data which has been read by one job
can be immediately changed by another job. Usually, the data that is read at the
time the SQL statement is executed and therefore it is very current (for example,
during FETCH). In the following cases, however, data is read prior to the execution
of the SQL statement and therefore the data may not be current (for example,
during OPEN).
v ALWCPYDTA(*OPTIMIZE) was specified and the optimizer determined that
making a copy of the data would perform better than not making a copy.
v Some queries require the database manager to create a temporary result table.
The data in the temporary result table will not reflect changes made after the
cursor was opened. A temporary result table is required when:
– The total length in bytes of storage for the columns specified in an ORDER
BY clause exceeds 2000 bytes.
– ORDER BY and GROUP BY clauses specify different columns or columns in
a different order.
– UNION or DISTINCT clauses are specified.
– ORDER BY or GROUP BY clauses specify columns which are not all from the
same table.
– Joining a logical file defined by the JOINDFT data definition specifications
(DDS) keyword with another file.
– Joining or specifying GROUP BY on a logical file which is based on multiple
database file members.
– The query contains a join in which at least one of the files is a view which
contains a GROUP BY clause.
– The query contains a GROUP BY clause which references a view that
contains a GROUP BY clause.
v A basic subquery is evaluated when the query is opened.

Journaling
The DB2 UDB for AS/400 journal support supplies an audit trail and forward and
backward recovery. Forward recovery can be used to take an older version of a
table and apply the changes logged on the journal to the table. Backward recovery
can be used to remove changes logged on the journal from the table.

368 DB2 UDB for AS/400 SQL Programming V4R4


When an SQL collection is created, a journal and journal receiver are created in the
collection. When SQL creates the journal and journal receiver, they are only created
on a user auxiliary storage pool (ASP) if the ASP clause is specified on the
CREATE COLLECTION or the CREATE SCHEMA statement. However, because
placing journal receivers on their own ASPs can improve performance, the person
managing the journal might want to create all future journal receivers on a separate
ASP.

When a table is created into the collection, it is automatically journaled to the


journal DB2 UDB for AS/400 created in the collection (QSQJRN). A table created in
a non-collection will also have journaling started if a journal named QSQJRN exists
in that library. After this point, it is your responsibility to use the journal functions to
manage the journal, the journal receivers, and the journaling of tables to the journal.
For example, if a table is moved into a collection, no automatic change to the
journaling status occurs. If a table is restored, the normal journal rules apply. That
is, if the table was journaled at the time of the save, it is journaled to the same
journal at restore time. If the table was not journaled at the time of the save, it is
not journaled at restore time.

The journal created in the SQL collection is normally the journal used for logging all
changes to SQL tables. You can, however, use the system journal functions to
journal SQL tables to a different journal. This may be necessary if a table in one
collection is a parent to a table in another collection. This is because DB2 UDB for
AS/400 requires that the parent and dependent file in a referential constraint be
journaled to the same journal when updates or deletes are performed to the parent
table.

A user can stop journaling on any table using the journal functions, but doing so
prevents an application from running under commitment control. If journaling is
stopped on a parent table of a referential constraint with a delete rule of NO
ACTION, CASCADE, SET NULL, or SET DEFAULT, all update and delete
operations will be prevented. Otherwise, an application is still able to function if you
have specified COMMIT(*NONE); however, this does not provide the same level of
integrity that journaling and commitment control provide.

Commitment Control
The DB2 UDB for AS/400 commitment control support provides a means to process
a group of database changes (updates, inserts, DDL operations, or deletes) as a
single unit of work (transaction). A commit operation guarantees that the group of
operations is completed. A rollback operation guarantees that the group of
operations is backed out. A commit operation can be issued through several
different interfaces. For example,
v An SQL COMMIT statement
v A CL COMMIT command
v A language commit statement (such as an RPG COMMIT statement)
A rollback operation can be issued through several different interfaces. For
example,
v An SQL ROLLBACK statement
v A CL ROLLBACK command
v A language rollback statement (such as an RPG ROLBK statement)

The only SQL statements that cannot be committed or rolled back are:

Chapter 21. DB2 UDB for AS/400 Data Protection 369


v DROP COLLECTION
v GRANT or REVOKE if an authority holder exists for the specified object

If commitment control was not already started when either an SQL statement is
executed with an isolation level other than COMMIT(*NONE) or a RELEASE
statement is executed, then DB2 UDB for AS/400 sets up the commitment control
environment by implicitly calling the CL command Start Commitment Control
(STRCMTCTL). DB2 UDB for AS/400 specifies NFYOBJ(*NONE) and
CMTSCOPE(*ACTGRP) parameters along with LCKLVL on the STRCMTCTL
command. The LCKLVL specified is the lock level on the COMMIT parameter on the
CRTSQLxxx, STRSQL, or RUNSQLSTM commands. In REXX, the LCKLVL
specified is the lock level on the SET OPTION statement. 16 You may use the
STRCMTCTL command to specify a different CMTSCOPE, NFYOBJ, or LCKLVL. If
you specify CMTSCOPE(*JOB) to start the job level commitment definition, DB2
UDB for AS/400 uses the job level commitment definition for programs in that
activation group.

Note: When using commitment control, the tables referred to in the application
program by Data Manipulation Language statements must be journaled.

For cursors that use column functions, GROUP BY, or HAVING, and are running
under commitment control, a ROLLBACK HOLD has no effect on the cursor’s
position. In addition, the following occurs under commitment control:
v If COMMIT(*CHG) and (ALWBLK(*NO) or (ALWBLK(*READ)) is specified for one
of these cursors, a message (CPI430B) is sent that says COMMIT(*CHG)
requested but not allowed.
v If COMMIT(*ALL), COMMIT(*RR), or COMMIT(*CS) with the KEEP LOCKS
clause is specified for one of the cursors, DB2 UDB for AS/400 will lock all
referenced tables in shared mode (*SHRNUP). The lock prevents concurrent
application processes from executing any but read-only operations on the named
table. A message (either SQL7902 or CPI430A) is sent that says COMMIT(*ALL),
COMMIT(*RR), or COMMIT(*CS) with the KEEP LOCKS clause is specified for
one of the cursors requested but not allowed. Message SQL0595 may also be
sent.

For cursors where either COMMIT(*ALL), COMMIT(*RR), or COMMIT(*CS) with the


KEEP LOCKS clause is specified and either catalog files are used or a temporary
result table is required, DB2 UDB for AS/400 will lock all referenced tables in
shared mode (*SHRNUP). This will prevent concurrent processes from executing
anything but read-only operations on the table(s). A message (either SQL7902 or
CPI430A) is sent that says COMMIT(*ALL) is requested but not allowed. Message
SQL0595 may also be sent.

If ALWBLK(*ALLREAD) and COMMIT(*CHG) were specified, when the program was


precompiled, all read only cursors will allow blocking of rows and a ROLLBACK
HOLD will not roll the cursor position back.

If COMMIT(*RR) is requested, the tables will be locked until the query is closed. If
the cursor is read only, the table will be locked (*SHRNUP). If the cursor is in

16. Note that the LCKLVL specified is only the default lock level. After commitment control is started, the SET TRANSACTION SQL
statement and the lock level specified on the COMMIT parameter on the CRTSQLxxx, STRSQL, or RUNSQLSTM commands will
override the default lock level.

370 DB2 UDB for AS/400 SQL Programming V4R4


update mode, the table will be locked (*EXCLRD). Since other users will be locked
out of the table, running with repeatable read will prevent concurrent access of the
table.

If an isolation level other then COMMIT(*NONE) was specified and the application
issues a ROLLBACK or the activation group ends normally (and the commitment
definition is not *JOB), all updates, inserts, deletes, and DDL operations made
within the unit of work are backed out. If the application issues a COMMIT or the
activation group ends normally, all updates, inserts, deletes, and DDL operations
made within the unit of work are committed.

DB2 UDB for AS/400 uses locks on rows to keep other jobs from accessing
changed data before a unit of work completes. If COMMIT(*ALL) is specified, read
locks on rows fetched are also used to prevent other jobs from changing data that
was read before a unit of work completes. This will not prevent other jobs from
reading the unchanged records. This ensures that, if the same unit of work rereads
a record, it gets the same result. Read locks do not prevent other jobs from fetching
the same rows.

Commitment control handles up to 4 million distinct row changes in a unit of work. If


COMMIT(*ALL) or COMMIT(*RR) is specified, all rows read are also included in the
limit. (If a row is changed or read more than once in a unit of work, it is only
counted once toward the limit.) Holding a large number of locks adversely affects
system performance and does not allow concurrent users to access rows locked in
the unit of work until the end of the unit of work. It is in your best interest to keep
the number of rows processed in a unit of work small.

Commitment control will allow up to 512 files for each journal to be open under
commitment control or closed with pending changes in a unit of work.

COMMIT HOLD and ROLLBACK HOLD allows you to keep the cursor open and
start another unit of work without issuing an OPEN again. The HOLD value is not
available when you are connected to a remote database that is not on an AS/400
system. However, the WITH HOLD option on DECLARE CURSOR may be used to
keep the cursor open after a COMMIT. This type of cursor is supported when you
are connected to a remote database that is not on an AS/400 system. Such a
cursor is closed on a rollback.
Table 36. Record Lock Duration
COMMIT Parameter
SQL Statement (See note 6) Duration of Record Locks Lock Type
SELECT INTO *NONE No locks
SET variable *CHG No locks
VALUES INTO *CS (See note 8) Row locked when read and released READ
*ALL (See note 2) From read until ROLLBACK or COMMIT READ
FETCH (read-only *NONE No locks
cursor) *CHG No locks
*CS (See note 8) From read until the next FETCH READ
*ALL (See note 2) From read until ROLLBACK or COMMIT READ

Chapter 21. DB2 UDB for AS/400 Data Protection 371


Table 36. Record Lock Duration (continued)
COMMIT Parameter
SQL Statement (See note 6) Duration of Record Locks Lock Type
FETCH (update or *NONE When record not updated or deleted UPDATE
delete capable cursor) from read until next FETCH
(See note 1) When record is updated or deleted
from read until UPDATE or DELETE
*CHG When record not updated or deleted UPDATE
from read until next FETCH
When record is updated or deleted
from read until COMMIT or ROLLBACK
*CS When record not updated or deleted UPDATE
from read until next FETCH
When record is updated or deleted
from read until COMMIT or ROLLBACK
*ALL From read until ROLLBACK or COMMIT UPDATE3
INSERT (target table) *NONE No locks
*CHG From insert until ROLLBACK or COMMIT UPDATE
*CS From insert until ROLLBACK or COMMIT UPDATE
*ALL From insert until ROLLBACK or COMMIT UPDATE4
INSERT (tables in *NONE No locks
subselect) *CHG No locks
*CS Each record locked while being read READ
*ALL From read until ROLLBACK or COMMIT READ
UPDATE (non-cursor) *NONE Each record locked while being updated UPDATE
*CHG From read until ROLLBACK or COMMIT UPDATE
*CS From read until ROLLBACK or COMMIT UPDATE
*ALL From read until ROLLBACK or COMMIT UPDATE
DELETE (non-cursor) *NONE Each record locked while being deleted UPDATE
*CHG From read until ROLLBACK or COMMIT UPDATE
*CS From read until ROLLBACK or COMMIT UPDATE
*ALL From read until ROLLBACK or COMMIT UPDATE
UPDATE (with cursor) *NONE Lock released when record updated UPDATE
*CHG From read until ROLLBACK or COMMIT UPDATE
*CS From read until ROLLBACK or COMMIT UPDATE
*ALL From read until ROLLBACK or COMMIT UPDATE
DELETE (with cursor) *NONE Lock released when record deleted UPDATE
*CHG From read until ROLLBACK or COMMIT UPDATE
*CS From read until ROLLBACK or COMMIT UPDATE
*ALL From read until ROLLBACK or COMMIT UPDATE
Subqueries (update or *NONE From read until next FETCH READ
delete capable cursor or *CHG From read until next FETCH READ
UPDATE or DELETE *CS From read until next FETCH READ
non-cursor) *ALL (see note 2) From read until ROLLBACK or COMMIT READ
Subqueries (read-only *NONE No locks
cursor or SELECT INTO) *CHG No locks
*CS Each record locked while being read READ
*ALL From read until ROLLBACK or COMMIT READ

372 DB2 UDB for AS/400 SQL Programming V4R4


Table 36. Record Lock Duration (continued)
COMMIT Parameter
SQL Statement (See note 6) Duration of Record Locks Lock Type
Notes:
1. A cursor is open with UPDATE or DELETE capabilities if the result table is not read-only (see description of
DECLARE CURSOR in DB2 UDB for AS/400 SQL Reference book) and if one of the following is true:
v The cursor is defined with a FOR UPDATE clause.
v The cursor is defined without a FOR UPDATE, FOR READ ONLY, or ORDER BY clause and the program
contains at least one of the following:
– Cursor UPDATE referring to the same cursor-name
– Cursor DELETE referring to the same cursor-name
– An EXECUTE or EXECUTE IMMEDIATE statement and ALWBLK(*READ) or ALWBLK(*NONE) was
specified on the CRTSQLxxx command.
2. A table or view can be locked exclusively in order to satisfy COMMIT(*ALL). If a subselect is processed that
includes a UNION, or if the processing of the query requires the use of a temporary result, an exclusive lock is
acquired to protect you from seeing uncommitted changes.
3. If the row is not updated or deleted, the lock is reduced to *READ.
4. An UPDATE lock on rows of the target table and a READ lock on the rows of the subselect table.
5. A table or view can be locked exclusively in order to satisfy repeatable read. Row locking is still done under
repeatable read. The locks acquired and their duration are identical to *ALL.
6. Repeatable read (*RR) record locks will be the same as the locks indicated for *ALL.
7. For a detailed explanation of isolation levels and locking, see the section entitled ″Isolation Level″ in Chapter 1 of
the DB2 UDB for AS/400 SQL Reference book.
8. If the KEEP LOCKS clause is specified with *CS, any read locks are held until the cursor is closed or until a
COMMIT or ROLLBACK is done. If no cursors are associated with the isolation clause, then locks are held until
the completion of the SQL statement.

Atomic Operations
When running under COMMIT(*CHG), COMMIT(*CS), or COMMIT(*ALL), all
operations are guaranteed to be atomic. That is, they will complete or they will
appear not to have started. This is true regardless of when or how the function was
ended or interrupted (such as power failure, abnormal job end, or job cancel).

If COMMIT (*NONE) is specified, however, some underlying database data


definition functions are not atomic. The following SQL data definition statements are
| guaranteed to be atomic:
| ALTER TABLE (See note 1)
| COMMENT ON (See note 2)
| LABEL ON (See note 2)
| GRANT (See note 3)
| REVOKE (See note 3)
| DROP TABLE (See note 4)
| DROP VIEW (See note 4)
| DROP INDEX
| DROP PACKAGE
|

Chapter 21. DB2 UDB for AS/400 Data Protection 373


Notes:
1. If constraints need to be added or removed, as well as column definitions
changed, the operations are processed one at a time, so the entire SQL
statement is not atomic. The order of operation is:
v remove constraints
v drop columns for which the RESTRICT option was specified
v all other column definition changes (DROP COLUMN CASCADE, ALTER
COLUMN, ADD COLUMN)
v add constraints
2. If multiple columns are specified for a COMMENT ON or LABEL ON statement,
the columns are processed one at a time, so the entire SQL statement is not
atomic, but the COMMENT ON or LABEL ON to each individual column or
object will be atomic.
3. If multiple tables, SQL packages, or users are specified for a GRANT or
REVOKE statement, the tables are processed one at a time, so the entire SQL
statement is not atomic, but the GRANT or REVOKE to each individual table will
be atomic.
4. If dependent views need to be dropped during DROP TABLE or DROP VIEW,
each dependent view is processed one at a time, so the entire SQL statement is
not atomic.

The following data definition statements are not atomic because they involve more
than one DB2 UDB for AS/400 database operation:
CREATE ALIAS
CREATE COLLECTION
| CREATE DISTINCT TYPE
| CREATE FUNCTION
| CREATE PROCEDURE
CREATE TABLE
CREATE VIEW
CREATE INDEX
CREATE SCHEMA
DROP ALIAS
DROP COLLECTION
| DROP DISTINCT TYPE
| DROP FUNCTION
| DROP PROCEDURE
DROP SCHEMA
RENAME (See note 1)
Notes:
1. RENAME is atomic only if the name or the system name is changed. When
both are changed, the RENAME is not atomic.

For example, a CREATE TABLE can be interrupted after the DB2 UDB for AS/400
physical file has been created, but before the member has been added. Therefore,
in the case of create statements, if an operation ends abnormally, you may have to
drop the object and then create it again. In the case of a DROP COLLECTION
statement, you may have to drop the collection again or use the CL command
Delete Library (DLTLIB) to remove the remaining parts of the collection.

374 DB2 UDB for AS/400 SQL Programming V4R4


Constraints
DB2 UDB for AS/400 supports unique, referential, and check constraints. A unique
constraint is a rule that guarantees that the values of a key are unique. A referential
constraint is a rule that all non-null values of foreign keys in a dependent table have
a corresponding parent key in a parent table. A check constraint is a rule that limits
the values allowed in a column or group of columns.

DB2 UDB for AS/400 will enforce the validity of the constraint during any DML (data
manipulation language) statement. Certain operations (such as restore of the
dependent table), however, cause the validity of the constraint to be unknown. In
this case, DML statements may be prevented until DB2 UDB for AS/400 has verified
the validity of the constraint.
v Unique constraints are implemented with indexes. If an index that implements a
unique constraint is invalid, the Edit Rebuild of Access Paths (EDTRBDAP)
command can be used to display any indexes that currently require rebuild.
v If DB2 UDB for AS/400 does not currently know whether a referential constraint
or check constraint is valid, the constraint is considered to be in a check pending
state. The Edit Check Pending Constraints (EDTCPCST) command can be used
to display any indexes that currently require rebuild.

For more information on constraints see the DB2 UDB for AS/400 Database
Programming book.

Save/Restore
| The AS/400 save/restore functions are used to save tables, views, indexes,
| journals, journal receivers, SQL packages, SQL procedures, user-defined functions,
| user-defined types, and collections on disk (save file) or to some external media
| (tape or diskette). The saved versions can be restored onto any AS/400 system at
| some later time. The save/restore function allows an entire collection, selected
| objects, or only objects changed since a given date and time to be saved. All
| information needed to restore an object to its previous state is saved. This function
| can be used to recover from damage to individual tables by restoring the data with
| a previous version of the table or the entire collection.

| When a program that was created for an SQL procedure or a service program that
| was created for an SQL function or a sourced function is restored, it is automatically
| added to the SYSROUTINES and SYSPARMS catalogs, as long as the procedure
| or function does not already exist with the same signature. SQL programs created
| in QSYS will not be created as SQL procedures when restored. Additionally,
| external programs or service programs that were referenced on a CREATE
| PROCEDURE or CREATE FUNCTION statement may contain the information
| required to register the routine in SYSROUTINES. If the information exists and the
| signature is unique, the functions or procedures will also be added to
| SYSROUTINES and SYSPARMS when restored.

| When an *SQLUDT object is restored for a user-defined type, the user-defined type
| is automatically added to the SYSTYPES catalog. The appropriate functions needed
| to cast between the user-defined type and the source type are also created, as long
| as the type and functions do not already exist.

Either a distributed SQL program or its associated SQL package can be saved and
restored to any number of AS/400 systems. This allows any number of copies of the
SQL programs on different systems to access the same SQL package on the same

Chapter 21. DB2 UDB for AS/400 Data Protection 375


application server. This also allows a single distributed SQL program to connect to
any number of application servers that have the SQL package restored
(CRTSQLPKG can also be used). SQL packages cannot be restored to a different
library.

Attention: Restoring a collection to an existing library or to a collection that has a


different name does not restore the journal, journal receivers, or IDDU dictionary (if
one exists). If the collection is restored to a collection with a different name, the
catalog views in that collection will only reflect objects in the old collection. The
catalog views in QSYS2, however, will appropriately reflect all objects.

Damage Tolerance
The AS/400 system provides several mechanisms to reduce or eliminate damage
caused by disk errors. For example, mirroring, checksums, and RAID disks can all
reduce the possibility of disk problems. The DB2 UDB for AS/400 functions also
have a certain amount of tolerance to damage caused by disk errors or system
errors.

A DROP operation always succeeds, regardless of the damage. This ensures that
should damage occur, at least the table, view, SQL package, or index can be
deleted and restored or created again.

In the event that a disk error has damaged a small portion of the rows in a table,
the DB2 UDB for AS/400 database manager allows you to read rows still
accessible.

Index Recovery
DB2 UDB for AS/400 supplies several functions to deal with index recovery.
v System managed index protection
The EDTRCYAP CL command allows a user to instruct DB2 UDB for AS/400 to
guarantee that in the event of a system or power failure, the amount of time
required to recover all indexes on the system is kept below a specified time. The
system automatically journals enough information in a system journal to limit the
recovery time to the specified amount.
v Journaling of indexes
DB2 UDB for AS/400 supplies an index journaling function that makes it
unnecessary to rebuild an entire index due to a power or system failure. If the
index is journaled, the system database support automatically makes sure the
index is in synchronization with the data in the tables without having to rebuild it
from scratch. SQL indexes are not journaled automatically. You can, however,
use the CL command Start Journal Access Path (STRJRNAP) to journal any
index created by DB2 UDB for AS/400.
v Index rebuild
All indexes on the system have a maintenance option that specifies when an
index is maintained. SQL indexes are created with an attribute of *IMMED
maintenance.
In the event of a power failure or abnormal system failure, if indexes were not
protected by one of the previously described techniques, those indexes in the
process of change may need to be rebuilt by the database manager to make
sure they agree with the actual data. All indexes on the system have a recovery
option that specifies when an index should be rebuilt if necessary. All SQL
indexes with an attribute of UNIQUE are created with a recovery attribute of *IPL

376 DB2 UDB for AS/400 SQL Programming V4R4


(this means that these indexes are rebuilt before the OS/400 has been started).
All other SQL indexes are created with the *AFTIPL recovery option (this means
that after the operating system has been started, indexes are asynchronously
rebuilt). During an IPL, the operator can see a display showing indexes needing
to be rebuilt and their recovery option. The operator can override the recovery
options.
v Save and restore of indexes
The save/restore function allows you to save indexes when a table is saved by
using ACCPTH(*YES) on the Save Object (SAVOBJ) or Save Library (SAVLIB)
CL commands. In the event of a restore when the indexes have also been saved,
there is no need to rebuild the indexes. Any indexes not previously saved and
restored are automatically and asynchronously rebuilt by the database manager.

Catalog Integrity
Catalogs contain information about tables, views, SQL packages, indexes,
procedures, and parameters in a collection. The database manager ensures that
the information in the catalog is accurate at all times. This is accomplished by
preventing end users from explicitly changing any information in the catalog and by
implicitly maintaining the information in the catalog when changes occur to the
tables, views, SQL packages, indexes, procedures, and parameters described in the
catalog.

The integrity of the catalog is maintained whether objects in the collection are
changed by SQL statements, OS/400 CL commands, System/38 Environment CL
commands, System/36 Environment functions, or any other product or utility on an
AS/400 system. For example, deleting a table can be done by running an SQL
DROP statement, issuing an OS/400 DLTF CL command, issuing a System/38
DLTF CL command or entering option 4 on a WRKF or WRKOBJ display.
Regardless of the interface used to delete the table, the database manager will
remove the description of the table from the catalog at the time the delete is
performed. The following is a list of functions and the associated effect on the
catalog:
Table 37. Effect of Various Functions on Catalogs
Function Effect on the Catalog
Add constraint to table Information added to catalog
Remove of constraint from table Related information removed from catalog
Create object into collection Information added to catalog
Delete of object from collection Related information removed from catalog
Restore of object into collection Information added to catalog
Change of object long comment Comment updated in catalog
Change of object label (text) Label updated in catalog
Change of object owner Owner updated in catalog
Move of object from a collection Related information removed from catalog
Move of object into collection Information added to catalog
Rename of object Name of object updated in catalog

Chapter 21. DB2 UDB for AS/400 Data Protection 377


User Auxiliary Storage Pool (ASP)
An SQL collection can be created in a user ASP by using the ASP clause on the
CREATE COLLECTION and CREATE SCHEMA statements. The CRTLIB command
can also be used to create a library in a user ASP. That library can then be used to
receive SQL tables, views, and indexes. See the Backup and Recovery book and
the Backup and Recovery book for more information on auxiliary storage pools.

378 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 22. Testing SQL Statements in Application Programs
This chapter describes how to establish a test environment for SQL statements in
an application program and how to debug this program.

Establishing a Test Environment


Some things you need to test your program are:
v Authorization. You need to be authorized to create tables and views, access
SQL data, and create and run programs.
v A test data structure. If your program updates, inserts, or deletes data from
tables and views, you should use test data to verify the running of the program. If
your program only retrieves data from tables and views, you might consider using
production-level data when testing your program. It is recommended, however,
that you use the CL command Start Debug (STRDBG) with UPDPROD(*NO) to
assure that the production level data does not accidentally get changed. See the
chapter on testing in the CL Programmingbook for more information on
debugging.
v Test input data. The input data your program uses during testing should be valid
data that represents as many possible input conditions as you can think of. You
cannot be sure that your output data is valid unless you use valid input data.
If your program verifies that input data is valid, include both valid and not valid
data to verify that the valid data is processed and the not valid data is detected.
You might have to refresh the data for subsequent tests.

To test the program thoroughly, test as many of the paths through the program as
possible. For example:
v Use input data that forces the program to run each of its branches.
v Check the results. For example, if the program updates a row, select the row to
see if it was updated correctly.
v Be sure to test the program error routines. Again, use input data that forces the
program to encounter as many of the anticipated error conditions as possible.
v Test the editing and validation routines your program uses. Give the program as
many different combinations of input data as possible to verify that it correctly
edits or validates that data.

Designing a Test Data Structure


To test an application that accesses SQL data, you might have to create test tables
and views:
v Test views of existing tables. If your application does not change data and the
data exists in one or more production-level tables, you might consider using a
view of the existing tables. It is also recommended that you use STRDBG
command with UPDPROD(*NO) to assure that the production level data does not
accidentally get changed. See the chapter on testing in the CL Programming for
more information on debugging.
v Test tables. When your application creates, changes, or deletes data, you will
probably want to test the application by using tables that contain test data. See
Chapter 2. Getting Started with SQL for a description of how to create tables and
views.

© Copyright IBM Corp. 1997, 1999 379


Also, you might want to use the CL command Create Duplicate Object
(CRTDUPOBJ) to create a duplicate test table, view, or index.

Authorization
Before you can create a table, you must be authorized to create tables and to use
the collection in which the table is to reside. In addition, you must have authority to
create and run the programs you want to test.

If you intend to use existing tables and views (either directly or as the basis for a
view), you must be authorized to access those tables and views.

If you want to create a view, you must be authorized to create views and must have
authorization to each table and view on which the view is based. For more
information on specific authorities required for any specific SQL statement, see the
DB2 UDB for AS/400 SQL Reference book.

Testing Your SQL Application Programs


There are two phases for testing DB2 UDB for AS/400 SQL applications: the
program debug phase and the performance verification phase.

The Program Debug Phase


This test phase is done to ensure that the SQL queries are specified correctly and
that the program is producing the correct results.

Debugging your program with SQL statements is much the same as debugging your
program without SQL statements. However, when SQL statements are run in a job
in the debug mode, the database manager puts messages in the job log about how
each SQL statement ran. This message is an indication of the SQLCODE for the
SQL statement. If the statement ran successfully, the SQLCODE value is zero, and
a completion message is issued. A negative SQLCODE results in a diagnostic
message. A positive SQLCODE results in an informational message.

The message is either a 4-digit code prefixed by SQL or a 5-digit code prefixed by
SQ. For example, an SQLCODE of −204 results in a message of SQL0204, and an
SQLCODE of 30000 results in a message of SQ30000.

Associated with a SQLCODE is a SQLSTATE. The SQLSTATE is an additional


return code provided in the SQLCA that identifies common error conditions among
the different IBM relational database products. The same error condition on different
relational database products will produce the same SQLSTATE. The same error
conditions will not produce the same SQLCODE. This return code is particularly
useful when determining the cause of errors returned from the relational database
operations performed on non-DB2 UDB for AS/400 system.

For non-ILE program debugging, references to high-level language statement


numbers in debug mode must be taken from the compile listing. For ILE program
debugging, precompile the program specifying DBGVIEW(*SOURCE) and then use
the source-level debugger.

SQL will always put messages in the job log for negative SQLCODEs and positive
codes other than +100 regardless of whether it is in debug mode or not.

380 DB2 UDB for AS/400 SQL Programming V4R4


The Performance Verification Phase
This test phase verifies that the appropriate indexes are available and that the
queries are coded in a manner that allows the database manager to resolve the
queries in the expected response time. The performance of an SQL application is
dependent on the attributes of the tables being accessed. If you use small tables,
the response time of the query is not affected by the availability of indexes.
However, when you run that same query on a database with large tables and
appropriate indexes do not exist, the response time for the queries can be very
long.

The test environment should resemble the production environment as closely as


possible. The test collection should have tables with the same names and
composition as the production collection. The same indexes need to be available
over the tables in both collections. The number of rows and the distribution of
values in the tables should be similar.

CL Command Usage for SQL Application Performance Verification


Verification of the performance of an SQL application can be done using the
following commands:
CHGQRYA The CL command Change Query Attribute
(CHGQRYA) can be used to prevent users from
running long queries. This command can be used
to set the parameter Query Time Limit
(QRYTIMLMT) to prevent a query from starting
whose estimated number of elapsed seconds is
longer than the specified number of seconds. This
stops the building of temporary indexes or other
resource intensive query operations.
Also, a query which is canceled because of the
query time limit creates performance information
messages in the job log, even if the job in not in
debug. For information restricting query runtime
using this command, see “Chapter 23. Using the
DB2 UDB for AS/400 Predictive Query Governor”
on page 391.
DSPJOB The CL command Display Job (DSPJOB) with
parameter OPTION(*OPNF) shows the indexes and
tables being used by an application that is running
in a job.
DSPJOB with parameter OPTION(*JOBLCK) can
be used to analyze object and row lock contention.
It displays the objects and rows that are locked and
the name of the job holding the lock.
DSPJOB with parameter OPTION(*CMTCTL)
shows the isolation level that the program is
running, the number of rows being locked during a
transaction, and the pending DDL functions. The
isolation level displayed is the default isolation level.
The actual isolation level, used for any SQL
program, is specified on the COMMIT parameter of
the CRTSQLxxx command.

Chapter 22. Testing SQL Statements in Application Programs 381


PRTSQLINF The CL command Print Structured Query Language
Information (PRTSQLINF) allows you to print
information about the embedded SQL statements in
a program, SQL package, or service program. The
information includes the SQL statements, the
access plans used during the running of the
statement, and a list of the command parameters
used to precompile the source member for the
object. For more information on printing information
about SQL Statements, see the PRTSQLINF
section in “Appendix D. DB2 UDB for AS/400 CL
Command Descriptions” on page 645.
TRCJOB The CL command Trace Job (TRCJOB) can be
used to capture a trace of the program modules
being run for an SQL application. The trace job
output lists the indexes and files being used when
the initial database open processing occurs for
each SQL statement. Also, the processing unit and
page resource usage for running each SQL
statement can be determined.

Performance Information Messages


You can evaluate the structure and performance of the given SQL statements in a
program using informational messages put in the job log by the database manager.
The messages are issued for an SQL program or interactive SQL when running in
the debug mode. The database manager may send any of the following messages
when appropriate. The ampersand variables (&1, &X) are replacement variables
that contain either an object name or some other substitution value when the
message appears in the job log. The messages are:
v CPI4321 Access path built for file &1.
v CPI4322 Access path built from keyed file &1.
v CPI4323 The OS/400 query access plan has been rebuilt.
v CPI4324 Temporary file built for file &1.
v CPI4325 Temporary result file built for query.
v CPI4326 File &1 processed in join position &X.
v CPI4327 File &1 processed in join position 1.
v CPI4328 Access path &4 was used by query.
v CPI4329 Arrival sequence access was used for file &1.
v CPI432A Query optimizer timed out.
v CPI432B Subselects processed as join query.
v CPI432C All access paths were considered for file &1.
v CPI432D Additional access path reason codes were used.
v CPI432E Selection fields mapped to different attributes.
v CPI432F Access path suggestion for file &1.
v CPI4330 &6 tasks used for parallel &10 scan of file &1.
v CPI4331 &6 tasks used for parallel index created over file &1.
v CPI4332 &1 host variables used in query.
v CPI4333 Hashing algorithm used to process join.
v CPI4334 Query implemented as reusable ODP.

382 DB2 UDB for AS/400 SQL Programming V4R4


v CPI4335 Optimizer debug messages for hash join step &1 follow:
v CPI4336 Group processing generated.
v CPI4337 Temporary hash table built for hash join step &1.
v CPI4338 &1 Access path(s) used for bitmap processing of file &2.
| v CPI4339 Query options retrieved from Library &1.
| v CPI433A Unable to retrieve query options file.
| v CPI433C Library &1 not found.
v CPI4341 Performing distributed query.
v CPI4342 Performing distributed join for query.
v CPI4345 Temporary distributed result file &4 built for query.
v SQL7910 SQL cursors closed.
v SQL7911 ODP reused.
v SQL7912 ODP created.
v SQL7913 ODP deleted.
v SQL7914 ODP not deleted.
v SQL7915 Access plan for SQL statement has been built.
v SQL7916 Blocking used for query.
v SQL7917 Access plan not updated.
v SQL7918 Reusable ODP deleted.
v SQL7919 Data conversion required on FETCH or embedded SELECT.
v SQL7939 Data conversion required on INSERT or UPDATE.

These messages provide feedback on how a query was run and, in some cases,
indicate the improvements that can be made to help the query run faster.

The messages contain message help that provides information about the cause for
the message, object name references, and possible user responses.

The time at which the message is sent does not necessarily indicate when the
associated function was performed. Some messages are sent altogether at the start
of a query run.

The causes and user responses for the following messages are paraphrased. The
actual message help is more complete and should be used when trying to
determine the meaning and responses for each message.

The possible user action for each message follows:

CPI4321 - Access path built for file &1.

This message indicates that a temporary access path was created to process the
query. The new access path is created by reading all of the records in the specified
file.

The time required to create an access path on each run of a query can be
significant. Consider creating a logical file (CRTLF) or an SQL index (CREATE
INDEX SQL statement):
v Over the file named in the message help.
v With key fields named in the message help.
v With the ascending or descending sequencing specified in the message help.

Chapter 22. Testing SQL Statements in Application Programs 383


v With the sort sequence table specified in the message help.

Consider creating the logical file with select or omit criteria that either match or
partially match the query’s predicates involving constants. The database manager
will consider using select or omit logical files even though they are not explicitly
specified on the query.

For certain queries, the optimizer may decide to create an access path even when
an existing one can be used. This might occur when a query has an ordering field
as a key field for an access path, and the only record selection specified uses a
different field. If the record selection results in roughly 20% of the records or more
to be returned, then the optimizer may create a new access path to get faster
performance when accessing the data. The new access path minimizes the amount
of data that needs to be read.

CPI4322 - Access path built from keyed file &1.

This message indicates that a temporary access path was created from the access
path of a keyed file.

Generally, this action should not take a significant amount of time or resource
because only a subset of the data in the file needs to be read. Sometimes even
faster performance can be achieved by creating a logical file or SQL index that
satisfies the access path requirement stated in the message help.

For more detail, see the previous message, CPI4321.

CPI4323 - The OS/400 query access plan has been rebuilt.

This message can be sent for a variety of reasons. The specific reason is provided
in the message help.

Most of the time, this message is sent when the queried file environment has
changed, making the current access plan obsolete. An example of the file
environment changing is when an access path required by the query no longer
exists on the system.

An access plan contains the instructions for how a query is to be run and lists the
access paths for running the query. If a needed access path is no longer available,
the query is again optimized, and a new access plan is created, replacing the old
one.

The process of again optimizing the query and building a new access plan at
runtime is a function of DB2 UDB for AS/400. It allows a query to be run as
efficiently as possible, using the most current state of the database without user
intervention.

The infrequent appearance of this message is not a cause for action. For example,
this message will be sent when an SQL package is run the first time after a restore,
or anytime the optimizer detects that a change has occurred (such as a new index
was created), that warrants an implicit rebuild. However, excessive rebuilds should
be avoided because extra query processing will occur. Excessive rebuilds may
indicate a possible application design problem or inefficient database management
practices.

CPI4324 - Temporary file built for file &1.

384 DB2 UDB for AS/400 SQL Programming V4R4


Before the query processing could begin, the data in the specified file had to be
copied into a temporary physical file to simplify running the query. The message
help contains the reason why this message was sent.

If the specified file selects few rows, usually less than 1000 rows, then the row
selection part of the query’s implementation should not take a significant amount of
resource and time. However if the query is taking more time and resources than
can be allowed, consider changing the query so that a temporary file is not
required.

One way to do this is by breaking the query into multiple steps. Consider using an
INSERT statement with a subselect to select only the records that are required into
a physical file, and then use that file’s records for the rest of the query.

CPI4325 - Temporary result file built for query.

A temporary result file was created to contain the intermediate results of the query.
The message help contains the reason why a temporary result file is required.

In some cases, creating a temporary result file provides the fastest way to run a
query. Other queries that have many records to be copied into the temporary result
file can take a significant amount of time. However, if the query is taking more time
and resources than can be allowed, consider changing the query so that a
temporary result file is not required.

CPI4326 - File &1 processed in join position &11.

This message provides the join position of the specified file when an access path is
used to access the file’s data. Join position pertains to the order in which the files
are joined.

The order in which files are joined can significantly influence the efficiency of a
query. The system processes the join of two files with different numbers of selected
records more efficiently when the file with the smaller number of selected records is
joined to the file with the larger number of selected records. For example, if two
files are being joined, the file with the fewest selected records should be in join
position 1 and the file with the larger number of selected records should be in join
position 2.

If the GROUP BY or ORDER BY clause is specified where all the columns in the
clause are referenced from one of the files in the query, that file becomes the first
file in the final join order. If the referenced file is a large file, the query may be slow.
To improve performance, consider one of the following:
v Add an additional column from a different file to the clause. A temporary result
table is used to allow the system to order the files in the most efficient join order.
v Specify the ALWCPYDTA(*OPTIMIZE) parameter on the ORDER BY clause. The
system orders the files in the most efficient join order.

When a query is changed as suggested above, a temporary result table may be


used to change the join order. The improved efficiency of the join order will, in most
cases, make up for any loss of efficiency caused by the temporary result.

If the query uses the JOIN clause or refers to a join logical file within the file
specifications, the order in which the files are specified will help determine the join

Chapter 22. Testing SQL Statements in Application Programs 385


order the optimizer uses. The optimizer cannot change the file join order if the
query contains a join logical file, or if either a left outer or exception join is specified
using the JOIN clause.

CPI4327 - File &1 processed in join position 1.

This message provides the name of the first or primary file of the join when arrival
sequence is used to select records from the file.

See the previous message, CPI4326, for information on join position and join
performance tips.

CPI4328 - Access path of file &4 was used by query.

This message names an existing access path that was used by the query.

The reason the access path was used is given in the message help.

CPI4329 - Arrival sequence access was used for file &1.

No access path was used to access the data in the specified file. The records were
scanned sequentially in arrival sequence.

The use of an access path may improve the performance of the query if record
selection is specified.

If an access path does not exist, you may want to create one whose key field
matches one of the fields in the record selection. You should only create an access
path if the record selection (WHERE clause) selects 20% or fewer records in the
file.

To force the use of an existing access path, change the ORDER BY clause of the
query to specify the first key field of the access path.

CPI432A - Query optimizer timed out for file &1.

The optimizer stops considering access paths when the time spent optimizing the
query exceeds an internal value that is associated with the estimated time to run
the query and the number of records in the queried files. Generally, the more
records in the files, the greater the number of access paths that will be considered.

When the estimated time to run the query is exceeded, the optimizer uses the
current best method for running the query. Either an access path has been found to
get the best performance, or an access path will have to be created, if necessary.
Exceeding the estimated time to run the query could mean that the optimizer did
not consider the best access path to run the query.

The message help contains a list of access paths that were considered before the
optimizer exceeded the estimated time.

To ensure that an access path is considered for optimization, specify the logical file
associated with the access path as the file to be queried. The optimizer will
consider the access path of the file specified on the query or SQL statement first.
Remember that SQL indexes cannot be queried.

You may want to delete any access paths that are no longer needed.

386 DB2 UDB for AS/400 SQL Programming V4R4


CPI432B - Subselects processed as join query.

Two or more SQL subselects were combined by the query optimizer and processed
as a join query. Generally, this method of processing is a good performing option.

CPI432C - All access paths were considered for file &1.

The optimizer considered all access paths built over the specified file. Since the
optimizer examined all access paths for the file, it determined the current best
access to the file.

The message help contains a list of the access paths. With each access path a
reason code is added. The reason code explains why the access path was not
used.

CPI432D - Additional access path reason codes were used.

Message CPI432A or CPI432C was issued immediately before this message.


Because of message length restrictions, some of the reason codes used by
messages CPI432A and CPI432C are explained in the message help of CPI432D.
Use the message help from this message to interpret the information returned from
message CPI432A or CPI432C.

CPI432E - Selection fields mapped to different attributes.

This message indicates that the query optimizer was not able to consider the usage
of an index to resolve one or more of the selection specifications of the query. If
there was an index available which otherwise could have been used to limit the
processing of the query to just a few rows, then the performance of this query will
be affected.

The attributes of a comparison value and a comparison column must match


otherwise a conversion will occur so that they do match. Generally, this conversion
occurs such that the value with the smallest attributes is mapped to the attributes of
the other value. When the attributes of the comparison column have to be mapped
to be compatible with that of the comparison value, the optimizer can no longer use
an index to implement this selection.

CPI4338 — &1 Access path(s) used for bitmap processing of file &2.

The optimizer chooses to use one or more access paths, in conjunction with the
query selection (WHERE clause), to build a bitmap. This resulting bitmap indicates
which records will actually be selected.

Conceptually, the bitmap contains one bit per record in the underlying table.
Corresponding bits for selected records are set to ’1’. All other bits are set to ’0’.

Once the bitmap is built, it is used, as appropriate, to avoid mapping in records


from the table not selected by the query. The use of the bitmap depends on
whether the bitmap is used in combination with the arrival sequence or with a
primary access path.

When bitmap processing is used with arrival sequence, either message CPI4327 or
CPI4329 will precede this message. In this case, the bitmap will help to selectively
map only those records from the table that the query selected.

Chapter 22. Testing SQL Statements in Application Programs 387


When bitmap processing is used with a primary access path, either message
CPI4326 or CPI4328 will precede this message. Records selected by the primary
access path will be checked against the bitmap before mapping the record from the
table.

Performance Information Messages and Open Data Paths


Several of the following SQL run-time messages refer to open data paths.

An open data path (ODP) definition is an internal object that is created when a
cursor is opened or when other SQL statements are run. It provides a direct link to
the data so that I/O operations can occur. ODPs are used on OPEN, INSERT,
UPDATE, DELETE, and SELECT INTO statements to perform their respective
operations on the data.

Even though SQL cursors are closed and SQL statements have already been run,
the database manager in many cases will save the associated ODPs of the SQL
operations to reuse them the next time the statement is run. So an SQL CLOSE
statement may close the SQL cursor but leave the ODP available to be used again
the next time the cursor is opened. This can significantly reduce the processing and
response time in running SQL statements.

The ability to reuse ODPs when SQL statements are run repeatedly is an important
consideration in achieving faster performance.

The following informational messages are issued at SQL run time:

SQL7910 - All SQL cursors closed.

This message is sent when the job’s call stack no longer contains a program that
has run an SQL statement.

Unless CLOSQLCSR(*ENDJOB) or CLOSQLCSR(*ENDACTGRP) was specified,


the SQL environment for reusing ODPs across program calls exists only until the
active programs that ran the SQL statements complete.

Except for ODPs associated with *ENDJOB or *ENDACTGRP cursors, all ODPs are
deleted when all the SQL programs on the call stack complete and the SQL
environment is exited.

This completion process includes closing of cursors, the deletion of ODPs, the
removal of prepared statements, and the release of locks.

Putting an SQL statement that can be run in the first program of an application
keeps the SQL environment active for the duration of that application. This allows
ODPs in other SQL programs to be reused when the programs are repeatedly
called. CLOSQLCSR(*ENDJOB) or CLOSQLCSR(*ENDACTGRP) can also be
specified.

SQL7911 - ODP reused.

This message indicates that the last time the statement was run or when a CLOSE
statement was run for this cursor, the ODP was not deleted. It will now be used
again. This should be an indication of very efficient use of resources by eliminating
unnecessary OPEN and CLOSE operations.

388 DB2 UDB for AS/400 SQL Programming V4R4


SQL7912 - ODP created.

No ODP was found that could be used again. The first time that the statement is
run or the cursor is opened for a process, an ODP will always have to be created.
However, if this message appears on every run of the statement or open of the
cursor, the tips recommended in “Improving Performance by Retaining Cursor
Positions for Non-ILE Program Calls” on page 467 should be applied to this
application.

SQL7913 - ODP deleted.

For a program that is run only once per job, this message could be normal.
However, if this message appears on every run of the statement or open of the
cursor, then the tips recommended in “Improving Performance by Retaining Cursor
Positions for Non-ILE Program Calls” on page 467 should be applied to this
application.

SQL7914 - ODP not deleted.

If the statement is rerun or the cursor is opened again, the ODP should be available
again for use.

SQL7915 - Access plan for SQL statement has been built.

The DB2 UDB for AS/400 precompilers allow the creation of the program objects
even when required tables are missing. In this case the binding of the access plan
is done when the program is first run. This message indicates that an access plan
was created and successfully stored in the program object.

SQL7916 - Blocking used for query.

SQL will request multiple records from the database manager when running this
statement instead of requesting one record at a time.

SQL7917 - Access plan not updated.

The database manager rebuilt the access plan for this statement, but the program
could not be updated with the new access plan. Another job is currently running the
program that has a shared lock on the access plan of the program.

The program cannot be updated with the new access plan until the job can obtain
an exclusive lock on the access plan of the program. The exclusive lock cannot be
obtained until the shared lock is released.

The statement will still run and the new access plan will be used; however, the
access plan will continue to be rebuilt when the statement is run until the program
is updated.

SQL7918 - Reusable ODP deleted.

A reusable ODP exists for this statement, but either the job’s library list or override
specifications have changed the query.

Chapter 22. Testing SQL Statements in Application Programs 389


The statement now refers to different files or uses different override specifications
than are in the existing ODP. The existing ODP cannot be reused, and a new ODP
must be created. To make it possible to reuse the ODP, avoid changing the library
list or the override specifications.

SQL7919 - Data conversion required on FETCH or embedded SELECT.

When mapping data to host variables, data conversions were required. When these
statements are run in the future, they will be slower than if no data conversions
were required. The statement ran successfully, but performance could be improved
by eliminating the data conversion. For example, a data conversion that would
cause this message to occur would be the mapping of a character string of a
certain length to a host variable character string with a different length. You could
also cause this error by mapping a numeric value to a host variable that is a
different type (decimal to integer). To prevent most conversions, use host variables
that are of identical type and length as the columns that are being fetched.

SQL7939 - Data conversion required on INSERT or UPDATE.

The attributes of the INSERT or UPDATE values are different than the attributes of
the columns receiving the values. Since the values must be converted, they cannot
be directly moved into the columns. Performance could be improved if the attributes
of the INSERT or UPDATE values matched the attributes of the columns receiving
the values.

390 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 23. Using the DB2 UDB for AS/400 Predictive Query
Governor
The DB2 UDB for AS/400 Predictive Query Governor (governor) can stop the
initiation of a query if the query’s estimated or predicted runtime (elapsed execution
time) is excessive. The governor acts before a query is run instead of while a query
is run. The governor can be used in any interactive or batch job on the AS/400. It
can be used with all DB2 UDB for AS/400 query interfaces and is not limited to use
with SQL queries.

| The ability of the governor to predict and stop queries before they are started is
| important because:
| v Operating a long-running query and abnormally ending the query before
| obtaining any results wastes system resources.
| v Some operations within a query cannot be interrupted by the End Request
| (ENDRQS) CL command. The creation of a temporary keyed access path or a
| query using a column function without a GROUP BY clause are two examples of
| these types of queries. It is important to not start these operations if they will take
| longer than the user wants to wait.

| The governor in DB2 UDB for AS/400 is based on the estimated runtime for a
query. If the query’s estimated runtime exceeds the user defined time limit, the
initiation of the query can be stopped.

| The time limit is user-defined and can be specified in one of three ways:
| v Using the Query Time Limit (QRYTIMLMT) parameter on the Change Query
| Attributes (CHGQRYA) CL command.
| v Setting the QQRYTIMLMT system value and allowing each job to use the value
| *SYSVAL on the CHGQRYA CL command.
v Setting the Query Time Limit option in the “Query Options File QAQQINI” on
page 543.

| The governor works in conjunction with the query optimizer. When a user requests
DB2 UDB for AS/400 to run a query, the following occurs:
1. The query access plan is evaluated by the optimizer.
As part of the evaluation, the optimizer predicts or estimates the runtime for the
query. This helps determine the best way to access and retrieve the data for the
query.
2. The estimated runtime is compared against the user-defined query time limit
currently in effect for the job or user session.
3. If the predicted runtime for the query is less than or equal to the query time
limit, the query governor lets the query run without interruption and no message
is sent to the user.
4. If the query time limit is exceeded, inquiry message CPA4259 is sent to the
user. The message states that the estimated query processing time of XX
seconds exceeds the time limit of YY seconds.

Note: A default reply can be established for this message so that the user does
not have the option to reply to the message, and the query request is
always ended.
5. If a default message reply is not used, the user chooses to do one of the
following:

© Copyright IBM Corp. 1997, 1999 391


v End the query request before it is actually run.
v Continue and run the query even though the predicted runtime exceeds the
governor time limit.

Cancelling a Query
When a query is expected to run longer than the set time limit, the governor issues
inquiry message CPA4259. The user enters a C to cancel the query or an I to
ignore the time limit and let the query run to completion. If the user enters C,
escape message CPF427F is issued to the SQL runtime code. SQL returns
SQLCODE -666.

General Implementation Considerations


| It is important to remember that the time limit generated by the optimizer is only an
| estimate. The actual query runtime could be more or less than the estimate, but the
| value of the two should be about the same. When setting the time limit for the
| entire system, it is usually best to set the limit to the maximum allowable time that
| any query should be allowed to run. By setting the limit too low you will run the risk
| of preventing some queries from completing and thus preventing the application
| from successfully finishing. There are many functions that use the query component
| to internally perform query requests. These requests will also be compared to the
| user-defined time limit.

User Application Implementation Considerations


| The time limit specified for the governor is established on a per-job basis by the
| query optimizer. The query optimizer determines the time limit using the following
| process:
| 1. The query optimizer attempts to extract the time limit from the QRYTIMLMT
| parameter on the CHGQRYA command.
| 2. If the time limit is not explicitly specified on the CHGQRYA command, it uses
| the query options file that is in use for this job.
| 3. If the time limit parameter in the query options file has been set to *DEFAULT,
| then the value that is stored in the QQRYTIMLMT system value is used for this
| job or user session.

| You can also set the time limit for a job other than the current job. You do this by
| using the JOB parameter on the CHGQRYA command to specify either a query
| options file library to search (QRYOPTLIB) or a specific QRYTIMLMT for that job.

After the source job runs the CHGQRYA command, effects of the governor on the
target job is not dependent upon the source job. The query time limit remains in
effect for the duration of the job or user session, or until the time limit is changed by
a CHGQRYA command. Under program control, a user could be given different
query time limits depending on the application function being performed, the time of
day, or the amount of system resources available. This provides a significant
amount of flexibility when trying to balance system resources with temporary query
requirements.

392 DB2 UDB for AS/400 SQL Programming V4R4


Controlling the Default Reply to the Inquiry Message
The system administrator can control whether the interactive user has the option of
ignoring the database query inquiry message by using the CHGJOB CL command
as follows:
v If a value of *DFT is specified for the INQMSGRPY parameter of the CHGJOB
CL command, the interactive user does not see the inquiry messages and the
query is canceled immediately.
v If a value of *RQD is specified for the INQMSGRPY parameter of the CHGJOB
CL command, the interactive user sees the inquiry and must reply to the inquiry.
v If a value of *SYSRPYL is specified for the INQMSGRPY parameter of the
CHGJOB CL command, a system reply list is used to determine whether the
interactive user sees the inquiry and whether a reply is necessary. For more
information on the *SYSRPYL parameter, see the CL Reference (Abridged) book.
The system reply list entries can be used to customize different default replies
based on user profile name, user id, or process names. The fully qualified job
name is available in the message data for inquiry message CPA4259. This will
allow the keyword CMPDTA to be used to select the system reply list entry that
applies to the process or user profile. The user profile name is 10 characters
long and starts at position 51. The process name is 10 character long and starts
at position 27. The following example will add a reply list element that will cause
the default reply of C to cancel any requests for jobs whose user profile is
’QPGMR’.
ADDRPYLE SEQNBR(56) MSGID(CPA4259) CMPDTA(QPGMR 51) RPY(C)

The following example will add a reply list element that will cause the default
reply of C to cancel any requests for jobs whose process name is ’QPADEV0011’.
ADDRPYLE SEQNBR(57) MSGID(CPA4259) CMPDTA(QPADEV0011 27) RPY(C)

Using the Governor for Performance Testing


The query governor lets you optimize performance without having to run through
several iterations of the query. If the query time limit is set to zero
( QRYTIMLMT(0) ) with the CHGQRYA command, the inquiry message is always
sent to the user saying the estimated time exceeds the query time limit. The
programmer can prompt for message help on the inquiry message and find the
same information which one can see from the PRTSQLINF (Print SQL Information)
command.

Additionally, if the query is canceled, the query optimizer evaluates the access plan
and sends the optimizer tuning messages to the joblog. This occurs even if the job
is not in debug mode. The user or a programmer can then review the optimizer
tuning messages in the joblog to see if additional tuning is needed to obtain optimal
query performance. Minimal system resources are used because the actual query
of the data is never actually done. If the files to be queried contain a large number
of records, this represents a significant savings in system resources.

| Be careful when you use this technique for performance testing, because all query
| requests will be stopped before they are run. This is especially important for a
| query that cannot be implemented in a single query step. For these types of
| queries, separate multiple query requests are issued, and then their results are
| accumulated before returning the final results. Stopping the query in one of these
| intermediate steps gives you only the performance information that relates to that
| intermediate step, and not for the entire query.

Chapter 23. Using the DB2 UDB for AS/400 Predictive Query Governor 393
Examples
| To set the query time limit for the current job or user session using query options
| file QAQQINI, specify QRYOPTLIB parameter on the CHGQRYA command to a
| user library where the QAQQINI file exists with the parameter set to
| QUERY_TIME_LIMIT, and the value set to a valid query time limit. For more
| information on setting the query options file, see “Query Options File QAQQINI” on
| page 543.

To set the query time limit for 45 seconds you would use the following CHGQRYA
command:
CHGQRYA JOB(*) QRYTIMLMT(45)

This sets the query time limit at 45 seconds. If the user runs a query with an
estimated runtime equal to or less than 45 seconds, the query runs without
interruption. The time limit remains in effect for the duration of the job or user
session, or until the time limit is changed by the CHGQRYA command.

Assume that the query optimizer estimated the runtime for a query as 135 seconds.
A message would be sent to the user that stated that the estimated runtime of 135
seconds exceeds the query time limit of 45 seconds.

| To set or change the query time limit for a job other than your current job, the
| CHGQRYA command is run using the JOB parameter. To set the query time limit to
| 45 seconds for job 123456/USERNAME/JOBNAME you would use the following
| CHGQRYA command:
| CHGQRYA JOB(123456/USERNAME/JOBNAME) QRYTIMLMT(45)

| This sets the query time limit at 45 seconds for job 123456/USERNAME/JOBNAME.
| If job 123456/USERNAME/JOBNAME tries to run a query with an estimated runtime
| equal to or less than 45 seconds the query runs without interruption. If the
| estimated runtime for the query is greater than 45 seconds, for example 50
| seconds, a message would be sent to the user stating that the estimated runtime of
| 50 seconds exceeds the query time limit of 45 seconds. The time limit remains in
| effect for the duration of job 123456/USERNAME/JOBNAME, or until the time limit
| for job 123456/USERNAME/JOBNAME is changed by the CHGQRYA command.

| To set or change the query time limit to the QQRYTIMLMT system value, use the
| following CHGQRYA command:
| CHGQRYA QRYTIMLMT(*SYSVAL)

| The QQRYTIMLMT system value is used for duration of the job or user session, or
| until the time limit is changed by the CHGQRYA command. This is the default
| behavior for the CHGQRYA command.

394 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 24. DB2 UDB for AS/400 Data Management and Query
Optimizer Tips
| This chapter provides guidelines for designing queries that will perform and will use
| system resources more efficiently. This chapter covers queries that are optimized by
| the query optimizer and includes interfaces such as SQL, OPNQRYF, and
| QUERY/400 queries. SQL and system resources more efficiently in application
| programs. As a general rule, most of the guidelines can be ignored, and the results
| will still be correct. However, if you apply the guidelines, your queries will run more
| efficiently.

| Note: The information in this chapter is complex. It may be helpful to experiment


| with an AS/400 system as you read this chapter to verify some of the
| information.

| If one understands how DB2 UDB for AS/400 processes queries, it is easier to
understand the performance impacts of the guidelines discussed in this chapter.
There are two major components of DB2 UDB for AS/400:
1. Data management methods
These methods are the algorithms used to retrieve data from the disk. The
methods include index usage and row selection techniques. In addition, parallel
access methods are available with the DB2 UDB Symmetric Multiprocessing
operating system feature.
2. Query optimizer
The query optimizer identifies the valid techniques which could be used to
implement the query and selects the most efficient technique.

General Optimization Tips


| Here are some tips to help your queries run as fast as possible:
v Create indexes whose leftmost key fields match your selection predicates to help
supply the optimizer with selectivity values (key range estimates).
v For join queries, create indexes that match your join fields to help the optimizer
determine the average number of matching rows.
v Minimize extraneous mapping by specifying only fields of interest on the query.
For example, in SQL, avoid SELECT* in favor of FOR FETCH ONLY on
read-only cursors.
v If your queries often use arrival sequence, use the RGZPFM (Reorganize
Physical File Member) command to remove deleted rows from tables or the
CHGPF (Change Physical File) REUSEDLT (*YES) command to reuse deleted
rows.

| For embedded SQL, consider using the following precompile options:


v Specify ALWCPYDTA(*OPTIMIZE) to allow the query optimizer to create
temporary copies of data if better performance can be obtained.
v Use CLOSWLCSR(*ENDJOB) or CLOSQLCSR(*ENDACTGRP) to allow open
data paths to remain open for future invocations.
v Specify DLYPRP(*YES) to delay SQL statement validation until an OPEN,
EXECUTE, or DESCRIBE statement is run. This option improves performance by
eliminating redundant validation.
v Use ALWBLK(*ALLREAD) to allow record blocking for read-only cursors.

© Copyright IBM Corp. 1997, 1999 395


| For OPNQRYF (Open Query File) queries, consider using the following parameters:
v Use ALWCPYDTA(*OPTIMIZE) to let the query optimizer create temporary copies
of data if it can obtain better performance by doing so.
v Use OPTIMIZE(*FIRSTIO) to bias the optimizer to use an existing index instead
of creating a temporary index.

Data Management Methods


This section introduces the fundamental techniques used by DB2 UDB for AS/400
and the AS/400 Licensed Internal Code to access data.

Access Path
An access path is the path used to locate data specified in a query. An access path
can be indexed, sequential, or a combination of both.

Sequential Access Path


A sequential access path uses the order of rows as they are stored in the table to
locate data specified in a query. Processing tables using the sequential access path
is similar to processing sequential or direct files on traditional systems.

Keyed Sequence Access Path


A keyed sequence access path provides access to a table that is arranged
according to the contents of key fields (indexes). The keyed sequence is the order
in which rows are retrieved. The access path is automatically maintained whenever
rows are added to or deleted from the table, or whenever the contents of the index
columns are changed. The best example of a keyed sequence access path is an
index created using the CREATE INDEX statement or a logical file created using
the CRTLF command.

Columns that are good candidates for creating keyed sequence access paths are:
| v Those frequently referenced in row selection predicates.
| v Those frequently referenced in grouping or ordering.
v Those used to join tables (see “Join Optimization” on page 426).

Encoded Vector Access Paths


An encoded vector access path provides access to a database file by assigning
codes to distinct key values and then representing these values in an array. The
elements of the array can be 1, 2, or 4 bytes in length, depending on the number of
distinct values that must be represented. Because of their compact size and relative
simplicity, encoded vector access paths provide for faster scans that can be more
easily processed in parallel.

You create encoded vector access paths by using the SQL CREATE INDEX
statement. For more information about accelerating your queries with encoded
vector indexes , go to the DB2 for AS/400 web pages.

For a further description of access paths, refer to the Data Management book.

396 DB2 UDB for AS/400 SQL Programming V4R4


Access Method
The Licensed Internal Code and DB2 UDB for AS/400 share the work on access
methods. The Licensed Internal Code does the low-level processing which includes
selection, join functions, hashing, and access path creation.

The query optimization process chooses the most efficient access method for each
query and keeps this information in the access plan. The type of access is
dependent on the number of rows, the expected number of page faults 17, and
other criteria.

The possible methods the optimizer can use to retrieve data include:
v Dataspace scan method (a dataspace is an internal object that contains the data
in a table) (page 399)
v Parallel pre-fetch method (page 401)
v Key selection method (page 404)
v Key positioning method (page 406)
v Parallel table or index pre-load (page 413)
v Index-from-index method (page 414)
v Index only access method (page 412)
v Hashing method (page 415)
v Bitmap processing method (page 416)

The DB2 UDB Symmetric Multiprocessing feature provides the optimizer with
additional methods for retrieving data that include parallel processing.

Symmetrical multiprocessing (SMP) is a form of parallelism achieved on a single


system where multiple processors (CPU and I/O processors) that share memory
and disk resource work simultaneously towards achieving a single end result. This
parallel processing means that the database manager can have more than one (or
all) of the system processors working on a single query simultaneously. The
performance of a CPU bound query can be significantly improved with this feature
on multiple-processor systems by distributing the processor load across more than
one processor on the system.

17. An interrupt that occurs when a program refers to a 4K-byte page that is not in main storage.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 397
┌───────────────────┐
│ QUERY │
└─────────┬─────────┘

┌────────────┬─────┴─────┬────────────┐
│ │ │ │
│ │ │ │
ø ø ø ø
┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐
│ │ │ │ │ │ │ │
│ CPU │ │ CPU │ │ CPU │ │ CPU │
│ │ │ │ │ │ │ │
└───┬───┘ └───┬───┘ └───┬───┘ └───┬───┘
│ │ │ │
└────────────┴─────┬─────┴────────────┘

┌─────────────┴──────────────┐
│ │
│ SHARED MEMORY │
│ │
└────────────────────────────┘

Figure 13. Database Symmetric Multiprocessing

The following methods are available to the optimizer once the DB2 UDB Symmetric
Multiprocessing feature has been installed on your system:
v Parallel data space scan method (page 402)
v Parallel key selection method (page 405)
v Parallel key positioning method (page 410)
v Parallel index only access method (parallel and non-parallel) (page 412)
v Parallel hashing method (parallel and non-parallel) (page “Hashing Access
Method” on page 415)
v Parallel bitmap processing method (page 416)

Ordering
An ORDER BY clause (or OPNQRYF KEYFLD parameter) must be specified to
guarantee a particular ordering of the results. Before parallel access methods were
available, the database manager processed table rows (and keyed sequences) in a
sequential manner. This caused the sequencing of the results to be somewhat
predictable even though an ordering was not included in the original query request.
Because parallel methods cause blocks of table rows and key values to be
processed concurrently, the ordering of the retrieved results becomes more random
and unpredictable. An ORDER BY clause is the only way to guarantee the specific
sequencing of the results. However, an ordering request should only be specified
when absolutely required, because the sorting of the results can increase both CPU
utilization and response time.

Enabling Parallel Processing


| The application or user must enable parallel processing for queries; the optimizer
| does not automatically use parallelism as the chosen access method. You can use
| the system-value QQRYDEGREE, the query options file, and the DEGREE
| parameter on the Change Query Attributes (CHGQRYA) command to control the

398 DB2 UDB for AS/400 SQL Programming V4R4


| degree of parallelism that the query optimizer uses. See “Controlling Parallel
| Processing” on page 473 for information on how to control parallel processing.

A set of database system tasks are created at system startup for use by the
database manager. The database manager uses the tasks to process and retrieve
data from different disk devices. Since these tasks can be run on multiple
processors simultaneously, the elapsed time of a query can be reduced. Even
though much of the I/O and CPU processing of a parallel query is done by the
tasks, the accounting of the I/O and CPU resources used are transferred to the
application job. The summarized I/O and CPU resources for this type of application
continue to be accurately displayed by the Work with Active Jobs (WRKACTJOB)
command.

Automatic Data Spreading


DB2 UDB for AS/400 automatically spreads the data across the disk devices
available in the auxiliary storage pool (ASP) where the data is allocated. This
ensures that the data is spread without user intervention. The spreading allows the
database manager to easily process the blocks of records on different disk devices
in parallel.

Even though DB2 UDB for AS/400 spreads data across disk devices within an ASP,
sometimes the allocation of the data extents (contiguous sets of data) might not be
spread evenly. This occurs when there is uneven allocation of space on the
devices, or when a new device is added to the ASP. The allocation of the data
space may be spread again by saving, deleting, and then restoring the table.

Dataspace Scan Access Method


| The rows in the table are processed in no guaranteed order. If you want the result
| in a particular sequence, you must specify the ORDER BY clause (or OPNQRYF
| KEYFLD parameter). All rows in the table are read. The selection criteria is applied
| to each row, and only the rows that match the criteria are returned to the calling
| application.

Dataspace scan can be very efficient for the following reasons:


v It minimizes the number of page I/O operations because all rows in a given page
are processed, and once the page is in main storage, the page is not retrieved
again.
v The database manager can easily predict the sequence of pages from the
dataspace for retrieval. For this reason, the database manager can schedule
asynchronous I/O of the pages into main storage from auxiliary storage. This is
commonly referred to as pre-fetching. This is done so that the page is available
in main storage when the database manager needs to access the data.

This selection method is very good when a large percentage of the rows are to be
selected. A large percentage is generally 20% or more.

| Dataspace scan processing can be adversely affected when rows are selected from
| a table that contains deleted rows. This is because the delete operation only marks
| rows as deleted. For dataspace scan processing, the database manager reads all
| of the deleted rows, even though none of the deleted rows are ever selected. You
| should use the Reorganize Physical File Member (RGZPFM) CL command to
| eliminate deleted rows. Specifying REUSEDLT(*YES) on the physical file can also
| reuse the deleted record space. SQL tables are created with REUSEDLT(*YES).

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 399
Dataspace scan processing is not very efficient when a small percentage of rows in
the table will be selected. Because all rows in the table are examined, this leads to
unnecessary use of I/O and processing unit resources.

The messages created by the PRTSQLINF CL command to describe a query in an


SQL program which is using the dataspace selection method would appear as
follows:
SQL4010 Arrival sequence access for file 1.

The Licensed Internal Code can use one of two algorithms for selection when a
dataspace scan is processed, intermediate buffer selection and dataspace element
selection.

The following pseudocode illustrates the intermediate buffer selection algorithm:

DO UNTIL END OF FILE

1. Address the next (or first) record

2. Map all column values to an internal buffer, performing all derived


operations.

3. Evaluate the selection criteria to a TRUE or FALSE value using


the column values as they were copied to internal buffer.

4. IF the selection is TRUE


THEN
Copy the values from the internal buffer into the
user's answer buffer.
ELSE
No operation
END

The dataspace entry algorithm is as follows:

DO UNTIL END OF FILE

1. Calculate a search limit. This limit is usually the number of


records which are already in active memory, or have already
had an I/O request done to be loaded into memory.

2. DO UNTIL (search limit reached


or record selection criteria is TRUE)
a. Address the next (or first) record

b. Evaluate any selection criteria which does not


require a derived value directly for the dataspace
record.

END

3. IF the selection is true


THEN
a. Map all column values to an internal buffer, performing all
derived operations.

b. Copy the values from the internal buffer into the


user's answer buffer.
ELSE
No operation
END

400 DB2 UDB for AS/400 SQL Programming V4R4


The dataspace entry selection algorithm provides better performance than
intermediate buffer selection for two reasons:
v Data movement and computations are only done on records which are selected.
v The loop in step 2 of the dataspace entry selection algorithm is generated into an
executable code burst. When a small percentage of records are actually
selected, DB2 UDB for AS/400 will be running this very small program until a
record is found.

No action is necessary for queries of this type to make use of the dataspace scan
method. Any query interface can utilize this improvement. However, the following
guidelines determine whether a selection predicate can be implemented as
dataspace selection:
v Neither operand of the predicate can be of any kind of a derived value, function,
substring, concatenation, or numeric expression.
v When both operands of a selection predicate are numeric columns, both columns
must have the same type, scale, and precision; otherwise, one operand is
mapped into a derived value. For example, a DECIMAL(3,1) must only be
compared against another DECIMAL(3,1) column.
v When one operand of a selection predicate is a numeric column and the other is
a literal or host variable, then the types must be the same and the precision and
scale of the literal/host variable must be less than or equal to that of the column.
v Selection predicates involving packed decimal or numeric types of columns can
only be done if the table was created by the SQL CREATE TABLE statement.
v A varying length character column cannot be referenced in the selection
predicate.
v When one operand of a selection predicate is a character column and the other
is a literal or host variable, then the length of the host variable cannot be greater
than that of the column.
v Comparison of character column data must not require CCSID or key board shift
translation.

It can be important to avoid intermediate buffer selection because the reduction in


CPU and response time for dataspace entry selection can be large, in some cases
as high as 70-80%. The queries that will benefit the most from dataspace selection
are those where less than 60% of the file is actually selected. The lower the
percentage of records selected, the more noticeable the performance benefit will
be.

Parallel Pre-Fetch Access Method


DB2 UDB for AS/400 can also use parallel pre-fetch processing to shorten the
processing time required for long-running I/O-bound dataspace scan queries.

| This method has the same characteristics as the dataspace scan method; except
| that the I/O processing is done in parallel. This is accomplished by starting multiple
| input streams for the table to pre-fetch the data. This method is most effective when
| the following are true:
| v The data is spread across multiple disk devices.
| v The query is not CPU-processing-intensive.
| v There is an ample amount of main storage available to hold the data collected
| from every input stream.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 401
| As mentioned previously, DB2 UDB for AS/400 automatically spreads the data
| across the disk devices without user intervention, allowing the database manager to
| pre-fetch table data in parallel. The database manager uses tasks to retrieve data
| from different disk devices. Usually the request is for an entire extent (contiguous
| set of data). This improves performance because the disk device can use smooth
| sequential access to the data. Because of this optimization, parallel prefetch can
| pre-load data to active memory faster than the SETOBJACC CL command.

Even though DB2 UDB for AS/400 spreads data across disk devices within an ASP,
sometimes the allocation of the dataspace extents may not be spread evenly. This
occurs when there is uneven allocation of space on the devices or a new device is
added to the ASP. The allocation of the dataspace can be respread by saving,
deleting, and restoring the table.

The query optimizer selects the candidate queries which can take advantage of this
type of implementation. The optimizer selects the candidates by estimating the CPU
time required to process the query and comparing the estimate to the amount of
time required for input processing. When the estimated input processing time
exceeds the CPU time, the query optimizer indicates that the query may be
implemented with parallel I/O.

| Parallel pre-fetch requires that I/O parallel processing must be enabled either by the
| system value QQRYDEGREE, the query option file, or by the DEGREE parameter
| on the Change Query Attributes (CHGQRYA) command. See “Controlling Parallel
| Processing” on page 473 for information on how to control parallel processing.
| Because queries being processed with parallel pre-fetch aggressively utilize main
| store and disk I/O resources, the number of queries that use parallel pre-fetch
| should be limited and controlled. Parallel prefetch utilizes multiple disk arms, but it
| does little utilization of multiple CPUs for any given query. Parallel prefetch I/O will
| use I/O resources intensely. Allowing a parallel prefetch query on a system with an
| overcommitted I/O subsystem may intensify the over-commitment problem.

You should run the job in a shared storage pool with the *CALC paging option
because this will cause more efficient use of active memory. DB2 UDB for AS/400
uses the automated system tuner to determine how much memory this process is
allowed to use. At run-time, the Licensed Internal Code will allow parallel pre-fetch
to be used only if the memory statistics indicate that it will not over-commit the
memory resources. For more information on the paging option see the “Automatic
System Tuning” section of the Work Management book.

Parallel pre-fetch requires that enough main storage be available to cache the data
being retrieved by the multiple input streams. For large files, the typical extent size
is 1 megabyte. This means that 2 megabytes of memory must be available in order
to use 2 input streams concurrently. Increasing the amount of available memory in
the pool allows more input streams to be used. If there is plenty of available
memory, the entire dataspace for the table may be loaded into active memory when
the query is opened.

The messages created by the PRTSQLINF command to describe a query in an


SQL program which is using the parallel pre-fetch access method would appear as
follows:
SQL4023 Parallel dataspace pre-fetch used.

402 DB2 UDB for AS/400 SQL Programming V4R4


Parallel Data Space Scan Method (available only when the DB2
UDB Symmetric Multiprocessing feature is installed)
DB2 UDB for AS/400 can use this parallel access method to shorten the processing
time required for long-running data space scan queries. The parallel data space
scan method reduces the I/O processing time like the parallel pre-fetch access
method. In addition, if running on a system that has more than one processor, this
method can reduce the elapsed time of a query by splitting the data space scan
processing into tasks that can be run on the multiple processors simultaneously. All
selection and column processing is performed in the task. The application’s job
schedules the work requests to the tasks and merges the results into the result
buffer that is returned to the application.

This method is most effective when the following are true:


v The data is spread across multiple disk devices.
v The system has multiple processors that are available.
v There is an ample amount of main storage available to hold the data buffers and
result buffers.

| As mentioned previously, DB2 UDB for AS/400 automatically spreads the data
| across the disk devices without user intervention, allowing the database manager to
| pre-fetch table data in parallel.

The query optimizer selects the candidate queries that can take advantage of this
type of implementation. The optimizer selects the candidates by estimating the CPU
time required to process the query and comparing the estimate to the amount of
time required for input processing. The optimizer reduces its estimated elapsed time
for data space scan based on the number of tasks it calculates should be used. It
calculates the number of tasks based on the number of processors in the system,
the amount of memory available in the job’s pool, and the current value of the
DEGREE query attribute. If the parallel data space scan is the fastest access
method, it is then chosen.

Parallel data space scan requires that SMP parallel processing must be enabled
either by the system value QQRYDEGREE, the query option file, or by the
DEGREE parameter on the Change Query Attributes (CHGQRYA) command. See
“Controlling Parallel Processing” on page 473 for information on how to control
parallel processing.

Parallel data space scan cannot be used for queries that require any of the
following:
v Specification of the *ALL commitment control level.
v Nested loop join implementation. See “Nested Loop Join Implementation” on
page 426.
| v Backward scrolling. For example, parallel data space scan cannot normally be
| used for queries defined by the Open Query File (OPNQRYF) command, which
| specify ALWCPYDTA(*YES) or ALWCPYDTA(*NO), because the application
| might attempt to position to the last record and retrieve previous records.
| SQL-defined queries that are not defined as scrollable can use this method.
| Parallel data space scan can be used during the creation of a temporary result,
| such as a sort or hash operation, no matter what interface was used to define
| the query. OPNQRYF can be defined as not scrollable by specifying the
| *OPTIMIZE parameter value for the ALWCPYDTA parameter, which enbles the
| usage of most of the parallel access methods.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 403
v Restoration of the cursor position. For instance, a query requiring that the cursor
position be restored as the result of the SQL ROLLBACK HOLD statement or the
ROLLBACK CL command. SQL applications using a commitment control level
other than *NONE should specify *ALLREAD as the value for precompiler
parameter ALWBLK to allow this method to be used.
v Update or delete capability.

You should run the job in a shared storage pool with the *CALC paging option, as
this will cause more efficient use of active memory. For more information on the
paging option see the “Automatic System Tuning” section of the Work Management
book.

Parallel data space scan requires active memory to buffer the data being retrieved
and to separate result buffers for each task. A typical total amount of memory
needed for each task is about 2 megabytes. For example, about 8 megabytes of
memory must be available in order to use 4 parallel data space scan tasks
concurrently. Increasing the amount of available memory in the pool allows more
input streams to be used. Queries that access tables with large varying length
character columns, or queries that generate result values that are larger than the
actual record length of the table might require more memory for each task.

The performance of parallel data space scan can be severely limited if numerous
record locking conflicts or data mapping errors occur.

Key Selection Access Method


This access method requires keyed sequence access paths. The entire index is
read and any selection criteria that references the key columns of the index is
applied against the index. The advantage of this method is that the dataspace is
only accessed to retrieve rows that satisfy the selection criteria applied against the
index. Any additional selection not performed through the key selection method is
performed at the dataspace level.

The key selection access method can be very expensive if the search condition
applies to a large number of rows because:
v The whole index is processed.
v For every key selected from the index, a random I/O to the dataspace occurs.

Normally, the optimizer would choose to use dataspace scan processing when the
search condition applies to a large number of rows. The optimizer only chooses the
key selection method if less than 20% of the keys are selected or if an operation
forces the use of an index. Options that might force the use of an index include:
v Ordering
v Grouping
v Joining

| In these cases, the optimizer may choose to create a temporary index rather than
| use an existing index. When the optimizer creates a temporary index, it uses a 32K
| page size. An index created using a CREATE INDEX statement or the CRTLF
| command normally uses only a 4K page size. The optimizer also processes as
| much of the selection as possible while building the temporary index. Nearly all
| temporary indexes built by the optimizer are select/omit or sparse indexes. Finally,
| the optimizer can use multiple parallel tasks when creating the index. The page size
| difference, corresponding performance improvement from swapping in fewer pages,

404 DB2 UDB for AS/400 SQL Programming V4R4


| and the ability to use parallel tasks to create the index may be enough to overcome
| the overhead of creating an index. Dataspace selection is used for building of
| temporary keyed access paths.

| If key selection access method is used because the query specified ordering (an
| index was required) the query performance might be improved by using the
| following parameters to allow the ordering to be done with the query sort.
| v For SQL, the following combinations of precompiler parameters:
| – ALWCPYDTA(*OPTIMIZE), ALWBLK(*ALLREAD), and COMMIT(*CHG or
| *CS)
| – ALWCPYDTA(*OPTIMIZE) and COMMIT(*NONE)
| v For OPNQRYF, the following parameters:
| – *ALWCPYDTA(*OPTIMIZE) and COMMIT(*NO)
| – ALWCPYDTA(*OPTIMIZE) and COMMIT(*YES) and the commitment control
| level is started with a commit level of *NONE, *CHG, or *CS

| When a query specifies a select/omit index and the optimizer decides to build a
| temporary index, all of the selection from the select/omit index is put into the
| temporary index after any applicable selection from the query.

Parallel Key Selection Access Method (available only when the


DB2 UDB Symmetric Multiprocessing feature is installed)
For the parallel key selection access method, the possible key values are logically
partitioned. Each partition is processed by a separate task just as in the key
selection access method. The number of partitions processed concurrently is
determined by the query optimizer. Because the keys are not processed in order,
this method cannot be used by the optimizer if the index is being used for ordering.
Key partitions that contain a larger portion of the existing keys from the index are
further split as processing of other partitions complete.

The following example illustrates a query where the optimizer could choose the key
selection method:
CREATE INDEX X1
ON EMPLOYEE(LASTNAME,WORKDEPT)

DECLARE BROWSE2 CURSOR FOR


SELECT * FROM EMPLOYEE
WHERE WORKDEPT = 'E01'
OPTIMIZE FOR 99999 ROWS

OPNQRYF example:
OPNQRYF FILE((EMPLOYEE))
QRYSLT('WORKDEPT *EQ ''E01''')

If the optimizer chooses to run this query in parallel with a degree of four, the
following might be the logical key partitions that get processed concurrently:
LASTNAME values LASTNAME values
leading character leading character
partition start partition end
'A' 'F'
'G' 'L'
'M' 'S'
'T' 'Z'

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 405
If there were fewer keys in the first and second partition, processing of those key
values would complete sooner than the third and fourth partitions. After the first two
partitions are finished, the remaining key values in the last two might be further
split. The following shows the four partitions that might be processed after the first
and second partition are finished and the splits have occurred:
LASTNAME values LASTNAME values
leading character leading character
partition start partition end
'O' 'P'
'Q' 'S'
'V' 'W'
'X' 'Z'

Parallel key selection cannot be used for queries that require any of the following:
v Specification of the *ALL commitment control level.
v Nested loop join implementation. See “Nested Loop Join Implementation” on
page 426.
| v Backward scrolling. For example, parallel key selection cannot be used for
| queries defined by the Open Query File (OPNQRYF) command which specify
| ALWCPYDTA(*YES) or ALWCPYDTA(*NO), because the application might
| attempt to position to the last record and retrieve previous records. SQL defined
| queries that are not defined as scrollable can use this method. Parallel key
| selection can be used during the creation of a temporary result, such as a sort or
| hash operation, no matter what interface was used to define the query.
| v Restoration of the cursor position (for instance, a query requiring that the cursor
| position be restored as the result of the SQL ROLLBACK HOLD statement or the
| ROLLBACK CL command). OPNQRYF can be defined as not scrollable by
| specifying the *OPTIMIZE parameter value for the ALWCPYDTA parameter,
| which enables the usage of most of the parallel access methods. SQL
| applications using a commitment control level other than *NONE should specify
| *ALLREAD as the value for precompiler parameter ALWBLK to allow this method
| to be used.
v Update or delete capabilitiy.

You should run the job in a shared pool with *CALC paging option as this will cause
more efficient use of active memory. For more information on the paging option see
the “Automatic System Tuning” section of the Work Management book.

| Parallel key selection requires that SMP parallel processing be enabled either by
| the system value QQRYDEGREE, the query options file, or by the DEGREE
| parameter on the Change Query Attributes (CHGQRYA) command. See “Controlling
| Parallel Processing” on page 473 for information on how to control parallel
| processing.

Key Positioning Access Method


This access method is very similar to the key selection access method. They both
require a keyed sequence access path. In the key selection access method,
processing starts at the beginning of the index and continues to the end. In the key
positioning access method, selection is against the index directly on a range of keys
that match some or all of the selection criteria. All the keys from this range are read
and any remaining key selection is performed. This is similar to the selection
performed by the key selection method. Any selection not performed through key
positioning or key selection is performed at the dataspace level. Because key

406 DB2 UDB for AS/400 SQL Programming V4R4


positioning only processes a subset of the keys in the index, the performance of the
key positioning method is better than the performance of the key selection method.

The key positioning method is most efficient when a small percentage of rows are
to be selected (less than approximately 20%). If more than approximately 20% of
the rows are to be selected, the optimizer generally chooses to:
v Use dataspace scan processing (if index is not required)
v Use key selection (if an index is required)
v Use query sort routine (if conditions apply)
For queries that do not require an index (no ordering, grouping, or join operations),
the optimizer tries to find an existing index to use for key positioning. If no existing
index can be found, the optimizer stops trying to use keyed access to the data
because it is faster to use dataspace scan processing than it is to build an index
and then perform key positioning.

The following example illustrates a query where the optimizer could choose the key
positioning method:
CREATE INDEX X1 ON EMPLOYEE(WORKDEPT)

DECLARE BROWSE2 CURSOR FOR


SELECT * FROM EMPLOYEE
WHERE WORKDEPT = 'E01'
OPTIMIZE FOR 99999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE))
| QRYSLT('WORKDEPT *EQ ''E01''')

| In this example, the database support uses X1 to position to the first index entry
with the WORKDEPT value equal to ’E01’. For each key equal to ’E01’, it randomly
accesses the dataspace 18 and selects the row. The query ends when the key
selection moves beyond the key value of E01.

Note that for this example all index entries processed and rows retrieved meet the
selection criteria. If additional selection is added that cannot be performed through
key positioning (such as selection columns which do not match the first key
columns of an index over multiple columns) the optimizer uses key selection to
perform as much additional selection as possible. Any remaining selection is
performed at the dataspace level.

The messages created by the PRTSQLINF CL command to describe this query in


an SQL program would appear as follows:
SQL4008 Access path X1 used for file 1.
SQL4011 Key row positioning used on file 1.

The key positioning access method has additional processing capabilities. One such
capability is to perform range selection across several values. For example:
CREATE INDEX X1 EMPLOYEE(WORKDEPT)

DECLARE BROWSE2 CURSOR FOR


SELECT * FROM EMPLOYEE
WHERE WORKDEPT BETWEEN 'E01' AND 'E11'
OPTIMIZE FOR 99999 ROWS

18. random accessing occurs because the keys may not be in the same sequence as the rows in the dataspace

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 407
| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE))
| QRYSLT('WORKDEPT *EQ %RANGE(''E01'' ''E11'')')

| In the previous example, the database support positions to the first index entry
equal to value ’E01’ and rows are processed until the last index entry for ’E11’ is
processed.

The messages created by PRTSQLINF CL command to describe this query in an


SQL program would appear as follows:
SQL4008 Access path X1 used for file 1.
SQL4011 Key row positioning used on file 1.

A further extension of this access method, called multi-range key positioning, is


available. It allows for the selection of rows for multiple ranges of values for the first
key columns of an index over multiple columns.
CREATE INDEX X1 ON EMPLOYEE(WORKDEPT)

DECLARE BROWSE2 CURSOR FOR


SELECT * FROM EMPLOYEE
WHERE WORKDEPT BETWEEN 'E01' AND 'E11'
OR WORKDEPT BETWEEN 'A00' AND 'B01'
OPTIMIZE FOR 99999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE))
| QRYSLT('WORKDEPT *EQ %RANGE(''E01'' ''E11'')
| *OR WORKDEPT *EQ %RANGE(''A00'' ''B01'')')

| In the previous example, the positioning and processing technique is used twice,
once for each range of values.

The messages created by PRTSQLINF CL command to describe this query in an


SQL program would appear as follows:
SQL4008 Access path X1 used for file 1.
SQL4011 Key row positioning used on file 1.

All of the key positioning examples have so far only used one key, the left-most key,
of the index. Key positioning also handles more than one key (although the keys
must be contiguous to the left-most key).
CREATE INDEX X2
ON EMPLOYEE(WORKDEPT,LASTNAME,FIRSTNME)

DECLARE BROWSE2 CURSOR FOR


SELECT * FROM EMPLOYEE
WHERE WORKDEPT = 'D11'
AND FIRSTNME = 'DAVID'
OPTIMIZE FOR 99999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE))
| QRYSLT('WORKDEPT *EQ ''D11''
| *AND FIRSTNME *EQ ''DAVID''')

| Because the two selection keys (WORKDEPT and FIRSTNME) are not contiguous,
there is no multiple key position support for this example. Therefore, only the
WORKDEPT = ’D11’ part of the selection can be applied against the index (single
key positioning). While this may be acceptable, it means that the processing of rows

408 DB2 UDB for AS/400 SQL Programming V4R4


starts with the first key of ’D11’ and then uses key selection to process the
FIRSTNME = ’DAVID’ against all 9 keys with WORKDEPT key value = ’D11’.

By creating the following index, X3, the above example query would run using
multiple key positioning.
CREATE INDEX X3
ON EMPLOYEE(WORKDEPT, FIRSTNME, LASTNAME)

Multiple key positioning support can apply both pieces of selection as key
positioning. This improves performance considerably. A starting value is built by
concatenating the two selection values into ’D11DAVID’ and selection is positioned
to the index entry whose left-most two keys have that value.

The messages created by the PRTSQLINF CL command when used to describe


this query in an SQL program would look like this:
SQL4008 Access path X3 used for file 1.
SQL4011 Key row positioning used on file 1.

| This next example shows a more interesting use of multiple key positioning.
|
| CREATE INDEX X3 ON EMPLOYEE(WORKDEPT,FIRSTNME)
|
| DECLARE BROWSE2 CURSOR FOR
| SELECT * FROM EMPLOYEE
| WHERE WORKDEPT = 'D11'
| AND FIRSTNME IN ('DAVID','BRUCE','WILLIAM')
| OPTIMIZE FOR 99999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE))
| QRYSLT('WORKDEPT *EQ ''D11''
| *AND FIRSTNME *EQ %VALUES(''DAVID'' ''BRUCE''
| ''WILLIAM'')')

| The query optimizer analyzes the WHERE clause and rewrites the clause into an
equivalent form:
DECLARE BROWSE2 CURSOR FOR
SELECT * FROM EMPLOYEE
WHERE (WORKDEPT = 'D11' AND FIRSTNME = 'DAVID')
OR (WORKDEPT = 'D11' AND FIRSTNME = 'BRUCE')
OR (WORKDEPT = 'D11' AND FIRSTNME = 'WILLIAM')
OPTIMIZE FOR 99999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE))
| QRYSLT('(WORKDEPT *EQ ''D11'' *AND FIRSTNME *EQ
| ''DAVID'')
| *OR (WORKDEPT *EQ ''D11'' *AND FIRSTNME *EQ ''BRUCE'')
| *OR (WORKDEPT *EQ ''D11'' *AND FIRSTNME *EQ ''WILLIAM'')')

| In the rewritten form of the query there are actually 3 separate ranges of key values
for the concatenated values of WORKDEPT and FIRSTNME:
Index X3 Start value Index X3 Stop value
'D11DAVID' 'D11DAVID'
'D11BRUCE' 'D11BRUCE'
'D11WILLIAM' 'D11WILLIAM'

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 409
Key positioning is performed over each range, significantly reducing the number of
keys selected to just 3. All of the selection can be accomplished through key
positioning.

The complexity of this range analysis can be taken to a further degree in the
following example:
DECLARE BROWSE2 CURSOR FOR
SELECT * FROM EMPLOYEE
WHERE (WORKDEPT = 'D11'
AND FIRSTNME IN ('DAVID','BRUCE','WILLIAM'))
OR (WORKDEPT = 'E11'
AND FIRSTNME IN ('PHILIP','MAUDE'))
OR (FIRSTNME BETWEEN 'CHRISTINE' AND 'DELORES'
AND WORKDEPT IN ('A00','C01'))

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE))
| QRYSLT('(WORKDEPT *EQ ''D11''
| *AND FIRSTNME *EQ %VALUES(''DAVID'' ''BRUCE'' ''WILLIAM''))
| *OR (WORKDEPT *EQ ''E11''
| *AND FIRSTNME *EQ %VALUES(''PHILIP'' ''MAUDE''))
| *OR (FIRSTNME *EQ %RANGE(''CHRISTINE'' ''DELORES'')
| *AND WORKDEPT *EQ %VALUES(''A00'' ''C01''))')

| The query optimizer analyzes the WHERE clause and rewrites the clause into an
equivalent form:
DECLARE BROWSE2 CURSOR FOR
SELECT * FROM EMPLOYEE
WHERE (WORKDEPT = 'D11' AND FIRSTNME
= 'DAVID')
OR (WORKDEPT = 'D11' AND FIRSTNME
= 'BRUCE')
OR (WORKDEPT = 'D11' AND FIRSTNME
= 'WILLIAM')
OR (WORKDEPT = 'E11' AND FIRSTNME
= 'PHILIP')
OR (WORKDEPT = 'E11' AND FIRSTNME
= 'MAUDE')
OR (WORKDEPT = 'A00' AND FIRSTNME
BETWEEN
'CHRISTINE' AND 'DELORES')
OR (WORKDEPT = 'C01' AND FIRSTNME BETWEEN
'CHRISTINE' AND 'DELORES')
OPTIMIZE FOR 99999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE))
| QRYSLT('(WORKDEPT *EQ ''D11'' *AND FIRSTNME *EQ
| ''DAVID'')
| *OR (WORKDEPT *EQ ''D11'' *AND FIRSTNME *EQ ''BRUCE'')
| *OR (WORKDEPT *EQ ''D11'' *AND FIRSTNME *EQ
| ''WILLIAM'')
| *OR (WORKDEPT *EQ ''E11'' *AND FIRSTNME *EQ ''PHILIP'')
| *OR (WORKDEPT *EQ ''E11'' *AND FIRSTNME *EQ ''MAUDE'')
| *OR (WORKDEPT *EQ ''A00'' *AND
| FIRSTNME *EQ %RANGE(''CHRISTINE'' ''DELORES''))
| *OR (WORKDEPT *EQ ''C01'' *AND
| FIRSTNME *EQ %RANGE(''CHRISTINE'' ''DELORES''))')

| In the query there are actually 7 separate ranges of key values for the
concatenated values of WORKDEPT and FIRSTNME:
Index X3 Start value Index X3 Stop value
'D11DAVID' 'D11DAVID'
'D11BRUCE' 'D11BRUCE'
'D11WILLIAM' 'D11WILLIAM'
'E11MAUDE' 'E11MAUDE'

410 DB2 UDB for AS/400 SQL Programming V4R4


'E11PHILIP' 'E11PHILIP'
'A00CHRISTINE' 'A00DELORES'
'C01CHRISTINE' 'C01DELORES'

Key positioning is performed over each range. Only those rows whose key values
fall within one of the ranges are returned. All of the selection can be accomplished
through key positioning. This significantly improves the performance of this query.

Parallel Key Positioning Access Method (available only when the


DB2 UDB Symmetric Multiprocessing feature is installed)
Using the parallel key positioning access method, the existing key ranges are
processed by separate tasks concurrently in separate database tasks. The number
of concurrent tasks is controlled by the optimizer. The query will start processing the
key ranges of the query up to the degree of parallelism being used. As processing
of those ranges completes, the next ones on the list are started. As processing for a
range completes and there are no more ranges in the list to process, ranges that
still have keys left to process are split, just as in the parallel key selection method.
The database manager attempts to keep all of the tasks that are being used busy,
each processing a separate key range. Whether using the single value, range of
values, or multi-range key positioning, the ranges can be further partitioned and
processed simultaneously. Because the keys are not processed in order, this
method can not be used by the optimizer if the index is being used for ordering.

Consider the following example if the SQL statement is run using parallel degree of
four.
DECLARE BROWSE2 CURSOR FOR
SELECT * FROM EMPLOYEE
WHERE (WORKDEPT = 'D11' AND FIRSTNME
= 'DAVID')
OR (WORKDEPT = 'D11' AND FIRSTNME
= 'BRUCE')
OR (WORKDEPT = 'D11' AND FIRSTNME
= 'WILLIAM')
OR (WORKDEPT = 'E11' AND FIRSTNME
= 'PHILIP')
OR (WORKDEPT = 'E11' AND FIRSTNME
= 'MAUDE')
OR (WORKDEPT = 'A00' AND FIRSTNME
BETWEEN
'CHRISTINE' AND 'DELORES')
OR (WORKDEPT = 'C01' AND FIRSTNME BETWEEN
'CHRISTINE' AND 'DELORES')
OPTIMIZE FOR 99999 ROWS

OPNQRYF example:
OPNQRYF FILE((EMPLOYEE))
QRYSLT('(WORKDEPT *EQ ''D11'' *AND FIRSTNME *EQ ''DAVID'')
*OR (WORKDEPT *EQ ''D11'' *AND FIRSTNME *EQ ''BRUCE'')
*OR (WORKDEPT *EQ ''D11'' *AND FIRSTNME *EQ ''WILLIAM'')
*OR (WORKDEPT *EQ ''E11'' *AND FIRSTNME *EQ ''PHILIP'')
*OR (WORKDEPT *EQ ''E11'' *AND FIRSTNME *EQ ''MAUDE'')
*OR (WORKDEPT *EQ ''A00'' *AND
FIRSTNME*EQ %RANGE(''CHRISTINE'' ''DELORES''))
*OR (WORKDEPT *EQ ''C01'' *AND
FIRSTNME *EQ %RANGE(''CHRISTINE'' ''DELORES''))')

The key ranges the database manager starts with are as follows:
Index X3 Start value Index X3 Stop value
Range 1 'D11DAVID' 'D11DAVID'
Range 2 'D11BRUCE' 'D11BRUCE'
Range 3 'D11WILLIAM' 'D11WILLIAM'
Range 4 'E11MAUDE' 'E11MAUDE'
Range 5 'E11PHILIP' 'E11PHILIP'
Range 6 'A00CHRISTINE' 'A00DELORES'
Range 7 'C01CHRISTINE' 'C01DELORES'

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 411
Ranges 1 to 4 are processed concurrently in separate tasks. As soon as one of
those four completes, range 5 is started. When another range completes, range 6 is
started, and so on. When one of the four ranges in progress completes and there
are no more new ones in the list to start, the remaining work left in one of the other
key ranges is split and each half is processed separately.

Parallel key positioning cannot be used for queries that require any of the following:
v Specification of the *ALL commitment control level.
v Nested loop join implementation. See “Nested Loop Join Implementation” on
page 426.
| v Backward scrolling. For example, parallel key positioning cannot be used for
| queries defined by the Open Query File (OPNQRYF) command, which specify
| ALWCPYDTA(*YES) or ALWCPYDTA(*NO), because the application might
| attempt to position to the last record and retrieve previous records. SQL-defined
| queries that are not defined as scrollable can use this method. Parallel key
| positioning can be used during the creation of a temporary result, such as a sort
| or hash operation, no matter what interface was used to define the query.
| OPNQRYF can be defined as not scrollable by specifying the *OPTIMIZE
| parameter value for the ALWCPYDTA parameter, which enbles the usage of most
| of the parallel access methods.
v Restoration of the cursor position. For instance, a query requiring that the cursor
position be restored as the result of the SQL ROLLBACK HOLD statement or the
ROLLBACK CL command. SQL applications using a commitment control level
other than *NONE should specify *ALLREAD as the value for precompiler
parameter ALWBLK to allow this method to be used.
v Update or delete capability.

You should run the job in a shared pool with the *CALC paging option as this will
cause more efficient use of active memory. For more information on the paging
option see the ″Automatic System Tuning″ section of Work Management book.

Parallel key selection requires that SMP parallel processing be enabled either by
the system value QQRYDEGREE, by the query options file PARALLEL_DEGREE
option, or by the DEGREE parameter on the Change Query Attributes (CHGQRYA)
command. See “Controlling Parallel Processing” on page 473 for information on
how to control parallel processing.

Index Only Access Method


The index only access method can be used in conjunction with any of the key
selection or key positioning access methods, including the parallel options for these
methods. (The parallel options are available only when the DB2 Symmetric
Multiprocessing feature is installed.) The processing for the selection does not
change from what has already been described for these methods.

However, all of the data is extracted from the index rather than performing a
random I/O to the data space. The index entry is then used as the input for any
derivation or result mapping that might have been specified on the query. The
optimizer chooses this method when:
v All of the columns that are referenced within the query can be found within a
permanent index or within the key fields of a temporary index that the optimizer
has decided to create.

412 DB2 UDB for AS/400 SQL Programming V4R4


v The data values must be able to be extracted from the index and returned to the
user in a readable format; in other words, none of the key fields that match the
query columns have:
– Absolute value specified
– Alternative collating sequence or sort sequence specified
– Zoned or digit force specified
v The query does not use a left outer join or an exception join.
v For non-SQL users, no variable length or null capable fields can require key
feedback.

The following example illustrates a query where the optimizer could choose to
perform index only access.
CREATE INDEX X2
ON EMPLOYEE(WORKDEPT,LASTNAME,FIRSTNME)

DECLARE BROWSE2 CURSOR FOR


SELECT FIRSTNME FROM EMPLOYEE
WHERE WORKDEPT = 'D11'
OPTIMIZE FOR 99999 ROWS

OPNQRYF example:
OPNQRYF FILE((EMPLOYEE))
QRYSLT('WORKDEPT *EQ ''D11''')

In this example, the database manager uses X2 to position to the index entries for
WORKDEPT=’D11’ and then extracts the value for the column FIRSTNME from those
entries.

Note that the index key fields do not have to be contiguous to the leftmost key of
the index for index only access to be performed. Any key field in the index can be
used to provide data for the index only query. The index is used simply as the
source for the data so the database manager can finish processing the query after
the selection has been completed.

The messages created by the PRTSQLINF command to describe this query in an


SQL program are as follows:
SQL4008 Access path X2 used for file 1.
SQL4011 Key row positioning used on file 1.
SQL4022 Index only access used on file 1.

Note: Index only access is implemented on a particular file, so it is possible to


perform index only access on some or all of the files of a join query.

Parallel Table or Index Based Pre-load Access Method


Some queries implemented with key selection can require a lot of random I/O in
order to access an index or a table. Because of this, a high percentage of the data
in the index or table is referenced. DB2 UDB for AS/400 attempts to avoid this
random I/O by initiating index- or table-based pre-load when query processing
begins. The data is loaded into active memory in parallel as is done for parallel
pre-fetch. After the table or index is loaded into memory, random access to the data
is achieved without further I/O. The DB2 UDB for AS/400 cost-based query
optimizer recognizes the queries and objects that benefit from table or index
pre-loads if I/O parallel processing has been enabled. See “Controlling Parallel
Processing” on page 473 for information on how to control parallel processing.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 413
The parallel pre-load method can be used with any of the other data access
methods. The pre-load is started when the query is opened and control is returned
to the application before the pre-load is finished. The application continues fetching
rows using the other database access methods without any knowledge of pre-load.

Index-From-Index Access Method


The database manager can build a temporary index from an existing index without
having to read all of the rows in the dataspace. Generally speaking, this selection
method is one of the most efficient. The temporary index that is created only
contains entries for rows that meet the selection predicates. This is similar to the
key access path created by a select/omit logical file or sparse index. The optimizer
chooses this method when:
v The query requires an index because it uses grouping, ordering, or join
processing.
v A permanent index exists that has selection columns as the left-most keys and
the left-most keys are very selective.
| v The selection columns are not the same as the ordering, grouping, or join-to
| columns.

To use the index-from-index access method, the database manager:


1. Uses key positioning on the permanent index with the query selection criteria
2. Builds index entries in the new temporary index using selected row entries.

The result is an index containing entries in the required key sequence for rows that
match the selection criteria.

A common index-from-index access method example follows:


CREATE INDEX X1 ON EMPLOYEE(WORKDEPT)

DECLARE BROWSE2 CURSOR FOR


SELECT * FROM EMPLOYEE
WHERE WORKDEPT = 'D11'
ORDER BY LASTNAME
OPTIMIZE FOR 99999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE))
| QRYSLT('WORKDEPT *EQ ''D11''')
| KEYFLD((LASTNAME))

| For this example, a temporary select/omit index is created with the primary key field
LASTNAME. It contains index entries for only those rows where WORKDEPT =
’D11’. If WORKDEPT = ’D11’, less than approximately 20% of the rows are
selected. The messages created by the PRTSQLINF CL command to describe this
query in an SQL program are as follows:
SQL4012 Access path created from keyed file X1 for file 1.
SQL4011 Key row positioning used on file 1.

| Rather than using the index-from-index access method, you can use the query sort
| routine:
| v For SQL (see “Improving Performance by Using the ALWCPYDTA Parameter” on
| page 465) specify either of the following precompile options:
| – ALWCPYDTA(*OPTIMIZE), ALWBLK(*ALLREAD), and COMMIT(*CHG or
| *CS)

414 DB2 UDB for AS/400 SQL Programming V4R4


| – ALWCPYDTA(*OPTIMIZE) and COMMIT(*NONE)
| v For OPNQRYF, specify either:
| – ALWCPYDTA(*OPTIMIZE) and COMMIT(*NO)
| – ALWCPYDTA(*OPTIMIZE) and COMMIT(*YES) and commitment control is
| started with a commit level of *NONE, or *CHG, or *CS

| This decision is based on the number of rows to be retrieved.

Hashing Access Method


The hashing access method provides an alternative method for those queries
(groupings and joins) that must process data in a grouped or correlated manner.
Keyed sequence access paths (indexes) are used to sort and group the data and
are effective in some cases for implementing grouping and join query operations.
However, if the optimizer had to create a temporary index for that query, extra
processor time and resources are used when creating this index before the
requested query can be run.

The hashing access method can complement keyed sequence access paths or
serve as an alternative. For each selected row, the specified grouping or join value
in the row is run through a hashing function. The computed hash value is then used
to search a specific partition of the hash table. A hash table is similar to a
temporary work table, but has a different structure that is logically partitioned based
on the specified query. If the row’s source value is not found in the table, then this
marks the first time that this source value has been encountered in the database
table. A new hash table entry is initialized with this first-time value and additional
processing is performed based on the query operation. If the row’s source value is
found in the table, the hash table entry for this value is retrieved and additional
query processing is performed based on the requested operation (such as grouping
or joining). The hash method can only correlate (or group) identical values; the hash
table rows are not guaranteed to be sorted in ascending or descending order.

The hashing method can be used only when the ALWCPYDTA(*OPTIMIZE) option
has been specified unless a temporary result is required, since the hash table built
by the database manager is a temporary copy of the selected rows.

The hashing algorithm allows the database manager to build a hash table that is
well-balanced, given that the source data is random and distributed. The hash table
itself is partitioned based on the requested query operation and the number of
source values being processed. The hashing algorithm then ensures that the new
hash table entries are distributed evenly across the hash table partitions. This
balanced distribution is necessary to guarantee that scans in different partitions of
the hash tables are processing the same number of entries. If one hash table
partition contains a majority of the hash table entries, then scans of that partition
are going to have to examine the majority of the entries in the hash table. This is
not very efficient.

Since the hash method typically processes the rows in a table sequentially, the
database manager can easily predict the sequence of memory pages from the
database table needed for query processing. This is similar to the advantages of
the dataspace scan access method. The predictability allows the database manager
to schedule asynchronous I/O of the table pages into main storage (also known as
pre-fetching). Pre-fetching enables very efficient I/O operations for the hash method
leading to improved query performance.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 415
In contrast, query processing with a keyed sequence access method causes a
random I/O to the database table for every key value examined. The I/O operations
are random since the keyed-order of the data in the index does not match the
physical order of the rows in the database table. Random I/O can reduce query
performance because it leads to unnecessary use of I/O and processor unit
resources.

A keyed sequence access path can also be used by the hash method to process
the table rows in keyed order. The keyed access path can significantly reduce the
number of table rows that the hash method has to process. This can offset the
random I/O costs associated with keyed sequence access paths.

The hash table creation and population takes place before the query is opened.
Once the hash table has been completely populated with the specified database
records, the hash table is used by the database manager to start returning the
results of the queries. Additional processing might be required on the resulting hash
table rows, depending on the requested query operations.

Since blocks of table rows are automatically spread, the hashing access method
can also be performed in parallel so that several groups of records are being
hashed at the same time. This shortens the amount of time it takes to hash all the
rows in the database table.

If the DB2 SMP feature is installed, the hashing methods can be performed in
parallel.

Bitmap Processing Method


As the name implies, this method generates bitmaps that are used during access to
the data space. The bitmap processing method is used to:
v Eliminate the random I/O that occurs on a data space when using a keyed
sequence access path in conjunction with the key position and/or key selection
method.
v Allow multiple keyed sequence access paths to be used to access a particular
table.

In this method, the optimizer chooses one or more keyed sequence access paths to
be used to aid in selecting records from the data space. Temporary bitmaps are
allocated (and initialized), one for each index. Each bitmap contains one bit for each
record in the underlying data space. For each index, key positioning and key
selection methods are used to apply selection criteria.

For each index entry selected, the bit associated with that record is set to ’1’ (i.e.
turned on). The data space is not accessed. When the processing of the index is
complete, the bitmap contains the information on which records are to be selected
from the underlying data space. This process is repeated for each index. If two or
more indexes are used, the temporary bitmaps are logically ANDed and ORed
together to obtain one resulting bitmap. Once the resulting bitmap is built, it is used
to avoid mapping in records from the data space unless they are selected by the
query.

It is important to note that the indexes used to generate the bitmaps are not actually
used to access the selected records. For this reason, they are called tertiary
indexes. Conversely, indexes used to access the final records are called primary
indexes. Primary indexes are used for ordering, grouping, joins, and for selection
when no bitmap is used.

416 DB2 UDB for AS/400 SQL Programming V4R4


The bitmap processing method is used in conjunction with primary access methods
data space scan, key selection, or key positioning. Bitmap processing, like parallel
pre-fetch and parallel table/index pre-load, does not actually select the records from
the data space; it assists the primary methods.

If the bitmap is used in conjunction with the data space scan method, the bitmap
initiates a skip-sequential processing. The data space scan (and parallel data space
scan) uses the bitmap to ″skip over″ non-selected records. This has several
advantages:
v No CPU processing is used processing non-selected records.
v I/O is minimized and the memory is not filled with the contents of the entire data
space.

The following example illustrates a query where the query optimizer chooses the
bitmap processing method in conjunction with the dataspace scan:
CREATE INDEX IX1 ON EMPLOYEE (WORKDEPT)
CREATE INDEX IX2 ON EMPLOYEE (SALARY)

DECLARE C1 CURSOR FOR


SELECT * FROM EMPLOYEE
WHERE WORKDEPT = 'E01' OR SALARY>50000
OPTIMIZE FOR 99999 ROWS

OPNQRYF example:
OPNQRYF FILE((EMPLOYEE))
QRYSLT('WORKDEPT *EQ ''E01'' *OR SALARY > 50000')

In this example, both indexes IX1 and IX2 are used. The database manager first
generates a bitmap from the results of applying selection WORKDEPT = ’E01’
against index IX1 (using key positioning). The database manager then generates a
bitmap from the results of applying selection SALARY>50000 against index IX2
(again using key positioning).

Next, the database manager combines these two bitmaps into one using OR logic.
Finally, a data space scan is initiated. The data space scan uses the bitmap to skip
through the data space records, retrieving only those selected by the bitmap.

This example also shows an additional capability provided with bitmap processing
(use of an index for ANDed selection was already possible but bitmap processing
now allows more than one index). When using bitmap processing, multiple index
usage is possible with selections where OR is the major boolean operator.

| The messages created by the PRTSQLINF command when used to describe this
| query would look like:
| SQL4010 Arrival sequence access for file 1.
| SQL4032 Access path IX1 used for bitmap processing of file 1.
| SQL4032 Access path IX2 used for bitmap processing of file 1.
| CPI4329 Arrival sequence access was used for file EMPLOYEE.
| CPI4388 2 Access path(s) used for bitmap processing of file EMPLOYEE.

| If the bitmap is used in conjunction with either the key selection or key positioning
method, it implies that the bitmap (generated from tertiary indexes) is being used to
aid a primary index access. The following example illustrates a query where bitmap
processing is used in conjunction with the key positioning for a primary index:

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 417
CREATE INDEX PIX ON EMPLOYEE (LASTNAME)
CREATE INDEX TIX1 ON EMPLOYEE (WORKDEPT)
CREATE INDEX TIX2 ON EMPLOYEE (SALARY)

DECLARE C1 CURSOR FOR


SELECT * FROM EMPLOYEE
WHERE WORKDEPT = 'E01' OR SALARY>50000
ORDER BY LASTNAME

OPNQRYF example:
OPNQRYF FILE((EMPLOYEE))
QRYSLT('WORKDEPT *EQ ''E01'' *OR SALARY > 50000')
KEYFLD(LASTNAME)

In this example, indexes TIX1 and TIX2 are used in bitmap processing. The
database manager first generates a bitmap from the results of applying selection
WORKDEPT = ’E01’ against index TIX1 (using key positioning). It then generates a
bitmap from the results of applying selection SALARY>50000 against index TIX2
(again using key positioning).

| The database manager then combines these two bitmaps into one using OR logic.
| A key selection method is initiated using (primary) index PIX. For each entry in
| index PIX, the bitmap is checked. If the entry is selected by the bitmap, then the
| data space record is retrieved and processed.

The messages created by the PRTSQLINF CL command, when used to describe


this query, would look like:
| SQL4008 Access path PIX used for file 1.
| SQL4032 Access path TIX1 used for bitmap processing of file 1.
| CPI4328 Access path of file PIX was used by query.
| CPI4338 2 Access path(s) used for bitmap processing of file EMPLOYEE.

| Bitmap processing can be used for join queries, as well. Since bitmap processing is
| on a per file basis, each file of a join can independently use or not use bitmap
| processing

| The following example illustrates a query where bitmap processing is used against
| the second file of a join query but not on the first file:
| CREATE INDEX EPIX ON EMPLOYEE(EMPNO)
| CREATE INDEX TIX1 ON EMPLOYEE(WORKDEPT)
| CREATE INDEX TIX2 ON EMPLOYEE(SALARY)
| DECLARE C1 CURSOR FOR
| SELECT * FROM PROJECT, EMPLOYEE
| WHERE RESEMP=EMPNO AND
| (WORKDEPT='E01' OR SALARY>50000)

| Using the OPNQRYF command:


| OPNQRYF FILE((PROJECT) (EMPLOYEE)) FORMAT(RESULTFILE)
| JFLD((1/RESPEMP 2/EMPNO))
| QRYSLT('2/WORKDEPT=''E01'' *OR 2/SALARY>50000')

| In this example, the optimizer decides that the join order is file PROJECT to file
| EMPLOYEE. Data space scan is used on file PROJECT. For file EMPLOYEE, index
| EPIX is used to process the join (primary index). Indexes TIX1 and TIX2 are used
| in bitmap processing.

| The database manager positions to the first record in file PROJECT. It then
| performs the join using index EPIX. Next, it generates a bitmap from the results of
| applying selection WORKDEPT=’E01’ against index TIX1 (using key positioning). It

418 DB2 UDB for AS/400 SQL Programming V4R4


| then generates a bitmap from the results of applying selection SALARY>50000
| against index TIX2 (again using key positioning).

| Next, the database manager combines these two bitmaps into one using OR logic.
| Finally, the entry that EPIX is currently positioned to is checked against the bitmap.
| The entry is either selected or rejected by the bitmap. If the entry is selected, the
| records are retrieved from the underlying data space. Next, index EPIX is probed
| for the next join record. When an entry is found, it is compared against the bitmap
| and either selected or rejected. Note that the bitmap was generated only once (the
| first time it was needed) and is just reused after that.

| The query optimizer debug messages put into the job log would look like:
| CPI4327 File PROJECT processed in join position 1.
| CPI4326 File EMPLOYEE processed in join position 2.
| CPI4338 2 Access path(s) used for bitmap processing of file EMPLOYEE.

| Bitmap processing alleviates some of the headache associated with having


| composite key indexes (multiple key fields in one index).

| For example, given an SQL query:


| DECLARE C1 CURSOR FOR
| SELECT * FROM EMPLOYEE
| WHERE WORKDEPT='D11' AND
| FIRSTNAME IN ('DAVID', 'BRUCE', 'WILLIAM')

| Or the same query using the OPNQRYF command:


| OPNQRYF FILE((EMPLOYEE))
| QRYSLT('WORKDEPT=''D11'' *AND
| FIRSTNME = %VALUES(''DAVID'' ''BRUCE'' ''WILLIAM'')')

| An index with keys (WORKDEPT, FIRSTNAME) would be the best index to use to
| satisfy this query. However, two indexes, one with a key of WORKDEPT and the
| other with a key of FIRSTNME could be used in bitmap processing, with their
| resulting bitmaps ANDed together and data space scan used to retrieve the result.

| With the bitmap processing method, you can create several indexes, each with only
| one key field, and have the optimizer use them as general purpose indexes for
| many queries. You can avoid problems involved with trying to determine the best
| composite key indexes for all queries being performed against a table. Bitmap
| processing, in comparison to using a multiple key field index, allows more ease of
| use, but at some cost to performance. Keep in mind that you will always achieve
| the best performance by using composite key indexes.

| Some additional points regarding bitmap processing:


| v As long as the DB2 SMP feature is installed, you can use parallel processing
| whenever you use bitmap processing. in this case, the bitmap is built from the
| results of performing either parallel key positioning and/or parallel key selection
| on the tertiary index.
| v Bitmaps are generated at the first record fetch (I/O). Therefore, the first record
| fetched may take longer to retrieve than subsequent records.
| v Bitmaps, by their nature, contain static selection. Once the bitmap is generated, it
| will not select any new or modified records.
| For example, suppose an OPNQRYF statement specifying (QRYSLT(’QUANTITY
| >5’) is opened using bitmap processing and the first record is read. Through a
| separate database operation, all records where QUANTITY is equal to 4 are
| updated so QUANTITY is equal to 10. Since the bitmap was already built (during

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 419
| the first record fetch from the OPNQRYF open identifier), these updated records
| will not be retrieved on subsequent fetches through the OPNQRYF open
| identifier.
| For this reason, the query optimizer will not consider bitmap processing if the
| ALWCPYDTA option is *NO. The exception to this is if the query contains
| grouping or one or more aggregate functions (for example, SUM, COUNT, MIN,
| MAX), in which case static data is already being made.
| v Do not use bitmap processing for a query that is insert, update, or delete
| capable. For OPNQRYF, the OPTION parameter must be set to *INP and the
| SEQONLY parameter must be set to *YES. There must not be any overrides to
| SEQONLY(*NO)).
|
Data Access Methods
The following table provides a summary of the data management methods
discussed.
Table 38. Summary of Data Management Methods
Access
Method Selection Process Good When Not Good When Selected When Advantages
“Dataspace Reads all rows. > 20% rows < 20% rows No ordering, Minimizes page I/O
Scan Access Selection criteria selected. selected. grouping, or joining through
Method” on applied to data in and > 20% rows pre-fetching.
page 399 dataspace. selected.
“Parallel Data retrieved from > 20% rows < 20% rows No ordering, Minimizes wait time
Pre-Fetch auxiliary storage in selected. selected. Query is grouping, or joining for page I/O
Access parallel streams. CPU bound. and > 20% rows through parallel
1. Adequate
Method” on Reads all rows. selected. pre-fetching.
active memory
page 401 Selection criteria
available.
applied to data in
dataspace. 2. Query would
otherwise be
I/O bound.
3. Data spread
across multiple
disk units.
“Parallel Data read and > 10% rows < 10% rows 1. DB2 UDB Significant
Data Space selected in parallel selected, large selected. Query is Symmetric performance
Scan tasks. table. CPU bound on a Multiprocessing especially on
Method uniprocessor installed. multiprocessors.
1. Adequate
(available system.
active memory 2. I/O bound or
only when
available. running on a
the DB2
2. Data spread multi-processor
UDB
across multiple system.
Symmetric
Multiprocessing disk units.
feature is 3. DB2 UDB
installed)” on Symmetric
page 403 Multiprocessing
installed.
4. Multi-processor
system.

420 DB2 UDB for AS/400 SQL Programming V4R4


Table 38. Summary of Data Management Methods (continued)
Access
Method Selection Process Good When Not Good When Selected When Advantages
“Key Selection criteria Ordering, grouping, Large number of Index is required Dataspace
Selection applied to index. and joining. rows selected. and cannot use accessed only for
Access key positioning rows matching key
Method” on method. selection criteria.
page 404
“Parallel Key Selection criteria Size of index is Large number of When ordering of Better I/O overlap
Selection applied to index in much less than the rows selected. results not because parallel
Access parallel tasks. dataspace. DB2 required. tasks perform the
Method UDB Symmetric I/O. Can fully utilize
(available Multiprocessing multiprocessor
only when must be installed. systems.
the DB2
UDB
Symmetric
Multiprocessing
feature is
installed)” on
page 405
“Key Selection criteria < 20% rows > 20% rows Selection columns Index and
Positioning applied to range of selected. selected. match left-most dataspace
Access index entries. keys and < 20% accessed only for
Method” on Commonly used rows selected. rows matching
page 406 option. selection criteria.
“Parallel Key Selection criteria < 20% rows Large number of 1. Index and
1. When ordering
Positioning applied to range of selected. DB2 UDB rows selected. dataspace
of results not
Access index entries in Symmetric accessed only
required.
Method parallel tasks. Multiprocessing for rows
(available must be installed. 2. Selection
matching
only when columns match
selection
the DB2 left-most keys
criteria.
UDB and < 20%
rows selected. 2. Better I/O
Symmetric
overlap
Multiprocessing
because
feature is
parallel tasks
installed)” on
perform the I/O.
page 411
3. Can fully utilize
a
multiprocessor
systems.
“Index-From- Key row positioning Ordering, grouping > 20% rows No existing index Index and
Index on permanent and joining. selected. to satisfy ordering dataspace
Access index. Builds but existing index accessed only for
Method” on temporary index does satisfy rows matching
page 414 over selected index selection and selection criteria.
entries. selecting < 20%
rows.
Sort routine Order data read > 20% rows < 20% rows Ordering specified; See dataspace
using dataspace selected or large selected or small either no index scan and key
scan processing or result set of rows. result set of rows. exists to satisfy the positioning in this
key positioning. ordering or a large table.
result set is
expected.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 421
Table 38. Summary of Data Management Methods (continued)
Access
Method Selection Process Good When Not Good When Selected When Advantages
“Index Only Done in All columns used in < 20% rows All columns used in Reduced I/O to the
Access combination with the query exist as selected or small the query exist as dataspace.
Method” on any of the other key fields. DB2 result set of rows. key fields and DB2
page 412 index access UDB Symmetric UDB Symmetric
methods Multiprocessing Multiprocessing is
must be installed. installed.
“Parallel Index or table data Excessive random Active memory is Excessive random Random page I/O
Table or loaded in parallel activity would already activity would result is avoided which
Index Based to avoid random otherwise occur over-committed. from processing can improve I/O
Pre-load access. against the object the query and bound queries.
Access and active memory active memory is
Method” on is available to hold available which can
page 413 the entire object. hold the entire
object.
“Hashing Rows with common Longer running Short running Join or grouping Reduce random
Access values are grouped grouping and/or queries. specified. I/O when
Method” on together. join queries. compared to index
page 415(Parallel methods. If DB2
or UDB Symmetric
non-parallel) Multiprocessing is
installed, possible
exploitation of SMP
parallelism.
“Bitmap Key position/key Selection can be >25% rows Indexes match Reduces page I/O
Processing selection used to applied to index selected. selection criteria. to the data space.
Method” on build bitmap. and either >5% or Allows multiple
page 416 Bitmap used to <25% rows indexes per table.
avoid touching selected or an OR
rows in table. operator is involved
in selection that
precludes the use
of only one index.

The Optimizer
The optimizer is an important part of DB2 UDB for AS/400 because the optimizer:
v Makes the key decisions which affect database performance.
v Identifies the techniques which could be used to implement the query.
v Selects the most efficient technique.
Data manipulation statements such as SELECT specify only what data the user
wants, not how to get to that data. This access path to the data is chosen by the
optimizer and stored in the access plan. This section covers the techniques
employed by the query optimizer for performing this task including:
v Cost estimation
v Access plan validation
v Join optimization
v Grouping optimization

422 DB2 UDB for AS/400 SQL Programming V4R4


Cost Estimation
At run-time, the optimizer chooses an optimal access method for the query by
calculating an implementation cost based on the current state of the database. The
optimizer models the access cost of each of the following:
v Reading rows directly from the table (dataspace scan processing)
v Reading rows through an access path (using either key selection or key
positioning)
v Creating an access path directly from the dataspace
v Creating an access path from an existing access path (index-from-index)
v Using the query sort routine or hashing method (if conditions are satisfied)

The cost of a particular method is the sum of:


v The start-up cost
v The cost associated with the given optimization mode.
| – For SQL, the precompile option ALWCPYDTA and the OPTIMIZE FOR n
| ROWS clause indicate to the query optimizer the optimization goal to be
| achieved.
| - The optimizer can optimize SQL queries with one of two goals:
| 1. Minimize the time required to retrieve the first buffer of rows from the
| table. This goal biases the optimization towards not creating an index.
| Either a data scan or an existing index is preferred. This mode can be
| specified in two ways:
| a. The OPTIMIZE FOR n ROWS allows the users to specify the
| number of rows they expect to retrieve from the query.
| The optimizer uses this value to determine the percentage of rows
| that will be returned and optimizes accordingly. A small value
| instructs the optimizer to minimize the time required to retrieve the
| first n rows.
| b. Specifying ALWCPYDTA(*NONE) or ALWCPYDTA(*YES) a
| precompiler option, allows the optimizer to minimize the time
| required to retrieve the first 3% of the resulting rows.
| This option is effective only if the OPTIMIZE FOR n ROWS was not
| specified.
| 2. Minimize the time to process the whole query assuming that all selected
| rows are returned to the application. Does not bias the optimizer to any
| particular access method. This mode can be specified in two ways:
| a. The OPTIMIZE FOR n ROWS allows the users to specify the
| number of rows they expect to retrieve from the query.
| The optimizer uses this value to determine the percentage of rows
| that will be returned and optimizes accordingly. A value greater than
| or equal to the expected number of resulting rows instructs the
| optimizer to minimize the time required to run the entire query.
| b. ALWCPYDTA(*OPTIMIZE) specified as a precompiler parameter.
| This option is effective only if the OPTIMIZE FOR n ROWS is not
| specified.
| – For OPNQRYF, note:
| - The cost associated with the given optimization parameter (*FIRSTIO,
| *ALLIO, or *MINWAIT).

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 423
| v *FIRSTIO–Minimize the time required to retrieve the first buffer of
| records from the file. Biases the optimization toward not creating an
| index. Either a data scan or an existing index is preferred. When
| *FIRSTIO is selected, users may also pass in the number of records
| they expect to retrieve from the query. The optimizer uses this value to
| determine the percentage of records that will be returned and optimizes
| accordingly. A small value would minimize the time required to retrieve
| the first n records, similar to *FIRSTIO. A large value would minimize the
| time to retrieve all n records, similar to *ALLIO.
| v *ALLIO–Minimize the time to process the whole query assuming that all
| query records are read from the file. Does not bias the optimizer to any
| particular access method.

| Note: If you specify ALWCPYDTA(*OPTIMIZE) and use the sort routine,


| your query resolves according to the *ALLIO optimize parameter.
| v *MINWAIT–Minimize delays when reading records from the file. Minimize
| I/O time at the expense of open time. Biases optimization toward either
| creating a temporary index or performing a sort. Either an index is
| created or an existing index is used.
| v The cost of any access path creations
v The cost of the expected number of page faults to read the rows and the cost of
processing the expected number of rows.
Page faults and number of rows processed may be predicted by statistics the
optimizer can obtain from the database objects, including:
– Table size
– Row size
– Index size
– Key size

Page faults can also be greatly affected if index only access can be performed,
thus eliminating any random I/O to the data space.

A weighted measure of the expected number of rows to process is based on


what the relational operators in the row selection predicates, default filter factors,
are likely to retrieve:
– 10% for equal
– 33% for less-than, greater-than, less-than-equal-to, or greater-than-equal-to
– 90% for not equal
| – 25% for BETWEEN range (OPNQRYF %RANGE)
| – 10% for each IN list value (OPNQRYF %VALUES)

Key range estimate is a method the optimizer uses to gain more accurate
estimates of the number of expected rows selected from one or more selection
predicates. The optimizer estimates by applying the selection predicates against
the left-most keys of an existing index. The default filter factors can then be
further refined by the estimate based on the key range. If an index exists whose
left-most keys match columns used in row selection predicates, that index can be
used to estimate the number of keys that match the selection criteria. The
estimate of the number of keys is based on the number of pages and key density
of the machine index and is done without actually accessing the keys. Full
indexes over columns used in selection predicates can significantly help
optimization.

424 DB2 UDB for AS/400 SQL Programming V4R4


Page faults and the number of rows processed are dependent on the type of
access the optimizer chooses. Refer to “Data Management Methods” on
page 396 for more information on access methods.

Access Plan Validation


An access plan is a control structure that describes the actions necessary to satisfy
each query request. An access plan contains information about the data and how to
extract it. For any query, whenever optimization occurs, an optimized plan of how to
access the requested data is developed. The information is kept in what is called a
mini plan. The mini plan, along with the query definition template (QDT), is used to
interface with the optimizer and make an access plan.
v For dynamic SQL, an access plan is created, but the plan is not saved. A new
access plan is created each time the PREPARE statement is run.
v For a DB2 UDB for AS/400 program, the access plan is saved in the associated
space of the program or package that contains embedded SQL statements.
v For OPNQRYF, an access plan is created but is not saved. A new access plan is
created each time the OPNQRYF command is processed.
v For Query/400, an access plan is saved as part of the query definition object.

Optimizer Decision-Making Rules


In performing its function, the optimizer uses a general set of guidelines to choose
the best method for accessing data. The optimizer:
v Determines the default filter factor for each predicate in the selection clause.
v Extracts attributes of the table from internally stored information.
v Performs an estimate key range to determine the true filter factor of the
predicates when the selection predicates match the left-most keys of an index.
v Determines the cost of creating an index over a table if an index is required.
v Determines the cost of using a sort routine or hashing method if selection
conditions apply and an index is required.
v Determines the cost of dataspace scan processing if an index is not required.
v For each index available, in the order of most recently created to oldest, the
optimizer does the following until its time limit is exceeded:
– Extracts attributes of the index from internally stored statistics.
– Determines if the index meets the selection criteria.
– Determines the cost of using the index using the estimated page faults and
the predicate filter factors to help determine the cost.
– Compares the cost of using this index with the previous cost (current best).
– Picks the cheaper one.
– Continues to search for best index until time out or no more indexes.

The time limit factor controls how much time is spent choosing an implementation. It
is based on how much time was spent so far and the current best implementation
cost found. Dynamic SQL queries are subject to the optimizer time restrictions.
Static SQL queries optimization time is not limited. For OPNQRYF, if you specify
OPTALLAP(*YES), the optimization time is not limited.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 425
For small tables, the query optimizer spends little time in query optimization. For
large tables, the query optimizer considers more indexes. Generally, the optimizer
considers five or six indexes (for each table of a join) before running out of
optimization time.

Join Optimization
| A join operation is a complex function that requires special attention in order to
| achieve good performance. This section describes how DB2 UDB for AS/400
| implements inner join queries and how optimization choices are made by the query
| optimizer. It also describes design tips and techniques which help avoid or solve
| performance problems.

| The optimization for other types of joins, LEFT OUTER JOIN or EXCEPTION JOIN
| (OPNQRYF JDFTVAL(*YES) or JDFTVAL(*ONLYDFT) parameter), is similar except
| that the join order is always the same as the order of the tables specified in the
| FROM clause (OPNQRYF FILE paramter). Information about these types of joins
| will not be detailed here, but most of the information and tips in this section also
| apply to joins of this type.

Nested Loop Join Implementation


DB2 UDB for AS/400 provides a nested loop join method. For this method, the
processing of the tables in the join are ordered. This order is called the join order.
The first table in the final join order is called the primary table. The other tables
are called secondary tables. Each join table position is called a dial. During the
join, DB2 UDB for AS/400:
1. Accesses the first primary table row selected by the predicates local to the
primary table.
2. Builds a key value from the join columns in the primary table.
3. Uses key positioning to locate the first row that satisfies the join condition for
the first secondary table using a keyed access path with keys matching the join
condition or local row selection columns of the secondary table.
4. Applies bitmap selection, if applicable.
5. Determines if the row is selected by applying any remaining selection local to
the first secondary dial.
If the secondary dial row is not selected then the next row that satisfies the join
condition is located. Steps 1 through 5 are repeated until a row that satisfies
both the join condition and any remaining selection is selected from all
secondary tables
6. Returns the result join row.
7. Processes the last secondary table again to find the next row that satisfies the
join condition in that dial.
During this processing, when no more rows that satisfy the join condition can be
selected, the processing backs up to the logical previous dial and attempts to
read the next row that satisfies its join condition.
8. Ends processing when all selected rows from the primary table are processed.
Note the following characteristics of a nested loop join:
v If ordering or grouping of result rows is specified over a single table, then that
table becomes the primary table and is processed with a keyed access path over
the table.

426 DB2 UDB for AS/400 SQL Programming V4R4


v If ordering or grouping of processing of the join result rows is specified on tables
from other than the primary dial or on columns from two or more dials, DB2 UDB
for AS/400 breaks the processing of the query into two parts:
1. Process the join query omitting the ordering or grouping processing and write
the result rows to a temporary work table. This allows the optimizer to
consider any table of the join query as a candidate for the primary table.
2. The ordering or grouping processing is then performed on the data in the
temporary work table.

| The query optimizer might also decide to break the query into these two parts to
| improve performance when the SQL ALWCPYDTA(*OPTIMIZE) precompiler
| parameter or the OPNQRYF KEYFLD, and ALWCPYDTA(*OPTIMIZE)
| parameters are specified.
v All rows that satisfy the join condition from each secondary dial are located using
a keyed access path. Rows are retrieved from secondary tables in random
sequence. This random disk I/O time often accounts for a large percentage of the
processing time of the query. Since a given secondary dial is searched once for
each row selected from the primary and the preceding secondary dials that
satisfy the join condition for each of the preceding secondary dials, a large
number of searches may be performed against the later dials. Any inefficiencies
in the processing of the later dials can significantly inflate the query processing
time. This is the reason why attention to performance considerations for join
queries can reduce the run-time of a join query from hours to minutes.
v Again, all selected rows from secondary dials are accessed through a keyed
access path. If an efficient keyed access path cannot be found, a temporary
keyed access path is created. Some join queries build temporary access paths
over secondary dials even when an access path exists for all of the join keys.
Because efficiency is very important for secondary dials of longer running
queries, the query optimizer may choose to build a temporary keyed access path
which contains only keys which pass the local row selection for that dial. This
preprocessing of row selection allows the database manager to process row
selection in one pass instead of each time rows are matched for a dial.

Hash Join
The hash join method is similar to nested loop join. Instead of using keyed access
paths to locate the matching rows in a secondary table, however, a hash temporary
result table is created that contains all of the rows selected by local selection
against the table. The structure of the hash table is such that rows with the same
join value are loaded into the same hash table partition (clustered). The location of
the rows for any given join value can be found by applying a hashing function to the
join value.

Hash join has several advantages over nested loop join:


v The structure of a hash temporary result table is simpler than that of an index, so
less CPU processing is required to build and probe a hash table.
v The rows in the hash result table contain all of the data required by the query so
there is no need to access the data space of the table with random I/O when
probing the hash table.
v Like join values are clustered, so all matching rows for a given join value can
usually be accessed with a single I/O request.
v The hash temporary result table can be built using SMP parallelism.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 427
v Unlike indexes, entries in hash tables are not updated to reflect changes of
column values in the underlying table. The existence of a hash table does not
affect the processing cost of other updating jobs in the system.

Hash join cannot be used for queries that:


| v Perform subqueries unless all subqueries in the query can be transformed to
| inner joins.
v Perform a UNION or UNION ALL.
v Perform left outer or exception join.
v Use a DDS created join logical file.
v Require live access to the data as specified by the *NO or *YES parameter
values for the ALWCPYDTA precompiler parameter. Hash join is used only for
queries running with ALWCPYDTA(*OPTIMIZE). This parameter can be specified
either on precompiler commands, the STRSQL CL command, or the OPNQRYF
CL command. The Client Access/400 ODBC driver and Query Management
driver always uses this mode.
Hash join can be used with OPTIMIZE(*YES) if a temporary result is required to
run the query.
v Require that the cursor position be restored as the result of the SQL ROLLBACK
HOLD statement or the ROLLBACK CL command. For SQL applications using
commitment control level other than *NONE, this requires that *ALLREAD be
specified as the value for the ALWBLK precompiler parameter.

The query attribute DEGREE, which can be changed by using the Change Query
attribute CL command (CHGQRYA), does not enable or disable the optimizer from
choosing to use hash join. However, hash join queries can use SMP parallelism if
the query attribute DEGREE is set to either *OPTIMIZE, *MAX, or *NBRTASKS.

Hash join is used in many of the same cases where a temporary index would have
been built. Join queries which are most likely to be implemented using hash join are
those where either:
v All rows in the various tables of the join are involved in producing result rows.
v Significant non-join selection is specified for the tables of the join which reduces
the number of rows in the tables that are involved with the join result.

The following is an example of a join query that would process all of the rows from
the queried tables:
SELECT *
FROM EMPLOYEE, EMP_ACT
WHERE EMPLOYEE.EMPNO = EMP_ACT.EMPNO
OPTIMIZE FOR 99999999 ROWS

| OPNQRYF example :
| OPNQRYF FILE((EMPLOYEE EMP_ACT)) FORMAT(FORMAT1)
| JFLD((1/EMPNO 2/EMPNO *EQ))
| ALWCPYDTA(*OPTIMIZE)

| This query is implemented using the following steps:


1. A temporary hash table is built over table EMP_ACT with a key of EMPNO. This
occurs when the query is opened.
2. For each row retrieved from the EMPLOYEE table, the temporary hash table will
be probed for any matching join values.
3. For each matching row found, a result row is returned.

428 DB2 UDB for AS/400 SQL Programming V4R4


The messages created by the PRTSQLINF CL command to describe this hash join
query in an SQL program would appear as follows:
SQL402A Hashing algorithm used to process join.
SQL402B File EMPLOYEE used in hash join step 1.
SQL402B File EMP_ACT used in hash join step 2.

The following is an example of a join query that would have the queried tables of
the join queried significantly reduced by local selection:
SELECT EMPNO, LASTNAME, DEPTNAME
FROM EMPLOYEE, DEPARTMENT
WHERE EMPLOYEE.WORKDEPT = DEPARTMENT.DEPTNO
AND EMPLOYEE.HIREDATE BETWEEN 1996-01-30 AND 1995-01-30
AND DEPARTMENT.DEPTNO IN ('A00', 'D01', 'D11', 'D21', 'E11')
OPTIMIZE FOR 99999999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE DEPARTMENT))
| FORMAT(FORMAT2)
| QRYSLT('1/HIREDATE *EQ %RANGE(''1996-01-30'' ''1995-01-30'')
| *AND 2/DEPTNO *EQ %VALUES(''A00'' ''D01'' ''D11'' ''D21''
| ''E11''')
| JFLD((1/WORKDEPT 2/DEPTNO *EQ))
| ALWCPYDTA(*OPTIMIZE)

| This query is implemented using the following steps:


1. A temporary hash table is built over table DEPARTMENT with key values of
DEPTNO containing rows matching the selection predicate, DEPTNO IN (’A00’,
’D01’, ’D11’, ’D21’, ’E11’). This occurs when the query is opened.
2. For each row retrieved from the EMPLOYEE table matching the selection
predicate, HIREDATE BETWEEN 1996-01-30 and 1995-01-30, the temporary
hash table will be probed for the matching join values.
3. For each matching row found, a result row is returned.

The messages created by the PRTSQLINF CL command to describe this hash join
query in an SQL program would appear as follows:
SQL402A Hashing algorithm used to process join.
SQL402B File EMPLOYEE used in hash join step 1.
SQL402B File DEPARTMENT used in hash join step 2.

When ordering, grouping, non-equal selection specified with operands derived from
columns of different tables, or result columns are derived from columns of different
tables, the hash join processing will be done and the result rows of the join will be
written to a temporary table. Then, as a second step, the query will be completed
using the temporary table.

The following is an example of a join query with selection specified with operands
derived from columns of different tables:
SELECT EMPNO, LASTNAME, DEPTNAME
FROM EMPLOYEE, DEPARTMENT
WHERE EMPLOYEE.WORKDEPT = DEPARTMENT.DEPTNO
AND EMPLOYEE.EMPNO > DEPARTMENT.MGRNO
OPTIMIZE FOR 99999999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE DEPARTMENT)
| FORMAT(FORMAT2)
| JFLD((1/WORKDEPT 2/DEPTNO *EQ) (1/EMPNO 2/MGRNO
| *GT))

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 429
| This query is implemented using the following steps:
1. A temporary hash table is built over table DEPARTMENT with a key of
DEPTNO. This occurs when the query is opened.
2. For each row retrieved from the EMPLOYEE table, the temporary hash table will
be probed for the matching join values.
3. For each matching row found, a result row is written to a temporary table.
4. After all of the join result rows are written to the temporary table, rows that are
selected by EMPNO > MGRNO are read from the temporary file and returned to
the application.

The messages created by the PRTSQLINF CL command to describe this hash join
query in an SQL program would appear as follows:
SQL402A Hashing algorithm used to process join.
SQL402B File EMPLOYEE used in hash join step 1.
SQL402B File DEPARTMENT used in hash join step 2.
SQL402C Temporary result table created for hash join query.

Join Optimization Algorithm


The query optimizer must determine the join columns, join operators, local row
selection, keyed access path usage, and dial ordering for a join query.

The join columns and join operators depend on the:


v Join column specifications of the query
v Join order
v Interaction of join columns with other row selection
v Keyed access path used.

Join specifications which are not implemented for the dial are either deferred until
they can be processed in a later dial or, if an inner join was being performed for this
dial, processed as row selection.

For a given dial, the only join specifications which are usable as join columns for
that dial are those being joined to a previous dial. For example, for the second dial
the only join specifications that can be used to satisfy the join condition are join
specifications which reference columns in the primary dial. Likewise, the third dial
can only use join specifications which reference columns in the primary and the
second dials and so on. Join specifications which reference later dials are deferred
until the referenced dial is processed.

For any given dial, only one type of join operator is normally implemented. For
example, if one inner join join specification has a join operator of ’=’ and the other
has a join operator of ’>’, the optimizer attempts to implement the join with the ’=’
operator. The ’>’ join specification is processed as row selection after a matching
row for the ’=’ specification is found. In addition, multiple join specifications that use
| the same operator are implemented together.

| Note: For OPNQRYF, only one type of join operator is allowed for either a left
| outer or an exception join.

| When looking for an existing keyed access path to access a secondary dial, the
query optimizer looks at the left-most key columns of the access path. For a given
dial and keyed access path, the join specifications which use the left-most key
columns can be used. For example:

430 DB2 UDB for AS/400 SQL Programming V4R4


DECLARE BROWSE2 CURSOR FOR
SELECT * FROM EMPLOYEE, EMP_ACT
WHERE EMPLOYEE.EMPNO = EMP_ACT.EMPNO
AND EMPLOYEE.HIREDATE = EMP_ACT.EMSTDATE
OPTIMIZE FOR 99999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE, EMP_ACT)) FORMAT(FORMAT1)
| JFLD((1/EMPNO 2/EMP_ACT *EQ)(1/HIREDATE 2/EMSTDATE
| *EQ))

| For the keyed access path over EMP_ACT with key columns EMPNO, PROJNO,
and EMSTDATE, the join operation is performed only on column EMPNO. After the
join is processed, row selection is done using column EMSTDATE.

The query optimizer also uses local row selection when choosing the best use of
the keyed access path for the secondary dial. If the previous example had been
expressed with a local predicate as:
DECLARE BROWSE2 CURSOR FOR
SELECT * FROM EMPLOYEE, EMP_ACT
WHERE EMPLOYEE.EMPNO = EMP_ACT.EMPNO
AND EMPLOYEE.HIREDATE = EMP_ACT.EMSTDATE
AND EMP_ACT.PROJNO = '123456'
OPTIMIZE FOR 99999 ROWS

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE, EMP_ACT)) FORMAT(FORMAT2)
| QRYSLT('2/PROJNO *EQ ''123456''')
| JFLD((1/EMPNO 2/EMP_ACT *EQ)(1/HIREDATE 2/EMSTDATE
| *EQ))

| the keyed access path with key columns EMPNO, PROJNO, and EMSTDATE are
fully utilized by combining join and selection into one operation against all three key
columns.

When creating a temporary keyed access path, the left-most key columns are the
usable join columns in that dial position. All local row selection for that dial is
processed when selecting keys for inclusion into the temporary keyed access path.
A temporary keyed access path is similar to the access path created for a
select/omit keyed logical file. The temporary index for the previous example would
have key fields of EMPNO and EMSTDATE.

| Since the OS/400 query optimizer attempts a combination of join and local record
| selection when determining access path usage, it is possible to achieve almost all
| of the same advantages of a temporary keyed access path by use of an existing
| access path. In the above example, using either implementation, an existing index
| may be used or a temporary index may be created. A temporary access path would
| have been built with the local row selection on PROJNO applied during the access
| path’s creation; the temporary access path would have key fields of EMP_ACT and
| EMSTDATE (to match the join selection). If, instead, an existing keyed access path
| was used with key fields of EMP_ACT, PROJNO, EMSTDATE (or PROJNO,
| EMP_ACT, EMSTDATE or EMSTDATE, PROJNO, EMP_ACT or ...) the local record
| selection could be applied at the same time as the join selection (rather than prior
| to the join selection, as happens when the temporary access path is created).

| The implementation using the existing index is more likely to provide faster
| performance because join and selection processing are combined without the
| overhead of building a temporary index. However, the use of the existing keyed

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 431
| access path may have just slightly slower I/O processing than the temporary access
| path because the local selection is run many times rather than once. In general, it is
| a good idea to have existing indexes available with key columns for the combination
| of join columns and columns using equal selection as the left-most keys.

Join Order Optimization


| The join order is fixed if any join logical files are referenced or a left outer or an
| exception join is used to implement any of the dials of the join. The join order is
| also fixed if the OPNQRYF JORDER(*FILE) parameter is specified or the query
| options file (QAQQINI) FORCE_JOIN_ORDER parameter is *YES. Otherwise, the
| following join ordering algorithm is used to determine the order of the tables:
| 1. Determine an access method for each individual table as candidates for the
| primary dial.
| 2. Estimate the number of rows returned for each table based on local row
| selection.
| If the join query with row ordering or group by processing is being processed in
| one step, then the table with the ordering or grouping columns is the primary
| table.
| 3. Determine an access method, cost, and expected number of rows returned for
| each join combination of candidate tables as primary and first secondary tables.
| The join order combinations estimated for a four table join would be:

| 1-2 2-1 1-3 3-1 1-4 4-1 2-3 3-2 2-4 4-2 3-4 4-3
| 4. Choose the combination with the lowest join cost.
| If the cost is nearly the same, then choose the combination which selects the
| fewest rows.
| 5. Determine the cost, access method, and expected number of rows for each
| remaining table joined to the previous secondary table.
| 6. Select an access method for each table that has the lowest cost for that table.
| 7. Choose the secondary table with the lowest join cost.
| If the cost is nearly the same, choose the combination which selects the fewest
| rows.
| 8. Repeat steps 4 through 7 until the lowest cost join order is determined.

| When a join logical file is referenced, a left outer or an excpetion join, or the join
| order is forced to the specified file order, the query optimizer loops through all of the
| dials in the order specified, and determines the lowest cost access methods.

Costing and Selecting Access Paths for Join Secondary dials


In step 3 and in step 5, the query optimizer has to estimate a cost and choose an
access method for a given dial combination. The choices made are similar to those
for row selection except that a keyed access path must be used.

As the query optimizer compares the various possible access choices, it must
assign a numeric cost value to each candidate and use that value to determine the
implementation which consumes the least amount of processing time. This costing
value is a combination of CPU and I/O time and is based on the following
assumptions:
v Table pages and keyed access path pages must be retrieved from auxiliary
storage. For example, the query optimizer is not aware that an entire table may
be loaded into active memory as the result of a SETOBJACC CL command.

432 DB2 UDB for AS/400 SQL Programming V4R4


Usage of this command may significantly improve the performance of a query,
but the query optimizer does not change the query implementation to take
advantage of the memory resident state of the table.
v The query is the only process running on the system. No allowance is given for
system CPU utilization or I/O waits which occur because of other processes
using the same resources. CPU related costs are scaled to the relative
processing speed of the system running the query.
v The values in a column are uniformly distributed across the table. For example, if
10% of the rows in a table have the same value, then it is assumed that every
tenth row in the table contains that value.
v The values in a column are independent from the values in any other columns in
a row. For example, if a column named A has a value of 1 in 50% of the rows in
a table and a column named B has a value of 2 in 50% of the rows, then it is
expected that a query which selects rows where A = 1, and B = 2 selects 25% of
the rows in the table.

The main factors of the join cost calculations for secondary dials are the number of
rows selected in all previous dials and the number of rows which match, on
average, each of the rows selected from previous dials. Both of these factors can
be derived by estimating the number of matching rows for a given dial.

When the join operator is something other than equal, the expected number of
matching rows is based on the following default filter factors:
v 33% for less-than, greater-than, less-than-equal-to, or greater-than-equal-to
v 90% for not equal
| v 25% for BETWEEN range (OPNQRYF %RANGE)
| v 10% for each IN list value (OPNQRYF %VALUES)

For example, when the join operator is less-than, the expected number of matching
rows is .33 * (number of rows in the dial). If no join specifications are active for the
current dial, the cartesian product is assumed to be the operator. For cartesian
products, the number of matching rows is every row in the dial, unless local row
selection can be applied to the keyed access path.

When the join operator is equal, the expected number of rows is the average
number of duplicate rows for a given value.

The AS/400 performs index maintenance (insertion and deletion of key values in an
index) and maintains a running count of the number of unique values for the given
key columns in the index. These statistics are bound with the index object and are
always maintained. The query optimizer uses these statistics when it is optimizing a
query. Maintaining these statistics adds no measurable amount of overhead to
index maintenance. This statistical information is only available for indexes which:
v Contain no varying length character keys.

Note: If you have varying length character columns used as join columns, you
can create an index which maps the varying length character column to a
fixed character key using the CRTLF CL command. An index that contains
fixed length character keys defined over varying length data supplies
average number of duplicate values statistics.
v Were created or rebuilt on an AS/400 system on which Version 2 Release 3 or a
later version is installed.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 433
Note: The query optimizer can use indexes created on earlier versions of
OS/400 to estimate if the join key values have a high or low average
number of duplicate values. If the index is defined with only the join keys,
the estimate is done based on the size of the index. In many cases,
additional keys in the index cause matching row estimates through that
index to not be valid. The performance of some join queries may be
improved by rebuilding these access paths.

Average number of duplicate values statistics are maintained only for the first 4
left-most keys of the index. For queries which specify more than 4 join columns, it
might be beneficial to create multiple additional indexes so that an index can be
found with average number of duplicate values statistics available within the 4
left-most key columns. This is particularly important if some of the join columns are
somewhat unique (low average number of duplicate values).

Three Field Key


┌───────┬───────┬───────┐
│ Key 1 │ Key 2 │ Key 3 │
└───┬───┴───┬───┴───┬───┘
│ │ │
ø │ │
Number │ │
of unique │ │
keys for │ │
Key 1 │ │
│ │ │
└───┬───┘ │
ø │
Number of │
unique keys │
for Key1 │
and Key 2 │
combination │
│ │
└─────┬─────┘
ø
Number of unique
keys for Key 1, Key2,
and Key 3 combination
(the full key)

Figure 14. Average number of duplicate values of a 3 key index

These statistics are maintained as part of index rebuild and creation.

Using the average number of duplicate values for equal joins or the default filter
value for the other join operators, we now have the number of matching rows. The
following formula is used to compute the number of join rows from previous dials.
NPREV = Rp * M2 * FF2 * ..... *Mn * FFn .....
NPREV
The number of join rows from all previous dials.
Rp The number of rows selected from the primary dial.
M2 The number of matching rows for dial 2.
FF2 Filtering reduction factor for predicates local to dial 2 that are not already
applied using M2 above.
Mn The number of matching rows for dial n.

434 DB2 UDB for AS/400 SQL Programming V4R4


FFn Filtering reduction factor for predicates local to dial n that are not already
applied using Mn above.

Note: Multiply the pair of matching rows (Mn) and filter reduction filter
factors (FFn) for each secondary dial preceding the current dial.

Now that it has calculated the number of join rows from previous dials, the optimizer
is ready to generate a cost for the access method.

Temporary Keyed Access Path or Hash Temporary Result Table


from Table
The first access method choice analyzed by the query optimizer is building a
temporary keyed access path or hash temporary result table from the table. The
basic formula for costing access of a join secondary dial through a temporary keyed
access path built from the table or hash table follows:
JSCOST = CRTDSI +
NPREV *((MATCH * FF * KeyAccess)
+ (MATCH * FF * FCost)) *
FirstIO
JSCOST
Join Secondary cost
CRTDSI
Cost to build the temporary keyed access path or a hash temporary result
table
NPREV
The number of join rows from all previous dials
MATCH
The number of matching rows (usually average duplicates)
KeyAccess
The cost to access a key in a keyed access path or a hash table
FF The filtering factor for local predicates of this dial (excluding selection
performed on earlier dials because of transitive closure)
FCost The cost to access a row from the table
FirstIO
A reduction ratio to reduce the non-startup cost because of an optimization
goal to optimize for the first buffer retrieval. For more information, see “Cost
Estimation” on page 423.

This secondary dial access method is used if no usable keyed access path is found
or if the temporary keyed access path or hash table performs better than any
existing keyed access path. This method can be better than using any existing
access path because the row selection is completed when the keyed access path
or hash table is created if any of the following are true:
v The number of matches (MATCH) is high.
v The number of join rows from all previous dials (NPREV) is high.
v There is some filtering reduction (FF < 100%).

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 435
Temporary Keyed Access Path or Hash Table from Keyed Access
Path
The basic cost formula for this access method choice is the same as that of using a
temporary keyed access path or hash table built from a table, with one exception.
The cost to build the temporary keyed access path, CRTDSI, is calculated to
include the selection of the rows through an existing keyed access path. This
access method is used for join secondary dial access for the same reason.
However, the creation from a keyed access path might be less costly.

Use an Existing Keyed Access Path


The final access method is to use an existing keyed access path. The basic formula
for costing access of a join secondary dial through an existing keyed access path
is:
JSCOST = NPREV *((MATCH * KeyAccess)
+ (MATCH * FCost)) *
FirstIO

JSCOST
Join Secondary cost
NPREV
The number of join rows from all previous dials
MATCH
The number of matching keys which will be found in this keyed access path
(usually average duplicates)
KeyAccess
The cost to access a key in a keyed access path
FCost The cost to access a row from the table
FirstIO
A reduction ratio to reduce the non-startup cost because of an optimization
goal to optimize for the first buffer retrieval. For more information, see “Cost
Estimation” on page 423.

If I/O optimization is used (that is, OPNQRYF OPTIMIZE(*FIRSTIO)), this is a likely


access method because the entire cost is reduced. Also, if the number of join rows
from all previous dials (NPREV), and the number of matching keys (MATCH) is low,
this may be the most efficient method.

The query optimizer considers using an index which only has a subset of the join
columns as the left-most leading keys when:
v It is able to determine from the average number of duplicate values statistics that
the average number of rows with duplicate values is quite low.
v The number of rows being selected from the previous dials is small.

Predicates Generated Through Transitive Closure


For join queries, the query optimizer may do some special processing to generate
additional selection. When the set of predicates that belong to a query logically infer
extra predicates, the query optimizer generates additional predicates. The purpose
is to provide more information during join optimization.

436 DB2 UDB for AS/400 SQL Programming V4R4


Example of Predicates being Added Because of Transitive
Closure
SELECT * FROM EMPLOYEE, EMP_ACT
WHERE EMPLOYEE.EMPNO = EMP_ACT.EMPNO
AND EMPLOYEE.EMPNO = '000010'

The optimizer will modify the query to be:


SELECT * FROM EMPLOYEE, EMP_ACT
WHERE EMPLOYEE.EMPNO = EMP_ACT.EMPNO
AND EMPLOYEE.EMPNO = '000010'
AND EMP_ACT.EMPNO = '000010'OPNQRYF example:

| OPNQRYF example:
| OPNQRYF FILE((EMPLOYEE EMP_ACT)) FORMAT(FORMAT1)
| QRYSLT('1/EMPNO *EQ ''000010''')
| JFLD((1/EMPNO 2/EMPNO *EQ))
|

| The optimizer will modify the query to be:


| OPNQRYF FILE((EMPLOYEE EMP_ACT)) FORMAT(FORMAT1)
| QRYSLT('1/EMPNO *EQ ''000010'' *AND
| 2/EMPNO *EQ ''000010''')
| JFLD((1/EMPNO 2/EMPNO *EQ))

| The following rules determine which predicates are added to other join dials:
v The dials affected must have join operators of equal.
v The predicate is isolatable, which means that a false condition from this
predicate would omit the row.
v One operand of the predicate is an equal join column and the other is a literal or
host variable.
| v The predicate operator is not LIKE or IN (OPNQRYF %WLDCRD, %VALUES, or
| *CT).
v The predicate is not connected to other predicates by OR.
v The join type for the dial is an inner join.

| The query optimizer generates a new predicate, whether or not a predicate already
| exists in the WHERE clause (OPNQRYF QRYSLT parameter).

| Some predicates are redundant. This occurs when a previous evaluation of other
| predicates in the query already determines the result that predicate provides.
| Redundant predicates can be specified by you or generated by the query optimizer
| during predicate manipulation. Redundant predicates with predicate operators of =,
| >, >=, <, <=, or BETWEEN (OPNQRYF *EQ, *GT, *GE, *LT, *LE, or %RANGE) are
| merged into a single predicate to reflect the most selective range.

Multiple Join Types for a Query


Even though multiple join types (inner, left outer and exception) can be specified in
the query using the JOIN syntax, the AS/400 Licensed Internal Code can only
support one join type for the entire query. This requires the optimizer to determine
what the overall join type for the query should be.

Note: This section does not apply to OPNQRYF.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 437
The optimizer will evaluate the join criteria along with any record selection that may
be specified in order to determine the join type for each dial and for the entire
query. Once this information is known the optimizer will generate additional
selection using the relative record number of the tables to simulate the different
types of joins that may occur within the query.

Since null values are returned for any unmatched rows for either a left outer or an
exception join, any isolatable selection specified for that dial, including any
additional join criteria that may be specified in the WHERE clause, will cause all of
the unmatched records to be eliminated (unless the selection is for an IS NULL
predicate). This will cause the join type for that dial to be changed to an inner join
(or an exception join) if the IS NULL predicate was specified.

In the following example a left outer join is specified between the tables
EMPLOYEE and DEPARTMENT. In the WHERE clause there are two selection
predicates that also apply to the DEPARTMENT table.
SELECT EMPNO, LASTNAME, DEPTNAME, PROJNO
FROM CORPDATA.EMPLOYEE XXX LEFT OUTER JOIN CORPDATA.DEPARTMENT YYY
ON XXX.WORKDEPT = YYY.DEPTNO
LEFT OUTER JOIN CORPDATA.PROJECT ZZZ
ON XXX.EMPNO = ZZZ.RESPEMP
WHERE XXX.EMPNO = YYY.MGRNO AND
YYY.DEPTNO IN ('A00', 'D01', 'D11', 'D21', 'E11')

The first selection predicate, XXX.EMPNO = YYY.MGRNO, is an additional join


condition that will be added to the join criteria and evaluated as an ″inner join″ join
condition. The second is an isolatable selection predicate that will eliminate any
unmatched records. Either one of these selection predicates will cause the join type
for the DEPARTMENT table to be changed from a left outer join to an inner join.

Even though the join between the EMPLOYEE and the DEPARTMENT table was
changed to an inner join the entire query will still need to remain a left outer join to
satisfy the join condition for the PROJECT table.

Note: Care must be taken when specifying multiple join types since they are
supported by appending selection to the query for any unmatched rows. This
means that the number of resulting rows that satisfy the join criteria can
become quite large before any selection is applied that will either select or
omit the unmatched rows based on that individual dial’s join type.

For more information on how to use the JOIN syntax see either “Joining Data from
More Than One Table” on page 75 or the DB2 UDB for AS/400 SQL Reference
book.

Sources of Join Query Performance Problems


The optimization algorithms described above benefit most join queries, but the
performance of a few queries may be degraded. This occurs when:
v An access path is not available which provides average number of duplicate
values statistics for the potential join columns.

Note: “Costing and Selecting Access Paths for Join Secondary dials” on
page 432 provides suggestions on how to avoid the restrictions about
indexes statistics or create additional indexes over the potential join
columns if they do not exist.

438 DB2 UDB for AS/400 SQL Programming V4R4


v The query optimizer uses default filter factors to estimate the number of rows
being selected when applying local selection to the table because indexes do not
exist over the selection columns.
Creating indexes over the selection columns allows the query optimizer to make
a more accurate filtering estimate by using key range estimates.
v The particular values selected for the join columns yield a significantly greater
number of matching rows than the average number of duplicate values for all
values of the join columns in the table (i.e. the data is not uniformly distributed).
Use DDS to build a logical file with a keyed access path with select/omit
specifications matching the local row selection. This provides the query optimizer
with a more accurate estimate of the number of matching rows for the keys
which are selected.

Note: The optimizer can better determine from the select/omit access path that
the data is not uniformly distributed.
v The query optimizer makes the wrong assumption about the number of rows
which will be retrieved from the answer set.
For SQL programs, specifying the precompile option ALWCPYDTA(*YES) makes
it more likely that the queries in that program will use an existing index. Likewise,
specifying ALWCPYDTA(*OPTIMIZE) makes it more likely that the queries in that
program will create a temporary index. The SQL clause OPTIMIZE FOR n
ROWS can also be used to influence the query optimizer.
| For the OPNQRYF command, the wrong performance option for the OPTIMIZE
| keyword may have been specified. Specify *FIRSTIO to make the use of an
| existing index more likely. Specify *ALLIO to make the creation of a temporary
| index more likely.

Improving Performance of Join Queries


If you are looking at a join query which is performing poorly or you are about to
create a new application which uses join queries, the following checklist may be
useful.
Table 39. Checklist for Creating an Application that Uses Join Queries
What to Do How It Helps
Check the database design. Make This gives the query optimizer a better opportunity to select an efficient access
sure that there are indexes method because it can determine the average number of duplicate values. Many
available over all of the join queries may be able to use the existing index to implement the query and avoid
columns and/or row selection the cost of creating a temporary index.
columns. If using CRTLF, make
sure that the index is not shared.
Check the query to see whether Since the query optimizer does not add predicates for predicates connected by
some complex predicates should OR or non-isolatable predicates, or predicate operators of LIKE or IN, modifying
be added to other dials to allow the query by adding these predicates may help.
the optimizer to get a better idea
of the selectivity of each dial.
Create a keyed access path which This step helps if the statistical characteristics are not uniform for the entire table.
includes Select/Omit specifications For example, if there is one value which has a high duplication factor and the rest
which match that of the query of the column values are unique, then a select/omit keyed access path allows the
using CRTLF CL command. optimizer to skew the distribution of values for that key and make the right
optimization for the selected values.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 439
Table 39. Checklist for Creating an Application that Uses Join Queries (continued)
What to Do How It Helps
Specify ALWCPYDTA(*OPTIMIZE) If the query is creating a temporary keyed access path, and you feel that the
or ALWCPYDTA(*YES) processing time would be better if the optimizer only used the existing access
path, specify ALWCPYDTA(*YES).

If the query is not creating a temporary keyed access path, and you feel that the
processing time would be better if a temporary keyed access path was created,
specify ALWCPYDTA(*OPTIMIZE).

| Alternatively, specify the OPTIMIZE FOR n ROWS to inform the optimizer of the
| application has intention to read every resulting row. To do this set n to a large
| number. You could also set n to a small number before ending the query.
| For OPNQRYF, specify If the query is creating a temporary keyed access path and you feel that the
| OPTIMIZE(*FIRSTIO) or processing time would be better if it would only use the existing access path, then
| OPTIMIZE(*ALLIO) specify OPTIMIZE(*FIRSTIO). If the query is not creating a temporary keyed
| access path and you feel that the processing time would be better if a temporary
| keyed access path was created then specify OPTIMIZE(*ALLIO).

440 DB2 UDB for AS/400 SQL Programming V4R4


Table 39. Checklist for Creating an Application that Uses Join Queries (continued)
What to Do How It Helps
| Use a join logical file or use the A join in which one file is joined with all secondary files consecutively is
| query options file (QAQQINI) sometimes called a star join (star join should be in bold). In the case of a star join
| FORCE_JOIN_ORDER parameter where all secondary join predicates contain a field reference to a particular file,
| of *YES. OPNQRYF users can there may be performance advantages if that file is placed in join position one. In
| specify JORDER(*FILE). Example A, all files are joined to file EMPLOYEE. The query optimizer can freely
| determine the join order. The query should be changed to force EMPLOYEE into
| join position one by using the query options file (QAQQINI)
| FORCE_JOIN_ORDER parameter of *YES or OPNQRYF JORDER(*FILE) as
| shown in example B. Note that in these examples the join type is a join with no
| default values returned (this is an inner join.). The reason for forcing the file into
| the first position is to avoid random I/O processing. If EMPLOYEE is not in join
| position one, every record in EMPLOYEE could be examined repeatedly during
| the join process. If EMPLOYEE is fairly large, considerable random I/O
| processing occurs resulting in poor performance. By forcing EMPLOYEE to the
| first position, random I/O processing is minimized.

| Example A: Start join query


| DECLARE C1 CURSOR FOR
| SELECT * FROM DEPARTMENT, EMP_ACT, EMPLOYEE,
| PROJECT
| WHERE DEPARTMENT.DEPTNO=EMPLOYEE.WORKDEPT
| AND EMP_ACT.EMPNO=EMPLOYEE.EMPNO
| AND EMPLOYEE.WORKDEPT=PROJECT.DEPTNO

| Example B: Star join query with order forced via


| FORCE_JOIN_ORDER
| DECLARE C1 CURSOR FOR
| SELECT * FROM EMPLOYEE, DEPARTMENT, EMP_ACT,
| PROJECT
| WHERE DEPARTMENT.DEPTNO=EMPLOYEE.WORKDEPT
| AND EMP_ACT.EMPNO=EMPLOYEE.EMPNO
| AND EMPLOYEE.WORKDEPT=PROJECT.DEPTNO
| OPNQRYF

| Example A: Start join query


| OPNQRYF FILE((DEPARTMENT EMP_ACT EMPLOYEE
| PROJECT)) FORMAT(FORMAT1)
| JFLD((1/DEPTNO 3/WORKDEPT *EQ)
| (2/EMPNO 3/EMPNO *EQ)
| (3/WORKDEPT 4/DEPTNO *EQ))

| Example B: Start join query with JORDER(*FILE) parameter


| OPNQRYF FILE((EMPLOYEE DEPARTMENT EMP_ACT
| PROJECT)) FORMAT(FORMAT1)
| JFLD((2/DEPTNO 1/WORKDEPT *EQ)
| (3/EMPNO 1/EMPNO *EQ)
| (1/WORKDEPT 4/DEPTNO *EQ))
| JORDER(*FILE)

| Note: Specifying fields from EMPLOYEE in the ORDER BY clause (OPNQRYF


| KEYFLD parameter) may also have the effect of placing EMPLOYEE in join
| position 1. This allows the query optimizer to choose the best order for the
| remaining files.
Specify ALWCPYDTA(*OPTIMIZE) In the cases where ordering is specified and all key columns are from a single
to allow the query optimizer to use dial, this allows the query optimizer to consider all possible join orders.
a sort routine.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 441
Table 39. Checklist for Creating an Application that Uses Join Queries (continued)
What to Do How It Helps
| Specify join predicates to prevent This improves performance by reducing the join fan-out. Every secondary file
| all of the records from one file should have at least one join predicate that references on of its fields as a ’join-to’
| from being joined to every record field.
| in the other file.

Improving Performance When Selecting Data from More than


Two Tables
If the select-statement you are considering accesses two or more tables, all the
recommendations suggested in “Effectively Using SQL Indexes” on page 446 apply.
The following suggestion is directed specifically to select-statements that access
several tables. For joins that involve more than two tables, you might want to
provide redundant information about the join columns. If you give the optimizer
extra information to work with when requesting a join. It can determine the best way
to do the join. The additional information might seem redundant, but is helpful to the
optimizer. For example, instead of coding:
EXEC SQL
DECLARE EMPACTDATA CURSOR FOR
SELECT LASTNAME, DEPTNAME, PROJNO, ACTNO
FROM CORPDATA.DEPARTMENT, CORPDATA.EMPLOYEE,
CORPDATA.EMP_ACT
WHERE DEPARTMENT.MGRNO = EMPLOYEE.EMPNO
AND EMPLOYEE.EMPNO = EMP_ACT.EMPNO
END-EXEC.

| When using the OPNQRYF command, specify:


| OPNQRYF FILE(CORPDATA/DEPARTMENT CORPDATA/EMPLOYEE CORPDATA/EMP_ACT)
| FORMAT(FORMAT1)
| JFLD((1/MGRNO 2/EMPNO *EQ) (2/EMPNO 3/EMP_ACT *EQ))

| Provide the optimizer with a little more data and code:


EXEC SQL
DECLARE EMPACTDATA CURSOR FOR
SELECT LASTNAME, DEPTNAME, PROJNO, ACTNO
FROM CORPDATA.DEPARTMENT, CORPDATA.EMPLOYEE,
CORPDATA.EMP_ACT
WHERE DEPARTMENT.MGRNO = EMPLOYEE.EMPNO
AND EMPLOYEE.EMPNO = EMP_ACT.EMPNO
AND DEPARTMENT.MGRNO = EMP_ACT.EMPNO
END-EXEC.

| When using the OPNQRYF command, specify:


| OPNQRYF FILE(CORPDATA/DEPARTMENT CORPDATA/EMPLOYEE CORPDATA/EMP_ACT)
| FORMAT(FORMAT1)
| JFLD((1/MGRNO 2/EMPNO *EQ) (2/EMPNO 3/EMP_ACT *EQ)
| (1/MGRNO 3/EMPNO *EQ))

| Grouping Optimization
This section describes how DB2 UDB for AS/400 implements grouping techniques
and how optimization choices are made by the query optimizer.

Grouping Hash Implementation


This technique uses the base hash access method to perform grouping or
summarization of the selected table rows. For each selected row, the specified

442 DB2 UDB for AS/400 SQL Programming V4R4


grouping value is run through the hash function. The computed hash value and
grouping value are used to quickly find the entry in the hash table corresponding to
the grouping value. If the current grouping value already has a row in the hash
table, the hash table entry is retrieved and summarized (updated) with the current
table row values based on the requested grouping column operations (such as
SUM or COUNT). If a hash table entry is not found for the current grouping value, a
new entry is inserted into the hash table and initialized with the current grouping
value.

The time required to receive the first group result for this implementation will most
likely be longer than other grouping implementations because the hash table must
be built and populated first. Once the hash table is completely populated, the
database manager uses the table to start returning the grouping results. Before
returning any results, the database manager must apply any specified grouping
selection criteria or ordering to the summary entries in the hash table.

The grouping hash method is most effective when the consolidation ratio is high.
The consolidation ratio is the ratio of the selected table rows to the computed
grouping results. If every database table row has its own unique grouping value,
then the hash table will become too large. This in turn will slow down the hashing
access method.

The optimizer estimates the consolidation ratio by first determining the number of
unique values in the specified grouping columns (that is, the expected number of
groups in the database table). The optimizer then examines the total number of
rows in the table and the specified selection criteria and uses the result of this
examination to estimate the consolidation ratio.

Indexes over the grouping columns can help make the optimizer’s ratio estimate
more accurate. Indexes improve the accuracy because they contain statistics that
include the average number of duplicate values for the key columns.

The optimizer also uses the expected number of groups estimate to compute the
number of partitions in the hash table. As mentioned earlier, the hashing access
method is more effective when the hash table is well-balanced. The number of hash
table partitions directly affects how entries are distributed across the hash table and
the uniformity of this distribution.

The hash function performs better when the grouping values consist of columns that
have non-numeric data types, with the exception of the integer (binary) data type. In
addition, specifying grouping value columns that are not associated with the
variable length and null column attributes allows the hash function to perform more
effectively.

Grouping with Keyed Sequence Implementation


This implementation utilizes the key selection or key positioning access methods to
perform the grouping. An index is required that contains all of the grouping columns
as contiguous leftmost key fields. The database manager accesses the individual
groups through the keyed access path and performs the requested summary
functions.

Since the index, by definition, already has all of the key values grouped together,
the first group result can be returned in less time than the hashing method. This is
because of the temporary result that is required for the hashing method. This

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 443
implementation can be beneficial if an application does not need to retrieve all of
the group results or if an index already exists that matches the grouping columns.

When the grouping is implemented with an index and a permanent index does not
already exist that satisfies grouping columns, a temporary index is created. The
grouping columns specified within the query are used as the key fields for this
index.

Eliminating Grouping Columns


All of the grouping columns are evaluated to determine if they can be removed from
the list of grouping columns. Only those grouping columns that have isolatable
selection predicates with an equal operator specified can be considered. This
guarantees that the column can only match a single value and will not help
determine a unique group. This processing is done to allow the optimizer to
consider more indexes to implement the query and to reduce the number of
columns that will be added as key fields to a temporary index or hash table.

The following example illustrates a query where the optimizer could eliminate a
grouping column.
| DECLARE DEPTEMP CURSOR FOR
| SELECT EMPNO, LASTNAME, WORKDEPT
| FROM CORPDATA.EMPLOYEE
| WHERE EMPNO = '000190'
| GROUP BY EMPNO, LASTNAME, WORKDEPT

| OPNQRYF example:
OPNQRYF FILE(EMPLOYEE) FORMAT(FORMAT1)
QRYSLT('EMPNO *EQ ''000190''')
GRPFLD(EMPNO LASTNAME WORKDEPT)

In this example, the optimizer can remove EMPNO from the list of grouping fields
because of the EMPNO = '000190' selection predicate. An index that only has
LASTNAME and WORKDEPT specified as key fields can be considered to
implement the query and if a temporary index or hash is required then EMPNO will
not be used.

Note: Even though EMPNO can be removed from the list of grouping columns, the
optimizer might still choose to use that index if a permanent index exists with
all three grouping columns.

Adding Additional Grouping Columns


The same logic that is applied to removing grouping columns can also be used to
add additional grouping columns to the query. This is only done when you are trying
to determine if an index can be used to implement the grouping.

The following example illustrates a query where the optimizer could add an
additional grouping column.
| CREATE INDEX X1 ON EMPLOYEE
| (LASTNAME, EMPNO, WORKDEPT)
|
| DECLARE DEPTEMP CURSOR FOR
| SELECT LASTNAME, WORKDEPT
| FROM CORPDATA.EMPLOYEE
| WHERE EMPNO = '000190'
| GROUP BY LASTNAME, WORKDEPT
|
|
444 DB2 UDB for AS/400 SQL Programming V4R4
| OPNQRYF example:
OPNQRYF FILE ((EMPLOYEE)) FORMAT(FORMAT1)
QRYSLT('EMPNO *EQ ''000190''')
GRPFLD(LASTNAME WORKDEPT)

For this query request, the optimizer can add EMPNO as an additional grouping
| column when considering X1 for the query.

| Grouping using Index Skip Key Processing


| Index Skip Key processing can be used when grouping with the keyed sequence
| implementation algorithm which uses an existing index. The index skip key
| processing algorithm:
| 1. Uses the index to position to a group and
| 2. finds the first record matching the selection criteria for the group, and if
| specified the first non-null MIN or MAX value in the group
| 3. Returns the group to the user
| 4. ″Skip″ to the next group and repeat processing
| This will improve performance by potentially not processing all index key values for
| a group.

| Index skip key processing can be used:


| v For single file queries using the keyed sequence grouping implementation when:
| – There are no column functions in the query, or
| – There is only a single MIN or MAX column function in the query and the
| operand of the MIN or MAX is the next key field in the index after the
| grouping fields. There can be no other grouping functions in the query. For the
| MIN function, the key field must be an ascending key; for the MAX function,
| the key field must be a descending key. If the query is whole file grouping, the
| operand of the MIN or MAX must be the first key field.
| Example 1, using SQL:
| CREATE INDEX IX1 ON EMPLOYEE (SALARY DESC)
|
| DECLARE C1 CURSOR FOR
| SELECT MAX(SALARY) FROM EMPLOYEE;

| Example 1, using the OPNQRYF command:


| OPNQRYF FILE(EMPLOYEE) FORMAT(FORMAT1)
| MAPFLD((MAXSAL '%MAX(SALARY)'))

| The query optimizer will chose to use the index IX1. The SLIC runtime code
| will scan the index until it finds the first non-null value for SALARY. Assuming
| that SALARY is not null, the runtime code will position to the first index key
| and return that key value as the MAX of salary. No more index keys will be
| processed.

| Example 2, using SQL:


| CREATE INDEX IX2 ON EMPLOYEE (DEPT, JOB,SALARY)
|
| DECLARE C1 CURSOR FOR
| SELECT DEPT, MIN(SALARY)
| FROM EMPLOYEE
| WHERE JOB='CLERK'
| GROUP BY DEPT

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 445
| Example 2, using the OPNQRYF command:
| OPNQRYF FILE(EMPLOYEE) FORMAT(FORMAT2)
| QRYSLT('JOB *EQ ''CLERK''')
| GRPFLD((DEPT))
| MAPFLD((MINSAL '%MIN(SALARY)'))

| The query optimizer will chose to use Index IX2. The SLIC runtime code will
| position to the first group for DEPT where JOB equals ’CLERK’ and will return
| the SALARY. The code will then skip to the next DEPT group where JOB
| equals ’CLERK’.
| v For join queries:
| – All grouping columns must be from a single file.
| – For each dial there can be at most one MIN or MAX column function operand
| that references the dial and no other column functions can exist in the query.
| – If the MIN or MAX function operand is from the same dial as the grouping
| columns, then it uses the same rules as single file queries.
| – If the MIN or MAX function operand is from a different dial then the join field
| for that dial must join to one of the grouping fields and the index for that dial
| must contain the join fields followed by the MIN or MAX operand.
| Example 1, using SQL:
| CREATE INDEX IX1 ON DEPARTMENT(DEPTNAME)
|
| CREATE INDEX IX2 ON EMPLOYEE(WORKDEPT, SALARY)
|
| DECLARE C1 CURSOR FOR
| SELECT DEPTNAME, MIN(SALARY)
| FROM DEPARTMENT, EMPLOYEE
| WHERE DEPARTMENT.DEPTNO=EMPLOYEE.WORKDEPT
| GROUP BY DEPARTMENT.DEPTNO;
|

| Example 1, using the OPNQRYF command:


| OPNQRYF FILE(DEPARTMENT EMPLOYEE) FORMAT(FORMAT1)
| JFLD((1/DEPTNO 2/WORKDEPT *EQ))
| GRPFLD((1/DEPTNO))
| MAPFLD((MINSAL '%MIN(SALARY)'))
|
Effectively Using SQL Indexes
DB2 UDB for AS/400 provides two basic means for accessing tables: a table scan
(sequential) and an index-based (direct) retrieval. Index-based retrieval is usually
more efficient than table scan. However, when a very large percentage of pages are
retrieved, table scan is more efficient than index-based retrieval.

If DB2 UDB for AS/400 cannot use an index to access the data in a table, it will
have to read all the data in the table. Very large tables present a special
performance problem: the high cost of retrieving all the data in the table. The
following suggestions help you to design code that allows DB2 UDB for AS/400 to
take advantage of available indexes.
1. Avoid numeric conversions.
| When a column value and a host variable (or literal value) are being compared,
| try to specify the same data types and attributes. DB2 UDB for AS/400 does not
| use an index for the named column if the host variable or literal value has a
| greater precision than the precision of the column. If the two items being
| compared have different data types, DB2 UDB for AS/400 will have to convert

446 DB2 UDB for AS/400 SQL Programming V4R4


| one or the other of the values, which can result in inaccuracies (because of
| limited machine precision). To avoid problems for columns and constants being
| compared, use the:
| v same data type
| v same scale, if applicable
| v same precision, if applicable
| For example, EDUCLVL is a halfword integer value (SMALLINT). When using
| SQL, specify:
| ... WHERE EDUCLVL < 11 AND
| EDUCLVL >= 2

| instead of
... WHERE EDUCLVL < 1.1E1 AND
EDUCLVL > 1.3

| When using the OPNQRYF command, specify:


| ... QRYSLT('EDUCLVL *LT 11 *AND ENUCLVL *GE 2')

| instead of
| ... QRYSLT('EDUCLVL *LT 1.1E1 *AND EDUCLVL *GT 1.3')

| If an index was created over the EDUCLVL column, then the optimizer does not
use the index in the second example because the precision of the constant is
greater than the precision of the column. In the first example, the optimizer
considers using the index, because the precisions are equal.
| 2. Avoid arithmetic expressions
| You should never have an arithmetic expression as an operand to be compared
| to a column in a row selection predicate. The optimizer does not use an index
| on a field that is being compared to an arithmetic expression. When using SQL,
| specify:
| ... WHERE SALARY > 16500
|

| instead of
| ... WHERE SALARY > 15000*1.1
|
| 3. Avoid character string padding.
Try to use the same data length when comparing a fixed-length character string
column value to a host variable or literal value. DB2 UDB for AS/400 does not
use an index if the literal value or host variable is longer than the column length.
For example, EMPNO is CHAR(6) and DEPTNO is CHAR(3). Specify:
... WHERE EMPNO > '000300' AND
DEPTNO < 'E20'

| instead of
| ... WHERE EMPNO > '000300 ' AND
| DEPTNO < 'E20 '

| When using the OPNQRYF command, specify:


... QRYSLT('EMPNO *GT "000300" *AND DEPTNO *LT "E20"')

instead of
... QRYSLT('EMPNO *GT "000300" *AND DEPTNO *LT "E20"')

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 447
4. Avoid the use of like patterns beginning with % or _.
The percent sign (%), and the underline (_), when used in the pattern of a LIKE
(OPNQRYF %WLDCRD) predicate, specify a character string that is similar to
the column value of rows you want to select. They can take advantage of
indexes when used to denote characters in the middle or at the end of a
character string, as in the following. When using SQL:
... WHERE LASTNAME LIKE 'J%SON%'

| When using the OPNQRYF command, specify:


... QRYSLT('LASTNAME *EQ WLDCRD(''J*SON*'')')

However, when used at the beginning of a character string, they can prevent
DB2 UDB for AS/400 from using any indexes that might be defined on the
LASTNAME column to limit the number of rows scanned. When using SQL:
... WHERE LASTNAME LIKE '%SON'

| When using the OPNQRYF command, specify:


... QRYSLT('LASTNAME *EQ WLDCRD(''*SON'')')

You should therefore avoid using these symbols at the beginning of character
strings, especially if you are accessing a particularly large table.
5. Be aware that DB2 UDB for AS/400 does not use an index in the following
instances:
v For a column that is expected to be updated; for example, your program
might include
EXEC SQL
DECLARE DEPTEMP CURSOR FOR
SELECT EMPNO, LASTNAME, WORKDEPT
FROM CORPDATA.EMPLOYEE
WHERE (WORKDEPT = 'D11' OR
WORKDEPT = 'D21') AND
EMPNO = '000190'
FOR UPDATE OF EMPNO, WORKDEPT
END-EXEC.

OPNQRYF example:
OPNQRYF FILE((CORPDATA/EMPLOYEE)) OPTION(*ALL)
QRYSLT('(WORKDEPT *EQ ''D11'' *OR WORKDEPT *EQ ''D21'')
*AND EMPNO *EQ ''000190''')

Even if you do not intend to update the employee’s department, DB2 UDB for
AS/400 cannot use an index with a key of WORKDEPT.

DB2 UDB for AS/400 can use an index if all of the updateable columns used
within the index are also used within the query as an isolatable selection
predicate with an equal operator. In the previous example DB2 UDB for
AS/400 would use an index with a key of EMPNO.

DB2 UDB for AS/400 can operate more efficiently if the FOR UPDATE OF
column list only names the column you intend to update: WORKDEPT.
Therefore, do not specify a column in the FOR UPDATE OF column list
unless you intend to update the column.

If you have an updateable cursor because of dynamic SQL or the FOR


UPDATE clause was not specified and the program contains an UPDATE
statement then all columns can be updated.

448 DB2 UDB for AS/400 SQL Programming V4R4


v For a column being compared with another column from the same row. For
example:
EXEC SQL
DECLARE DEPTDATA CURSOR FOR
SELECT WORKDEPT, DEPTNAME
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = ADMRDEPT
END-EXEC.

OPNQRYF example:
OPNQRYF FILE (EMPLOYEE) FORMAT(FORMAT1)
QRYSLT('WORKDEPT *EQ ADMRDEPT')

Even though there is an index for WORKDEPT and another index for
ADMRDEPT, DB2 UDB for AS/400 will not use either index. The index has
no added benefit because every row of the table needs to be looked at.

Using Indexes With Sort Sequence


The following sections provide useful information about how indexes work with sort
sequence tables. For more information on how Sort Sequence tables work, see the
DB2 UDB for AS/400 SQL Reference book.

Using Indexes and Sort Sequence With Selection, Joins, or Grouping


Before using an existing index, DB2 UDB for AS/400 ensures the attributes of the
columns (selection, join, or grouping columns) match the attributes of the key fields
in the existing index. The sort sequence table is an additional attribute that must be
compared.

The sort sequence table associated with the query (specified by the SRTSEQ and
LANGID parameters) must match the sort sequence table with which the existing
index was built. DB2 UDB for AS/400 compares the sort sequence tables. If they do
not match, the existing index cannot be used.

There is an exception to this, however. If the sort sequence table associated with
the query is a unique-weight sequence table (including *HEX), DB2 UDB for AS/400
acts as though no sort sequence table is specified for selection, join, or grouping
columns that use the following operators and predicates:
v equal (=) operator
v not equal (|= or <>) operator
| v LIKE predicate (OPNQRYF %WLDCRD and *CT)
| v IN predicate (OPNQRYF %VALUES)

When these conditions are true, DB2 UDB for AS/400 is free to use any existing
index where the key fields match the columns and either:
v The index does not contain a sort sequence table or
v The index contains a unique-weight sort sequence table

Note: The table does not have to match the unique-weight sort sequence table
associated with the query.

Note: Bitmap processing has a special consideration when multiple indexes are
used for a table. If two or more indexes have a common key field between

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 449
them that is also referenced in the query selection, then those indexes must
either use the same sort sequence table or use no sort sequence table.

Ordering
Unless the optimizer chooses to do a sort to satisfy the ordering request, the sort
sequence table associated with the index must match the sort sequence table
associated with the query.

When a sort is used, the translation is done during the sort. Since the sort is
handling the sort sequence requirement, this allows DB2 UDB for AS/400 to use
any existing index that meets the selection criteria.

Example Indexes
For the purposes of the examples, assume three indexes are created.

Assume an index HEXIX was created with *HEX as the sort sequence.
CREATE INDEX HEXIX ON STAFF (JOB)

Assume an index UNQIX was created with a unique-weight sort sequence.


CREATE INDEX UNQIX ON STAFF (JOB)

Assume an index SHRIX was created with a shared-weight sort sequence.


CREATE INDEX SHRIX ON STAFF (JOB)

Example 1
Equals selection with no sort sequence table (SRTSEQ(*HEX)).
SELECT * FROM STAFF
WHERE JOB = 'MGR'

When using the OPNQRYF command, specify:


OPNQRYF FILE((STAFF))
QRYSLT('JOB *EQ ''MGR''')
SRTSEQ(*HEX)

DB2 UDB for AS/400 could use either index HEXIX or index UNQIX.

Example 2
Equals selection with a unique-weight sort sequence table
(SRTSEQ(*LANGIDUNQ) LANGID(ENU)).
SELECT * FROM STAFF
WHERE JOB = 'MGR'

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF))
| QRYSLT('JOB *EQ ''MGR''')
| SRTSEQ(*LANGIDUNQ) LANGID(ENU)

| DB2 UDB for AS/400 could use either index HEXIX or index UNQIX.

450 DB2 UDB for AS/400 SQL Programming V4R4


Example 3
Equal selection with a shared-weight sort sequence table (SRTSEQ(*LANGIDSHR)
LANGID(ENU)).
SELECT * FROM STAFF
WHERE JOB = 'MGR'

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF))
| QRYSLT('JOB *EQ ''MGR''')
| SRTSEQ(*LANGIDSHR) LANGID(ENU)

| DB2 UDB for AS/400 could only use index SHRIX.

Example 4
Greater than selection with a unique-weight sort sequence table
(SRTSEQ(*LANGIDUNQ) LANGID(ENU)).
SELECT * FROM STAFF
WHERE JOB > 'MGR'

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF))
| QRYSLT('JOB *GT ''MGR''')
| SRTSEQ(*LANGIDUNQ) LANGID(ENU)

| DB2 UDB for AS/400 could only use index UNQIX.

Example 5
Join selection with a unique-weight sort sequence table (SRTSEQ(*LANGIDUNQ)
LANGID(ENU)).
SELECT * FROM STAFF S1, STAFF S2
WHERE S1.JOB = S2.JOB

or the same query using the JOIN syntax.


SELECT *
FROM STAFF S1 INNER JOIN STAFF S2
ON S1.JOB = S2.JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE(STAFF STAFF)
| FORMAT(FORMAT1)
| JFLD((1/JOB 2/JOB *EQ))
| SRTSEQ(*LANGIDUNQ) LANGID(ENU)

| DB2 UDB for AS/400 could use either index HEXIX or index UNQIX for either
query.

Example 6
Join selection with a shared-weight sort sequence table (SRTSEQ(*LANGIDSHR)
LANGID(ENU)).
SELECT * FROM STAFF S1, STAFF S2
WHERE S1.JOB = S2.JOB

or the same query using the JOIN syntax.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 451
SELECT *
FROM STAFF S1 INNER JOIN STAFF S2
ON S1.JOB = S2.JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE(STAFF STAFF) FORMAT(FORMAT1)
| JFLD((1/JOB 2/JOB *EQ))
| SRTSEQ(*LANGIDSHR) LANGID(ENU)

| DB2 UDB for AS/400 could only use index SHRIX for either query.

Example 7
Ordering with no sort sequence table (SRTSEQ(*HEX)).
SELECT * FROM STAFF
WHERE JOB = 'MGR'
ORDER BY JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF))
| QRYSLT('JOB *EQ ''MGR''')
| KEYFLD(JOB)
| SRTSEQ(*HEX)

| DB2 UDB for AS/400 could only use index HEXIX.

Example 8
Ordering with a unique-weight sort sequence table (SRTSEQ(*LANGIDUNQ)
LANGID(ENU)).
SELECT * FROM STAFF
WHERE JOB = 'MGR'
ORDER BY JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF))
| QRYSLT('JOB *EQ ''MGR''')
| KEYFLD(JOB) SRTSEQ(*LANGIDUNQ) LANGID(ENU)

| DB2 UDB for AS/400 could only use index UNQIX.

Example 9
Ordering with a shared-weight sort sequence table (SRTSEQ(*LANGIDSHR)
LANGID(ENU)).
SELECT * FROM STAFF
WHERE JOB = 'MGR'
ORDER BY JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF))
| QRYSLT('JOB *EQ ''MGR''')
| KEYFLD(JOB) SRTSEQ(*LANGIDSHR) LANGID(ENU)

| DB2 UDB for AS/400 could only use index SHRIX.

452 DB2 UDB for AS/400 SQL Programming V4R4


Example 10
Ordering with ALWCPYDTA(*OPTIMIZE) and a unique-weight sort sequence table
(SRTSEQ(*LANGIDUNQ) LANGID(ENU)).
SELECT * FROM STAFF
WHERE JOB = 'MGR'
ORDER BY JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF))
| QRYSLT('JOB *EQ ''MGR''')
| KEYFLD(JOB)
| SRTSEQ(*LANGIDUNQ) LANGID(ENU)
| ALWCPYDTA(*OPTIMIZE)

| DB2 UDB for AS/400 could use either index HEXIX or index UNQIX for selection.
Ordering would be done during the sort using the *LANGIDUNQ sort sequence
table.

Example 11
Grouping with no sort sequence table (SRTSEQ(*HEX)).
SELECT JOB FROM STAFF
GROUP BY JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF)) FORMAT(FORMAT2)
| GRPFLD((JOB))
| SRTSEQ(*HEX)

| DB2 UDB for AS/400 could use either index HEXIX or index UNQIX.

Example 12
Grouping with a unique-weight sort sequence table (SRTSEQ(*LANGIDUNQ)
LANGID(ENU)).
SELECT JOB FROM STAFF
GROUP BY JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF)) FORMAT(FORMAT2)
| GRPFLD((JOB))
| SRTSEQ(*LANGIDUNQ) LANGID(ENU)

| DB2 UDB for AS/400 could use either index HEXIX or index UNQIX.

Example 13
Grouping with a shared-weight sort sequence table (SRTSEQ(*LANGIDSHR)
LANGID(ENU)).
SELECT JOB FROM STAFF
GROUP BY JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF)) FORMAT(FORMAT2)
| GRPFLD((JOB))
| SRTSEQ(*LANGIDSHR) LANGID(ENU)

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 453
| DB2 UDB for AS/400 could only use index SHRIX.

The following examples assume 3 more indexes are created over columns JOB and
SALARY. The CREATE INDEX statements precede the examples.

Assume an index HEXIX2 was created with *HEX as the sort sequence.
CREATE INDEX HEXIX2 ON STAFF (JOB, SALARY)

Assume an index UNQIX2 was created and the sort sequence is a unique-weight
sort sequence.
CREATE INDEX UNQIX2 ON STAFF (JOB, SALARY)

Assume an index SHRIX2 was created with a shared-weight sort sequence.


CREATE INDEX SHRIX2 ON STAFF (JOB, SALARY)

Example 14
Ordering and grouping on the same columns with a unique-weight sort sequence
table (SRTSEQ(*LANGIDUNQ) LANGID(ENU)).
SELECT JOB, SALARY FROM STAFF
GROUP BY JOB, SALARY
ORDER BY JOB, SALARY

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF)) FORMAT(FORMAT3)
| GRPFLD(JOB SALARY)
| KEYFLD(JOB SALARY)
| SRTSEQ(*LANGIDUNQ) LANGID(ENU)

| DB2 UDB for AS/400 could use UNQIX2 to satisfy both the grouping and ordering
requirements. If index UNQIX2 did not exist, DB2 UDB for AS/400 would create an
index using a sort sequence table of *LANGIDUNQ.

Example 15
Ordering and grouping on the same columns with ALWCPYDTA(*OPTIMIZE) and a
unique-weight sort sequence table (SRTSEQ(*LANGIDUNQ) LANGID(ENU)).
SELECT JOB, SALARY FROM STAFF
GROUP BY JOB, SALARY
ORDER BY JOB, SALARY

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF)) FORMAT(FORMAT3)
| GRPFLD(JOB SALARY)
| KEYFLD(JOB SALARY)
| SRTSEQ(*LANGIDUNQ) LANGID(ENU)
| ALWCPYDTA(*OPTIMIZE)

| DB2 UDB for AS/400 could use UNQIX2 to satisfy both the grouping and ordering
requirements. If index UNQIX2 did not exist, DB2 UDB for AS/400 would either:
v Create an index using a sort sequence table of *LANGIDUNQ or
v Use index HEXIX2 to satisfy the grouping and to perform a sort to satisfy the
ordering

454 DB2 UDB for AS/400 SQL Programming V4R4


Example 16
Ordering and grouping on the same columns with a shared-weight sort sequence
table (SRTSEQ(*LANGIDSHR) LANGID(ENU)).
SELECT JOB, SALARY FROM STAFF
GROUP BY JOB, SALARY
ORDER BY JOB, SALARY

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF)) FORMAT(FORMAT3)
| GRPFLD(JOB SALARY)
| KEYFLD(JOB SALARY)
| SRTSEQ(*LANGIDSHR) LANGID(ENU)

| DB2 UDB for AS/400 could use SHRIX2 to satisfy both the grouping and ordering
requirements. If index SHRIX2 did not exist, DB2 UDB for AS/400 would create an
index using a sort sequence table of *LANGIDSHR.

Example 17
Ordering and grouping on the same columns with ALWCPYDTA(*OPTIMIZE) and a
shared-weight sort sequence table (SRTSEQ(*LANGIDSHR) LANGID(ENU).
SELECT JOB, SALARY FROM STAFF
GROUP BY JOB, SALARY
ORDER BY JOB, SALARY

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF)) FORMAT(FORMAT3)
| GRPFLD(JOB SALARY)
| KEYFLD(JOB SALARY)
| SRTSEQ(*LANGIDSHR) LANGID(ENU)
| ALWCPYDTA(*OPTIMIZE)

| DB2 UDB for AS/400 could use SHRIX2 to satisfy both the grouping and ordering
requirements. If index SHRIX2 did not exist, DB2 UDB for AS/400 would create an
index using a sort sequence table of *LANGIDSHR.

Example 18
Ordering and grouping on different columns with a unique-weight sort sequence
table (SRTSEQ(LANGIDUNQ) LANGID(ENU)).
SELECT JOB, SALARY FROM STAFF
GROUP BY JOB, SALARY
ORDER BY SALARY, JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF)) FORMAT(FORMAT3)
| GRPFLD(JOB SALARY)
| KEYFLD(SALARY JOB)
| SRTSEQ(*LANGIDSHR) LANGID(ENU)

| DB2 UDB for AS/400 could use index HEXIX2 or index UNQIX2 to satisfy the
grouping requirements. A temporary result would be created containing the grouping
results. A temporary index would then be built over the temporary result using a
*LANGIDUNQ sort sequence table to satisfy the ordering requirements.

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 455
Example 19
Ordering and grouping on different columns with ALWCPYDTA(*OPTIMIZE) and a
unique-weight sort sequence table (SRTSEQ(*LANGIDUNQ) LANGID(ENU)).
SELECT JOB, SALARY FROM STAFF
GROUP BY JOB, SALARY
ORDER BY SALARY, JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF)) FORMAT(FORMAT3)
| GRPFLD(JOB SALARY)
| KEYFLD(SALARY JOB)
| SRTSEQ(*LANGIDUNQ) LANGID(ENU)
| ALWCPYDTA(*OPTIMIZE)

| DB2 UDB for AS/400 could use index HEXIX2 or index UNQIX2 to satisfy the
grouping requirements. A sort would be performed to satisfy the ordering
requirements.

Example 20
Ordering and grouping on different columns with ALWCPYDTA(*OPTIMIZE) and a
shared-weight sort sequence table (SRTSEQ(*LANGIDSHR) LANGID(ENU)).
SELECT JOB, SALARY FROM STAFF
GROUP BY JOB, SALARY
ORDER BY SALARY, JOB

| When using the OPNQRYF command, specify:


| OPNQRYF FILE((STAFF)) FORMAT(FORMAT3)
| GRPFLD(JOB SALARY)
| KEYFLD(SALARY JOB)
| SRTSEQ(*LANGIDSHR) LANGID(ENU)
| ALWCPYDTA(*OPTIMIZE)

| DB2 UDB for AS/400 could use index SHRIX2 to satisfy the grouping requirements.
A sort would be performed to satisfy the ordering requirements.

Tips for using VARCHAR and VARGRAPHIC data types


Variable-length column (VARCHAR or VARGRAPHIC) support allows you to define
any number of columns in a table as variable length. If you use VARCHAR or
VARGRAPHIC support, the size of a table can usually be reduced.

Data in a variable-length column is stored internally in two areas: a fixed-length or


ALLOCATE area and an overflow area. If a default value is specified, the allocated
length is at least as large as the value. The following points help you determine the
best way to use your storage area.

When you define a table with variable-length data, you must decide the width of the
ALLOCATE area. If the primary goal is:
v Space saving: use ALLOCATE(0).
v Performance: the ALLOCATE area should be wide enough to incorporate at
least 90% to 95% of the values for the column.

It is possible to balance space savings and performance. In the following example


of an electronic phone book, the following data is used:

456 DB2 UDB for AS/400 SQL Programming V4R4


v 8600 names identified by: last, first, and middle name
v The Last, First, and Middle columns are variable length.
v The shortest last name is 2 characters; the longest is 22 characters.

This example shows how space can be saved by using variable-length columns.
The fixed-length column table uses the most space. The table with the carefully
calculated allocate sizes uses less disk space. The table that was defined with no
allocate size (with all of the data stored in the overflow area) uses the least disk
space.

Number of
Total Records in
Variety of Last Name First Name Middle Name Physical File Overflow
Support Max/Alloc Max/Alloc Max/Alloc Size Space
Fixed Length 22 22 22 567 K 0
Variable 40/10 40/10 40/7 408 K 73
Length
Variable- 40/0 40/0 40/0 373 K 8600
Length
Default

In many applications performance must be considered. If you use the default


ALLOCATE(0), it will double the disk unit traffic. ALLOCATE(0) requires two reads;
one to read the fixed-length portion of the row and one to read the overflow space.
The variable-length implementation, with the carefully chosen ALLOCATE,
minimizes overflow and space and maximizes performance. The size of the physical
file is 28% smaller than the fixed-length implementation. Because 1% of rows are in
the overflow area, the access requiring two reads is minimized. The variable-length
implementation performs about the same as the fixed-length implementation.

To create the table using the ALLOCATE keyword:


CREATE TABLE PHONEDIR
(LAST VARCHAR(40) ALLOCATE(10),
FIRST VARCHAR(40) ALLOCATE(10),
MIDDLE VARCHAR(40) ALLOCATE(7))

If you are using host variables to insert or update variable-length columns, the host
variables should be variable length. Because blanks are not truncated from
fixed-length host variables, using fixed-length host variables would cause more rows
to spill into the overflow space. This would increase the size of the table.

In this example, fixed-length host variables are used to insert a row into a table:
01 LAST-NAME PIC X(40).
...
MOVE "SMITH" TO LAST-NAME.
EXEC SQL
INSERT INTO PHONEDIR
VALUES(:LAST-NAME, :FIRST-NAME, :MIDDLE-NAME, :PHONE)
END-EXEC.

The host-variable LAST-NAME is not variable length. The string “SMITH”, followed
by 35 blanks, is inserted into the VARCHAR column LAST. The value is longer than
the allocate size of 10. Thirty of thirty-five trailing blanks are in the overflow area.

In this example, variable-length host variables are used to insert a row into a table:

Chapter 24. DB2 UDB for AS/400 Data Management and Query Optimizer Tips 457
01 VLAST-NAME.
49 LAST-NAME-LEN PIC S9(4) BINARY.
49 LAST-NAME-DATA PIC X(40).
...
MOVE "SMITH" TO LAST-NAME-DATA.
MOVE 5 TO LAST-NAME-LEN.
EXEC SQL
INSERT INTO PHONEDIR
VALUES(:VLAST-NAME, :VFIRST-NAME, :VMIDDLE-NAME, :PHONE)
END-EXEC.

The host variable VLAST-NAME is variable length. The actual length of the data is
set to 5. The value is shorter than the allocated length. It can be placed in the fixed
portion of the column.

For more information about using variable-length host variables, see Chapter 12.
Coding SQL Statements in C and C++ Applications, through Chapter 17. Coding
SQL Statements in REXX Applications.

Running the RGZPFM command against tables that contain variable-length columns
can improve performance. The fragments in the overflow area that are not in use
are compacted by the RGZPFM command. This reduces the read time for rows that
overflow, increases the locality of reference, and produces optimal order for serial
batch processing.

Choose the appropriate maximum length for variable-length columns. Selecting


lengths that are too long increases the process access group (PAG). A large PAG
slows performance. A large maximum length makes SEQONLY(*YES) less effective.
Variable-length columns longer than 2000 bytes are not eligible as key columns.

458 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 25. Additional SQL performance considerations
The SQL data manipulation language statements must do database open
operations in order to create an open data path (ODP) to the data. An open data
path is the path through which all input/output operations for the file are performed.
In a sense, it connects the SQL application to a file. The number of open operations
in a program can significantly affect performance. A database open operation
occurs on:
v An OPEN statement
v SELECT INTO statement
v An INSERT statement with a VALUES clause
v An UPDATE statement with a WHERE condition
v An UPDATE statement with a WHERE CURRENT OF cursor and SET clauses
that refer to operators or functions
v A DELETE statement with a WHERE condition

An INSERT statement with a select-statement requires two open operations. Certain


forms of subqueries may also require one open per subselect.

To minimize the number of opens, DB2 UDB for AS/400 leaves the open data path
(ODP) open and reuses the ODP if the statement is run again, unless:
v GROUP BY contains columns from more than one table.
v The ODP used a host variable to build a subset temporary index. The OS/400
database support may choose to build a temporary index with entries for only the
rows that match the row selection specified in the SQL statement. If a host
variable was used in the row selection, the temporary index will not have the
entries required for a different value contained in the host variable.
v Ordering was specified on a host variable value.
v A host variable is used to specify the pattern of a LIKE predicate. The host
variable value has either underscores (_) or involves more than one search
pattern: for ’%ABC%DEF’, two patterns are involved, ABC and DEF.
v An Override Database File (OVRDBF) or Delete Override (DLTOVR) CL
command has been issued since the ODP was opened, which would affect the
SQL statement execution.

Note: Only overrides that affect the name of the table being referred to will
cause the ODP to be closed within a given program invocation.
v A change to the library list since the last open has occurred, which would change
the file selected by an unqualified referral in system naming mode.
v The file being queried is a join logical file and its join type (JDFTVAL) does not
match the join type specified in the query.
v The format specified for a logical file references more than one physical file.
v The file is a complex SQL view that requires a temporary file to contain the
results of the SQL view.

DB2 UDB for AS/400 only reuses ODPs opened by the same statement. An
identical statement coded later in the program does not reuse an ODP from any
other statement. If the identical statement must be run in the program many times,
code it once in a subroutine and call the subroutine to run the statement.

© Copyright IBM Corp. 1997, 1999 459


The ODPs opened by DB2 UDB for AS/400 are closed when any of the following
occurs:
v A CLOSE, INSERT, UPDATE, DELETE, or SELECT INTO statement completes
and the ODP required a temporary result or a subset temporary index.
v The Reclaim Resources (RCLRSC) command is issued. A RCLRSC is issued
when the first COBOL program on the call stack ends or when a COBOL
program issues the STOP RUN COBOL statement. RCLRSC will not close ODPs
created for programs precompiled using CLOSQLCSR(*ENDJOB). For interaction
of RCLRSC with non-default activation groups, see the following books:
– ILE C for AS/400 Programmer’s Guide
– ILE COBOL for AS/400 Programmer’s Guide
– ILE RPG for AS/400 Programmer’s Guide
v When the last program that contains SQL statements on the call stack exits,
except for ODPs created for programs precompiled using
CLOSQLCSR(*ENDJOB) or modules precompiled using
CLOSQLCSR(*ENDACTGRP).
v When a CONNECT (Type 1) statement changes the application server for an
activation group, all ODPs created for the activation group are closed.
v When a DISCONNECT statement ends a connection to the application server, all
ODPs for that application server are closed.
v When a released connection is ended by a successful COMMIT, all ODPs for
that application server are closed.

You can control whether DB2 UDB for AS/400 keeps the ODPs open by:
v Designing the application so a program that issues an SQL statement is always
on the call stack
v Using the CLOSQLCSR(*ENDJOB) or CLOSQLCSR(*ENDACTGRP) parameter

DB2 UDB for AS/400 does an open operation for the first execution of each
UPDATE WHERE CURRENT OF when any expression in the SET clause contains
an operator or function. The open can be avoided by coding the function or
operation in the host language code.

For example, the following UPDATE causes DB2 UDB for AS/400 to do an open
operation:
EXEC SQL
FETCH EMPT INTO :SALARY
END-EXEC.

EXEC SQL
UPDATE CORPDATA.EMPLOYEE
SET SALARY = :SALARY + 1000
WHERE CURRENT OF EMPT
END-EXEC.

Instead, use the following coding technique to avoid opens:


EXEC SQL
FETCH EMPT INTO :SALARY
END EXEC.

ADD 1000 TO SALARY.

EXEC SQL

460 DB2 UDB for AS/400 SQL Programming V4R4


UPDATE CORPDATA.EMPLOYEE
SET SALARY = :SALARY
WHERE CURRENT OF EMPT
END-EXEC.

The CL commands Trace Job (TRCJOB) or Display Journal (DSPJRN) can be used
to determine the number of opens being performed by an SQL statement.

Improving Performance by Using Database Manager Blocking


Considerations
To improve performance, the SQL run-time attempts to retrieve and insert records
from the database manager a block at a time whenever possible. You can control
blocking, if desired, by using the SEQONLY parameter on the CL command
Override Database File (OVRDBF) prior to calling the application program that
contains the SQL statements or by specifying the ALWBLK parameter on the
CRTSQLxxx commands. The database manager does not allow blocking in the
following situations:
v The cursor is update or delete capable.
v The length of the row plus the feedback information is greater than 32767. The
minimum size for the feedback information is 11 bytes. The feedback size is
increased by the number of bytes in the key fields for the index used by the
cursor and by the number of key fields, if any, that are null capable.
v COMMIT(*CS) is specified and ALWBLK(*ALLREAD) is not specified.
v COMMIT(*ALL) is specified and the following are true:
– A SELECT INTO statement or a blocked FETCH statement is not used
– The query does not use column functions or specify group by columns.
– A temporary result table does not have to be created.
v COMMIT(*CHG) is specified and ALWBLK(*ALLREAD) is not specified.
v The cursor contains at least one subquery and the outermost subselect provided
a correlated reference for a subquery or the outermost subselect processed a
subquery with an IN, = ANY, or < > ALL subquery predicate operator, which is
treated as a correlated reference.

The SQL run-time automatically blocks records with the database manager in the
following cases:
v INSERT
If an INSERT statement contains a select-statement, inserted records are
blocked and not actually inserted into the target table until the block is full. The
SQL run-time automatically does blocking for blocked inserts.

Note: If an INSERT with a VALUES clause is specified, the SQL run-time might
not actually close the internal cursor used to perform the inserts until the
program ends. If the same INSERT statement is run again, a full open is
not necessary and the application runs much faster.
v OPEN
Blocking is done under the OPEN statement when the records are retrieved if all
of the following conditions are true:
– The cursor is only used for FETCH statements.
– No EXECUTE or EXECUTE IMMEDIATE statements are in the program, or
ALWBLK(*ALLREAD) was specified, or the cursor is declared with the FOR
FETCH ONLY clause.

Chapter 25. Additional SQL performance considerations 461


– COMMIT(*CHG) and ALWBLK(*ALLREAD) are specified, COMMIT(*CS) and
ALWBLK(*ALLREAD) are specified, or COMMIT(*NONE) is specified.

Improving Performance Using FETCH FOR n ROWS


Applications that perform many FETCH statements in succession may be improved
by using FETCH FOR n ROWS. With this clause, you can retrieve multiple rows of
data from a table and put them into a host structure array or row storage area with
a single FETCH. For more information on declaring arrays of host structures or row
storage areas, see the DB2 UDB for AS/400 SQL Reference book or the individual
programming chapters.

An SQL application that uses a FETCH statement, without the FOR n ROWS
clause, can be improved by using the multiple-row FETCH statement to retrieve
multiple rows. After the host structure array or row storage area has been filled by
the FETCH, the application can loop through the data in the array or storage area
to process each of the individual records. The statement runs faster because the
SQL run-time was called only once and all the data was simultaneously returned to
the application program.

You can change the application program to allow the database manager to block
the records that the SQL run-time retrieves from the tables. For more information,
see “Improving Performance by Using Database Manager Blocking Considerations”
on page 461.

In the following table, the program attempted to FETCH 100 rows into the
application. Note the differences in the table for the number of calls to SQL run-time
and the database manager when blocking can be performed.
Table 40. Number of Calls Using a FETCH Statement
Database Manager Not Using Database Manager Using
Blocking Blocking
Single-Row FETCH 100 SQL calls 100 database 100 SQL calls 1 database call
Statement calls
Multiple-Row FETCH 1 SQL run-time call 100 1 SQL run-time call 1
Statement database calls database call

Improving Performance with SQL Blocking


Special performance considerations should be made for the following points when
using FETCH FOR n ROWS. You can improve SQL blocking performance with the
following:
v The attribute information in the host structure array or the descriptor associated
with the row storage area matches the attributes of the columns retrieved.
v The application should retrieve as many rows as possible with a single
multiple-row FETCH call. The blocking factor for a multiple-row FETCH request is
not controlled by the system page sizes or the SEQONLY parameter on the
OVRDBF command. It is controlled by the number of rows requested on the
multiple-row FETCH request.
v Do not mix single- and multiple-row FETCH requests against the same cursor
within a program. If one FETCH against a cursor is treated as a multiple-row

462 DB2 UDB for AS/400 SQL Programming V4R4


FETCH, all fetches against that cursor are treated as multiple-row fetches. In that
case, each of the single-row FETCH requests would be treated as a multiple-row
FETCH of one row.
v The PRIOR, CURRENT, and RELATIVE scroll options should not be used with
multiple-row FETCH statements. To allow random movement of the cursor by the
application, the database manager must maintain the same cursor position as the
application. Therefore, the SQL run-time treats all FETCH requests against a
scrollable cursor with these options specified as multiple-row FETCH requests.

Improving Performance Using INSERT n ROWS


Applications that perform many INSERT statements in succession may be improved
by using INSERT n ROWS. With this clause, you can insert one or more rows of
data from a host structure array into a target table. This array must be an array of
structures where the elements of the structure correspond to columns in the target
table.

An SQL application that loops over an INSERT...VALUES statement (without the n


ROWS clause) can be improved by using the INSERT n ROWS statement to insert
multiple rows into the table. After the application has looped to fill the host array
with records, a single INSERT n ROWS statement can be run to insert the entire
array into the table. The statement runs faster because the SQL run-time was only
called once and all the data was simultaneously inserted into the target table.

In the following table, the program attempted to INSERT 100 rows into a table. Note
the differences in the number of calls to SQL run-time and to the database manager
when blocking can be performed.
Table 41. Number of Calls Using an INSERT Statement
Database Manager Not Using Database Manager Using
Blocking Blocking
Single-Row INSERT 100 SQL run-time calls 100 100 SQL run-time calls 1
Statement database calls database call
Multiple-Row INSERT 1 SQL run-time call 100 1 SQL run-time call 1
Statement database calls database call

Improving Performance When Paging Interactively Displayed Data


In large tables, paging performance is usually degraded because of the
REFRESH(*ALWAYS) parameter on the STRSQL command which dynamically
retrieves the latest data directly from the table. Paging performance can be
improved by specifying REFRESH(*FORWARD).

When interactively displaying data using REFRESH(*FORWARD), the results of a


select-statement are copied to a temporary file as you page forward through the
display. Other users sharing the table can make changes to the rows while you are
displaying the select-statement results. If you page backward or forward to rows
that have already been displayed, the rows shown are those in the temporary file
instead of those in the updated table.

The refresh option can be changed on the Session Services display.

Chapter 25. Additional SQL performance considerations 463


Improving Performance by Using SELECT Statements Effectively
The number of columns specified in the select list of a SELECT statement causes
the database manager to retrieve the data from the underlying tables and map the
data into host variables in the application programs. By minimizing the number of
columns specified, processing unit resource usage can be conserved. Even though
it is convenient to code SELECT *, it is far better to explicitly code the columns
actually required for the application. This is especially important if index-only access
is desired or if all of the columns will participate in a sort operation (as happens for
SELECT DISTINCT and for SELECT UNION).

Improving Performance by Using Live Data


The term live data refers to the type of access that the database manager uses
when it retrieves data without making a copy of the data. Using this type of access,
the data, which is returned to the program, always reflects the current values of the
data in the database. The programmer can control whether the database manager
uses a copy of the data or retrieves the data directly. This is done by specifying the
allow copy data (ALWCPYDTA) parameter on the precompiler commands or on the
Start SQL (STRSQL) command.

Specifying ALWCPYDTA(*NO) instructs the database manager to always use live


data. Live data access can be used as a performance advantage because the
cursor does not have to be closed and opened again to refresh the data being
retrieved. An example application demonstrating this advantage is one that
produces a list on a display. If the display screen can only show 20 elements of the
list at a time, then, after the initial 20 elements are displayed, the application
programmer can request that the next 20 rows be displayed. A typical SQL
application designed for an operating system other than the OS/400 operating
system, might be structured as follows:
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT EMPNO, LASTNAME, WORKDEPT
FROM CORPDATA.EMPLOYEE
ORDER BY EMPNO
END-EXEC.

EXEC SQL
OPEN C1
END-EXEC.

* PERFORM FETCH-C1-PARA 20 TIMES.

MOVE EMPNO to LAST-EMPNO.

EXEC SQL
CLOSE C1
END-EXEC.

* Show the display and wait for the user to indicate that
* the next 20 rows should be displayed.

EXEC SQL
DECLARE C2 CURSOR FOR
SELECT EMPNO, LASTNAME, WORKDEPT
FROM CORPDATA.EMPLOYEE
WHERE EMPNO > :LAST-EMPNO
ORDER BY EMPNO
END-EXEC.

464 DB2 UDB for AS/400 SQL Programming V4R4


EXEC SQL
OPEN C2
END-EXEC.

* PERFORM FETCH-C21-PARA 20 TIMES.

* Show the display with these 20 rows of data.

EXEC SQL
CLOSE C2
END-EXEC.

In the above example, notice that an additional cursor had to be opened to continue
the list and to get current data. This could result in creating an additional ODP that
would increase the processing time on the AS/400 system. In place of the above
example, the programmer could design the application specifying
ALWCPYDTA(*NO) with the following SQL statements:
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT EMPNO, LASTNAME, WORKDEPT
FROM CORPDATA.EMPLOYEE
ORDER BY EMPNO
END-EXEC.

EXEC SQL
OPEN C1
END-EXEC.

* Display the screen with these 20 rows of data.

* PERFORM FETCH-C1-PARA 20 TIMES.

* Show the display and wait for the user to indicate that
* the next 20 rows should be displayed.

* PERFORM FETCH-C1-PARA 20 TIMES.

EXEC SQL
CLOSE C1
END-EXEC.

In the above example, the query could perform better if the FOR 20 ROWS clause
was used on the multiple-row FETCH statement. Then, the 20 rows would be
retrieved in one operation.

Improving Performance by Using the ALWCPYDTA Parameter


Some complex queries can perform better by using a sort or hashing method to
evaluate the query instead of using or creating an index. By using the sort or hash,
the database manager is able to separate the row selection from the ordering and
grouping process. This separation allows the use of the most efficient index for the
selection. For example, consider the following SQL statement:
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT EMPNO, LASTNAME, WORKDEPT
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = 'A00'
ORDER BY LASTNAME
END-EXEC.

Chapter 25. Additional SQL performance considerations 465


In the above example when ALWCPYDTA(*NO) or ALWCPYDTA(*YES) is specified,
the database manager may try to create an index from the first index with a column
named LASTNAME, if such an index exists. The rows in the table are scanned,
using the index, to select only the rows matching the WHERE condition.

If ALWCPYDTA(*OPTIMIZE) is specified, the database manager uses an index with


the first index column of WORKDEPT. It then makes a copy of all of the rows that
match the WHERE condition. Finally, it may sort the copied rows by the values in
LASTNAME. This row selection processing is significantly more efficient, because
the index used immediately locates the rows to be selected.

ALWCPYDTA(*OPTIMIZE) optimizes the total time required to process the query.


However, the time required to receive the first row may be increased because a
copy of the data must be made prior to returning the first row of the result table.
This initial change in response time may be important for applications presenting
interactive displays or that retrieve only the first few rows of the query. The DB2
UDB for AS/400 query optimizer can be influenced to avoid sorting by using the
OPTIMIZE clause. Refer to “Improving Performance by Using the Optimize Clause”
for more information.

Queries that involve a join operation may also benefit from


ALWCPYDTA(*OPTIMIZE) because the join order can be optimized regardless of
the ORDER BY specification.

Note: The hashing method cannot be used to implement the grouping on queries
that involve a nested loop join implementation and do not require a
temporary result to be created.

Improving Performance by Using the Optimize Clause


If an application is not going to retrieve the entire result table for a cursor, using the
OPTIMIZE clause can improve performance. The query optimizer modifies the cost
estimates to retrieve the subset of rows using the value specified on the OPTIMIZE
clause.

Assume the following query returns 1000 rows:


EXEC SQL
DECLARE C1 CURSOR FOR
SELECT EMPNO, LASTNAME, WORKDEPT
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = 'A00'
ORDER BY LASTNAME
OPTIMIZE FOR 100 ROWS
END EXEC.

The optimizer calculates the following costs.

The optimize ratio = optimize for n rows value / estimated number of rows in
answer set.
Cost using a temporarily created index:

Cost to retrieve answer set rows


+ Cost to create the index
+ Cost to retrieve the rows again
with a temporary index * optimize ratio

466 DB2 UDB for AS/400 SQL Programming V4R4


Cost using a SORT:

Cost to retrieve answer set rows


+ Cost for SORT input processing
+ Cost for SORT output processing * optimize ratio

Cost using an existing index:

Cost to retrieve answer set rows


using an existing index * optimize ratio

In the previous examples, the estimated cost to sort or to create an index is not
adjusted by the optimize ratio. This enables the optimizer to balance the
optimization and preprocessing requirements. If the optimize number is larger than
the number of rows in the result table, no adjustments are made to the cost
estimates. If the OPTIMIZE clause is not specified for a query, a default value is
used based on the statement type, value of ALWCPYDTA specified, or output
device.

Statement Type ALWCPYDTA(*OPTIMIZE) ALWCPYDTA(*YES or *NO)


DECLARE CURSOR The number or rows in the 3% or the number of rows in
result table. the result table.
Embedded Select 2 2
INTERACTIVE Select output 3% or the number of rows in 3% or the number of rows in
to display the result table. the result table.
INTERACTIVE Select output The number of rows in the The number of rows in the
to printer or database file result table. result table.

The OPTIMIZE clause influences the optimization of a query:


v To use an existing index (by specifying a small number).
v To enable the creation of an index or to run a sort or a hash by specifying a large
number of possible rows in the answer set.

Improving Performance by Retaining Cursor Positions


You can improve performance by retaining cursor positions. The next two sections
provide information on retaining cursors for non-ILE and ILE program calls.

Improving Performance by Retaining Cursor Positions for Non-ILE


Program Calls
For non-ILE program calls, the close SQL cursor (CLOSQLCSR) parameter allows
you to specify the scope of the following:
v The cursors
v The prepared statements
v The locks

When used properly, the CLOSQLCSR parameter can reduce the number of SQL
OPEN, PREPARE, and LOCK statements needed. It can also simplify applications
by allowing you to retain cursor positions across program calls.

Chapter 25. Additional SQL performance considerations 467


*ENDPGM
This is the default for all non-ILE precompilers. With this option, a cursor
remains open and accessible only while the program that opened it is on
the call stack. When the program ends, the SQL cursor can no longer be
used. Prepared statements are also lost when the program ends. Locks,
however, remain until the last SQL program on the call stack has
completed.
*ENDSQL
With this option, SQL cursors and prepared statements created by a
program remain open until the last SQL program on the call stack has
completed. They cannot be used by other programs, only by a different call
to the same program. Locks remain until the last SQL program in the call
stack completes.
*ENDJOB
This option allows you to keep SQL cursors, prepared statements, and
locks active for the duration of the job. When the last SQL program on the
stack has completed, any SQL resources created by *ENDJOB programs
are still active. The locks remain in effect. The SQL cursors that were not
explicitly closed by the CLOSE, COMMIT, or ROLLBACK statements remain
open. The prepared statements are still usable on subsequent calls to the
same program.

Improving Performance by Retaining Cursor Positions across ILE


Program Calls
For ILE program calls, the close SQL cursor (CLOSQLCSR) parameter allows you
to specify the scope of the following:
v The cursors
v The prepared statements
v The locks
When used properly, the CLOSQLCSR parameter can reduce the number of SQL
OPEN, PREPARE, and LOCK statements needed. It can also simplify applications
by allowing you to retain cursor positions across program calls.
*ENDACTGRP
This is the default for the ILE precompilers. With this option, SQL cursors
and prepared statements remain open until the activation group that the
program is running under ends. They cannot be used by other programs,
only by a different call to the same program. Locks remain until the
activation group ends.
*ENDMOD
With this option, a cursor remains open and accessible only while the
module that opened it is active. When the module ends, the SQL cursor can
no longer be used. Prepared statements will also be lost when the module
ends. Locks, however, remain until the last SQL program in the call stack
completes.

468 DB2 UDB for AS/400 SQL Programming V4R4


General Rules for Retaining Cursor Positions For All Program Calls
When using programs compiled with either CLOSQLCSR(*ENDPGM) or
CLOSQLCSR(*ENDMOD), a cursor must be opened every time the program or
module is called, in order to access the data. If the SQL program or module is
going to be called several times, and you want to take advantage of a reusable
ODP, then the cursor must be explicitly closed before the program or module exits.

Using the CLOSQLCSR parameter and specifying *ENDSQL, *ENDJOB, or


*ENDACTGRP, you may not need to run an OPEN and a CLOSE statement on
every call. In addition to having fewer statements to run, you can maintain the
cursor position between calls to the program or module.

The following examples of SQL statements help demonstrate the advantage of


using the CLOSQLCSR parameter:
EXEC SQL
DECLARE DEPTDATA CURSOR FOR
SELECT EMPNO, LASTNAME
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = :DEPTNUM
END-EXEC.

EXEC SQL
OPEN DEPTDATA
END-EXEC.

EXEC SQL
FETCH DEPTDATA INTO :EMPNUM, :LNAME
END-EXEC.

EXEC SQL
CLOSE DEPTDATA
END-EXEC.

If this program is called several times from another SQL program, it will be able to
use a reusable ODP. This means that, as long as SQL remains active between the
calls to this program, the OPEN statement will not require a database open
operation. However, the cursor is still positioned to the first result row after each
OPEN statement, and the FETCH statement will always return the first row.

In the following example, the CLOSE statement has been removed:


EXEC SQL
DECLARE DEPTDATA CURSOR FOR
SELECT EMPNO, LASTNAME
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = :DEPTNUM
END-EXEC.

IF CURSOR-CLOSED IS = TRUE THEN


EXEC SQL
OPEN DEPTDATA
END-EXEC.

EXEC SQL
FETCH DEPTDATA INTO :EMPNUM, :LNAME
END-EXEC.

If this program is precompiled with the *ENDJOB option or the *ENDACTGRP


option and the activation group remains active, the cursor position is maintained.
The cursor position is also maintained when the following occurs:

Chapter 25. Additional SQL performance considerations 469


v The program is precompiled with the *ENDSQL option.
v SQL remains active between program calls.

The result of this strategy is that each call to the program retrieves the next record
in the cursor. On subsequent data requests, the OPEN statement is unnecessary
and, in fact, fails with a -502 SQLCODE. You can ignore the error, or add code to
skip the OPEN. This can be done by using a FETCH statement first, and only
running the OPEN statement if the FETCH operation failed.

This technique also applies to prepared statements. A program could first try the
EXECUTE, and if it fails, perform the PREPARE. The result is that the PREPARE
would only be needed on the first call to the program, assuming the correct
CLOSQLCSR option was chosen. Of course, if the statement can change between
calls to the program, it should perform the PREPARE in all cases.

The main program could also control this by sending a special parameter on the
first call only. This special parameter value would indicate that because it is the first
call, the subprogram should perform the OPENs, PREPAREs, and LOCKs.

Note: If you are using COBOL programs, do not use the STOP RUN statement.
When the first COBOL program on the call stack ends or a STOP RUN
statement runs, a reclaim resource (RCLRSC) operation is done. This
operation closes the SQL cursor. The *ENDSQL option does not work as
desired.

Improving Performance of SQL PREPARE Statements


The processing which occurs when an SQL PREPARE statement is run is similar to
the processing which occurs during precompile processing. The statement being
prepared is:
v Syntax checked
v Validated to ensure that the usage of objects are valid.
v Has an access plan built
Again when the statement is executed or opened, the database manager will
revalidate that the access plan is still valid. Much of this open processing validation
is redundant with the validation which occurred during the PREPARE processing.
The DLYPRP(*YES) parameter specifies whether PREPARE statements in this
program will completely validate the dynamic statement. The validation will be
completed when the dynamic statement is opened or executed. This parameter can
provide a significant performance enhancement for programs which use the
PREPARE SQL statement because it eliminates redundant validation. Programs
specifying this precompile option should check the SQLCODE and SQLSTATE after
running the OPEN or EXECUTE statement to ensure the statement is valid.
DLYPRP(*YES) will not provide any performance improvement if the INTO clause is
used on the PREPARE statement or if a DESCRIBE statement uses the dynamic
statement before an OPEN is issued for the statement.

Effects on Performance When Using Long Object Names


Long object names are converted internally to system object names when used in
SQL statements. This conversion can have some performance impacts. If the long
object name is qualified with a library name, then the conversion to the short name
happens at precompile time. In this case, there is no performance impact when the

470 DB2 UDB for AS/400 SQL Programming V4R4


statement is executed. However, if the long object name is unqualified, the
conversion is done at execution time, and has a small performance impact.

Improving Performance Using the Precompile Options


Several precompile options are available for creating programs with improved
performance. They are only options because using them may impact the function of
the application. For this reason, the default values for these parameters is the value
that will ensure successful migration of applications from prior releases. However,
performance may be improved by specifying other options. The following table
shows these precompile options and their performance impacts:

Precompile Option Optimal Value Improvements Considerations Related Topics


ALWCPYDTA *OPTIMIZE Queries where the A copy of the data See “Improving
ordering or grouping may be made when Performance by Using
criteria conflicts with the query is opened. the ALWCPYDTA
the selection criteria. Parameter” on
page 465.
ALWBLK *ALLREAD Additional read-only ROLLBACK HOLD See “Improving
cursors use blocking. may not change the Performance by Using
position of a read-only Database Manager
cursor.Dynamic Blocking
processing of Considerations” on
positioned updates or page 461.
deletes might fail.
CLOSQLCSR *ENDJOB *ENDSQL Cursor position can Implicit closing of SQL See “Improving
or *ENDACTGRP be retained across cursor is not done Performance by
program invocations. when the program Retaining Cursor
invocation ends. Positions for Non-ILE
Program Calls” on
page 467.
DLYPRP *YES Programs using SQL Complete validation of See “Improving
PREPARE statements the prepared Performance of SQL
may run faster. statement is delayed PREPARE
until the statement is Statements” on
run or opened. page 470.
TGTRLS *CURRENT (the The precompiler can The program object See “Improving
default) generate code that cannot be used on a Performance by Using
will take advantage of system from a Structure Parameter
performance previous release. Passing Techniques”
enhancements on page 472.
available in the
current release.

Some of these options may be suitable for most of your applications. Use the
command CRTDUPOBJ to create a copy of the SQL CRTSQLxxx command and
the CHGCMDDFT command to customize the optimal values for the precompile
parameters. The DSPPGM, DSPSRVPGM, DSPMOD, or PRTSQLINF commands
can be used to show the precompile options used for an existing program object.

Chapter 25. Additional SQL performance considerations 471


Improving Performance by Using Structure Parameter Passing
Techniques
The SQL precompiler uses two methods of passing host variables to the SQL run
time.

The original method was to pass each host variable as a separate parameter. For
example:
CALL QSQROUTE
(SQLCA, hostvariable1, hostvariable2, hostvariable3)

The second method is to create a data structure with an element for each host
variable referenced in the statement. Then that data structure could be passed as a
parameter. For example:
CALL QSQROUTE
(SQLCA, hostvariable structure)

The second method will provide better performance.

Note: The structure parameter passing technique is not used for SQL statements
for special cases in PL/I and RPG for AS/400 programs (see “Differences in
PL/I Because of Structure Parameter Passing Techniques” on page 294 and
“Differences in RPG for AS/400 Because of Structure Parameter Passing
Techniques” on page 307.

Background Information on Parameter Passing


Additional code is created in the program to move the input host variable data to
the structure before the call to the SQL program. After the call to the SQL program,
code is added that moves the data from the structure to the output host variables.

The precompiler creates the structure so that the SQL header is first, followed by
the input host variables, the output host variables, the indicators for the input host
variables, and the indicators for the output host variables. Because the output host
variables are created in a contiguous storage space, the SQL run-time support can
check for a match with the I/O buffer (each result column attribute is checked for a
matching host variable attribute) and move the data with one instruction if they all
match.

The SQL header on the structure contains information unique to the statement so
that SQL does not have to reconstruct the information on each call. Some of this
information is added and processed by the SQL run-time support. SQL run-time
support creates an SQLDA internally for each statement that uses host variables.
With the original parameter list, the host variable address could be different for each
call of the statement and, therefore, SQL run-time support rebuilds the SQLDA for
each call of the statement. With structure parameter passing, the structure is
created as a static variable, and the address of the elements will not change. SQL
run-time support builds the SQLDA the first time the statement is called, and saves
the SQLDA so it can be used on future calls of the statement.

With the original type of parameter passing, the number of host variables that could
be referred to in a program was approximately 4000 because of an architecture limit
of 4100 pointers in a program. Each parameter required a pointer. With the

472 DB2 UDB for AS/400 SQL Programming V4R4


structure parameter passing, only two parameters are passed for each SQL
statement, therefore, the limit of 4000 pointers does not apply.

Some Differences Because of Structure Parameter Passing Techniques


You need to be aware of the following differences in the parameter passing
techniques when embedding SQL statements into application programs:
v SQLCODE +326 is returned when the structure parameter passing technique is
used and the number of host variables specified is greater than the number of
columns in the select list.
The extra output host variables are ignored by the original parameter passing
technique, but with the structure parameter passing technique, the host variable
is set to the value in the SQL created structure (blanks are used for character
host variables and zeros are used for numeric host variables).Attention: This
could cause incorrect results when the extra output host variables overlap with
other host variables.

An example of this problem, using RPG for AS/400, follows:


ISTRUC DS
I 1 1 A
I 2 2 B
I 1 2 C

SELECT * INTO :STRUC FROM ATABLE

In the above example, if ATABLE has only one or two columns, the SQLCODE
will be set to +326. When the assignment to C from the SQL structure is done,
the contents of A and B will be blank instead of the value of the column
corresponding to A and B.
v With the original parameter passing technique, SQLCODE -302 or -304 is
returned when a conversion error occurs (because of numeric data that is not
valid) while processing the data for a host variable. However, with the structure
parameter passing technique, SQL does not detect this error. The conversion
error occurs in the host language statements that reference the host variable. For
example, if a DECIMAL(5,2) input host variable contains the invalid data
’FFFFFF’X, an error will occur in the host language when the data is moved into
the data structure.
v The structure created by SQL uses names that start with the letters SQL. If
existing programs use variable names starting with SQL, those names may
conflict with the SQL-created names.
v The contents of the SQL-created data structure must not be changed by the
application programs.

Controlling Parallel Processing


This section describes how parallel processing can be turned on and off. If the DB2
UDB Symmetric Multiprocessing feature is installed, then symmetric multiprocessing
(SMP) can also be turned on and off. This control is available for system wide
control through the system value QQRYDEGREE. At a job level, this control is
available using the DEGREE parameter on the CHGQRYA command.

Even though parallelism has been enabled for a system or given job, the individual
queries that run in a job might not actually use a parallel method. This might be
because of functional restrictions, or the optimizer might choose a non-parallel

Chapter 25. Additional SQL performance considerations 473


method because it runs faster. See the previous sections that describe the
performance characteristics and restrictions of each of the parallel access methods.

Because queries being processed with parallel access methods aggressively use
main storage, CPU, and disk resources, the number of queries that use parallel
processing should be limited and controlled.

Controlling Parallel Processing System Wide


The QQRYDEGREE system value can be used to control parallel processing for a
system. The current value of the system value can be displayed or modified using
the following CL commands:
v WRKSYSVAL - Work with System Value
v CHGSYSVAL - Change System Value
v DSPSYSVAL - Display System Value
v RTVSYSVAL - Retrieve System Value

The special values for QQRYDEGREE control whether parallel processing is


allowed by default for all jobs on the system. The possible values are:
*NONE
No parallel processing is allowed for database query processing.
*IO
I/O parallel processing is allowed for queries.
*OPTIMIZE
The query optimizer can choose to use any number of tasks for either I/O or
SMP parallel processing to process the queries. SMP parallel processing is
used only if the DB2 UDB Symmetric Multiprocessing feature is installed. The
query optimizer chooses to use parallel processing to minimize elapsed time
based on the job’s share of the memory in the pool.
*MAX
The query optimizer can choose to use either I/O or SMP parallel processing to
process the query. SMP parallel processing can be used only if the DB2 UDB
Symmetric Multiprocessing feature is installed. The choices made by the query
optimizer are similar to those made for parameter value *OPTIMIZE, except the
optimizer assumes that all active memory in the pool can be used to process
the query.

The default value of the QQRYDEGREE system value is *NONE, so the value must
be changed if parallel query processing is desired as the default for jobs run on the
system.

Changing this system value affects all jobs that will be run or are currently running
on the system whose DEGREE query attribute is *SYSVAL. However, queries that
have already been started or queries using reusable ODPs are not affected.

Controlling Parallel Processing for a Job


Query parallel processing can also be controlled at the job level using the DEGREE
parameter of the Change Query Attributes (CHGQRYA) command. The parallel
processing option allowed and, optionally, the number of tasks that can be used

474 DB2 UDB for AS/400 SQL Programming V4R4


when running database queries in the job can be specified. You can prompt on the
CHGQRYA command in an interactive job to display the current values of the
DEGREE query attribute.

Changing the DEGREE query attribute does not affect queries that have already
been started or queries using reusable ODPs.

Job: B,I Pgm: B,I REXX: B,I Exec

(1) (2)
ÊÊ CHGQRYA Ê
*
JOB( user-name/ job-name )
job-number/
Ê Ê
*SAME *SAME
QRYTIMLMT( *NOMAX ) DEGREE ( *NONE )
*SYSVAL *IO
seconds *OPTIMIZE
*MAX
*SYSVAL
*ANY
*NBRTASKS number-of-tasks

Ê ÊÍ
*SAME *SAME
ASYNCJ ( *LOCAL ) APYRMT ( *YES )
*DIST *NO
*NONE
*ANY

Notes:
1. Value *ANY is equivalent to value *IO.
2. All parameters preceding this point can be specified in positional form.

The parameter values for the DEGREE keyword are:


*SAME
The parallel degree query attribute does not change.
*NONE
No parallel processing is allowed for database query processing.
*IO
Any number of tasks can be used when the database query optimizer chooses
to use I/O parallel processing for queries. SMP parallel processing is not
allowed.
*OPTIMIZE
The query optimizer can choose to use any number of tasks for either I/O or
SMP parallel processing to process the query. SMP parallel processing can be
used only if the DB2 UDB Symmetric Multiprocessing feature is installed. Use of
parallel processing and the number of tasks used is determined with respect to
the number of processors available in the system, the job’s share of the amount
of active memory available in the pool in which the job is run, and whether the
expected elapsed time for the query is limited by CPU processing or I/O
resources. The query optimizer chooses an implementation that minimizes
elapsed time based on the job’s share of the memory in the pool.

Chapter 25. Additional SQL performance considerations 475


*MAX
The query optimizer can choose to use either I/O or SMP parallel processing to
process the query. SMP parallel processing can be used only if the DB2 UDB
Symmetric Multiprocessing feature is installed. The choices made by the query
optimizer are similar to those made for parameter value *OPTIMIZE except the
optimizer assumes that all active memory in the pool can be used to process
the query.
*NBRTASKS number-of-tasks
Specifies the number of tasks to be used when the query optimizer chooses to
use SMP parallel processing to process a query. I/O parallelism is also allowed.
SMP parallel processing can be used only if the DB2 UDB Symmetric
Multiprocessing feature is installed.

| Using a number of tasks less than the number of processors available on the
| system restricts the number of processors used simultaneously for running a
| given query. A larger number of tasks ensures that the query is allowed to use
| all of the processors available on the system to run the query. Too many tasks
| can degrade performance because of the over commitment of active memory
| and the overhead cost of managing all of the tasks.
*SYSVAL
Specifies that the processing option used should be set to the current value of
the QQRYDEGREE system value.
*ANY
Parameter value *ANY has the same meaning as *IO. The *ANY value is
maintained for compatibility with prior releases.

The initial value of the DEGREE attribute for a job is *SYSVAL.

See the CL Reference (Abridged) book for more information about the CHGQRYA
command.

476 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 26. Monitoring and Optimizing Query Performance
Tools
Optimizing Query Performance Using Query Optimization Tools
| You can use query optimization tools to improve data retrieval time. Use the results
| of the tools to:
| v Change the “Data Access Methods” on page 420 chosen by the system
| v Create the correct indexes

| The query optimization tools to use in this iterative process include:


v “Query optimizer debug messages”
v “Print SQL information” on page 478
v “Database monitor statistics” on page 478
v “Change query attributes” on page 543
v “Query Options File QAQQINI” on page 543
v “Memory Resident Database Monitor APIs” on page 524
v You can use the Operations Navigator SQL Performance monitor to work with
“Memory Resident Database Monitor APIs” on page 524.
You may want to quickly check out the “Comparison table of query optimization
tools” on page 542 to learn:
v What information each tool can yield about your query
v When in the process a specific tool can analyze your query
v The tasks each tool can perform to improve your query
If you are experienced with query optimization, you may want to refer to a list of
“General Optimization Tips” on page 395.

Query optimizer debug messages


| Query optimizer debug messages issue informational messages to the joblog about
| the implementation of a query. These messages explain what happened during the
| query optimization process. For example, you can learn:
| v Why an index was or was not used
| v Why a temporary result was required
| v Whether joins and blocking are used
| v What type of index was advised by the optimizer
| v Status of the job’s queries
| v Access paths used
| v Status of the cursor
| The optimizer automatically logs messages for OPNQRYF, SQL Query Manager,
| interactive SQL, embedded SQL, and all AS/400 HLLs. To view the messages, put
| your job into debug mode using one of the following methods:
| v Use the following command:
| STRDBG PGM(Library/program) UPDPROD(*YES)

© Copyright IBM Corp. 1997, 1999 477


| v Set the QRYOPTLIB parameter on the Change Query Attributes (CHGQRYA)
| command to a user library where the QAQQINI file exists. Set the parameter on
| the QAQQINI file to MESSAGES_DEBUG, and set the value to *YES.
| Pressing F10 from the command Entry panel displays the message text. To see the
| second-level text, press F1 (Help). The second-level text sometimes offers hints for
| improving query performance.

See “Performance Information Messages” on page 382 for the specific meanings of
the debug messages.

Print SQL information


| The PRTSQLINF command gathers information about the embedded SQL
| statements in a program, SQL package (the object normally used to store the
| access plan for a remote query), or service program. It then puts the information in
| a spooled file. PRTSQLINF provides information about:
| v The SQL statements being executed
| v The type of access plan used during execution. This includes information about
| how the query will be implemented, the indexes used, the join order, whether a
| sort is done, whether a database scan is sued, and whether an index is created.
| v A list of the command parameters used to precompile the source member for the
| object.
| To gather this information, run PRTSQLINF against a saved access plan. This
| means you must execute or at least prepare the query (using SQL’s PREPARE
| statement) before you use the command. It is best to execute the query because
| the access paln created as a result of PREPARE is relatively sparse and may well
| change after the first run. PRTSQLINF’s requirement of a saved access plan means
| the command cannot be used with OPNQRYF.

| PRTSQLINF gives output that is similar to the information you can get from debug
| messages, but PRTSQLINF must be run against a saved access plan. The query
| optimizer automatically logs information messages about the current query
| processing when your job is in debug mode. So, query debug messages work at
| runtime while PRTSQLINF works retroactively.

Database monitor statistics


| Database monitor statistics provide the most complete information about a query.
| You can log all information and statistics for queries that you run on a particular job
| or at a system level. The STRDBMON and ENDDBMON CL commands start and
| end the collection of database performance statistics.

| You can monitor a specific job or all jobs on the system. The statistics gathered are
| placed in the output database file specified on the command. Each job in the
| system can be monitored concurrently by two monitors:
| v One started specifically on that job
| v One started for all jobs in the system
| When a job is monitored by two monitors, each monitor is logging records to a
| different output file. You can identify records in the output database file by each
| record’s unique identification number.

478 DB2 UDB for AS/400 SQL Programming V4R4


| STRDBMON provides the same information as the two earlier tools (Query
| optimizer debug messages (STRDBG) and Print SQL information (PRTSQLINF))
| along with the following information:
| v System and job name
| v SQL statement and sub-select number
| v Start and end timestamp
| v Estimated processing time
| v Total rows in file queried
| v Number of rows selected
| v Estimated number of rows selected
| v Estimated number of joined rows
| v Key fields for advised index
| v Total optimization time
| v Join type and method
| v ODP implementation

| This chapter discusses monitoring database query performance. Database monitor


statistics provide the most complete information about a query. You can gather
performance statistics for a specific query or for every query on the system. There
are a variety of ways of gathering the statistics:
v “Start Database Monitor (STRDBMON) Command” and “End Database Monitor
(ENDDBMON) Command” on page 480
v Start Performance Monitor (STRPFRMON) command with the STRDBMON
parameter
v “Memory Resident Database Monitor APIs” on page 524
v You can use “Optimizing Query Performance Using Query Optimization Tools” on
page 477 to improve data retrieval time.

You can use these performance statistics to generate various reports. For instance,
you can include reports that show queries that:
v Use an abundance of the system resources.
v Take an extremely long time to execute.
v Did not run because of the query governor time limit.
v Create a temporary keyed access path during execution
v Use the query sort during execution
v Could perform faster with the creation of a keyed logical file containing keys
suggested by the query optimizer.

Note: A query that is cancelled by an end request generally does not generate
performance statistics.

Start Database Monitor (STRDBMON) Command


The STRDBMON command starts the collection of database performance statistics
for a specific job or all jobs on the system. The statistics are placed in an output
database file and member specified on the command. If the output file and/or
member does not exist, one is created based upon the file and format definition of
model file QSYS/QAQQDBMN. If the output file and/or member exist, the record
format of the output file must be named QQQDBMN.

Chapter 26. Monitoring and Optimizing Query Performance Tools 479


You can specify a replace/append option that allows you to clear the member of
information before writing records or to just append new information to the end of
the existing file.

You can also specify a force record write option that allows you to control how
many records are kept in the record buffer of each job being monitored before
forcing the records to be written to the output file. By specifying a force record write
value of 1, FRCRCD(1), monitor records will appear in the log as soon as they are
created. FRCRCD(1) also ensures that the physical sequence of the records are
most likely, but not guaranteed, to be in time sequence. However, FRCRCD(1) will
cause the most negative performance impact on the jobs being monitored. By
specifying a larger number for the FRCRCD parameter, the performance impact of
monitoring can be lessened.

Specifying *DETAIL on the TYPE parameter of the STRDBMON command indicates


that detail records, as well as summary records, are to be collected. This is only
useful for non-SQL queries, those queries which do not generate a QQQ1000
record. For non-SQL queries the only way to determine the number of records
returned and the total time to return those records is to collect detail records.
Currently the only detail record is QQQ3019. The DDS for this record is shown in
Figure 32 on page 523. While the detail record contains valuable information it
creates a slight performance degradation for each block of records returned.
Therefore its use should be closely monitored.

If the monitor is started on all jobs, any jobs waiting on job queues or any jobs
started during the monitoring period will have statistics gathered from them once
they begin. If the monitor is started on a specific job, that job must be active in the
system when the command is issued. Each job in the system can be monitored
concurrently by only two monitors:
v One started specifically on that job.
v One started on all jobs in the system.
When a job is monitored by two monitors and each monitor is logging to a different
output file, monitor records will be written to both logs for this job. If both monitors
have selected the same output file then the monitor records are not duplicated in
the output file.

End Database Monitor (ENDDBMON) Command


The ENDDBMON command ends the Database Monitor for a specific job or all jobs
on the system. If an attempt to end the monitor on all jobs is issued, there must
have been a previous STRDBMON issued for all jobs. If a particular job is specified
on this command, the job must have the monitor started explicitly and specifically
on that job.

In the following sequence:


1. Start monitoring all jobs in the system.
2. Start monitoring a specific job.
3. End monitoring on all jobs.
The specific job monitor continues to run because an explicit start of the monitor
was done on it. It continues to run until an ENDDBMON on the specific job is
issued.

In the following sequence:

480 DB2 UDB for AS/400 SQL Programming V4R4


1. Start monitoring all jobs in the system.
2. Start monitoring a specific job.
3. End monitoring on the specific job.
The all job monitor continues to run, even over the specific job, until an
ENDDBMON for all jobs is issued.

In the following sequence:


1. Start monitoring a specific job.
2. Start monitoring all jobs in the system.
3. End monitoring on all jobs.
The specific job monitor continues to run until an ENDDBMON for the specific job is
issued.

In the following sequence:


1. Start monitoring a specific job.
2. Start monitoring all jobs in the system.
3. End monitoring on the specific job.
The all job monitor continues to run for all jobs, including the specific job.

When an all job monitor is ended, all of the jobs on the system will be triggered to
close the output file, however, the ENDDBMON command can complete before all
of the monitored jobs have written their final performance records to the log. Use
the work with object locks, WRKOBJLCK, CL command to see that all of the
monitored jobs no longer hold locks on the output file before assuming the
monitoring is complete.

Database Monitor Performance Records


The records in the database file are uniquely identified by their record identification
number. These records are defined in several different logical files which are not
shipped with the system and must be created by the user, if desired. The logical
files can be created with the DDS shown in “Database Monitor Logical File DDS” on
page 493. The field descriptions are explained in the tables following each figure.

Note: The database monitor logical files are keyed logical files that contain some
select/omit criteria. Therefore, there will be some maintenance overhead
associated with these files while the database monitor is active. The user
may wish to minimize this overhead while the database monitor is active,
especially if monitoring all jobs. When monitoring all jobs the number of
records generated could be quite large.

Possible ways to minimize maintenance overhead associated with database monitor


logical files:
v Do not create the database monitor logical files until the database monitor has
completed.
v Create the database monitor logical files using dynamic select/omit criteria
(DYNSLT keyword on logical file’s DDS).
v Create the database monitor logical files with rebuild access path maintenance
specified on the CRTLF command (*REBLD option on MAINT parameter).
By minimizing the maintenance overhead at run time, you are merely delaying the
maintenance cost until the database monitor logical file is either created or opened.

Chapter 26. Monitoring and Optimizing Query Performance Tools 481


The choice is to either spend the time while the database monitor is active or spend
the time after the database monitor has completed.

Query Optimizer Index Advisor


The query optimizer analyzes the record selection in the query and determines,
based on default values, if creation of a permanent index would improve
performance. If the optimizer determines that a permanent index would be
beneficial, it returns the key fields necessary to create the suggested index.

The index advisor information can be found in the Database Monitor logical files
QQQ3000, QQQ3001 and QQQ3002. The advisor information is stored in fields
QQIDXA, QQIDXK and QQIDXD. When the QQIDXA field contains a value of ’Y’
the optimizer is advising you to create an index using the key fields shown in field
QQIDXD. The intention of creating this index is to improve the performance of the
query.

In the list of key fields contained in field QQIDXD the optimizer has listed what it
considers the suggested primary and secondary key fields. Primary key fields are
fields that should significantly reduce the number of keys selected based on the
corresponding query selection. Secondary key fields are fields that may or may not
significantly reduce the number of keys selected.

The optimizer is able to perform key positioning over any combination of the
primary key fields, plus one additional secondary key field. Therefore it is important
that the first secondary key field be the most selective secondary key field. The
optimizer will use key selection with any of the remaining secondary key fields.
While key selection is not as fast as key positioning it can still reduce the number of
keys selected. Hence, secondary key fields that are fairly selective should be
included.

Field QQIDXK contains the number of suggested primary key fields that are listed in
field QQIDXD. These are the left-most suggested key fields. The remaining key
fields are considered secondary key fields and are listed in order of expected
selectivity based on the query. For example, assuming QQIDXK contains the value
of 4 and QQIDXD specifies 7 key fields, then the first 4 key fields specified in
QQIDXK would be the primary key fields. The remaining 3 key fields would be the
suggested secondary key fields.

It is up to the user to determine the true selectivity of any secondary key fields and
to determine whether those key fields should be included when creating the index.
When building the index the primary key fields should be the left-most key fields
followed by any of the secondary key fields the user chooses and they should be
prioritized by selectivity.

Note: After creating the suggested index and executing the query again, it is
possible that the query optimizer will choose not to use the suggested index.

Database Monitor Examples


Suppose you have an application program with SQL statements and you want to
analyze and performance tune these queries. The first step in analyzing the
performance is collection of data. The following examples show how you might
collect and analyze data using STRDBMON and ENDDBMON.

482 DB2 UDB for AS/400 SQL Programming V4R4


Performance data is collected in LIB/PERFDATA for an application running in your
current job. The following sequence collects performance data and prepares to
analyze it.
1. STRDBMON FILE(LIB/PERFDATA). If this file does not already exist, the
command will create one from the skeleton file in QSYS/QAQQDBMN.
2. Run your application
3. ENDDBMON
4. Create logical files over LIB/PERFDATA using the DDS shown in “Database
Monitor Logical File DDS” on page 493.
You are now ready to analyze the data. The following examples give you a few
ideas on how to use this data. You should closely study the physical and logical file
DDS to understand all the data being collected so you can create queries that give
the best information for your applications.

Performance Analysis Example 1


Determine which queries in your SQL application are implemented with table scans.
The complete information can be obtained by joining two logical files: QQQ1000,
which contains information about the SQL statements, and QQQ3000, which
contains data about queries performing table scans. The following SQL query could
be used:
SELECT A.QQTLN, A.QQTFN, A.QQTOTR, A.QQIDXA, B.QQROWR,
(B.QQETIM - B.QQSTIM) AS TOT_TIME, B.QQSTTX
FROM LIB/QQQ3000 A, LIB/QQQ1000 B
WHERE A.QQJFLD = B.QQJFLD
AND A.QQUCNT = B.QQUCNT

Sample output of this query is shown in Table 42. The critical thing to understand is
the join criteria
WHERE A.QQJFLD = B.QQJFLD
AND A.QQUCNT = B.QQUCNT

A lot of data about many queries is contained in multiple records in file


LIB/PERFDATA. It is not uncommon for data about a single query to be contained
in 10 or more records within the file. The combination of defining the logical files
and then joining the files together allows you to piece together all the data for a
query or set of queries. Field QQJFLD uniquely identifies all data common to a job;
field QQUCNT is unique at the query level. The combination of the two, when
referenced in the context of the logical files, connects the query implementation to
the query statement information. scale=’table-scale-factor’
Table 42. Output for SQL Queries that Performed Table Scans
Table Total Index Rows
Lib Name Name Rows Advised Returned TOT_TIME Statement Text
LIB1 TBL1 20000 Y 10 6.2 SELECT * FROM LIB1/TBL1
WHERE FLD1 = 'A'
LIB1 TBL2 100 N 100 0.9 SELECT * FROM LIB1/TBL2
LIB1 TBL1 20000 Y 32 7.1 SELECT * FROM LIB1/TBL1
WHERE FLD1 = 'B' AND
FLD2 > 9000

If the query does not use SQL, the SQL information record (QQQ1000) is not
created. This makes it more difficult to determine which records in LIB/PERFDATA
pertain to which query. When using SQL, record QQQ1000 contains the actual SQL
statement text that matches the performance records to the corresponding query.

Chapter 26. Monitoring and Optimizing Query Performance Tools 483


Only through SQL is the statement text captured. For queries executed using the
OPNQRYF command, the OPNID parameter is captured and can be used to tie the
records to the query. The OPNID is contained in field QQOPID of record QQQ3014.

Performance Analysis Example 2


Similar to the preceding example that showed which SQL applications were
implemented with table scans, the following example shows all queries that are
implemented with table scans.
SELECT A.QQTLN, A.QQTFN, A.QQTOTR, A.QQIDXA,
B.QQOPID, B.QQTTIM, C.QQCLKT, C.QQRCDR, D.QQROWR,
(D.QQETIM - D.QQSTIM) AS TOT_TIME, D.QQSTTX
FROM LIB/QQQ3000 A INNER JOIN LIB/QQQ3014 B
ON (A.QQJFLD = B.QQJFLD AND
A.QQUCNT = B.QQUCNT)
LEFT OUTER JOIN LIB/QQQ3019 C
ON (A.QQJFLD = C.QQJFLD AND
A.QQUCNT = C.QQUCNT)
LEFT OUTER JOIN LIB/QQQ1000 D
ON (A.QQJFLD = D.QQJFLD AND
A.QQUCNT = D.QQUCNT)

In this example, the output for all queries that performed table scans are shown in
Table 43.

Note: The fields selected from file QQQ1000 do return NULL default values if the
query was not executed using SQL. For this example assume the default
value for character data is blanks and the default value for numeric data is
an asterisk (*).
Table 43. Output for All Queries that Performed Table Scans
ODP
Lib Table Total Index Query Open Clock Recs Rows TOT_
Name Name Rows Advised OPNID Time Time Rtned Rtned TIME Statement Text
LIB1 TBL1 20000 Y 1.1 4.7 10 10 6.2 SELECT *
FROM LIB1/TBL1
WHERE FLD1 = 'A'
LIB1 TBL2 100 N 0.1 0.7 100 100 0.9 SELECT *
FROM LIB1/TBL2
LIB1 TBL1 20000 Y 2.6 4.4 32 32 7.1 SELECT *
FROM LIB1/TBL1
WHERE FLD1 = 'A'
AND FLD2 > 9000
LIB1 TBL4 4000 N QRY04 1.2 4.2 724 * *

If the SQL statement text is not needed, joining to file QQQ1000 is not necessary.
You can determine the total time and rows selected from data in the QQQ3014 and
QQQ3019 records.

Performance Analysis Example 3


Your next step may include further analysis of the table scan data. The previous
examples contained a field titled Index Advised. A Y (yes) in this field is a hint from
the query optimizer that the query may perform better with an index to access the
data. For the queries where an index is advised, notice that the records selected by
the query are low in comparison to the total number of records in the table. This is
another indication that a table scan may not be optimal. Finally, a long execution
time may highlight queries that may be improved by performance tuning.

484 DB2 UDB for AS/400 SQL Programming V4R4


The next logical step is to look into the index advised optimizer hint. The following
query could be used for this:
SELECT A.QQTLN, A.QQTFN, A.QQIDXA, A.QQIDXD,
A.QQIDXK, B.QQOPID, C.QQSTTX
FROM LIB/QQQ3000 A INNER JOIN LIB/QQQ3014 B
ON (A.QQJFLD = B.QQJFLD AND
A.QQUCNT = B.QQUCNT)
LEFT OUTER JOIN LIB/QQQ1000 C
ON (A.QQJFLD = C.QQJFLD AND
A.QQUCNT = C.QQUCNT)
WHERE A.QQIDXA = 'Y'

There are two slight modifications from the first example. First, the selected fields
have been changed. Most important is the selection of field QQIDXD that contains a
list of possible key fields to use when creating the index suggested by the query
optimizer. Second, the query selection limits the output to those table scan queries
where the optimizer advises that an index be created (A.QQIDXA = ’Y’). Table 44
shows what the results might look like.
Table 44. Output with Recommended Key Fields
Advised Advised
Table Index Key Primary Query
Lib Name Name Advised Fields Key OPNID Statement Text
LIB1 TBL1 Y FLD1 1 SELECT * FROM LIB1/TBL1
WHERE FLD1 = 'A'
LIB1 TBL1 Y FLD1, 1 SELECT * FROM LIB1/TBL1
FLD2 WHERE FLD1 = 'B' AND
FLD2 > 9000
LIB1 TBL4 Y FLD1, 1 QRY04
FLD4

At this point you should determine whether it makes sense to create a permanent
index as advised by the optimizer. In this example, creating one index over
LIB1/TBL1 would satisfy all three queries since each use a primary or left-most key
field of FLD1. By creating one index over LIB1/TBL1 with key fields FLD1, FLD2,
there is potential to improve the performance of the second query even more. The
frequency these queries are run and the overhead of maintaining an additional
index over the file should be considered when deciding whether or not to create the
suggested index.

If you create a permanent index over FLD1, FLD2 the next sequence of steps
would be to:
1. Start the performance monitor again
2. Re-run the application
3. End the performance monitor
4. Re-evaluate the data.

It is likely that the three index-advised queries are no longer performing table scans.

Additional Database Monitor Examples


The following are additional ideas or examples on how to extract information from
the performance monitor statistics. All of the examples assume data has been
collected in LIB/PERFDATA and the documented logical files have been created.
1. How many queries are performing dynamic replans?

Chapter 26. Monitoring and Optimizing Query Performance Tools 485


SELECT COUNT(*)
FROM LIB/QQQ1000
WHERE QQDYNR <> 'NA'
2. What is the statement text and the reason for the dynamic replans?
SELECT QQDYNR, QQSTTX
FROM LIB/QQQ1000
WHERE QQDYNR <> 'NA'

Note: You have to refer to the description of field QQDYNR for definitions of
the dynamic replan reason codes.
3. How many indexes have been created over LIB1/TBL1?
SELECT COUNT(*)
FROM LIB/QQQ3002
WHERE QQTLN = 'LIB1'
AND QQTFN = 'TBL1'
4. What key fields are used for all indexes created over LIB1/TBL1 and what is
the associated SQL statement text?
SELECT A.QQTLN, A.QQTFN, A.QQIDXD, B.QQSTTX
FROM LIB/QQQ3002 A, LIB/QQQ1000 B
WHERE A.QQJFLD = B.QQJFLD
AND A.QQUCNT = B.QQUCNT
AND A.QQTLN = 'LIB1'
AND A.QQTFN = 'TBL1'

Note: This query shows key fields only from queries executed using SQL.
5. What key fields are used for all indexes created over LIB1/TBL1 and what was
the associated SQL statement text or query open ID?
SELECT A.QQTLN, A.QQTFN, A.QQIDXD,
B.QQOPID,C.QQSTTX
FROM LIB/QQQ3002 A INNER JOIN LIB/QQQ3014 B
ON (A.QQJFLD = B.QQJFLD AND
A.QQUCNT = B.QQUCNT)
LEFT OUTER JOIN LIB/QQQ1000 C
ON (A.QQJFLD = C.QQJFLD AND
A.QQUCNT = C.QQUCNT)
WHERE A.QQTLN = 'LIB1'
AND A.QQTFN = 'TBL1'

Note: This query shows key fields from all queries on the system.
6. What types of SQL statements are being performed? Which are performed
most frequently?
SELECT QQSTOP, COUNT(*)
FROM LIB/QQQ1000
GROUP BY QQSTOP
ORDER BY 2 DESC
7. Which SQL queries are the most time consuming? Which user is running these
queries?
SELECT (QQETIM - QQSTIM), QQUSER, QQSTTX
FROM LIB/QQQ1000
ORDER BY 1 DESC
8. Which queries are the most time consuming?
SELECT (A.QQTTIM + B.QQCLKT), A.QQOPID, C.QQSTTX
FROM LIB/QQQ3014 A LEFT OUTER JOIN LIB/QQQ3019 B
ON (A.QQJFLD = B.QQJFLD AND
A.QQUCNT = B.QQUCNT)
LEFT OUTER JOIN LIB/QQQ1000 C
ON (A.QQJFLD = C.QQJFLD AND
A.QQUCNT = C.QQUCNT)
ORDER BY 1 DESC

486 DB2 UDB for AS/400 SQL Programming V4R4


Note: This example assumes detail data has been collected into record
QQQ3019.
9. Show the data for all SQL queries with the data for each SQL query logically
grouped together.
SELECT A.*
FROM LIB/PERFDATA A, LIB/QQQ1000 B
WHERE A.QQJFLD = B.QQJFLD
AND A.QQUCNT = B.QQUCNT

Note: This might be used within a report that will format the the interesting
data into a more readable format. For example, all reason code fields
could be expanded by the report to print the definition of the reason
code (i.e., physical field QQRCOD = ’T1’ means a table scan was
performed because no indexes exist over the queried file).
10. How many queries are being implemented with temporary files because a key
length of greater than 2000 bytes or more than 120 key fields was specified for
ordering?
SELECT COUNT(*)
FROM LIB/QQQ3004
WHERE QQRCOD = 'F6'
11. Which SQL queries were implemented with nonreusable ODPs?
SELECT B.QQSTTX
FROM LIB/QQQ3010 A, LIB/QQQ1000 B
WHERE A.QQJFLD = B.QQJFLD
AND A.QQUCNT = B.QQUCNT
AND A.QQODPI = 'N'
12. What is the estimated time for all queries stopped by the query governor?
SELECT QQEPT, QQOPID
FROM LIB/QQQ3014
WHERE QQGVNS = 'Y'

Note: This example assumes detail data has been collected into record
QQQ3019.
13. Which queries estimated time exceeds actual time?
SELECT A.QQEPT, (A.QQTTIM + B.QQCLKT), A.QQOPID,
C.QQTTIM, C.QQSTTX
FROM LIB/QQQ3014 A LEFT OUTER JOIN LIB/QQQ3019 B
ON (A.QQJFLD = B.QQJFLD AND
A.QQUCNT = B.QQUCNT)
LEFT OUTER JOIN LIB/QQQ1000 C
ON (A.QQJFLD = C.QQJFLD AND
A.QQUCNT = C.QQUCNT)
WHERE A.QQEPT/1000 > (A.QQTTIM + B.QQCLKT)

Note: This example assumes detail data has been collected into record
QQQ3019.
14. Should a PTF for queries that perform UNION exists be applied. It should be
applied if any queries are performing UNION. Do any of the queries perform
this function?
SELECT COUNT(*)
FROM QQQ3014
WHERE QQUNIN = 'Y'

Note: If result is greater than 0, the PTF should be applied.


15. You are a system administrator and an upgrade to the next release is planned.
A comparison between the two releases would be interesting.

Chapter 26. Monitoring and Optimizing Query Performance Tools 487


v Collect data from your application on the current release and save this data
in LIB/CUR_DATA
v Move to the next release
v Collect data from your application on the new release and save this data in
a different file: LIB/NEW_DATA
v Write a program to compare the results. You will need to compare the
statement text between the records in the two files to correlate the data.

488 DB2 UDB for AS/400 SQL Programming V4R4


Database Monitor Physical File DDS
|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor physical file record format
A*
A R QQQDBMN TEXT('Database +
Monitor')
A QQRID 15P TEXT('Record +
ID') +
EDTCDE(4) +
COLHDG('Record' 'ID')
A QQTIME Z TEXT('Time record was +
created') +
COLHDG('Created' 'Time')
A QQJFLD 46H TEXT('Join Field') +
COLHDG('Join' 'Field')
A QQRDBN 18A TEXT('Relational +
Database Name') +
COLHDG('Relational' +
'Database' 'Name')
A QQSYS 8A TEXT('System Name') +
COLHDG('System' 'Name')
A QQJOB 10A TEXT('Job Name') +
COLHDG('Job' 'Name')
A QQUSER 10A TEXT('Job User') +
COLHDG('Job' 'User')
A QQJNUM 6A TEXT('Job Number') +
COLHDG('Job' 'Number')
A QQUCNT 15P TEXT('Unique Counter') +
ALWNULL +
COLHDG('Unique' 'Counter')
A QQUDEF 100A VARLEN TEXT('User Defined +
Field') +
ALWNULL +
COLHDG('User' 'Defined' +
'Field')
A QQSTN 15P TEXT('Statement Number') +
ALWNULL +
COLHDG('Statement' +
'Number')
A QQQDTN 15P TEXT('Subselect Number') +
ALWNULL +
COLHDG('Subselect' 'Number')
A QQQDTL 15P TEXT('Nested level of +
subselect') +
ALWNULL +
COLHDG('Nested' +
'Level of' +
'Subselect')
A QQMATN 15P TEXT('Subselect of +
materialized view') +
ALWNULL +
COLHDG('Subselect of' +
'Materialized' 'View')
A QQMATL 15P TEXT('Nested level of +
Views subselect') +
ALWNULL +
COLHDG('Nested Level' +
'of View's' +
'Subselect')

Figure 15. QSYS/QAQQDBMN Performance Statistics Physical File DDS (1 of 4)

Chapter 26. Monitoring and Optimizing Query Performance Tools 489


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A QQTLN 10A TEXT('Library') +
ALWNULL +
COLHDG('Library' 'Name')
A QQTFN 10A TEXT('File') +
ALWNULL +
COLHDG('File' 'Name')
A QQTMN 10A TEXT('Member') +
ALWNULL +
COLHDG('Member' 'Name')
A QQPTLN 10A TEXT('Physical Library') +
ALWNULL +
COLHDG('Library of' +
'Physical File')
A QQPTFN 10A TEXT('Physical File') +
ALWNULL +
COLHDG('Name of' +
'Physical File')
A QQPTMN 10A TEXT('Physical Member') +
ALWNULL +
COLHDG('Member of' +
'Physical' 'File')
A QQILNM 10A TEXT('Index Library') +
ALWNULL +
COLHDG('Index' 'Library')
A QQIFNM 10A TEXT('Index File') +
ALWNULL +
COLHDG('Index' 'Name')
A QQIMNM 10A TEXT('Index Member') +
ALWNULL +
COLHDG('Index' 'Member')
A QQNTNM 10A TEXT('NLSS Table') +
ALWNULL +
COLHDG('NLSS' 'Table')
A QQNLNM 10A TEXT('NLSS Library') +
ALWNULL +
COLHDG('NLSS' 'Library')
A QQSTIM Z TEXT('Start timestamp') +
ALWNULL +
COLHDG('Start' 'Time')
A QQETIM Z TEXT('End timestamp') +
ALWNULL +
COLHDG('End' 'Time')
A QQKP 1A TEXT('Key positioning') +
ALWNULL +
COLHDG('Key' 'Positioning')
A QQKS 1A TEXT('Key selection') +
ALWNULL +
COLHDG('Key' 'Selection')
A QQTOTR 15P TEXT('Total row in table') +
ALWNULL +
COLHDG('Total' 'Rows')
A QQTMPR 15P TEXT('Number of rows in +
temporary') +
ALWNULL +
COLHDG('Number' 'of Rows' +
'in Temporary')
A QQJNP 15P TEXT('Join Position') +
ALWNULL +
COLHDG('Join' 'Position')

Figure 16. QSYS/QAQQDBMN Performance Statistics Physical File DDS (2 of 4)

490 DB2 UDB for AS/400 SQL Programming V4R4


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A QQEPT 15P TEXT('Estimated processing +
time') +
ALWNULL +
COLHDG('Estimated' +
'Processing' 'Time')
A QQDSS 1A TEXT('Data space +
selection') ALWNULL
COLHDG('Data' 'Space' +
'Selection')
A QQIDXA 1A TEXT('Index advised') +
ALWNULL +
COLHDG('Index' 'Advised')
A QQORDG 1A TEXT('Ordering') ALWNULL
COLHDG('Ordering')
A QQGRPG 1A TEXT('Grouping') +
ALWNULL +
COLHDG('Grouping')
A QQJNG 1A TEXT('Join') ALWNULL
COLHDG('Join')
A QQUNIN 1A TEXT('Union') +
ALWNULL +
COLHDG('Union')
A QQSUBQ 1A TEXT('Subquery') +
ALWNULL +
COLHDG('Subquery')
A QQHSTV 1A TEXT('Host Variables') +
ALWNULL +
COLHDG('Host' 'Variables')
A QQRCDS 1A TEXT('Record Selection') +
ALWNULL +
COLHDG('Record' 'Selection')
A QQRCOD 2A TEXT('Reason Code') +
ALWNULL +
COLHDG('Reason' 'Code')
A QQRSS 15P TEXT('Number of rows +
selected or sorted') +
ALWNULL +
COLHDG('Number' +
'of Rows' 'Selected')
A QQREST 15P TEXT('Estimated number +
of rows selected') +
ALWNULL +
COLHDG('Estimated' +
'Number of' +
'Rows Selected')
A QQRIDX 15P TEXT('Number of entries +
in index created') +
ALWNULL +
COLHDG('Number of' +
'Entries in' +
'Index Created')
A QQFKEY 15P TEXT('Estimated keys for +
key positioning') +
ALWNULL +
COLHDG('Estimated' +
'Entries for' +
'Key Positioning')

Figure 17. QSYS/QAQQDBMN Performance Statistics Physical File DDS (3 of 4)

Chapter 26. Monitoring and Optimizing Query Performance Tools 491


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A QQKSEL 15P TEXT('Estimated keys for +
key selection') +
ALWNULL +
COLHDG('Estimated' +
'Entries for' +
'Key Selection')
A QQAJN 15P TEXT('Estimated number +
of joined rows') +
ALWNULL +
COLHDG('Estimated' +
'Number of' +
'Joined Rows')
A QQIDXD 1000A VARLEN TEXT('Key fields +
for the index advised') +
ALWNULL +
COLHDG('Advised' 'Key' +
'Fields')
A QQC11 1A ALWNULL
A QQC12 1A ALWNULL
A QQC13 1A ALWNULL
A QQC14 1A ALWNULL
A QQC15 1A ALWNULL
A QQC16 1A ALWNULL
A QQC18 1A ALWNULL
A QQC21 2A ALWNULL
A QQC22 2A ALWNULL
A QQC23 2A ALWNULL
A QQI1 15P ALWNULL
A QQI2 15P ALWNULL
A QQI3 15P ALWNULL
A QQI4 15P ALWNULL
A QQI5 15P ALWNULL
A QQI6 15P ALWNULL
A QQI7 15P ALWNULL
A QQI8 15P ALWNULL
A QQI9 15P ALWNULL TEXT('Thread +
Identifier') +
COLHDG('Thread' +
'Identifier')
A QQIA 15P ALWNULL
A QQF1 15P ALWNULL
A QQF2 15P ALWNULL
A QQF3 15P ALWNULL
A QQC61 6A ALWNULL
A QQC81 8A ALWNULL
A QQC82 8A ALWNULL
A QQC83 8A ALWNULL
A QQC84 8A ALWNULL
A QQC101 10A ALWNULL
A QQC102 10A ALWNULL
A QQC103 10A ALWNULL
A QQC104 10A ALWNULL
A QQC105 10A ALWNULL
A QQC106 10A ALWNULL
A QQC181 18A ALWNULL
A QQC182 18A ALWNULL
A QQC183 18A ALWNULL
A QQC301 30A VARLEN ALWNULL
A QQC302 30A VARLEN ALWNULL
A QQC303 30A VARLEN ALWNULL
A QQ1000 1000A VARLEN ALWNULL
A QQTIM1 Z ALWNULL
A QQTIM2 Z ALWNULL

Figure 18. QSYS/QAQQDBMN Performance Statistics Physical File DDS (4 of 4)

492 DB2 UDB for AS/400 SQL Programming V4R4


Database Monitor Logical File DDS
|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 1000
A*
A R QQQ1000 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQUCNT
A QQRCNT RENAME(QQI5) +
COLHDG('Refresh' +
'Counter')
A QQUDEF
A QQSTN
A QQSTF RENAME(QQC11) +
COLHDG('Statement' +
'Function')
A QQSTOP RENAME(QQC21) +
COLHDG('Statement' +
'Operation')
A QQSTTY RENAME(QQC12) +
COLHDG('Statement' 'Type')
A QQPARS RENAME(QQC13) +
COLHDG('Parse' 'Required')
A QQPNAM RENAME(QQC103) +
COLHDG('Package' 'Name')
A QQPLIB RENAME(QQC104) +
COLHDG('Package' 'Library')
A QQCNAM RENAME(QQC181) +
COLHDG('Cursor' 'Name')
A QQSNAM RENAME(QQC182) +
COLHDG('Statement' 'Name')

Figure 19. Summary record for SQL Information (Part 1 of 2)

Chapter 26. Monitoring and Optimizing Query Performance Tools 493


A QQSTIM
A QQSTTX RENAME(QQ1000) +
COLHDG('Statement' 'Text')
A QQSTOC RENAME(QQC14) +
COLHDG('Statement' +
'Outcome')
A QQROWR RENAME(QQI2) +
COLHDG('Rows' 'Returned')
A QQDYNR RENAME(QQC22) +
COLHDG('Dynamic' 'Replan')
A QQDACV RENAME(QQC16) +
COLHDG('Data' 'Conversion')
A QQTTIM RENAME(QQI4) +
COLHDG('Total' 'Time')
A QQTTMM RENAME(QQI6) +
COLHDG('Total' 'Time' +
'Microseconds')
A QQTSLM RENAME(QQI7) +
COLHDG('Total' 'Statement'
'Length')
A QQROWF RENAME(QQI3) +
COLHDG('Rows' 'Fetched')
A QQETIM
A K QQJFLD
A S QQRID CMP(EQ 1000)

Figure 19. Summary record for SQL Information (Part 2 of 2)

Table 45. QQQ1000 - Summary record for SQL Information


Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQRCNT QQI5 Unique refresh counter
QQUDEF QQUDEF User defined field
QQSTN QQSTN Statement number (unique per statement)
QQSTF QQC11 Statement function
S - Select
U - Update
I - Insert
D - Delete
L - Data definition language
O - Other

494 DB2 UDB for AS/400 SQL Programming V4R4


Table 45. QQQ1000 - Summary record for SQL Information (continued)
Logical Field Name Physical Field Name Description
QQSTOP QQC21 Statement operation
AL - Alter table
CA - Call
CC - Create collection or Create schema
CF - Create function
CI - Create index
CL - Close
CO - Comment on
CM - Commit
CN - Connect
CP - Create procedure
CS - Create alias
CT - Create table
CV - Create view
CY - Create type
DP - Declare procedure
DL - Delete
DE - Describe
DT - Describe table
DI - Disconnect
DR - Drop
EX - Execute
EI - Execute immediate
FE - Fetch
FL - Free locator
GR - Grant
IN - Insert
LO - Label on
LK - Lock
MT - More text
OP - Open
PR - Prepare
RE - Release
RT - Rename table
RV - Revoke
RO - Rollback
SI - Select into
SC - Set connection
SE - Set variable
SP - Set path
SR - Set result sets
ST - Set transaction
UP - Update
VI - Value information
QQSTTY QQC12 Statement type
D - Dynamic statement
S - Static statement
QQPARS QQC13 Parse required,
Y - Yes
N - No
QQPNAM QQC103 Name of the package or name of the program that contains the
current SQL statement
QQPLIB QQC104 Name of the library containing the package
QQCNAM QQC181 Name of the cursor corresponding to this SQL statement, if
applicable

Chapter 26. Monitoring and Optimizing Query Performance Tools 495


Table 45. QQQ1000 - Summary record for SQL Information (continued)
Logical Field Name Physical Field Name Description
QQSNAM QQC182 Name of statement for SQL statement, if applicable
QQSTIM QQSTIM Time this statement entered
QQSTTX QQ1000 Statement text
QQSTOC QQC14 Statement outcome
S - Successful
U - Unsuccessful
QQROWR QQI2 Number of result rows returned
QQDYNR QQC22 Dynamic replan (access plan rebuilt)
NA - No replan.
NR - SQL QDT rebuilt for new release.
A1 - A file or member is not the same object
as the one referenced when the access
plan was last built. Some reasons they
could be different are:
- Object was deleted and recreated.
- Object was saved and restored.
- Library list was changed.
- Object was renamed.
- Object was moved.
- Object was overridden to a different
object.
- This is the first run of this query
after the object containing the
query has been restored.
A2 - Access plan was built to use a reusable
Open Data Path (ODP) and the optimizer
chose to use a non-reusable ODP for
this call.
A3 - Access plan was built to use a non-reusable
Open Data Path (ODP) and the optimizer
chose to use a reusable ODP for this call.
A4 - The number of records in the file member
has changed by more than 10% since the
access plan was last built.
A5 - A new access path exists over one of the
files in the query.
A6 - An access path that was used for this
access plan no longer exists or is no
longer valid.
A7 - OS/400 Query requires the access plan
to be rebuilt because of system
programming changes.
A8 - The CCSID of the current job is
different than the CCSID of the job
that last created the access plan.
A9 - The value of one or more of the
following is different for the
current job than it was for the
job that last created this access
plan:
- date format.
- date separator.
- time format.
- time separator.

496 DB2 UDB for AS/400 SQL Programming V4R4


Table 45. QQQ1000 - Summary record for SQL Information (continued)
Logical Field Name Physical Field Name Description
AA - The sort sequence table specified
is different than the sort sequence
table that was used when this
access plan was created.
AB - Storage pool changed or DEGREE
parameter of CHGQRYA command changed.
AC - The system feature DB2 multisystem has
been installed or removed..
AD - The value of the degree query attribute has
changed.
AE - A view is either being opened by a high level
language or a view is being materialized.
AF - A user-defined type or user-defined function
is not the same object as the one referred to in
the access plan.
B0 - The options specified have changed as a result
of the query options file QAQQINI.
QQDACV QQC16 Data conversion
N - No.
0 - Not applicable.
1 - Lengths do not match.
2 - Numeric types do not match.
3 - C host variable is NUL-terminated
4 - Host variable or column is
variable length and the other
is not variable length.
5 - CCSID conversion.
6 - DRDA and NULL capable, variable
length, contained in a partial
row, derived expression, or
blocked fetch with not enough
host variables.
7 - Data, time, or timestamp column.
8 - Too many host variables.
9 - Target table of an insert is
not an SQL table.
QQTTIM QQI4 Total time (Universal Time Coordinated) for this statement, in
milliseconds. For fetches, this includes all fetches for this OPEN
of the cursor.
QQTTMM QQI6 Total time (Universal Time Coordinated) for this statement, in
microseconds. For fetches, this includes all fetches for this
OPEN of the cursor.
QQTSLM QQI7 Total text length includes the length of the text, in this record
and any other records, which are related because of the ’MT’
operation type.
QQROWF QQI3 Total rows fetched for cursor
QQETIM QQETIM Time SQL request completed

Chapter 26. Monitoring and Optimizing Query Performance Tools 497


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3000
A*
A R QQQ3000 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQMATL
A QQTLN
A QQTFN
A QQTMN
A QQPTLN
A QQPTFN
A QQPTMN
A QQTOTR
A QQREST
A QQAJN
A QQEPT
A QQJNP
A QQJNDS RENAME(QQI1) +
COLHDG('Data Space' 'Number')
A QQJNMT RENAME(QQC21) +
COLHDG('Join' 'Method')
A QQJNTY RENAME(QQC22) +
COLHDG('Join' 'Type')
A QQJNOP RENAME(QQC23) +
COLHDG('Join' 'Operator')
A QQIDXK RENAME(QQI2) +
COLHDG('Advised' 'Primary' 'Keys')
A QQDSS
A QQIDXA
A QQRCOD
A QQIDXD
A K QQJFLD
A S QQRID CMP(EQ 3000)

Figure 20. Summary record for Arrival Sequence

Table 46. QQQ3000 - Summary record for Arrival Sequence


Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name

498 DB2 UDB for AS/400 SQL Programming V4R4


Table 46. QQQ3000 - Summary record for Arrival Sequence (continued)
Logical Field Name Physical Field Name Description
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per QDT)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQTLN QQTLN Library
QQTFN QQTFN File
QQTMN QQTMN Member
QQPTLN QQPTLN Physical library
QQPTFN QQPTFN Physical file
QQPTMN QQPTMN Physical member
QQTOTR QQTOTR Total rows in table
QQREST QQREST Estimated number of rows selected
QQAJN QQAJN Estimated number of joined rows
QQEPT QQEPT Estimated processing time, in seconds
QQJNP QQJNP Join position - when available
QQJNDS QQI1 Data space number
QQJNMT QQC21 Join method - when available
NL - Nested loop
MF - Nested loop with selection
HJ - Hash join
QQJNTY QQC22 Join type - when available
IN - Inner join
PO - Left partial outer join
EX - Exception join
QQJNOP QQC23 Join operator - when available
EQ - Equal
NE - Not equal
GT - Greater than
GE - Greater than or equal
LT - Less than
LE - Less than or equal
CP - Cartesian product
QQIDXK QQI2 Number of advised key fields that use key positioning
QQDSS QQDSS Data space selection
Y - Yes
N - No
QQIDXA QQIDXA Index advised
Y - Yes
N - No

Chapter 26. Monitoring and Optimizing Query Performance Tools 499


Table 46. QQQ3000 - Summary record for Arrival Sequence (continued)
Logical Field Name Physical Field Name Description
QQRCOD QQRCOD Reason code
T1 - No indexes exist.
T2 - Indexes exist, but none
could be used.
T3 - Optimizer chose table scan
over available indexes.
QQIDXD QQIDXD Key fields for the index advised

500 DB2 UDB for AS/400 SQL Programming V4R4


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3001
A*
A R QQQ3001 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQMATL
A QQMATL
A QQTLN
A QQTFN
A QQTMN
A QQPTLN
A QQPTFN
A QQPTMN
A QQILNM
A QQIFNM
A QQIMNM
A QQTOTR
A QQREST
A QQFKEY
A QQKSEL
A QQAJN
A QQEPT
A QQJNP
A QQJNDS RENAME(QQI1) +
COLHDG('Data Space' +
'Number')
A QQJNMT RENAME(QQC21) +
COLHDG('Join' 'Method')
A QQJNTY RENAME(QQC22) +
COLHDG('Join' 'Type')
A QQJNOP RENAME(QQC23) +
COLHDG('Join' 'Operator')
A QQIDXK RENAME(QQI2) +
COLHDG('Advised' +
'Primary' +
'Keys')

Figure 21. Summary record for Using Existing Index (Part 1 of 2)

Chapter 26. Monitoring and Optimizing Query Performance Tools 501


A QQKP
A QQKPN RENAME(QQI3) +
COLHDG('Number of Key' +
'Positioning' +
'Fields')
A QQKS
A QQDSS
A QQIDXA
A QQRCOD
A QQCST RENAME(QQC11) +
COLHDG('Constraint' +
'Indicator')
A QQIDXD
A QQCSTN RENAME(QQ1000) +
COLHDG('Constraint' +
'Name')
A K QQJFLD
A S QQRID CMP(EQ 3001)

Figure 21. Summary record for Using Existing Index (Part 2 of 2)

Table 47. QQQ3001 - Summary record for Using Existing Index


Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per QDT)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQTLN QQTLN Library
QQTFN QQTFN File
QQTMN QQTMN Member
QQPTLN QQPTLN Physical library
QQPTFN QQPTFN Physical file
QQPTMN QQPTMN Physical member
QQILNM QQILNM Index library
QQIFNM QQIFNM Index file
QQIMNM QQIMNM Index member
QQTOTR QQTOTR Total rows in table
QQREST QQREST Estimated number of rows selected

502 DB2 UDB for AS/400 SQL Programming V4R4


Table 47. QQQ3001 - Summary record for Using Existing Index (continued)
Logical Field Name Physical Field Name Description
QQFKEY QQFKEY Keys selected thru key positioning
QQKSEL QQKSEL Keys selected thru key selection
QQAJN QQAJN Estimated number of joined rows
QQEPT QQEPT Estimated processing time, in seconds
QQJNP QQJNP Join position - when available
QQJNDS QQI1 Data space number
QQJNMT QQC21 Join method - when available
NL - Nested loop
MF - Nested loop with selection
HJ - Hash join
QQJNTY QQC22 Join type - when available
IN - Inner join
PO - Left partial outer join
EX - Exception join
QQJNOP QQC23 Join operator - when available
EQ - Equal
NE - Not equal
GT - Greater than
GE - Greater than or equal
LT - Less than
LE - Less than or equal
CP - Cartesian product
QQIDXK QQI2 Number of advised key fields that use key positioning
QQKP QQKP Key positioning
Y - Yes
N - No
QQKS QQKS Key selection
Y - Yes
N - No
QQDSS QQDSS Data space selection
Y - Yes
N - No
QQIDXA QQIDXA Index advised
Y - Yes
N - No
QQRCOD QQRCOD Reason code
I1 - Record selection
I2 - Ordering/Grouping
I3 - Record selection and
Ordering/Grouping
I4 - Nested loop join
I5 - Record selection using
bitmap processing
QQCST QQC11 Constraint indicator
Y - Yes
N - No
QQIDXD QQIDXD Key fields for index advised
QQCSTN QQC1000 Constraint name

Chapter 26. Monitoring and Optimizing Query Performance Tools 503


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A* Database Monitor logical file 3002
A R QQQ3002 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQMATL
A QQTLN
A QQTFN
A QQTMN
A QQPTLN
A QQPTFN
A QQPTMN
A QQILNM
A QQIFNM
A QQIMNM
A QQNTNM
A QQNLNM
A QQSTIM
A QQETIM
A QQTOTR
A QQRIDX
A QQREST
A QQFKEY
A QQKSEL
A QQAJN
A QQJNP

Figure 22. Summary record for Index Created (Part 1 of 2)

504 DB2 UDB for AS/400 SQL Programming V4R4


A QQJNDS RENAME(QQI1) +
COLHDG('Data Space' 'Number')
A QQJNMT RENAME(QQC21) +
COLHDG('Join' 'Method')
A QQJNTY RENAME(QQC22) +
COLHDG('Join' 'Type')
A QQJNOP RENAME(QQC23) +
COLHDG('Join' 'Operator')
A QQIDXK RENAME(QQI2) +
COLHDG('Advised' 'Primary' 'Keys')
A QQEPT
A QQKP
A QQKPN RENAME(QQI3) +
COLHDG('Number of Key' +
'Positioning' + 'Fields')
A QQKS
A QQDSS
A QQIDXA
A QQRCOD
A QQIDXD
A QQCRTK RENAME(QQ1000) +
COLHDG('Key Fields' +
'of Index' 'Created')
A K QQJFLD
A S QQRID CMP(EQ 3002)

Figure 22. Summary record for Index Created (Part 2 of 2)

Table 48. QQQ3002 - Summary record for Index Created


Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per QDT)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQTLN QQTLN Library
QQTFN QQTFN File
QQTMN QQTMN Member
QQPTLN QQPTLN Physical library
QQPTFN QQPTFN Physical file
QQPTMN QQPTMN Physical member

Chapter 26. Monitoring and Optimizing Query Performance Tools 505


Table 48. QQQ3002 - Summary record for Index Created (continued)
Logical Field Name Physical Field Name Description
QQILNM QQILNM Index library
QQIFNM QQIFNM Index file
QQIMNM QQIMNM Index member
QQNTNM QQNTNM NLSS library
QQNLNM QQNLNM NLSS table
QQSTIM QQSTIM Start timestamp
QQETIM QQETIM End timestamp
QQTOTR QQTOTR Total rows in table
QQRIDX QQRIDX Number of entries in index created
QQREST QQREST Estimated number of rows selected
QQFKEY QQFKEY Keys selected thru key positioning
QQKSEL QQKSEL Keys selected thru key selection
QQAJN QQAJN Estimated number of joined rows
QQEPT QQEPT Estimated processing time, in seconds
QQJNP QQJNP Join position - when available
QQJNDS QQI1 Data space number
QQJNMT QQC21 Join method - when available
NL - Nested loop
MF - Nested loop with selection
HJ - Hash join
QQJNTY QQC22 Join type - when available
IN - Inner join
PO - Left partial outer join
EX - Exception join
QQJNOP QQC23 Join operator - when available
EQ - Equal
NE - Not equal
GT - Greater than
GE - Greater than or equal
LT - Less than
LE - Less than or equal
CP - Cartesian product
QQIDXK QQI2 Number of advised key fields that use key positioning
QQKP QQKP Key positioning
Y - Yes
N - No
QQKS QQKS Key selection
Y - Yes
N - No
QQDSS QQDSS Data space selection
Y - Yes
N - No
QQIDXA QQIDXA Index advised
Y - Yes
N - No

506 DB2 UDB for AS/400 SQL Programming V4R4


Table 48. QQQ3002 - Summary record for Index Created (continued)
Logical Field Name Physical Field Name Description
QQRCOD QQRCOD Reason code
I1 - Record selection
I2 - Ordering/Grouping
I3 - Record selection and
Ordering/Grouping
I4 - Nested loop join
QQIDXD QQIDXD Key fields for index advised
QQCRTK QQ1000 Key fields for index created

|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3003
A*
A R QQQ3003 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQMATL
A QQSTIM
A QQETIM
A QQRSS
A QQSSIZ RENAME(QQI1) +
COLHDG('Size of' +
'Sort' +
'Space')
A QQPSIZ RENAME(QQI2) +
COLHDG('Pool' +
'Size')
A QQPID RENAME(QQI3) +
COLHDG('Pool' +
'ID')
A QQIBUF RENAME(QQI4) +
COLHDG('Internal' +
'Buffer' +
'Length')
A QQEBUF RENAME(QQI5) +
COLHDG('External' +
'Buffer' +
'Length')
A QQRCOD
A K QQJFLD
A S QQRID CMP(EQ 3003)

Figure 23. Summary record for Query Sort

Chapter 26. Monitoring and Optimizing Query Performance Tools 507


Table 49. QQQ3003 - Summary record for Query Sort
Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per QDT)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQSTIM QQSTIM Start timestamp
QQETIM QQETIM End timestamp
QQRSS QQRSS Number of rows selected or sorted
QQSSIZ QQI1 Size of sort space
QQPSIZ QQI2 Pool size
QQPID QQI3 Pool id
QQIBUF QQI4 Internal sort buffer length
QQEBUF QQI5 External sort buffer length
QQRCOD QQRCOD Reason code
F1 Query contains grouping fields (GROUP BY) from more that
one file, or contains grouping fields from a secondary file of
a join query that cannot be reordered.
F2 Query contains ordering fields (ORDER BY) from more that
one file, or contains ordering fields from a secondary file of
a join query that cannot be reordered.
F3 The grouping and ordering fields are not compatible.
F4 DISTINCT was specified for the query.
F5 UNION was specified for the query.
F6 Query had to be implemented using a sort. Key length of
more than 2000 bytes or more than 120 key fields specified
for ordering.
F7 Query optimizer chose to use a sort rather than an access
path to order the results of the query.
F8 Perform specified record selection to minimize I/O wait time.

508 DB2 UDB for AS/400 SQL Programming V4R4


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3004
A*
A R QQQ3004 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQMATL
A QQTLN
A QQTFN
A QQTMN
A QQSTIM
A QQETIM
A QQDFVL RENAME(QQC11) +
COLHDG('Default' +
'Values')
A QQTMPR
A QQRCOD
A K QQJFLD
A S QQRID CMP(EQ 3004)

Figure 24. Summary record for Temporary File

Table 50. QQQ3004 - Summary record for Temporary File


Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per QDT)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQTLN QQTLN Library

Chapter 26. Monitoring and Optimizing Query Performance Tools 509


Table 50. QQQ3004 - Summary record for Temporary File (continued)
Logical Field Name Physical Field Name Description
QQTFN QQTFN File
QQTMN QQTMN Member
QQSTIM QQSTIM Start timestamp
QQETIM QQETIM End timestamp
QQDFVL QQC11 Default values may be present in temporary
Y - Yes
N - No
QQTMPR QQTMPR Number of rows in the temporary
QQRCOD QQRCOD Reason code
F1 Query contains grouping fields (GROUP BY) from more that
one file, or contains grouping fields from a secondary file of
a join query that cannot be reordered.
F2 Query contains ordering fields (ORDER BY) from more that
one file, or contains ordering fields from a secondary file of
a join query that cannot be reordered.
F3 The grouping and ordering fields are not compatible.
F4 DISTINCT was specified for the query.
F5 UNION was specified for the query
F6 Query had to be implemented using a sort. Key length of
more than 2000 bytes or more than 120 key fields specified
for ordering.
F7 Query optimizer chose to use a sort rather than an access
path to order the results of the query.
F8 Perform specified record selection to minimize I/O wait time.
F9 File is a JLF and its join type does not match the join type
specified in the query.
FA Format specified for the logical file references more than 1
physical file.
FB File is a complex SQL view or derived table requiring a
temporary file to contain the result of the SQL view or
derived table.

510 DB2 UDB for AS/400 SQL Programming V4R4


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3005
A*
A R QQQ3005 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQMATL
A QQTLN
A QQTFN
A QQTMN
A QQLCKF RENAME(QQC11) +
COLHDG('Lock' +
'Indicator')
A QQULCK RENAME(QQC12) +
COLHDG('Unlock' +
'Request')
A QQRCOD
A K QQJFLD
A S QQRID CMP(EQ 3005)

Figure 25. Summary record for Table Locked

Table 51. QQQ3005 - Summary record for Table Locked


Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per QDT)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQTLN QQTLN Library

Chapter 26. Monitoring and Optimizing Query Performance Tools 511


Table 51. QQQ3005 - Summary record for Table Locked (continued)
Logical Field Name Physical Field Name Description
QQTFN QQTFN File
QQTMN QQTMN Member
QQLCKF QQC11 Successful lock indicator
Y - Yes
N - No
QQULCK QQC12 Unlock request
Y - Yes
N - No
QQRCOD QQRCOD Reason code
L1 - UNION with *ALL or
*CS with Keep Locks
L2 - DISTINCT with *ALL or
*CS with Keep Locks
L3 - No duplicate keys with *ALL or
*CS with Keep Locks
L4 - Temporary needed with *ALL or
*CS with Keep Locks
L5 - System File with *ALL or
*CS with Keep Locks
L6 - Orderby > 2000 bytes with *ALL or
*CS with Keep Locks
L9 - Unknown

|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3006
A*
A R QQQ3006 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQMATL
A QQTLN
A QQTFN
A QQTMN
A QQPTLN
A QQPTFN
A QQPTMN
A QQRCOD
A K QQJFLD
A S QQRID CMP(EQ 3006)

Figure 26. Summary record for Access Plan Rebuilt

512 DB2 UDB for AS/400 SQL Programming V4R4


Table 52. QQQ3006 - Summary record for Access Plan Rebuilt
Logical Field Physical Field
Name Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per QDT)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQTLN QQTLN Library
QQTFN QQTFN File
QQTMN QQTMN Member
QQPTLN QQPTLN Physical library
QQPTFN QQPTFN Physical file
QQPTMN QQPTMN Physical member

Chapter 26. Monitoring and Optimizing Query Performance Tools 513


Table 52. QQQ3006 - Summary record for Access Plan Rebuilt (continued)
Logical Field Physical Field
Name Name Description
QQRCOD QQRCOD Reason code why access plan was rebuilt
A1 A file or member is not the same object as the one referenced when the
access plan was last built. Some reasons they could be different are:
v Object was deleted and recreated.
v Object was saved and restored.
v Library list was changed.
v Object was renamed.
v Object was moved.
v Object was overridden to a different object.
v This is the first run of this query after the object containing the query
has been restored.
A2 Access plan was built to use a reusable Open Data Path (ODP) and the
optimizer chose to use a non-reusable ODP for this call.
A3 Access plan was built to use a non-reusable Open Data Path (ODP)
and the optimizer chose to use a reusable ODP for this call.
A4 The number of records in the file member has changed by more than
10% since the access plan was last built.
A5 A new access path exists over one of the files in the query.
A6 An access path that was used for this access plan no longer exists or is
no longer valid.
A7 OS/400 Query requires the access plan to be rebuilt because of system
programming changes.
A8 The CCSID of the current job is different than the CCSID of the job that
last created the access plan.
A9 The value of one or more of the following is different for the current job
than it was for the job that last created this access plan:
v date format
v date separator
v time format
v time separator

AA The sort sequence table specified is different than the sort sequence
table that was used when this access plan was created.
AB Storage pool changed or DEGREE parameter of CHGQRYA command
changed.
AC The system feature DB2 multisystem has been installed or removed.
AD The value of the degree query attribute has changed.
AE A view is either being opened by a high level language or a view is
being materialized.
AF A user-defined type or user-defined function is not the same object as
the one referred to in the access plan.
B0 The options specified have changed as a result of the query options file
QAQQINI.

514 DB2 UDB for AS/400 SQL Programming V4R4


Table 52. QQQ3006 - Summary record for Access Plan Rebuilt (continued)
Logical Field Physical Field
Name Name Description
QQINLN QQC101 Query Options Library Name
QQINFN QQC102 Query Options File Name

|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3007
A*
A R QQQ3007 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQMATL
A QQTLN
A QQTFN
A QQTMN
A QQPTLN
A QQPTFN
A QQPTMN
A QQIDXN RENAME(QQ1000) +
COLHDG('Index' +
'Names')
A QQTOUT RENAME(QQC11) +
COLHDG('Optimizer' +
'Timed Out')
A K QQJFLD
A S QQRID CMP(EQ 3007)

Figure 27. Summary record for Optimizer Timed Out

Table 53. QQQ3007 - Summary record for Optimizer Timed Out


Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier

Chapter 26. Monitoring and Optimizing Query Performance Tools 515


Table 53. QQQ3007 - Summary record for Optimizer Timed Out (continued)
Logical Field Name Physical Field Name Description
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per QDT)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQTLN QQTLN Library
QQTFN QQTFN File
QQTMN QQTMN Member
QQPTLN QQPTLN Physical library
QQPTFN QQPTFN Physical file
QQPTMN QQPTMN Physical member
QQIDXN QQ1000 Index names
QQTOUT QQC11 Optimizer timed out
Y - Yes
N - No

|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3008
A*
A R QQQ3008 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQMATL
A QQORGQ RENAME(QQI1) +
COLHDG('Original' +
'Number' +
'of QDTs')
A QQMRGQ RENAME(QQI2) +
COLHDG('Number' +
'of QDTs' +
'Merged')
A K QQJFLD
A S QQRID CMP(EQ 3008)

Figure 28. Summary record for Subquery Processing

516 DB2 UDB for AS/400 SQL Programming V4R4


Table 54. QQQ3008 - Summary record for Subquery Processing
Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per QDT)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQORGQ QQI1 Original number of QDTs
QQMRGQ QQI2 Number of QDTs merged

Chapter 26. Monitoring and Optimizing Query Performance Tools 517


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3010
A*
A R QQQ3010 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQRCNT RENAME(QQI5) +
COLHDG('Refresh' +
'Counter')
A QQUDEF
A QQODPI RENAME(QQC11) +
COLHDG('ODP' +
'Implementation')
A QQHVI RENAME(QQC12) +
COLHDG('Host Variable' +
'Implementation')
A QQHVAR RENAME(QQ1000) +
COLHDG('Host Variable' +
'Values')
A K QQJFLD
A S QQRID CMP(EQ 3010)

Figure 29. Summary record for Host Variable and ODP Implementation

Table 55. QQQ3010 - Summary record for Host Variable and ODP Implementation
Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQRCNT QQRCNT Unique refresh counter
QQUDEF QQUDEF User defined field
QQODPI QQC11 ODP implementation
R - Reusable ODP (ISV)
N - Nonreusable ODP (V2)
’ ’ - Field not used

518 DB2 UDB for AS/400 SQL Programming V4R4


Table 55. QQQ3010 - Summary record for Host Variable and ODP Implementation (continued)
Logical Field Name Physical Field Name Description
QQHVI QQC12 Host variable implementation
I - Interface supplied values (ISV)
V - Host variables treated as literals (V2)
U - File management row positioning (UP)
QQHVAR QQ1000 Host variable values

|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3014
A*
A R QQQ3014 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQMATL
A QQREST
A QQEPT
A QQTTIM RENAME(QQI1) +
COLHDG('ODP' +
'Open' 'Time')
A QQORDG
A QQGRPG
A QQJNG
A QQJNTY RENAME(QQC22) +
COLHDG('Join' +
'Type')

Figure 30. Summary record for Generic Query Information (Part 1 of 2)

Chapter 26. Monitoring and Optimizing Query Performance Tools 519


A QQUNIN
A QQSUBQ
A QQHSTV
A QQRCDS
A QQGVNE RENAME(QQC11) +
COLHDG('Query' +
'Governor' +
'Enabled')
A QQGVNS RENAME(QQC12) +
COLHDG('Stopped' +
'by Query' +
'Governor')
A QQOPID RENAME(QQC101) +
COLHDG('Query' +
'Open ID')
A QQINFN RENAME(QQC102) +
COLHDG('Query' +
'Options' +
'File Name')
A QQINLN RENAME(QQC103) +
COLHDG('Query' +
'Options' +
'Library')
A QQIDXSK RENAME(QQC13) +
COLHDG('Index' +
'Skip Key') +
"Processing')
A K QQJFLD
A S QQRID CMP(EQ 3014)

Figure 30. Summary record for Generic Query Information (Part 2 of 2)

Table 56. QQQ3014 - Summary record for Generic Query Information


Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per query)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQREST QQREST Estimated number of rows selected
QQEPT QQEPT Estimated processing time, in seconds
QQTTIM QQI1 Time spent to open cursor, in milliseconds

520 DB2 UDB for AS/400 SQL Programming V4R4


Table 56. QQQ3014 - Summary record for Generic Query Information (continued)
Logical Field Name Physical Field Name Description
QQORDG QQORDG Ordering
Y - Yes
N - No
QQGRPG QQGRPG Grouping
Y - Yes
N - No
QQJNG QQJNG Joining
Y - Yes
N - No
QQJNTY QQC22 Join type - when available
IN - Inner join
PO - Left partial outer join
EX - Exception join
QQUNIN QQUNIN Union
Y - Yes
N - No
QQSUBQ QQSUBQ Subquery
Y - Yes
N - No
QQHSTV QQHSTV Host variables
Y - Yes
N - No
QQRCDS QQRCDS Record selection
Y - Yes
N - No
QQGVNE QQC11 Query governor enabled
Y - Yes
N - No
QQGVNS QQC12 Query governor stopped the query
Y - Yes
N - No
QQOPID QQC101 Query open ID
QQINLN QQC102 Query Options Library Name
QQINFN QQC103 Query Options File Name
QQIDXSK QQC13 Index skip key processing indicator
Y - Yes
N - No

Chapter 26. Monitoring and Optimizing Query Performance Tools 521


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3018
A*
A R QQQ3018 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUDEF
A QQJOBT RENAME(QQC11)+
COLHDG('Job' +
'Type')
A QQCMDT RENAME(QQC12) +
COLHDG('Command' +
'Type')
A QQJOBI RENAME(QQC301) +
COLHDG('Job' +
'Info')
A K QQJFLD
A S QQRID CMP(EQ 3018)

Figure 31. Summary record for STRDBMON/ENDDBMON

Table 57. QQQ3018 - Summary record for STRDBMON/ENDDBMON


Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUDEF QQUDEF User defined field
QQJOBT QQC11 Type of job monitored
C - Current
J - Job name
A - All
QQCMDT QQC12 Command type
S - STRDBMON
E - ENDDBMON
QQJOBI QQC301 Monitored job information
* - Current job
Job number/User/Job name
*ALL - All jobs

522 DB2 UDB for AS/400 SQL Programming V4R4


|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
A*
A* Database Monitor logical file 3019
A*
A R QQQ3019 PFILE(*CURLIB/QAQQDBMN)
A QQRID
A QQTIME
A QQJFLD
A QQRDBN
A QQSYS
A QQJOB
A QQUSER
A QQJNUM
A QQTHRD RENAME(QQI9) +
COLHDG('Thread' +
'Identifier')
A QQUCNT
A QQUDEF
A QQQDTN
A QQQDTL
A QQMATN
A QQCPUT RENAME(QQI1) +
COLHDG('Record' +
'Retrieval' +
'CPU Time')
A QQCLKT RENAME(QQI2) +
COLHDG('Record' +
'Retrieval' +
'Clock Time')
A QQSYNR RENAME(QQI3) +
COLHDG('Synch' +
'Reads')
A QQSYNW RENAME(QQI4) +
COLHDG('Synch' +
'Writes')
A QQASYR RENAME(QQI5) +
COLHDG('Asynch' +
'Reads')
A QQASYW RENAME(QQI6) +
COLHDG('Asynch' +
'Writes')
A QQRCDR RENAME(QQI7) +
COLHDG('Records' +
'Returned')
A QQGETC RENAME(QQI8) +
COLHDG('Number' +
'of GETs')
A K QQJFLD
A S QQRID CMP(EQ 3019)

Figure 32. Detail record for Records Retrieved

Table 58. QQQ3019 - Detail record for Records Retrieved


Logical Field Name Physical Field Name Description
QQRID QQRID Record identification
QQTIME QQTIME Time record was created
QQJFLD QQJFLD Join field (unique per job)
QQRDBN QQRDBN Relational database name
QQSYS QQSYS System name
QQJOB QQJOB Job name

Chapter 26. Monitoring and Optimizing Query Performance Tools 523


Table 58. QQQ3019 - Detail record for Records Retrieved (continued)
Logical Field Name Physical Field Name Description
QQUSER QQUSER Job user
QQJNUM QQJNUM Job number
QQTHRD QQI9 Thread identifier
QQUCNT QQUCNT Unique count (unique per query)
QQUDEF QQUDEF User defined field
QQQDTN QQQDTN QDT number (unique per query)
QQQDTL QQQDTL QDT subquery nested level
QQMATN QQMATN Materialized view QDT number
QQMATL QQMATL Materialized view nested level
QQCPUT QQI1 CPU time to return all records, in milliseconds
QQCLKT QQI2 Clock time to return all records, in milliseconds
QQSYNR QQI3 Number of synchronous database reads
QQSYNW QQI4 Number of synchronous database writes
QQASYR QQI5 Number of asynchronous database reads
QQASYW QQI6 Number of asynchronous database writes
QQRCDR QQI7 Number of records returned
QQGETC QQI8 Number of calls to retrieve records returned

Memory Resident Database Monitor APIs


The Memory Resident Database Monitor (DBMon) is a tool that provides another
method for monitoring database performance. This tool is only intended for SQL
performance monitoring and is useful for programmers and performance analysts.
The DBMon monitor, with the help of a new set of APIs, takes database monitoring
statistics and manages them for the user in memory. This memory-based monitor
reduces CPU overhead as well as resulting file sizes.

The Start Database Monitor (STRDBMON) can constrain system resources when
collecting performance information. This overhead is mainly attributed to the fact
that performance information is written directly to a database file as the information
is collected. The memory-based collection mode reduces the system resources
consumed by collecting and managing performance results in memory. This allows
the monitor to gather database performance statistics with a minimal impact to the
performance of the system as whole (or to the performance of individual SQL
statements).

The DBMon monitor collects much of the same information as the STRDBMON
monitor, but the performance statistics are kept in memory. At the expense of some
detail, information is summarized for identical SQL statements to reduce the amount
of information collected. The objective is to get the statistics to memory as fast as
possible while deferring any manipulation or conversion of the data until the
performance data is dumped to a result file for analysis.

524 DB2 UDB for AS/400 SQL Programming V4R4


The DBMon monitor is not meant to replace the STRDBMON monitor. There are
circumstances where the loss of detail in the DBMon monitor will not be sufficient to
fully analyze an SQL statement. In these cases, the STRDBMON monitor should
still be used.

The DBMon monitor manages the data in memory combining and accumulating the
information into a series of record formats. This means that for each unique SQL
statement, information is accumulated from each run of the statement and the detail
information is only collected for the most expensive statement execution.

Each SQL statement is identified by the monitor according to the:


v statement name
v package (or program)
v library that contains the prepared statement
v cursor name that is used
For pure dynamic statements, the statement text is kept in a separate space and
the statement identification will be handled internally via a pointer.

| A new set of APIs enable support for the DBMon monitor. An API supports each of
| the following activities:
| v Start the new monitor
| v Dump statistics to files
| v Clear the monitor data from memory
| v Query the monitor status
| v End the new monitor
| When you start the new monitor, information is stored in the local address space of
| each job that the system monitors. As each statement completes, the system
| moves information from the local job space to a common system space. If more
| statements are executed than can fit in this amount of common system space, the
| system drops the statements that have not been executed recently.

External API Description


The memory resident database monitor is controlled by a set of APIs. For additional
information, see the System API Reference manual.
Table 59. External API Description
QQQSSDBM API to start the SQL monitor
QQQCSDBM API to clear SQL monitor memory
QQQDSDBM API to dump the contents of the SQL monitor
to file
QQQESDBM API to end the SQL monitor
QQQQSDBM API to query status of the database monitor

External File Description


The memory resident database monitor uses its own set of physical files instead of
using the single physical with logical files that the STRDBMON monitor uses. The
memory resident database monitor files closely match the suggested logical files of
the STRDBMON monitor.

Chapter 26. Monitoring and Optimizing Query Performance Tools 525


Table 60. External File Description
QAQQQRYI Query (SQL) information
QAQQTEXT SQL statement text
QAQQ3000 Table scan
QAQQ3001 Index used
QAQQ3002 Index created
QAQQ3003 Sort
QAQQ3004 Temporary file
QAQQ3007 Optimizer time out/ all access paths
considered
QAQQ3008 Subquery
QAQQ3010 Host variable values

The information relating to the locked tables (QQQ3005) was omitted and the
replan information was combined with the QAQQQRYI, and QQQ3010 (ODP and
host variable information) is found in both QAQQ3010 and QAQQQRYI files.

External File Description (QAQQQRYI)


Table 61. QAQQQRYI - Summary Record for SQL Information
Column Name Description
QQKEY Join field (unique per query) used to link records for a single query together
QQTIME Time record was created
QQJOB Job name
QQUSER Job user
QQJNUM Job number
QQTHID Thread Id
QQUDEF User defined field
QQPLIB Name of the library containing the program or package
QQPNAM Name of the package or name of the program that contains the current SQL
statement
QQSNAM Name of the sttement for SQL statement, if applicable
QQCNT Statement usage count
QQAVGT Average runtime (ms)
QQMINT Minimum runtime (ms)
QQMAXT Maximum runtime (ms)
QQOPNT Open time for most expensive execution (ms)
QQFETT Fetch time for most expensive execution (ms)
QQCLST Close time for most expensive execution (ms)
QQOTHT Other time for most expensive execution (ms)
QQLTU Time statement last used
QQMETU Most expensive time used
QQAPRT Access plan rebuild time
QQFULO Number of full opens
QQPSUO Number of pseudo-opens

526 DB2 UDB for AS/400 SQL Programming V4R4


Table 61. QAQQQRYI - Summary Record for SQL Information (continued)
Column Name Description
QQTOTR Total rows in file if non-join
QQRROW Number of result rows returned
QQRROW Statement function
S - SelectU - Update
I - Insert
D - Delete
L - Data definition language
O - Other
QQSTOP Statement operation
AL - Alter table
CA - Call
CC - Create collection or Create schema
CD - Create distinct type
CF - Create function
CI - Create index
CL - Close
CO - Comment on
CM - Commit
CN - Connect
CP - Create procedure
CS - Create alias
CT - Create table
CV - Create view
DC- Declare cursor
DP - Declare procedure
DL - Delete
DE - Describe
DT - Describe table
DI - Disconnect
DR - Drop
EX - Execute
EI - Execute immediate
FE - Fetch
FC - Fetch/Close
FL - Free locator
GR - Grant
IN - Insert
LO - Label on
LK - Lock
OP - Open
OC - Open/Fetch/Close
OD - Open/Fetch/Close/Delete
OF - Open/Fetch
OU - Open/Fetch/Close/Update
PR - Prepare
RE - Release
RT - Rename table
RV - Revoke
RO - Rollback
SI - Select into
SC - Set connection
SV - Set variable
SP - Set path
SR - Set results
ST - Set transaction
UP - Update

Chapter 26. Monitoring and Optimizing Query Performance Tools 527


Table 61. QAQQQRYI - Summary Record for SQL Information (continued)
Column Name Description
QQODPI ODP implementation
R - Reusable ODP (ISV)
N - Non-reusable ODP (V2)
QQHVI Host variable implementation
I - Interface supplied values (ISV)
V - Host variables treated as literals (V2)
U - File management row positioning (UP)
QQAPR Access plan rebuilt
A1 A file or member is not the same object as the one referenced when the
access plan was last built. Some reasons they could be different are:
v Object was deleted and recreated.
v Object was saved and restored.
v Library list was changed.
v Object was renamed.
v Object was moved.
v Object was overridden to a different object.
v This is the first run of this query after the object containing the query has
been restored.
A2 Access plan was built to use a reusable Open Data Path (ODP) and the
optimizer chose to use a non-reusable ODP for this call.
A3 Access plan was built to use a non-reusable Open Data Path (ODP) and the
optimizer chose to use a reusable ODP for this call.
A4 The number of records in the file member has changed by more than 10%
since the access plan was last built.
A5 A new access path exists over one of the files in the query.
A6 An access path that was used for this access plan no longer exists or is no
longer valid.
A7 OS/400 Query requires the access plan to be rebuilt because of system
programming changes.
A8 The CCSID of the current job is different than the CCSID of the job that last
created the access plan.
A9 The value of one or more of the following is different for the current job than it
was for the job that last created this access plan:
v date format
v date separator
v time format
v time separator

528 DB2 UDB for AS/400 SQL Programming V4R4


Table 61. QAQQQRYI - Summary Record for SQL Information (continued)
Column Name Description

AA The sort sequence table specified is different than the sort sequence table that
was used when this access plan was created.
AB Storage pool changed or DEGREE parameter of CHGQRYA command
changed.
AC The system feature DB2 multisystem has been installed or removed.
AD The value of the degree query attribute has changed.
AE A view is either being opened by a high level language or a view is being
materialized.
AF A user-defined type or user-defined function is not the same object as the one
referred to in the access plan.
B0 The options specified have changed as a result of the query options file
QAQQINI.

QQDACV Data conversion


N No.
0 Not applicable.
1 Lengths do not match.
2 Numeric types do not match.
3 C host variable is NUL-terminated.
4 Host variable or column is variable length and the other s not variable length.
5 CCSID conversion.
6 DRDA and NULL capable, variable ength, contained in a partial row, derived
expression, or blocked fetch with not enough host variables.
7 Data, time, or timestamp column.
8 Too many host variables.
9 Target table of an insert is not an SQL table.

QQCTS Statement table scan usage count


QQCIU Statement index usage count
QQCIC Statement index creation count
QQCSO Statement sort usage countr
QQCTF Statement temporary file count
QQCIA Statement index advised count
QQCAPR Statement access plan rebuild count
QQARSS Average result set size
QQC11 Statement temporary file count
QQCTS Reserved
QQC12 Reserved
QQC21 Reserved
QQC22 Reserved
QQI1 Reserved

Chapter 26. Monitoring and Optimizing Query Performance Tools 529


Table 61. QAQQQRYI - Summary Record for SQL Information (continued)
Column Name Description
QQI2 Reserved
QQC301 Reserved
QQC302 Reserved
QQC1000 Reserved

External File Description (QAQQTEXT)


Table 62. QAQQTEXT - Summary Record for SQL Statement
Column Name Description
QQKEY Join field (unique per query) used to link records for a single query
togetherecord identification
QQTIME Time record was created
QQSTTX Statement text
QQC11 Reserved
QQC12 Reserved
QQC21 Reserved
QQC22 Reserved
QQQI1 Reserved
QQI2 Reserved
QQC301 Reserved
QQC302 Reserved
QQ1000 Reserved

External File Description (QAQQ3000)


Table 63. QAQQ3000 - Summary Record for Arrival Sequence
Column Name Description
QQKEY Join field (unique per query) used to link records for a single query
togetherecord identification
QQTIME Time record was created
QQQDTN QDT number (unique per ODT)
QQQDTL QDT subquery nested level
QQMATN Materialized view QDT number
QQMATL Materialized view nested level
QQTLN Physical library
QQPTFN Physical file
QQTOTR Total rows in table
QQREST Estimated number of rows selected
QQAJN Estimated number of joined rows
QQEPT Estimated procesing time, in seconds
QQJNP Join position - when available
QQJNDS Data space number

530 DB2 UDB for AS/400 SQL Programming V4R4


Table 63. QAQQ3000 - Summary Record for Arrival Sequence (continued)
Column Name Description
QQJNMT Join method - when available
NL - Nested loop
MF - Nested loop with selection
HJ - Hash join
QQJNTY Join type - when available
IN - Inner join
PO - Left partial outer join
EX - Exception join
QQJNOP Join operator - when available
EQ - Equal
NE - Not equal
GT - Greater than
GE - Greater than or equal
LT - Less than
LE - Less than or equal
CP - Cartesian product
QQDSS Data space selection
Y - Yes
N - No
QQIDXA Index advised
Y - Yes
N - No
QQRCOD Reason code
T1 - No indexes exist.
T2 - Indexes exist, but none could be used.
T3 - Optimizer chose table scan over available indexes.
QQLTLN Library-long
QQLTFN File-long
QQLPTL Physical library-long
QQLPTF Physical file-long
QQIDXD Key fields for the index advised
QQC11 Reserved
QQC12 Reserved
QQC21 Reserved
QQC22 Reserved
QQI1 Reserved
QQI2 Reserved
QQC301 Reserved
QQC302 Reserved
QQ1000 Reserved

External File Description (QAQQ3001)


Table 64. QQQ3001 - Summary Record for Using Existing Index
Column Name Description
QQKEY Join field (unique per query) used to link records for a single query together
QQTIME Time record was created

Chapter 26. Monitoring and Optimizing Query Performance Tools 531


Table 64. QQQ3001 - Summary Record for Using Existing Index (continued)
Column Name Description
QQQDTN QDT number (unique per QDT)
QQQDTL RQDT subquery nested levelelational database name
QQMATN Materialized view QDT number
QQMATL Materialized view nested level
QQTLN Library
QQTFN File
QQILNM Index library
QQIFNM Index file
QQTOTR Total rows in table
QQREST Estimated number of rows selected
QQAJN Join position - when available
QQEPT Estimated procesing time, in seconds
QQJNMT Join method - when available
NL - Nested loop
MF - Nested loop with selection
HJ - Hash join
QQJNTY Join type - when available
IN - Inner join
PO - Left partial outer join
EX - Exception join
QQJNOP Join operator - when available
EQ - Equal
NE - Not equal
GT - Greater than
GE - Greater than or equal
LT - Less than
LE - Less than or equal
CP - Cartesian product
QQIDXK Number of advised key fields that use key positioning
QQKP Key positioning
Y - Yes
N - No
QQKS Key selection
Y - Yes
N - No
QQDSS Data space selection
Y - Yes
N - No
QQIDXA Index advised
Y - Yes
N - No

532 DB2 UDB for AS/400 SQL Programming V4R4


Table 64. QQQ3001 - Summary Record for Using Existing Index (continued)
Column Name Description
QQRCOD Reason code
I1 - Record selection
I2 - Ordering/Grouping
I3 - Record selection and
Ordering/Grouping
I4 - Nested loop join
I5 - Record selection using
bitmap processing
QQCST Constraint indicator
Y - Yes
N - No
QQCSTN Constraint name
QQLTLN Library-long
QQLTFN File-long
QQLPTL Physical library-long
QQLPTF Physical file-long
QQIDXD Key fields for the index advised
QQC11 Reserved
QQC12 Reserved
QQC21 Reserved
QQC22 Reserved
QQI1 Reserved
QQI2 Reserved
QQC301 Reserved
QQC302 Reserved
QQ1000 Reserved

External File Description (QAQQ3002)


Table 65. QQQ3002 - Summary Rrecord for Index Created
Column Name Description
QQKEY Join field (unique per query) used to link records for a single query together
QQTIME Time record was created
QQQDTN QDT number (unique per QDT)
QQQDTL RQDT subquery nested levelelational database name
QQMATN Materialized view QDT number
QQMATL Materialized view nested level
QQTLN Library
QQTFN File
QQILNM Index library
QQIFNM Index file
QQNTNM NLSS table
QQNLNM NLSS library
QQTOTR Total rows in table

Chapter 26. Monitoring and Optimizing Query Performance Tools 533


Table 65. QQQ3002 - Summary Rrecord for Index Created (continued)
Column Name Description
QQRIDX Number of entries in index created
QQREST Estimated number of rows selected
QQFKEY Number of key positioning keys
QQKSEL Number of key selection keys
QQAJN Estimated number of joined rows
QQJNP Join position - when available
QQJNDS Data space number
QQJNMT Join method - when available
NL - Nested loop
MF - Nested loop with selection
HJ - Hash join
QQJNTY Join type - when available
IN - Inner join
PO - Left partial outer join
EX - Exception join
QQJNOP Join operator - when available
EQ - Equal
NE - Not equal
GT - Greater than
GE - Greater than or equal
LT - Less than
LE - Less than or equal
CP - Cartesian product
QQIDXK Number of advised key fields that use key positioning
QQEPT Estimated procesing time, in seconds
QQKP Key positioning
Y - Yes
N - No
QQKPN Number of key positioning fields
QQKS Key selection
Y - Yes
N - No
QQDSS Data space selection
Y - Yes
N - No
QQIDXA Index advised
Y - Yes
N - No
QQRCOD Reason code
I1 - Record selection
I2 - Ordering/Grouping
I3 - Record selection and
Ordering/Grouping
I4 - Nested loop join
I5 - Record selection using
bitmap processing
QQCST Constraint indicator
Y - Yes
N - No

534 DB2 UDB for AS/400 SQL Programming V4R4


Table 65. QQQ3002 - Summary Rrecord for Index Created (continued)
Column Name Description
QQCSTN Constraint name
QQTTIM Index create time
QQLTLN Library-long
QQLTFN File-long
QQLPTL Physical library-long
QQLPTF Physical file-long
QQLILN Index library-long
QQLIFN Index file-long
QQLNTN NLSS table-long
QQLNLN NLSS library-long
QQIDXD Key fields for the index advised
QQCRTK Key fields for index created
QQC11 Reserved
QQC12 Reserved
QQC21 Reserved
QQC22 Reserved
QQI1 Reserved
QQI2 Reserved
QQC301 Reserved
QQC302 Reserved
QQ1000 Reserved

External File Description (QAQQ3003)


Table 66. QQQ3003 - Summary Record for Query Sort
Column Name Description
QQKEY Join field (unique per query) used to link records for a single query together
QQTIME Time record was created
QQQDTN QDT number (unique per QDT)
QQQDTL RQDT subquery nested levelelational database name
QQMATN Materialized view QDT number
QQMATL Materialized view nested level
QQTTIM Sort time
QQRSS Number of rows selected or sorted
QQSIZ Size of sort space
QQPSIZ Pool size
QQPID Pool id
QQIBUF Internal sort buffer length
QQEBUF External sort buffer length

Chapter 26. Monitoring and Optimizing Query Performance Tools 535


Table 66. QQQ3003 - Summary Record for Query Sort (continued)
Column Name Description
QQRCOD Reason code
F1 Query contains grouping fields (Group By) from more than one file, or contains
grouping fields from a secondary file of a join query that cannot be reordered.
F2 Query contains ordering fields (Order By) from more than one file, or contains
ordering fields from a secondary file of a join query that cannot be reordered.
F3 The grouping and ordering fields are not compatible.
F4 DISTINCT was specified for the query.
F5 UNION was specified for the query.
F6 Query had to be implemented using a sort. Key length of more than 2000
bytes or more than 120 fields specified for ordering.
F7 Query optimizer chose to use a sort rather than an access path to order the
results of the query.
F8 Perform specified record selection to minimize I/O wait time.

QQC11 Reserved
QQC12 Reserved
QQC21 Reserved
QQC22 Reserved
QQI1 Reserved
QQI2 Reserved
QQC301 Reserved
QQC302 Reserved
QQ1000 Reserved

External File Description (QAQQ3004)


Table 67. QQQ3004 - Summary Record for Temporary File
Column Name Description
QQKEY Join field (unique per query) used to link records for a single query together
QQTIME Time record was created
QQQDTN QDT number (unique per QDT)
QQQDTL RQDT subquery nested levelelational database name
QQMATN Materialized view QDT number
QQMATL Materialized view nested level
QQTLN Library
QQTFN File
QQTTIM Temporary file create time
QQTMPR Number of rows in temporary

536 DB2 UDB for AS/400 SQL Programming V4R4


Table 67. QQQ3004 - Summary Record for Temporary File (continued)
Column Name Description
QQRCOD Reason code
F1 Query contains grouping fields (Group By) from more than one file, or contains
grouping fields from a secondary file of a join query that cannot be reordered.
F2 Query contains ordering fields (Order By) from more than one file, or contains
ordering fields from a secondary file of a join query that cannot be reordered.
F3 The grouping and ordering fields are not compatible.
F4 DISTINCT was specified for the query.
F5 UNION was specified for the query.
F6 Query had to be implemented using a sort. Key length of more than 2000
bytes or more than 120 fields specified for ordering.
F7 Query optimizer chose to use a sort rather than an access path to order the
results of the query.
F8 Perform specified record selection to minimize I/O wait time.
F9 File is a JLF and its join type does not match the join type specified in the
query.
FA Format specified for the logical file references more than one physical file.
FB File is a complex SQL view requiring a temporary file to contain the results of
the SQL view.

QQDFVL Default values may be present in temporary


Y - Yes
N - No
QQLTLN Library-long
QQLTFN File-long
QQC11 Reserved
QQC12 Reserved
QQC21 Reserved
QQC22 Reserved
QQI1 Reserved
QQI2 Reserved
QQC301 Reserved
QQC302 Reserved
QQ1000 Reserved

External File Description (QAQQ3007)


Table 68. QQQ3007 - Summary Record for Optimizer Information
Column Name Description
QQKEY Join field (unique per query) used to link records for a single query together
QQTIME Time record was created
QQQDTN QDT number (unique per QDT)
QQQDTL RQDT subquery nested levelelational database name
QQMATN Materialized view QDT number

Chapter 26. Monitoring and Optimizing Query Performance Tools 537


Table 68. QQQ3007 - Summary Record for Optimizer Information (continued)
Column Name Description
QQMATL Materialized view nested level
QQTLN Library
QQTFN File
QQPTLN Physical library
QQPTFN Physical file
QQTOUT Optimizer timed out
Y - Yes
N - No.
QQIRSN Reason code
QQLTLN Library-long
QQLTFN File-long
QQPTL Physical library-long
QQPTF Physical file-long
QQIDXN Index names
QQC11 Reserved
QQC12 Reserved
QQC21 Reserved
QQC22 Reserved
QQI1 Reserved
QQI2 Reserved
QQC301 Reserved
QQC302 Reserved
QQ1000 Reserved

External File Description (QAQQ3008)


Table 69. QQQ3008 - Summary Record for Subquery Processing
Column Name Description
QQKEY Join field (unique per query) used to link records for a single query together
QQTIME Time record was created
QQQDTN QDT number (unique per QDT)
QQQDTL RQDT subquery nested levelelational database name
QQMATN Materialized view QDT number
QQMATL Materialized view nested level
QQORGQ Materialized view QDT number
QQMRGQ Materialized view nested level
QQC11 Reserved
QQC12 Reserved
QQC21 Reserved
QQC22 Reserved
QQI1 Reserved
QQI2 Reserved

538 DB2 UDB for AS/400 SQL Programming V4R4


Table 69. QQQ3008 - Summary Record for Subquery Processing (continued)
Column Name Description
QQC301 Reserved
QQC302 Reserved
QQ1000 Reserved

External File Description (QAQQ3010)


Table 70. QQQ3010 - Summary Record for Host Variable and ODP Implementation
Column Name Description
QQKEY Join field (unique per query) used to link records for a single query together
QQTIME Time record was created
QQHVAR Host variable values
QQC11 Reserved
QQC12 Reserved
QQC21 Reserved
QQC22 Reserved
QQI1 Reserved
QQI2 Reserved
QQC301 Reserved
QQC302 Reserved

Sample SQL Queries


| As with the STRDBMON monitor, it is up to the user to extract the information from
| the files in which all of the monitored data is stored. This can be done through any
| query interface that the user wishes.

| If you are using Operation Navigator with the support for the SQL Monitor, you have
| the ability to analyze the results direct through the GUI interface. There are a
| number of shipped queries that can be used or modified to extract the information
| from any of the files.

| The sample query listed below will give the user the Basic Statement Information
| about all of the statements that were monitored.
| SELECT
| /* Database Performance Monitor Basic Statement Information */
|
| /* Time */
| a.QQTIME as "Time",
|
| /* Costs */
| DECIMAL(QQMAXT/1000,18,3) as "Maximum Runtime",
| DECIMAL(QQAVGT/1000,18,3) as "Average Runtime",
| DECIMAL(QQMINT/1000,18,3) as "Minimum Runtime",
| DECIMAL(QQOPNT/1000,18,3) as "Maximum Open Time",
| DECIMAL(QQFETT/1000,18,3) as "Maximum Fetch Time ",
| DECIMAL(QQCLST/1000,18,3) as "Maximum Close Time",
| DECIMAL(QQOTHT/1000,18,3) as "Maximum Other Time ",
| QQMETU as "Most Expensive Use",
| QQLTU as "Last Use",
|
| /* Statement Identification */
| CASE QQSTOP

Chapter 26. Monitoring and Optimizing Query Performance Tools 539


| WHEN 'AL' THEN 'ALTER TABLE'
| WHEN 'CA' THEN 'CALL'
| WHEN 'CD' THEN 'CREATE DISTINCT TYPE'
| WHEN 'CF' THEN 'CREATE FUNCTION'
| WHEN 'CL' THEN 'CLOSE'
| WHEN 'CO' THEN 'COMMENT ON'
| WHEN 'CM' THEN 'COMMIT'
| WHEN 'CN' THEN 'CONNECT'
| WHEN 'CC' THEN 'CREATE COLLECTION'
| WHEN 'CI' THEN 'CREATE INDEX'
| WHEN 'CP' THEN 'CREATE PROCEDURE'
| WHEN 'CS' THEN 'CREATE ALIAS'
| WHEN 'CT' THEN 'CREATE TABLE'
| WHEN 'CV' THEN 'CREATE VIEW'
| WHEN 'DC' THEN 'DECLARE CURSOR'
| WHEN 'DD' THEN 'DELETE...DELETE'
| WHEN 'DE' THEN 'DESCRIBE'
| WHEN 'DF' THEN 'DELETE...FETCH'
| WHEN 'DI' THEN 'DISCONNECT'
| WHEN 'DK' THEN 'DELETE...CLOSE'
| WHEN 'DL' THEN 'DELETE'
| WHEN 'DP' THEN 'DECLARE PROCEDURE'
| WHEN 'DR' THEN 'DROP'
| WHEN 'DT' THEN 'DESCRIBE TABLE'
| WHEN 'DU' THEN 'DELETE...UPDATE'
| WHEN 'EX' THEN 'EXECUTE'
| WHEN 'EI' THEN 'EXECUTE IMMEDIATE'
| WHEN 'FC' THEN 'FETCH...CLOSE'
| WHEN 'FD' THEN 'FETCH...DELETE'
| WHEN 'FE' THEN 'FETCH'
| WHEN 'FF' THEN 'FETCH...FETCH'
| WHEN 'FL' THEN 'FREE LOCATOR'
| WHEN 'FU' THEN 'FETCH...UPDATE'
| WHEN 'GR' THEN 'GRANT'
| WHEN 'IC' THEN 'INSERT'
| WHEN 'IN' THEN 'INSERT'
| WHEN 'LO' THEN 'LABEL ON'
| WHEN 'LK' THEN 'LOCK'
| WHEN 'OC' THEN 'OPEN...CLOSE'
| WHEN 'OD' THEN 'OPEN...DELETE'
| WHEN 'OF' THEN 'OPEN...FETCH'
| WHEN 'OP' THEN 'OPEN'
| WHEN 'OU' THEN 'OPEN...UPDATE'
| WHEN 'PR' THEN 'PREPARE'
| WHEN 'RE' THEN 'RELEASE'
| WHEN 'RO' THEN 'ROLLBACK'
| WHEN 'RT' THEN 'RENAME'
| WHEN 'RV' THEN 'REVOKE'
| WHEN 'SC' THEN 'SET CONNECTION'
| WHEN 'SI' THEN 'SELECT INTO'
| WHEN 'SK' THEN 'SELECT INTO'
| WHEN 'SP' THEN 'SET PATH'
| WHEN 'SR' THEN 'SET RESULTS'
| WHEN 'ST' THEN 'SET TRANSACTION'
| WHEN 'SV' THEN 'SET VARIABLE'
| WHEN 'UC' THEN 'UPDATE...CLOSE'
| WHEN 'UD' THEN 'UPDATE...DELETE'
| WHEN 'UF' THEN 'UPDATE...FETCH'
| WHEN 'UP' THEN 'UPDATE'
| WHEN 'UU' THEN 'UPDATE...UPDATE'
| ELSE QQSTOP
| END as "Operation",
| QQCNT as "Statement Usage Count ",
| varchar(b.QQSTTX,20000) as "Statement Text",
| varchar(qqhvar,500) as "Host Variable Values",
|
| /* Opens */

540 DB2 UDB for AS/400 SQL Programming V4R4


| QQFULO as "Full Opens",
| QQPSUO as "Pseudo Opens",
|
| /* Row Sizes */
| QQTOTR as "Table Rows",
| QQRROW as "Result Rows",
| QQARSS as "Average Result Size",
|
| /* Implementation */
| CASE QQODPI
| WHEN 'R' THEN 'Reusable'
| WHEN 'N' THEN 'Non-Reusable'
| ELSE QQODPI
| END as "ODP Implementation",
|
| CASE QQHVI
| WHEN 'I' THEN 'ISV'
| WHEN 'V' THEN 'V2'
| WHEN 'U' THEN 'UP'
| ELSE QQHVI
| END as "Host Variable Implementation",
|
| CASE QQDACV
| WHEN 'N' THEN NULL
| WHEN '0' THEN NULL
| WHEN '1' THEN 'Different Lengths'
| WHEN '2' THEN 'Different Numeric Types'
| WHEN '3' THEN 'C NUL-terminated Variable'
| WHEN '4' THEN 'Varying Length Fixed Length'
| WHEN '5' THEN 'CCSID Conversion'
| WHEN '6' THEN 'DRDA Mapping Required'
| WHEN '7' THEN 'Datetime Column'
| WHEN '8' THEN 'Too Many Host Variables'
| WHEN '9' THEN 'Target Table Is Not A SQL Table'
| ELSE QQDACV
| END as "Data Conversion",
| QQCTS as "Table Scan Count",
|
| /* Index Information */
| QQCIU as "Index Use Count",
| QQCIC as "Index Create Count",
| QQCIA as "Index Advised Count",
|
| /* Copy of data */
| QQCTF as "Temporary Table Count",
| QQCSO as "Sort Count",
|
| /* Access Plan Rebuild */
| QQAPRT as "Last Access Plan Rebuilt",
| QQCAPR as "Access Plan Rebuild Count",
|
| CASE QQAPR
| WHEN 'A1' THEN 'Different File Or Member'
| WHEN 'A2' THEN 'Reusable Plan to Non-Reusable Plan Change'
| WHEN 'A3' THEN 'Non-Reusable To Reusable Plan Change'
| WHEN 'A4' THEN 'More Than Ten Percent Change In Number Of Rows'
| WHEN 'A5' THEN 'New Access Path Found'
| WHEN 'A6' THEN 'Access Path No Longer Found Or Valid'
| WHEN 'A7' THEN 'System Programming Change'
| WHEN 'A8' THEN 'Different CCSID'
| WHEN 'A9' THEN 'Different Date Or Time Format'
| WHEN 'AA' THEN 'Different Sort Sequence Table'
| ELSE QQAPR
| END as "Access Plan Rebuild Reason",
|
| /* Job-user-program identification */
| QQJOB as "Job",

Chapter 26. Monitoring and Optimizing Query Performance Tools 541


| QQUSER as "Job User",
| QQJNUM as "Job Number",
| QQTHID as "Thread ID",
| QQPLIB as "Program Library",
| QQPNAM as "Program",
|
| /* Statement attributes */
| QQUDEF as "User Defined Field",
| QQCNAM as "Cursor",
| QQSNAM as "Statement Name"
|
| FROM <> a left join <> b on a.qqkey=b.qqkey
| left join <> c on a.qqkey=c.qqkey
|
| ORDER BY "Maximum Runtime" DESC

| Record Identification
| A new join key field has been generated (QQKEY) to ease joining multiple physical
| files together. This field replaces the job (QQJOB) and unique query counters
| (QQCNT) that the existing database monitor used. The join key field contains a
| unique identifier that allows all of the information for this query to be received from
| each of the physical files.

| This join key field does not replace all of the detail fields that are still required to
| identify the specific information about the individual steps of a query. The Query
| Definition templte (QDT) Number or the Subselect Number identifies information
| about each detailed step. Use these fields to identify which records belong to each
| step of the query process:
| v QQQDTN - Query Definition Template Number
| v QQQDTL - Query Definition Template Subselect Number (Subquery)
| v QQMATN - Materialized Query Definition Tempalte Number (View)
| v QQMATL - Materialized Query Definition Template Subselect Number (View w/
| Subquery)
| Use these fields when the monitored query contains a subquery, union, or a view
| operation. All query types can generate multiple QDT’s to satisfy the original query
| request. The system uses these fields to separate the information for each QDT
| while still allowing each QDT to be identified as belonging to this original query
| (QQKEY).

Comparison table of query optimization tools


PRTSQLINF STRDBG/CHGQRYA STRDBMON Memory-Based
Monitor
Available without Only available when Only available when Onlly available when
running query (after the query is run the query is run the query is run
access plan has been
created)
Displayed for all Displayed only for Displayed only for Displayed only for
queries in SQL those queries which those queries which those queries which
program, whether are executed are executed are executed
executed or not
Information on host Limited information All information on All information on
variable on the host variables, host variables,
implementation implementation of implementation, and implementation, and
host variables values values

542 DB2 UDB for AS/400 SQL Programming V4R4


PRTSQLINF STRDBG/CHGQRYA STRDBMON Memory-Based
Monitor
Available only to SQL Available to all query Available to all query Available only to SQL
users with programs, users (OPNQRYF, users (OPNQRYF, interfaces
packages, or service SQL, QUERY/400) SQL, QUERY/400)
programs
Messages printed to Messages displayed Performance records Performance
spool file in job log written to database information collected
file in memory and then
written to database
file
Easier to tie Difficult to tie Uniquely identifies Repeated query
messages to query messages to query every query requests are
with subqueries or with subqueries or summarized
unions unions

Change query attributes


| You can modify different types of attributes of queries that you will execute during a
| certain job with the CHGQRYA command. The types of attributes that you can
| modify include:
| v Predictive Query Governor
| v Query Parallelism
| v Asynchronous Job
| v Apply CHGQRYA to remote

| Before the system intitiates a query, the system checks the query time limit against
| the estimated elapsed query time. The system also uses a time limit of zero to
| optimize performance on queries without having to run through several iterations.

| You can check the inquiry message CPA4259 for the predicted runtime and for what
| operations the query will perform. If the query is cancelled, debug messages will be
| written to the joblog.

| The “Chapter 23. Using the DB2 UDB for AS/400 Predictive Query Governor” on
| page 391 can stop the initiation of a query if the query’s estimated or predicted
| runtime (elapsed execution time) is excessive. The governor acts before a query is
| run instead of while a query is run. The governor can be used in any interactive or
| batch job on the AS/400. It can be used with all DB2 UDB for AS/400 query
| interfaces and is not limited to use with SQL queries.

Query Options File QAQQINI


The query options file QAQQINI support provides the ability to dynamically modify
or override the environment in which queries are executed through the CHGQRYA
command and the QAQQINI file.

The query options file QAQQINI is used to set the attributes used by the Query
Optimizer. For each query that is run the query option values are retrieved from the
QAQQINI file in the library specified on the QRYOPTLIB parameter of the
CHGQRYA CL command and used to optimize or implement the query.

Chapter 26. Monitoring and Optimizing Query Performance Tools 543


| Environmental attributes that you can modify through the QAQQINI file include:
| v APPLY_REMOTE
| v ASYNC_JOB_USAGE
| v FORCE_ORDER_JOIN
| v MESSAGES_DEBUG
| v OPTIMIZE_STATISTIC_LIMITATION
| v PARALLEL_DEGREE
| v PARAMETER_MARKER_CONVERSION
| v QUERY_TIME_LIMIT
| v UDF_TIME_OUT

| Specifying the QAQQINI file


| CHGQRYA (Change Query Attributes) CL command has a parameter QRYOPTLIB
| (query options library) which allows the user to specify which library currently
| contains or will contain the query options file QAQQINI. The query options file will
| be retrieved from the library specified on the QRYOPTLIB parameter for each query
| and remains in effect for the duration of the job or user session, or until the
| QRYOPTLIB parameter is changed by the CHGQRYA command.

If no library is specified for this parameter, then the library QUSRSYS is searched
for the existence of the QAQQINI file. If a query options file is not found for a query,
no attributes will be modified. The initial value of the QRYOPTLIB parameter for a
job is QUSRSYS.

Creating the QAQQINI Query Options File


| ach system is shipped with a QAQQINI template file in library QSYS. The QAQQINI
| file in QSYS is to be used as a template when creating all user specified QAQQINI
| files. To create your own QAQQINI file use the CRTDUPOBJ CL command to
| create a copy of the QAQQINI file into the library which will be specified on the
| CHGQRYA QRYOPTLIB parameter. The filename must remain QAQQINI, for
| example:
| CRTDUPOBJ OBJ(QAQQINI)
| FROMLIB(QSYS)
| OBJTYPE(*FILE)
| TOLIB(MYLIB)
| DATA(*YES)

| Because system-supplied triggers are attached to the QAQQINI file in QSYS it is


| imperative that the only means of copying the QAQQINI file is through the
| CRTDUPOBJ CL command.

Note: It is recommended that the file QAQQINI, in QSYS, not be modified. This is
the original template that is to be duplicated into QUSRSYS or a user
specified library for use.

QAQQINI Query Options File Format


Query Options File:
UNIQUE
R QAQQINI TEXT('Query options + file')

QQPARM 256A VARLEN(10) +

544 DB2 UDB for AS/400 SQL Programming V4R4


TEXT('Query +
option parameter') +
COLHDG('Parameter')
QQVAL 256A VARLEN(10) +
TEXT('Query option +
parameter value') +
COLHDG('Parameter Value')
QQTEXT 1000G VARLEN(100) +
TEXT('Query +
option text') +
ALWNULL +
COLHDG('Query Option' +
'Text') +
CCSID(13488) +
DFT(*NULL)
K QQPARM

| The QAQQINI file shipped in the library QSYS has been pre-populated with the
| following records:
Table 71. QAQQINI File Records. Description
QQPARM QQVAL
APPLY_REMOTE *DEFAULT
ASYNC_JOB_USAGE *DEFAULT
FORCE_JOIN_ORDER *DEFAULT
MESSAGES_DEBUG *DEFAULT
OPTIMIZE_STATISTIC_LIMITATION *DEFAULT
PARALLEL_DEGREE *DEFAULT
PARAMETER_MARKER_CONVERSION *DEFAULT
QUERY_TIME_LIMIT *DEFAULT
UDF_TIME_OUT *DEFAULT

Setting the Options within the Query Options File


The QAQQINI file query options can be modified with the INSERT, UPDATE, or
DELETE SQL statements.

For the following examples, a QAQQINI file has already been created in library
MyLib. To update an existing record in MyLib/QAQQINI use the UPDATE SQL
statment. This example sets MESSAGES_DEBUG = *YES so that the query
optimizer will print out the optimizer debug messages:

UPDATE MyLib/QAQQINI SET QQVAL='*YES'


WHERE QQPARM='MESSAGES_DEBUG'

To delete an existing record in MyLib/QAQQINI use the DELETE SQL statement.


This example removes the QUERY_TIME_LIMIT record from the QAQQINI file:
DELETE FROM MyLib/QAQQINI
WHERE QQPARM='QUERY_TIME_LIMIT'

To insert a new record into MyLib/QAQQINI use the INSERT SQL statement. This
example adds the QUERY_TIME_LIMIT record with a value of *NOMAX to the
QAQQINI file:
INSERT INTO MyLib/QAQQINI
VALUES('QUERY_TIME_LIMIT','*NOMAX','New time limit set by DBAdmin')

Chapter 26. Monitoring and Optimizing Query Performance Tools 545


QAQQINI Query Options
| The tables below summarize the query options that can be specified on the
| QAQQINI command:

Parameter value Description


APPLY_REMOTE Specifies, for database queries involving
distributed files, whether or not the
CHGQRYA attributes are applied to the jobs
on the remote system associated with this
job.
ASYNC_JOB_USAGE Specifies the circumstances in which
asynchronous (temp writer) jobs can be used
to help process database queries in the job.
Only applies to queries involving distributed
files.
FORCE_JOIN_ORDER Specifies whether the Query Optimizer is not
allowed to reorder files during
implementation of a join query.
MESSAGES_DEBUG This option issues all the Query Optimizer
debug messages that would normally be
issued if the job was in debug mode.
OPTIMIZE_STATISTIC_LIMITATION Specifies the circumstances in which
statistics gathering is allowed for query
optimization.
PARALLEL_DEGREE Specifies the parallel processing option that
can be used when running database queries
and database file keyed access path builds,
rebuilds, and maintenance in the job.
PARAMETER_MARKER_CONVERSION This option will disallow database queries
with literals to be implemented as parameter
markers.
QUERY_TIME_LIMIT Specifies a limit for database queries allowed
to be started, based on the estimated
number of elapsed seconds that the query
requires to process.
UDF_TIME_OUT Specifies, for database queries involving
UDFs, the number of seconds that the
database should wait for a UDF to finish.

Table 72. Query Options Specified on QAQQINI Command


Parameter Value Description
*DEFAULT The default value is set to *NO.
*NO The CHGQRYA attributes for the job are not applied to the
remote jobs. The remote jobs will use the attributes associated
to them on their systems.
APPLY_REMOTE *YES The query attributes for the job are applied to the remote jobs
used in processing database queries involving distributed files.
For attributes where *SYSVAL is specified, the system value
on the remote system is used for the remote job. This option
requires that, if CHGQRYA was used for this job, the remote
jobs must have authority to use the CHGQRYA command.

546 DB2 UDB for AS/400 SQL Programming V4R4


Table 72. Query Options Specified on QAQQINI Command (continued)
Parameter Value Description
*DEFAULT The default value is set to *LOCAL.
*LOCAL Asynchronous jobs may be used for database queries that
involve only files local to the system where the database
queries are being run. In addition, for queries involving
distributed files, this option allows the communications
required to be asynchronous. This allows each system
involved in the query of the distributed files to run its portion of
the query at the same time (in parallel) as the other systems.
ASYNC_JOB_USAGE
*DIST Asynchronous jobs may be used for database queries that
involve distributed files.
*ANY Asynchronous jobs may be used for any database query.
*NONE No asynchronous jobs are allowed to be used for database
query processing. In addition, all processing for queries
involving distributed files occurs synchronously. Therefore, no
inter-system parallel processing will occur.
*DEFAULT The default is set to *NO.
*NO Allow the optimizer to re-order join files.
FORCE_JOIN_ORDER
*YES Do not allow the query optimizer to re-order join files as part of
its optimization process. The join will occur in the order in
which the files were specified in the query.
*DEFAULT The default is set to *NO.
MESSAGES_DEBUG *NO No debug messages are to be displayed.
*YES Issue all Query Optimizer debug messages
The amount of time spent in statistics gathering is determined
*DEFAULT
by the query optimizer.
*NO No index statistics will be gathered by the query optimizer.
Default statistics will be used for optimization. (Use this option
sparingly.)
OPTIMIZE_STATISTIC_ *PERCENTAGE Specifies the maximum percentage of the index that will be
LIMITATION integer value searched while gathering statistics. Valid values for integer
value are 1 to 99.
*MAX_NUMBER_ Specifies the largest table size, in number of records, for
OF_RECORDS_ which gathering statistics is allowed. For tables with more
ALLOWED integer records than the specified value, the optimizer will not gather
value statistics and will use default values.

Chapter 26. Monitoring and Optimizing Query Performance Tools 547


Table 72. Query Options Specified on QAQQINI Command (continued)
Parameter Value Description
*DEFAULT The default value is set to *SYSVAL.
*SYSVAL The processing option used is set to the current value of the
system value, QQRYDEGREE.
*IO Any number of tasks can be used when the database query
optimizer chooses to use I/O parallel processing for queries.
SMP parallel processing is not allowed.
*OPTIMIZE The query optimizer can choose to use any number of tasks
for either I/O or SMP parallel processing to process the query
or database file keyed access path build, rebuild, or
maintenance. SMP parallel processing is used only if the
system feature, DB2 Symmetric Multiprocessing for OS/400, is
installed. Use of parallel processing and the number of tasks
used is determined with respect to the number of processors
available in the system, this job has a share of the amount of
active memory available in the pool in which the job is run,
PARALLEL_DEGREE and whether the expected elapsed time for the query or
database file keyed access path build or rebuild is limited by
CPU processing or I/O resources. The query optimizer
chooses an implementation that minimizes elapsed time based
on the job has a share of the memory in the pool.
*MAX The query optimizer chooses to use either I/O or SMP parallel
processing to process the query. SMP parallel processing will
only be used if the system feature, DB2 Symmetric
Multiprocessing for OS/400, is installed. The choices made by
the query optimizer are similar to those made for parameter
value *OPTIMIZE except the optimizer assumes that all active
memory in the pool can be used to process the query or
database file keyed access path build, rebuild, or
maintenance.
*NONE No parallel processing is allowed for database query
processing or database file keyed access path build, rebuild,
or maintenance.
*DEFAULT The default value is set to *NO.
PARAMETER_MARKER_
*NO Constants cannot be implemented as parameter markers.
CONVERSION
*YES Constants can be implemented as parameter markers.
*DEFAULT The default value is set to *SYSVAL.
*SYSVAL The query time limit for this job will be obtained from the
system value, QQRYTIMLMT.
*NOMAX There is no maximum number of estimated elapsed seconds.
QUERY_TIME_LIMIT
integer value Specifies the maximum value that is checked against the
estimated number of elapsed seconds required to run a query.
If the estimated elapsed seconds is greater than this value, the
query is not started. Valid values range from 0 through
2147352578.

548 DB2 UDB for AS/400 SQL Programming V4R4


Table 72. Query Options Specified on QAQQINI Command (continued)
Parameter Value Description
The amount of time to wait is determined by the database.
*DEFAULT
The default is 30 seconds.
*MAX The maximum amount of time that the database will wait for
the UDF to finish.
UDF_TIME_OUT
integer value Specify the number of seconds that the database should wait
for a UDF to finish. If the value given exceeds the database
maximum wait time, the maximum wait time will be used by
the database. Minimum value is 1 and maximum value is
system defined.

QAQQINI Query Options File Authority Requirements


QAQQINI is shippped with a *PUBLIC *USE authority. This allows users to view the
query options file, but not change it. It is recommended that only the system or
database administrator have *CHANGE authority to the QAQQINI query options file.

The query options file, which resides in the library specified on the CHGQRYA CL
command QRYOPTLIB parameter, is always used by the query optimizer. This is
true even if the user has no authority to the query options library and file. This
provides the system administrator with an additional security mechanism.

When the QAQQINI file resides in the library QUSRSYS the query options will
effect all of the query users on the system. To prevent anyone from inserting,
deleting, or updating the query options, the system administrator should remove
update authority from *PUBLIC to the file. This will prevent users from changing the
data in the file.

When the QAQQINI file resides in a user library, specified on the CHGQRYA CL
command option QRYOPTLIB, the query options will effect all of the querys run for
that user’s job. To prevent the query options from being retrieved from a particular
library the system administrator can revoke authority to the CHGQRYA CL
command.

QAQQINI File System Supplied Triggers


The query options file QAQQINI file uses a system-supplied trigger program in
order to process any changes made to the file. A trigger cannot be removed from or
added to the file QAQQINI.

If an error occurs on the update of the QAQQINI file (an INSERT, DELETE, or
UPDATE operation), the following SQL0443 diagnostic message will be issued:
Trigger program or external routine detected an error.

Chapter 26. Monitoring and Optimizing Query Performance Tools 549


550 DB2 UDB for AS/400 SQL Programming V4R4
Chapter 27. Solving Common Database Problems
This chapter describes techniques for solving some common database problems.
Techniques are provided to help you do the following tasks:
v Page through retrieved data
v Retrieve data in reverse order
v Establish position at the end of a table
v Add data to the end of a table
v Update data as it is retrieved from a table
v Update data previously retrieved
v Change the table definition

Paging through Retrieved Data


When a program retrieves data from the database, the FETCH statement allows the
program to page forward through the data. If you are using a scrollable cursor, then
the program can page anywhere in the file, based on the scroll option specified on
the FETCH statement. This allows the program to retrieve the data more than once.
Several options that can be used to page through the data are listed in 56.

Retrieving in Reverse Order


If there is only one row for each value of DEPTNO, then the following statement
specifies a unique ordering of rows:
SELECT * FROM DEPARTMENT
WHERE LOCATION = 'MINNESOTA'
ORDER BY DEPTNO

To retrieve the same rows in reverse order, simply specify that the order is
descending, as in this statement:
SELECT * FROM DEPARTMENT
WHERE LOCATION = 'MINNESOTA'
ORDER BY DEPTNO DESC

A cursor on the second statement would retrieve rows in exactly the opposite order
from a cursor on the first statement. But that is guaranteed only if the first statement
specifies a unique ordering.

If both statements are required in the same program, it might be useful to have two
indexes on the DEPTNO column, one in ascending order and one in descending
order.

Establishing Position at the End of a Table


For a scrollable cursor, the end of the table can be determined by the following:
FETCH AFTER FROM C1

Once the cursor is positioned at the end of the table, the program can use the
PRIOR or RELATIVE scroll options to position and fetch data starting from the end
of the table.

© Copyright IBM Corp. 1997, 1999 551


Adding Data to the End of a Table
The order in which rows are returned to your program depends on the ORDER BY
clause in the SQL statement. To get the effect of adding data to the end of a table,
include a sequence number column in the table definition. Then, when you retrieve
data from the table, use an ORDER BY clause naming that column.

Updating Data as It Is Retrieved from a Table


You can update rows of data as you retrieve them. On the select-statement, use
FOR UPDATE OF followed by a list of columns that may be updated. Then use the
cursor-controlled UPDATE statement. The WHERE CURRENT OF clause names
the cursor that points to the row you want to update. If a FOR UPDATE OF, an
ORDER BY, a FOR READ ONLY, or a SCROLL clause without the DYNAMIC
clause is not specified, all columns can be updated.

If a multiple-row FETCH statement has been specified and run, the cursor is
positioned on the last row of the block. Therefore, if the WHERE CURRENT OF
clause is specified on the UPDATE statement, the last row in the block is updated.
If a row within the block must be updated, the program must first position the cursor
on that row. Then the UPDATE WHERE CURRENT OF can be specified. Consider
the following example:
Table 73. Updating a Table
Scrollable Cursor SQL Statement Comments
EXEC SQL
DECLARE THISEMP DYNAMIC SCROLL CURSOR FOR
SELECT EMPNO, WORKDEPT, BONUS
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = ’D11’
FOR UPDATE OF BONUS
END-EXEC.
EXEC SQL
OPEN THISEMP
END-EXEC.
EXEC SQL
WHENEVER NOT FOUND
GO TO CLOSE-THISEMP
END-EXEC.
EXEC SQL DEPTINFO and
FETCH NEXT FROM THISEMP IND-ARRAY are declared
FOR 5 ROWS in the program as a host
INTO :DEPTINFO :IND-ARRAY structure array and an
END-EXEC. indicator array.
... determine if any employees in department D11 receive a
bonus less than $500.00. If so, update that record to the new
minimum of $500.00.
EXEC SQL ... positions to the record in
FETCH RELATIVE :NUMBACK FROM THISEMP the block to update by
END-EXEC. fetching in the reverse
order.

552 DB2 UDB for AS/400 SQL Programming V4R4


Table 73. Updating a Table (continued)
Scrollable Cursor SQL Statement Comments
EXEC SQL ... updates the bonus for
UPDATE CORPDATA.EMPLOYEE the employee in
SET BONUS = 500 department D11 that is
WHERE CURRENT OF THISEMP under the new $500.00
END-EXEC. minimum.
EXEC SQL ... positions to the
FETCH RELATIVE :NUMBACK FROM THISEMP beginning of the same
FOR 5 ROWS block that was already
INTO :DEPTINFO :IND-ARRAY fetched and fetches the
END-EXEC. block again. (NUMBACK
-(5 - NUMBACK - 1))
... branch back to determine if any more employees in the block
have a bonus under $500.00.

... branch back to fetch and process the next block of rows.
CLOSE-THISEMP.
EXEC SQL
CLOSE THISEMP
END-EXEC.

Restrictions
You cannot use FOR UPDATE OF with a select-statement that includes any of
these elements:
v The first FROM clause identifies more than one table or view.
v The first FROM clause identifies a read-only view.
v The first SELECT clause specifies the keyword DISTINCT.
v The outer subselect contains a GROUP BY clause.
v The outer subselect contains a HAVING clause.
v The first SELECT clause contains a column function.
v The select-statement contains a subquery such that the base object of the outer
subselect and of the subquery is the same table.
v The select-statement contains a UNION or UNION ALL operator.
v The select-statement includes a FOR READ ONLY clause.
v The SCROLL keyword is specified without DYNAMIC.

If a FOR UPDATE OF clause is specified, you cannot update columns that were not
named in the FOR UPDATE OF clause. But you can name columns in the FOR
UPDATE OF clause that are not in the SELECT list, as in this example:
SELECT A, B, C FROM TABLE
FOR UPDATE OF A,E

Do not name more columns than you need in the FOR UPDATE OF clause;
indexes on those columns are not used when you access the table.

Updating Data Previously Retrieved


You can page through and update data that had previously been retrieved by doing
one of three things:

Chapter 27. Solving Common Database Problems 553


v Use the UPDATE statement with a WHERE clause that names all of the values
in the row or specifies a unique key of the table. You can code one statement,
using host variables in the WHERE clause, and run the same statement many
times with different values of the variables to update different rows.
v For a scrollable cursor, the program can use the appropriate scroll options to
retrieve the row that had previously been fetched. Then, using the WHERE
CURRENT OF clause on the UPDATE statement, the row can be changed to the
appropriate value.

Changing the Table Definition


You can add, drop, and alter columns in a table using the SQL ALTER TABLE
statement or the Change Physical File (CHGPF) CL command.

See the DB2 UDB for AS/400 SQL Reference book for information on how to use
the SQL ALTER TABLE statement. See the CL Reference (Abridged) book for
information on how to use the Change Physical File (CHGPF) CL command.

You can also dynamically create a view of the table, which includes only the
columns you want, in the order you want.

554 DB2 UDB for AS/400 SQL Programming V4R4


Chapter 28. Distributed Relational Database Function
A distributed relational database consists of a set of SQL objects that are spread
across interconnected computer systems. These relational databases can be of the
same type (for example, DB2 UDB for AS/400) or of different types (DB2 for
OS/390, DB2 for VM, DB2 Universal Database (UDB), or non-IBM database
management systems which support DRDA). Each relational database has a
relational database manager to manage the tables in its environment. The database
managers communicate and cooperate with each other in a way that allows a given
database manager access to run SQL statements on a relational database on
another system.

The application requester supports the application side of a connection. The


application server is the local or remote database to which an application requester
is connected. DB2 UDB for AS/400 provides support for Distributed Relational
Database Architecture (DRDA) to allow an application requester to communicate
with application servers. In addition, DB2 UDB for AS/400 can invoke exit programs
to allow access to data on other database management systems which do not
support DRDA. These exit programs are called application requester driver (ARD)
programs.

DB2 UDB for AS/400 supports two levels of distributed relational database:
v Remote unit of work (RUW)
Remote unit of work is where the preparation and running of SQL statements
occurs at only one application server during a unit of work. DB2 UDB for AS/400
supports RUW over either APPC or TCP/IP.
v Distributed unit of work (DUW)
Distributed unit of work is where the preparation and running of SQL statements
can occur at multiple applications servers during a unit of work. However, a
single SQL statement can only refer to objects located at a single application
server. DB2 UDB for AS/400 supports DUW over APPC only.

For comprehensive information about distributed relational databases, see the


Distributed Database Programming book.

DB2 UDB for AS/400 Distributed Relational Database Support


The DB2 UDB Query Manager and SQL Development Kit licensed program
supports interactive access to distributed databases with the following SQL
statements:
v CONNECT
v SET CONNECTION
v DISCONNECT
v RELEASE
v DROP PACKAGE
v GRANT PACKAGE
v REVOKE PACKAGE
For detailed descriptions of these statements, see the DB2 UDB for AS/400 SQL
Reference book.

© Copyright IBM Corp. 1997, 1999 555


Additional support is provided by the development kit through parameters on the
SQL precompiler commands:
Create SQL ILE C Object (CRTSQLCI) command
Create SQL COBOL Program (CRTSQLCBL) command
Create SQL ILE COBOL Object (CRTSQLCBLI) command
Create SQL PL/I Program (CRTSQLPLI) command
Create SQL RPG Program (CRTSQLRPG) command
Create SQL ILE RPG Object (CRTSQLRPGI) command

For more information on the SQL precompiler commands, see the topic
“Chapter 18. Preparing and Running a Program with SQL Statements” on page 333.
The create SQL Package (CRTSQLPKG) command lets you create an SQL
package from an SQL program that was created as a distributed program. Syntax
and parameter definitions for the CRTSQLPKG and CRTSQLxxx commands are
provided in Appendix D. DB2 UDB for AS/400 CL Command Descriptions.

DB2 UDB for AS/400 Distributed Relational Database Example Program


A remote unit of work relational database sample program has been shipped with
the SQL product. There are several files and members within the QSQL library to
help you set up an environment that will run a distributed DB2 UDB for AS/400
sample program.

To use these files and members, you need to run the SETUP batch job located in
the file QSQL/QSQSAMP. The SETUP batch job allows you to customize the
example to do the following:
v Create the QSQSAMP library at the local and remote locations.
v Set up relational database directory entries at the local and remote locations.
v Create application panels at the local location.
v Precompile, compile, and run programs to create distributed sample application
collections, tables, indexes, and views.
v Load data into the tables at the local and remote locations.
v Precompile and compile programs.
v Create SQL packages at the remote location for the application programs.
v Precompile, compile, and run the program to update the location column in the
department table.

Before running the SETUP, you may need to edit the SETUP member of the
QSQL/QSQSAMP file. Instructions are included in the member as comments. To
run the SETUP, specify the following command on the AS/400 command line:

========> SBMDBJOB QSQL/QSQSAMP SETUP

Wait for the batch job to complete.

To use the sample program, specify the following command on the command line:
========> ADDLIBLE QSQSAMP

556 DB2 UDB for AS/400 SQL Programming V4R4


To call the first display that allows you to customize the sample program, specify
the following command on the command line.
========> CALL QSQ8HC3

The following display appears. From this display, you can customize your database
sample program.
DB2 for OS/400 ORGANIZATION APPLICATION

ACTION...........: _ A (ADD) E (ERASE)


D (DISPLAY) U (UPDATE)

OBJECT...........: __ DE (DEPARTMENT) EM (EMPLOYEE)


DS (DEPT STRUCTURE)

SEARCH CRITERIA..: __ DI (DEPARTMENT ID) MN (MANAGER NAME)


DN (DEPARTMENT NAME) EI (EMPLOYEE ID)
MI (MANAGER ID) EN (EMPLOYEE NAME)

LOCATION.........: ________________ (BLANK IMPLIES LOCAL LOCATION)

DATA.............: _______________________________

Bottom

F3=Exit
(C) COPYRIGHT IBM CORP. 1982, 1991

SQL Package Support


The OS/400 program supports an object called an SQL package. (OS/400 object
type is *SQLPKG.) The SQL package contains the control structures and access
plans necessary to process SQL statements on the application server when running
a distributed program. An SQL package can be created when:
v The RDB parameter is specified on the CRTSQLxxx command and the program
object is successfully created. The SQL package will be created on the system
specified by the RDB parameter.
If the compile is unsuccessful or the compile only creates the module object, the
SQL package will not be created.
v Using the CRTSQLPKG command. The CRTSQLPKG can be used to create a
package when the package was not created at precompile time or if the package
is needed at an RDB other than the one specified on the precompile command.

The Delete SQL Package (DLTSQLPKG) command allows you to delete an SQL
package on the local system.

An SQL package is not created unless the privileges held by the authorization ID
associated with the creation of the SQL package includes appropriate authority for
creating a package on the remote system (the application server). To run the
program, the authorization ID must include EXECUTE privileges on the SQL
package. On AS/400 systems, the EXECUTE privilege includes system authority of
*OBJOPR and *EXECUTE.

The syntax for the Create SQL Package (CRTSQLPKG) command is shown in
Appendix D. DB2 UDB for AS/400 CL Command Descriptions.

Chapter 28. Distributed Relational Database Function 557


Valid SQL Statements in an SQL Package
Programs that connect to another AS/400 can use any of the SQL statements as
described in the DB2 UDB for AS/400 SQL Reference book, except the SET
TRANSACTION statement. Programs compiled using DB2 UDB for AS/400 that
refer to a system that is not DB2 UDB for AS/400 can use executable SQL
statements supported by that remote system. The precompiler will continue to issue
diagnostic messages for statements it does not understand. These statements are
sent to the remote system during the creation of the SQL package. The run-time
support will return a SQLCODE of -84 or -525 when the statement cannot be run on
the current application server. For example, multiple-row FETCH, blocked INSERT,
and scrollable cursor support are allowed only in distributed programs where both
the application requester and application server are OS/400 at Version 2 Release 2
or later. For more information, see the appendix that contains the section
″Considerations for Using Distributed Relational Database″ in the DB2 UDB for
AS/400 SQL Reference, SC41-5612-02 book.

Considerations for Creating an SQL Package


There are many considerations to think about when you are creating an SQL
package. Some of these considerations are listed below.

CRTSQLPKG Authorization
When creating an SQL package on an AS/400 system the authorization ID used
must have *USE authority to the CRTSQLPKG command.

Creating a Package on a non-DB2 UDB for AS/400


When you create a program and SQL package for a non-DB2 UDB for AS/400, and
try to use SQL statements that are unique to that relational database, the
CRTSQLxxx GENLVL parameter should be set to 30. The program will be created
unless a message with a severity level of greater than 30 is issued. If a message is
issued with a severity level of greater than 30, the statement is probably not valid
for any relational database. For example, undefined or unusable host variables or
constants that are not valid would generate a message severity greater than 30.

The precompiler listing should be checked for unexpected messages when running
with a GENLVL greater than 10. When you are creating a package for a DB2
Universal Database, you must set the GENLVL parameter to a value less than 20.

If the RDB parameter specifies a system that is not a DB2 UDB for AS/400 system,
then the following options should not be used on the CRTSQLxxx command:
v COMMIT(*NONE)
v OPTION(*SYS)
v DATFMT(*MDY)
v DATFMT(*DMY)
v DATFMT(*JUL)
v DATFMT(*YMD)
v DATFMT(*JOB)
v DYNUSRPRF(*OWNER)
v TIMFMT(*HMS) if TIMSEP(*BLANK) or TIMSEP(’,’) is specified
v SRTSEQ(*JOBRUN)

558 DB2 UDB for AS/400 SQL Programming V4R4


v SRTSEQ(*LANGIDUNQ)
v SRTSEQ(*LANGIDSHR)
v SRTSEQ(library-name/table-name)

Note: When connecting to a DB2 Universal Database application server, the


following additional rules apply:
v The specified date and time formats must be the same format
v A value of *BLANK must be used for the TEXT parameter
v Default collections (DFTRDBCOL) are not supported
v The CCSID of the source program from which the package is being created must
not be 65535; if 65535 is used, an empty package is created.

Target Release (TGTRLS)


While creating the package, the SQL statements are checked to determine which
release can support the function. This release is set as the restore level of the
package. For example, if the package contains a CREATE TABLE statement which
adds a FOREIGN KEY constraint to the table, then the restore level of the package
will be Version 3 Release 1, because FOREIGN KEY constraints were not
supported prior to this release. TGTRLS message are suppressed when the
TGTRLS parameter is *CURRENT.

SQL Statement Size


The create SQL package function may not be able to handle the same size SQL
statement that the precompiler can process. During the precompile of the SQL
program, the SQL statement is placed into the associated space of the program.
When this occurs, each token is separated by a blank. In addition, when the RDB
parameter is specified, the host variables of the source statement are replaced with
an ’H’. The create SQL package function passes this statement to the application
server, along with a list of the host variables for that statement. The addition of the
blanks between the tokens and the replacement of host variables may cause the
statement to exceed the maximum SQL statement size (SQL0101 reason 5).

Statements that do not require a Package


In some cases, you might try to create an SQL package but the SQL package will
not be created and the program will still run. This situation occurs when the
program contains only SQL statements that do not require an SQL package to run.
For example, a program that contains only the SQL statement DESCRIBE TABLE
will generate message SQL5041 during SQL package creation. The SQL
statements that do not require an SQL package are:
v DESCRIBE TABLE
v COMMIT
v ROLLBACK
v CONNECT
v SET CONNECTION
v DISCONNECT
v RELEASE

Package Object Type


SQL packages are always created as non-ILE objects and always run in the default
activation group.

Chapter 28. Distributed Relational Database Function 559


ILE programs and service programs
ILE programs and service programs that bind several modules containing SQL
statements must have a separate SQL package for each module.

Package Creation Connection


The type of connection done for the package creation is based on the type of
connect requested using the RDBCNNMTH parameter. If RDBCNNMTH(*DUW)
was specified, commitment control is used and the connection may be a read-only
connection. If the connection is read-only, then the package creation will fail.

Unit of Work
Because package creation implicitly performs a commit or rollback, the commit
definition must be at a unit of work boundary before the package creation is
attempted. The following conditions must all be true for a commit definition to be at
a unit of work boundary:
v SQL is at a unit of work boundary.
v There are no local or DDM files open using commitment control and no closed
local or DDM files with pending changes.
v There are no API resources registered.
v There are no LU 6.2 resources registered that are not associated with DRDA or
DDM.

Creating Packages Locally


The name specified on the RDB parameter can be the name of the local system. If
it is the name of the local system, the SQL package will be created on the local
system. The SQL package can be saved (SAVOBJ command) and then restored
(RSTOBJ command) to another AS/400 system. When you run the program with a
connection to the local system, the SQL package is not used. If you specify
*LOCAL for the RDB parameter, an *SQLPKG object is not created, but the
package information is saved in the *PGM object.

Labels
You can use the LABEL ON statement to create a description for the SQL package.

Consistency Token
The program and its associated SQL package contain a consistency token that is
checked when a call is made to the SQL package. The consistency tokens must
match or the package cannot be used. It is possible for the program and SQL
package to appear to be uncoordinated. Assume the program is on the AS/400
system and the application server is another AS/400 system. The program is
running in session A and it is recreated in session B (where the SQL package is
also recreated). The next call to the program in session A could result in a
consistency token error. To avoid locating the SQL package on each call, SQL
maintains a list of addresses for SQL packages that are used by each session.
When session B re-creates the SQL package, the old SQL package is moved to the
QRPLOBJ library. The address to the SQL package in session A is still valid. (This
situation can be avoided by creating the program and SQL package from the
session that is running the program, or by submitting a remote command to delete
the old SQL package before creating the program.)

560 DB2 UDB for AS/400 SQL Programming V4R4


To use the new SQL package, you should end the connection with the remote
system. You can either sign off the session and then sign on again, or you can use
the interactive SQL (STRSQL) command to issue a DISCONNECT for unprotected
network connections or a RELEASE followed by a COMMIT for protected
connections. RCLDDMCNV should then be used to end the network connections.
Call the program again.

SQL and Recursion


If you invoke SQL from an attention key program while you are already
precompiling, you will receive unpredictable results.

The CRTSQLxxx, CRTSQLPKG, STRSQL commands and the SQL run-time


environment are not recursive. They will produce unpredictable results if recursion
is attempted. Recursion would occur if while one of the commands is running, (or
running a program with embedded SQL statements) the job is interrupted before the
command has completed, and another SQL function is started.

CCSID Considerations for SQL


If you are running a distributed application and one of your systems is not an
AS/400 system, the job CCSID value on the AS/400 cannot be set to 65535.

Before requesting that the remote system create an SQL package, the application
requester always converts the name specified on the RDB parameter, SQL package
name, library name, and the text of the SQL package from the CCSID of the job to
CCSID 500. This is required by DRDA. When the remote relational database is an
AS/400 system, the names are not converted from CCSID 500 to the job CCSID.

It is recommended that delimited identifiers not be used for table, view, index,
collection, library, or SQL package names. Conversion of names does not occur
between systems with different CCSIDs. Consider the following example with
system A running with a CCSID of 37 and system B running with a CCSID of 500.
v Create a program that creates a table with the name ″a¬b|c″ on system A.
v Save program ″a¬b|c″ on system A, then restore it to system B.
v The code point for ¬ in CCSID 37 is x’5F’ while in CCSID 500 it is x’BA’.
v On system B the name would display ″a[b]c″. If you created a program that
referenced the table whose name was ″a¬b|c.″, the program would not find the
table.

The at sign (@), pound sign (#), and dollar sign ($) characters should not be used
in SQL object names. Their code points depend on the CCSID used. If you use
delimited names or the three national extenders, the name resolution functions may
possibly fail in a future release.

Connection Management and Activation Groups

Connections and conversations


Prior to the use of TCP/IP by DRDA, the term ’connection’ was not ambiguous. It
referred to a connection from the SQL point of view. That is, a connection started at
the time one did a CONNECT TO some RDB, and ended when a DISCONNECT
was done or a RELEASE ALL followed by a successful COMMIT occurred. The

Chapter 28. Distributed Relational Database Function 561


APPC conversation may or may not have been kept up, depending on the job’s
DDMCNV attribute value, and whether the conversation was with an AS/400 or
other type of system.

TCP/IP terminology does not include the term ’conversation’. A similar concept
exists, however. With the advent of TCP/IP support by DRDA, use of the term
’conversation’ will be replaced, in this book, by the more general term ’connection’,
unless the discussion is specifically about an APPC conversation. Therefore, there
are now two different types of connections about which the reader must be aware:
SQL connections of the type described above, and ’network’ connections which
replace the term ’conversation’.

Where there would be the possibility of confusion between the two types of
connections, the word will be qualified by ’SQL’ or ’network’ to allow the reader to
understand the intended meaning.

SQL connections are managed at the activation group level. Each activation group
within a job manages its own connections and these connections are not shared
across activation groups. For programs that run in the default activation group,
connections are still managed as they were prior to Version 2 Release 3.

The following is an example of an application that runs in multiple activation groups.


This example is used to illustrate the interaction between activation groups,
connection management, and commitment control. It is not a recommended coding
style.

Source Code for PGM1:


....
EXEC SQL
CONNECT TO SYSB
END-EXEC.
EXEC SQL
SELECT ....
END-EXEC.
CALL PGM2.
....

Figure 33. Source Code for PGM1

Command to create program and SQL package for PGM1:


CRTSQLCBL PGM(PGM1) COMMIT(*NONE) RDB(SYSB)

562 DB2 UDB for AS/400 SQL Programming V4R4


Source Code for PGM2:
...
EXEC SQL
CONNECT TO SYSC;
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT ....;
EXEC SQL
OPEN C1;
do {
EXEC SQL
FETCH C1 INTO :st1;
EXEC SQL
UPDATE ...
SET COL1 = COL1+10
WHERE CURRENT OF C1;
PGM3(st1);
} while SQLCODE == 0;
EXEC SQL
CLOSE C1;
EXEC SQL COMMIT;
....

Figure 34. Source Code for PGM2

Command to create program and SQL package for PGM2:


CRTSQLCI OBJ(PGM2) COMMIT(*CHG) RDB(SYSC) OBJTYPE(*PGM)

Source Code for PGM3:


...
EXEC SQL
INSERT INTO TAB VALUES(:st1);
EXEC SQL COMMIT;
....

Figure 35. Source Code for PGM3

Commands to create program and SQL package for PGM3:


CRTSQLCI OBJ(PGM3) COMMIT(*CHG) RDB(SYSD) OBJTYPE(*MODULE)
CRTPGM PGM(PGM3) ACTGRP(APPGRP)
CRTSQLPKG PGM(PGM3) RDB(SYSD)

Chapter 28. Distributed Relational Database Function 563


SYSA
SYSB (Remote)
Job:
Call Job:
Default Activation
Group:
Default Activation
Group:
SQL Package
Connect for PGM1
PGM1

Call

SYSC (Remote)
Job:
System-Named Default Activation
Activation Group:
Group:
Connect
PGM2
SQL Package
for PGM2

Call Return Call

Activation Group
APPGRP:
SYSD (Remote)

PGM3 Job:
Connect Default Activation
Group:

SQLPackage
for PGM3

RV2W577-3

In this example, PGM1 is a non-ILE program created using the CRTSQLCBL


command. This program runs in the default activation group. PGM2 is created using
the CRTSQLCI command, and it runs in a system-named activation group. PGM3 is
also created using the CRTSQLCI command, but it runs in the activation group
named APPGRP. Because APPGRP is not the default value for the ACTGRP
parameter, the CRTPGM command is issued separately. The CRTPGM command is
followed by a CRTSQLPKG command that creates the SQL package object on the
SYSD relational database. In this example, the user has not explicitly started the
job level commitment definition. SQL implicitly starts commitment control.
1. PGM1 is called and runs in the default activation group.
2. PGM1 connects to relational database SYSB and runs a SELECT statement.
3. PGM1 then calls PGM2, which runs in a system-named activation group.
4. PGM2 does a connect to relational database SYSC. Because PGM1 and PGM2
are in different activation groups, the connection started by PGM2 in the
system-named activation group does not disconnect the connection started by
PGM1 in the default activation group. Both connections are active. PGM2 opens
the cursor and fetches and updates a row. PGM2 is running under commitment
control, is in the middle of a unit of work, and is not at a connectable state.
5. PGM2 calls PGM3, which runs in activation group APPGRP.
6. The INSERT statement is the first statement run in activation group APPGRP.
The first SQL statement causes an implicit connect to relational database
SYSD. A row is inserted into table TAB located at relational database SYSD.
The insert is then committed. The pending changes in the system-named

564 DB2 UDB for AS/400 SQL Programming V4R4


activation group are not committed, because commitment control was started by
SQL with a commit scope of activation group.
7. PGM3 is then exited and control returns to PGM2. PGM2 fetches and updates
another row.
8. PGM3 is called again to insert the row. An implicit connect was done on the first
call to PGM3. It is not done on subsequent calls because the activation group
did not end between calls to PGM3. Finally, all the rows are processed by
PGM2 and the unit of work associated with the system-named activation group
is committed.

Multiple Connections to the Same Relational Database


If different activation groups connect to the same relational database, each SQL
connection has its own network connection and its own application server job. If
activation groups are run with commitment control, changes committed in one
activation group do not commit changes in other activation groups unless the
job-level commitment definition is used.

SYSA SYSB
Job: Job:

Default ActivationGroup:
Connect

Job:

System-Named
Connect
Activation Group:

RV2W578-2

Implicit Connection Management for the Default Activation Group


The application requester can implicitly connect to an application server. Implicit
SQL connection occurs when the application requester detects the first SQL
statement is being issued by the first active SQL program for the default activation
group and the following items are true:
v The SQL statement being issued is not a CONNECT statement with parameters.
v SQL is not active in the default activation group.

Chapter 28. Distributed Relational Database Function 565


For a distributed program, the implicit SQL connection is to the relational database
specified on the RDB parameter. For a nondistributed program, the implicit SQL
connection is to the local relational database.

SQL will end any active connections in the default activation group when SQL
becomes not active. SQL becomes not active when:
v The application requester detects the first active SQL program for the process
has ended and the following are all true:
– There are no pending SQL changes
– There are no connections using protected connections
– A SET TRANSACTION statement is not active
– No programs that were precompiled with CLOSQLCSR(*ENDJOB) were run.

If there are pending changes, protected connections, or an active SET


TRANSACTION statement, SQL is placed in the exited state. If programs
precompiled with CLOSQLCSR(*ENDJOB) were run, SQL will remain active for
the default activation group until the job ends.
v At the end of a unit of work if SQL is in the exited state. This occurs when you
issue a COMMIT or ROLLBACK command outside of an SQL program.
v At the end of a job.

Implicit Connection Management for Nondefault Activation Groups


The application requester can implicitly connect to an application server. Implicit
SQL connection occurs when the application requester detects that the first SQL
statement issued for the activation group is not a CONNECT statement with
parameters.

For a distributed program, the implicit SQL connection is made to the relational
database specified on the RDB parameter. For a nondistributed program, the
implicit SQL connection is made to the local relational database.

Implicit disconnect can occur at the following times in a process:


v When the activation group ends, if commitment control is not active, activation
group level commitment control is active, or the job level commitment definition is
at a unit of work boundary.
If the job level commitment definition is active and not at a unit of work boundary,
SQL is placed in the exited state.
v If SQL is in the exited state, when the job level commitment definition is
committed or rolled back.
v At the end of a job.

Distributed Support
DB2 UDB for AS/400 supports two levels of distributed relational database:
v Remote unit of work (RUW)
Remote unit of work is where the preparation and running of SQL statements
occurs at only one application server during a unit of work. An activation group
with an application process at an application requester can connect to an
application server and, within one or more units of work, run any number of static
or dynamic SQL statements that refer to objects on the application server.
Remote unit of work is also referred to as DRDA level 1.

566 DB2 UDB for AS/400 SQL Programming V4R4


v Distributed unit of work (DUW)
Distributed unit of work is where the preparation and running of SQL statements
can occur at multiple applications servers during a unit of work. However, a
single SQL statement can only refer to objects located at a single application
server. Distributed unit of work is also referred to as DRDA level 2.
Distributed unit of work allows:
– Update access to multiple application servers in one logical unit of work
or
– Update access to a single application server with read access to multiple
application servers, in one logical unit of work.

Whether multiple application servers can be updated in a unit of work is


dependent on the existence of a sync point manager at the application requester,
sync point managers at the application servers, and two-phase commit protocol
support between the application requester and the application servers.

The sync point manager is a system component that coordinates commit and
rollback operations among the participants in the two-phase commit protocol.
When running distributed updates, the sync point managers on the different
systems cooperate to ensure that resources reach a consistent state. The
protocols and flows used by sync point managers are also referred to as
two-phase commit protocols.

If two-phase commit protocols will be used, the connection is a protected


resource; otherwise the connection is an unprotected resource.

The type of data transport protocols used between systems affects whether the
network connection is protected or unprotected. In OS/400 V4R2, TCP/IP
connections are always unprotected; thus they can participate in a distributed unit
of work in only a limited way.

For example, if the first connection made from the program is to an AS/400 over
TCP/IP, updates can be performed over it, but any subsequent connections, even
over APPC, will be read only.

Note that when using Interactive SQL, the first SQL connection is to the local
system. Therefore in order to make updates to a remote system using TCP/IP,
you must do a RELEASE ALL followed by a COMMIT to end all SQL connections
before doing the CONNECT TO remote-tcp-system.

Determining Connection Type


When a remote connection is established it will use either an unprotected or
protected network connection. With regards to committable updates, this SQL
connection may be read-only, updateable, or unknown whether it is updateable
when the connection is established. A committable update is any insert, delete,
update, or DDL statement that is run under commitment control. If the connection is
read-only, changes using COMMIT(*NONE) can still be run. After a CONNECT or
SET CONNECTION, SQLERRD(4) of the SQLCA indicates the type of connection.
SQLERRD(4) will also indicate if the connection uses a unprotected or protected
network connection. Specific values are:
1. Committable updates can be performed on the connection. The connection is
unprotected. This will occur when:

Chapter 28. Distributed Relational Database Function 567


v The connection is established using remote unit of work
(RDBCNNMTH(*RUW)). This also includes local connections and application
requester driver (ARD) connections using remote unit of work.
v If the connection is established using distributed unit of work
(RDBCNNMTH(*DUW)) then all the following are true:
– The connection is not local.
– The application server does not support distributed unit of work. For
example, a DB2 UDB for AS/400 application server with a release of
OS/400 prior to Version 3 Release 1.
– The commitment control level of the program issuing the connect is not
*NONE.
– Either no connections to other application servers (including local) exist
that can perform committable updates or all connections are read-only
connections to application servers that do not support distributed unit of
work.
– There are no open updateable local files under commitment control for the
commitment definition.
– There are no open updateable DDM files that use a different connection
under commitment control for the commitment definition.
– There are no API commitment control resources for the commitment
definition.
– There are no protected connections registered for the commitment
definition.

If running with commitment control, SQL will register a one-phase updateable


DRDA resource for remote connections or a two-phase updateable DRDA
resource for local and ARD connections.
2. No committable updates can be performed on the connection. The connection is
read-only. The network connection is unprotected.
This will never occur for applications compiled with remote unit of work
connection management (*RUW).
For distributed unit of work applications, this will occur only when the following
are true when the connection is established:
v The connection is not local.
v The application server does not support distributed unit of work
v At least one of the following is true:
– The commitment control level of the program issuing the connect is
*NONE.
– Another connection exists to an application server that does not support
distributed unit-of-work and that application server can perform
committable updates
– Another connection exists to an application server that supports distributed
unit-of-work (including local).
– There are open updateable local files under commitment control for the
commitment definition.
– There are open updateable DDM files that use a different connection
under commitment control for the commitment definition.
– There are no one-phase API commitment control resources for the
commitment definition.
– There are protected connections registered for the commitment definition.

568 DB2 UDB for AS/400 SQL Programming V4R4


If running with commitment control, SQL will register a one-phase read-only
resource.
3. It is unknown if committable updates can be performed. The connection is
protected.
This will never occur for applications compiled with remote unit of work
connection management (*RUW).
For distributed unit of work applications, this will occur when all of the following
are true when the connection is established:
v The connection is not local.
v The commitment control level of the program issuing the connect is not
*NONE.
v The application server supports both distributed unit of work and two-phase
commit protocol (protected connections).

If running with commitment control, SQL will register a two-phase undetermined


resource.
4. It is unknown if committable updates can be performed. The connection is not
protected.
This will never occur for applications compiled with remote unit of work
connection management (*RUW).
For distributed unit of work, this will occur only when all of the following are true
when the connection is established:
v The connection is not local.
v The application server supports distributed unit of work
v Either the application server does not support two-phase commit protocols
(protected connections) or the commitment control level of the program
issuing the connect is *NONE.

If running with commitment control, SQL will register a one-phase DRDA


undetermined resource.
5. It is unknown if committable updates can be performed and the connection is a
local connection using distributed unit of work or an ARD connection using
distributed unit of work.
If running with commitment control, SQL will register a two-phase DRDA
undetermined resource.

For more information on two-phase and one-phase resources, see the Backup and
Recovery book.

The following table summarizes the type of connection that will result for remote
distributed unit of work connections. SQLERRD(4) is set on successful CONNECT
and SET CONNECTION statements.
Table 74. Summary of Connection Type
Other
Application Application Updateable
Connect under Server Supports Server Supports One-phase
Commitment Two-phase Distributed Unit Resource
Control Commit of Work Registered SQLERRD(4)
No No No No 2
No No No Yes 2

Chapter 28. Distributed Relational Database Function 569


Table 74. Summary of Connection Type (continued)
Other
Application Application Updateable
Connect under Server Supports Server Supports One-phase
Commitment Two-phase Distributed Unit Resource
Control Commit of Work Registered SQLERRD(4)
No No Yes No 4
No No Yes Yes 4
No Yes No No 2
No Yes No Yes 2
No Yes Yes No 4
No Yes Yes Yes 4
Yes No No No 1
Yes No No Yes 2
Yes No Yes No 4
Yes No Yes Yes 4
Yes Yes No No N/A *
Yes Yes No Yes N/A *
Yes Yes Yes No 3
Yes Yes Yes Yes 3
*DRDA does not allow protected connections to be used to application servers which only
support remote unit of work (DRDA1). This includes all DB2 for AS/400 TCP/IP connections.

Connect and Commitment Control Restrictions


There are some restrictions on when you can connect using commitment control.
These restrictions also apply to attempting to run statements using commitment
control but the connection was established using COMMIT(*NONE).

If a two-phase undetermined or updateable resource is registered or a one-phase


updateable resource is registered, another one-phase updateable resource cannot
not be registered.

Furthermore, when protected connections are inactive and the DDMCNV job
attribute is *KEEP, these unused DDM connections will also cause the CONNECT
statements in programs compiled with RUW connection management to fail.

If running with RUW connection management and using the job-level commitment
definition, then there are some restrictions.
v If the job-level commitment definition is used by more than one activation group,
all RUW connections must be to the local relational database.
v If the connection is remote, only one activation group may use the job-level
commitment definition for RUW connections.

Determining Connection Status


The CONNECT statement without parameters can be used to determine if the
current connection is updateable or read-only for the current unit of work. A value of
1 or 2 will be returned in SQLERRD(3). The value in SQLERRD(3) is determined as
follows:

570 DB2 UDB for AS/400 SQL Programming V4R4


1. Committable updates can be performed on the connection for the unit of work.
This will occur when one of the following is true:
v SQLERRD(4) has a value of 1.
v All of the following are true:
– SQLERRD(4) has a value of 3 or 5.
– No connection exists to an application server that does not support
distributed unit of work which can perform committable updates.
– One of the following is true:
- The first committable update is performed on a connection that uses a
protected connection, is performed on the local database, or is
performed on a connection to an ARD program.
- There there are open updateable local files under commitment control.
- There are open updateable DDM files that use protected connections.
- There are two-phase API commitment control resources.
- No committable updates have been made.
v All of the following are true:
– SQLERRD(4) has a value of 4
– No other connections exist to an application server that does not support
distributed unit of work which can perform committable updates.
– The first committable update is performed on this connection or no
committable updates have been made.
– There are no open updateable DDM files that use protected connections.
– There are no open updateable local files under commitment control.
– There are no two-phase API commitment control resources.
2. No committable updates can be performed on the connection for this unit of
work.
This will occur when one of the following is true:
v SQLERRD(4) has a value of 2.
v SQLERRD(4) has a value of 3 or 5 and one of the following is true:
– A connection exists to an updateable application server that only supports
remote unit of work.
– The first committable update is performed on a connection that uses an
unprotected connection.
v SQLERRD(4) has a value of 4 and one of the following is true:
– A connection exists to an updateable application server that only supports
remote unit of work.
– The first committable update was not performed on this connection.
– There are open updateable DDM files that use protected connections.
– There are open updateable local files under commitment control.
– There are two-phase API commitment control resources.

This following table summarizes how SQLERRD(3) is determined based on the


SQLERRD(4) value, if there is an updateable connection to an application server
that only supports remote unit of work, and where the first committable update
occurred.

Chapter 28. Distributed Relational Database Function 571


Table 75. Summary of Determining SQLERRD(3) Values
Connection Exists
to Updateable
Remote Unit of Where First
Work Application Committable Update
SQLERRD(4) Server Occurred * SQLERRD(3)
1 -- -- 1
2 -- -- 2
3 Yes -- 2
3 No no updates 1
3 No one-phase 2
3 No this connection 1
3 No two-phase 1
4 Yes -- 2
4 No no updates 1
4 No one-phase 2
4 No this connection 1
4 No two-phase 2
5 Yes -- 2
5 No no updates 1
5 No one-phase 2
5 No this connection 1
5 No two-phase 1
* The terms in this column are defined as:
v No updates indicates no committable updates have been performed, no DDM files open
for update using a protected connection, no local files are open for update, and no
commitment control APIs are registered.
v One-phase indicates the first committable update was performed using an unprotected
connection or DDM files are open for update using unprotected connections.
v Two-phase indicates a committable update was performed on a two-phase
distributed-unit-of-work application server, DDM files are open for update using a protected
connection, commitment control APIs are registered, or local files are open for update
under commitment control.

When the value of SQLERRD(4) is 3, 4, or 5 (due to an ARD program) and the


value of SQLERRD(3) is 2, if an attempt is made to perform a committable update
over the connection, the unit of work will be placed in a rollback required state. If an
unit of work is in a rollback required state, the only statement allowed is a
ROLLBACK statement; all other statements will result in SQLCODE -918.

Distributed Unit of Work Connection Considerations


When connecting in a distributed unit of work application, there are many
considerations. This section lists some design considerations.
v If the unit of work will perform updates at more than one application server and
commitment control will be used, all connections over which updates will be done
should be made using commitment control. If the connections are done not using
commitment control and later committable updates are performed, read-only
connections for the unit of work are likely to result.

572 DB2 UDB for AS/400 SQL Programming V4R4


v Other non-SQL commit resources, such as local files, DDM files, and
commitment control API resources, will affect the updateable and read-only
status of a connection.
v If connecting using commitment control to an application server that does not
support distributed unit of work (for example, a V4R2 AS/400 using TCP/IP), that
connection will be either updateable or read-only. If the connection is updateable
it is the only updateable connection.

Ending Connections
Because remote connections use resources, connections that are no longer going
to be used should be ended as soon as possible. Connections can be ended
implicitly or explicitly. For a description of when connections are implicitly ended see
“Implicit Connection Management for the Default Activation Group” on page 565 and
“Implicit Connection Management for Nondefault Activation Groups” on page 566.
Connections can be explicitly ended by either the DISCONNECT statement or the
RELEASE statement followed by a successful COMMIT. The DISCONNECT
statement can only be used with connections that use unprotected connections or
with local connections. The DISCONNECT statement will end the connection when
the statement is run. The RELEASE statement can be used with either protected or
unprotected connections. When the RELEASE statement is run, the connection is
not ended but instead placed into the released state. A connection that is in the
release stated can still be used. The connection is not ended until a successful
COMMIT is run. A ROLLBACK or an unsuccessful COMMIT will not end a
connection in the released state.

When a remote SQL connection is established, a DDM network connection (APPC


conversation or TCP/IP connection) is used. When the SQL connection is ended,
the network connection may either be placed in the unused state or dropped.
Whether a network connection is dropped or placed in the unused state depends on
the DDMCNV job attribute. If the job attribute value is *KEEP and the connection is
to another AS/400, the connection becomes unused. If the job attribute value is
*DROP and the connection is to another AS/400, the connection is dropped. If the
connection is to a non-AS/400, the connection is always dropped. *DROP is
desirable in the following situations:
v When the cost of maintaining the unused connection is high and the connection
will not be used relatively soon.
v When running with a mixture of programs, some compiled with RUW connection
management and some programs compiled with DUW connection management.
Attempts to run programs compiled with RUW connection management to remote
locations will fail when protected connections exist.
v When running with protected connections using either DDM or DRDA. Additional
overhead is incurred on commits and rollbacks for unused protected connections.

The Reclaim DDM connections (RCLDDMCNV) command may be used to end all
unused connections.

Distributed Unit of Work


Distributed unit of work (DUW) allows access to multiple application servers within
the same unit of work. Each SQL statement can access only one application server.
Using distributed unit of work allows changes at multiple applications servers to be
committed or rolled back within a single unit of work.

Chapter 28. Distributed Relational Database Function 573


Managing Distributed Unit of Work Connections
The CONNECT, SET CONNECTION, DISCONNECT, and RELEASE statements
are used to manage connections in the DUW environment. A distributed unit of work
CONNECT is run when the program is precompiled using RDBCNNMTH(*DUW),
which is the default. This form of the CONNECT statement does not disconnect
existing connections but instead places the previous connection in the dormant
state. The relational database specified on the CONNECT statement becomes the
current connection. The CONNECT statement can only be used to start new
connections; if you want to switch between existing connections, the SET
CONNECTION statement must be used. Because connections use system
resources, connections should be ended when they are no longer needed. The
RELEASE or DISCONNECT statement can be used to end connections. The
RELEASE statement must be followed by a successful commit in order for the
connections to end.

The following is an example of a C program running in a DUW environment that


uses commitment control.

....
EXEC SQL WHENEVER SQLERROR GO TO done;
EXEC SQL WHENEVER NOT FOUND GO TO done;
....
EXEC SQL
DECLARE C1 CURSOR WITH HOLD FOR
SELECT PARTNO, PRICE
FROM PARTS
WHERE SITES_UPDATED = 'N'
FOR UPDATE OF SITES_UPDATED;
/* Connect to the systems */
EXEC SQL CONNECT TO LOCALSYS;
EXEC SQL CONNECT TO SYSB;
EXEC SQL CONNECT TO SYSC;
/* Make the local system the current connection */
EXEC SQL SET CONNECTION LOCALSYS;
/* Open the cursor */
EXEC SQL OPEN C1;

Figure 36. Example of Distributed Unit of Work Program (Part 1 of 4)

574 DB2 UDB for AS/400 SQL Programming V4R4


while (SQLCODE==0)
{
/* Fetch the first row */
EXEC SQL FETCH C1 INTO :partnumber,:price;
/* Update the row which indicates that the updates have been
propagated to the other sites */
EXEC SQL UPDATE PARTS SET SITES_UPDATED='Y'
WHERE CURRENT OF C1;
/* Check if the part data is on SYSB */
if ((partnumber > 10) && (partnumber < 100))
{
/* Make SYSB the current connection and update the price */
EXEC SQL SET CONNECTION SYSB;
EXEC SQL UPDATE PARTS
SET PRICE=:price
WHERE PARTNO=:partnumber;
}

Figure 36. Example of Distributed Unit of Work Program (Part 2 of 4)

/* Check if the part data is on SYSC */


if ((partnumber > 50) && (partnumber < 200))
{
/* Make SYSC the current connection and update the price */
EXEC SQL SET CONNECTION SYSC;
EXEC SQL UPDATE PARTS
SET PRICE=:price
WHERE PARTNO=:partnumber;
}
/* Commit the changes made at all 3 sites */
EXEC SQL COMMIT;
/* Set the current connection to local so the next row
can be fetched */
EXEC SQL SET CONNECTION LOCALSYS;
}
done:

Figure 36. Example of Distributed Unit of Work Program (Part 3 of 4)

EXEC SQL WHENEVER SQLERROR CONTINUE;


/* Release the connections that are no longer being used */
EXEC SQL RELEASE SYSB;
EXEC SQL RELEASE SYSC;
/* Close the cursor */
EXEC SQL CLOSE C1;
/* Do another commit which will end the released connections.
The local connection is still active because it was not
released. */
EXEC SQL COMMIT;
...

Figure 36. Example of Distributed Unit of Work Program (Part 4 of 4)

In this program, there are 3 application servers active: LOCALSYS which the local
system, and 2 remote systems, SYSB and SYSC. SYSB and SYSC also support
distributed unit of work and two-phase commit. Initially all connections are made
active by using the CONNECT statement for each of the application servers
involved in the transaction. When using DUW, a CONNECT statement does not
disconnect the previous connection, but instead places the previous connection in

Chapter 28. Distributed Relational Database Function 575


the dormant state. After all the application servers, have been connected, the local
connection is made the current connection using the SET CONNECTION
statement. The cursor is then opened and the first row of data fetched. It is then
determined at which application servers the data needs to be updated. If SYSB
needs to be updated, then SYSB is made the current connection using the SET
CONNECTION statement and the update is run. The same is done for SYSC. The
changes are then committed. Because two-phase commit is being used, it is
guaranteed that the changes are committed at the local system and the two remote
systems. Because the cursor was declared WITH HOLD, it remains open after the
commit. The current connection is then changed to the local system so that the next
row of data can be fetched. This set of fetches, updates, and commits is repeated
until all the data has been processed. After all the data has been fetched, the
connections for both remote systems are released. They can not be disconnected
because they use protected connections. After the connections are released, a
commit is issued to end the connections. The local system is still connected and
continues processing.

Checking Connection Status


If running in an environment where it is possible to have read-only connections, the
status of the connection should be checked before doing committable updates. This
will prevent the unit of work from entering the rollback required state. The following
COBOL example shows how to check the connection status.

...
EXEC SQL
SET CONNECTION SYS5
END-EXEC.
...
* Check if the connection is updateable.
EXEC SQL CONNECT END-EXEC.
* If connection is updateable, update sales information otherwise
* inform the user.
IF SQLERRD(3) = 1 THEN
EXEC SQL
INSERT INTO SALES_TABLE
VALUES(:SALES-DATA)
END-EXEC
ELSE
DISPLAY 'Unable to update sales information at this time'.
...

Figure 37. Example of Checking Connection Status

Cursors and Prepared Statements


Cursors and prepared statements are scoped to the compilation unit and also to the
connection. Scoping to the compilation unit means that a program called from
another separately compiled program cannot use a cursor or prepared statement
that was opened or prepared by the calling program. Scoping to the connection
means that each connection within a program can have its own separate instance
of a cursor or prepared statement.

The following distributed unit of work example shows how the same cursor name is
opened in two different connections, resulting in two instances of cursor C1.

576 DB2 UDB for AS/400 SQL Programming V4R4


.....
EXEC SQL DECLARE C1 CURSOR FOR
SELECT * FROM CORPDATA.EMPLOYEE;
/* Connect to local and open C1 */
EXEC SQL CONNECT TO LOCALSYS;
EXEC SQL OPEN C1;
/* Connect to the remote system and open C1 */
EXEC SQL CONNECT TO SYSA;
EXEC SQL OPEN C1;
/* Keep processing until done */
while (NOT_DONE) {
/* Fetch a row of data from the local system */
EXEC SQL SET CONNECTION LOCALSYS;
EXEC SQL FETCH C1 INTO :local_emp_struct;
/* Fetch a row of data from the remote system */
EXEC SQL SET CONNECTION SYSA;
EXEC SQL FETCH C1 INTO :rmt_emp_struct;
/* Process the data */
.....
}
/* Close the cursor on the remote system */
EXEC SQL CLOSE C1;
/* Close the cursor on the local system */
EXEC SQL SET CONNECTION LOCALSYS;
EXEC SQL CLOSE C1;
.....

Figure 38. Example of Cursors in a DUW program

Application Requester Driver Programs


To complement database access provided by products that implement DRDA, DB2
UDB for AS/400 provides an interface for writing exit programs on a DB2 UDB for
AS/400 application requester to process SQL requests. Such an exit program is
called an application requester driver. The AS/400 calls the ARD program during
the following operations:
v During package creation performed using the CRTSQLPKG or CRTSQLxxx
commands, when the relational database (RDB) parameter matches the RDB
name corresponding to the ARD program.
v Processing of SQL statements when the current connection is to an RDB name
corresponding to the ARD program.

These calls allow the ARD program to pass the SQL statements and information
about the statements to a remote relational database and return results back to the
system. The system then returns the results to the application or the user. Access
to relational databases accessed by ARD programs appears like access to DRDA
application servers in the unlike environment.

For more information about application requester driver programs, see the System
API Reference.

Chapter 28. Distributed Relational Database Function 577


Problem Handling
The primary strategy for capturing and reporting error information for the AS/400
distributed database function is called first failure data capture (FFDC). The
purpose of FFDC support is to provide accurate information on errors detected in
the DDM components of the OS/400 system from which an APAR 19 can be
created. By means of this function, key structures and the DDM data stream are
automatically dumped to a spool file. The first 1024 bytes of the error information
are also logged in the system error log. This automatic dumping of error information
on the first occurrence of an error means that the failure should not have to be
recreated to be reported by the customer. FFDC is active in both the application
requester and application server functions of the OS/400 DDM component.
However, for the FFDC data to be logged, the system value QSFWERRLOG must
be set to *LOG.

Note: Not all negative SQLCODEs are dumped; only those that can be used to
produce an APAR are dumped. For more information on handling problems
on distributed relational database operations, see the Distributed Database
Problem Determination Guide

When an SQL error is detected, an SQLCODE with a corresponding SQLSTATE is


returned in the SQLCA. For more information on these codes, see Appendix B.
SQLCODEs and SQLSTATEs.

19. Authorized Program Analysis Report (APAR).

578 DB2 UDB for AS/400 SQL Programming V4R4


Appendix A. DB2 UDB for AS/400 Sample Tables
This appendix contains the sample tables referred to and used in this guide and the
DB2 UDB for AS/400 SQL Reference book. Along with the tables are the SQL
statements for creating the tables. For detailed information on creating tables, see
“Creating and Using a Table” on page 14.

As a group, the EMPLOYEE, DEPARTMENT, PROJECT, and EMP_ACT tables


include information that describes employees, departments, projects, and activities.
This information makes up a sample application demonstrating some of the features
of the DB2 UDB Query Manager and SQL Development Kit licensed program. The
tables are in a collection named CORPDATA (for corporate data).

The tables are:


v Department table (CORPDATA.DEPARTMENT)
v Employee table (CORPDATA.EMPLOYEE)
v Employee to project activity table (CORPDATA.EMP_ACT)
v Project table (CORPDATA.PROJECT)
v Class Schedule table (CL_SCHED)
v In Tray table (IN_TRAY)
Notes:
1. In these sample tables, a question mark (?) indicates a null value.
2. The IN_TRAY and CL_SCHED tables are used to illustrate examples that
include dates and times given in the DB2 UDB for AS/400 SQL Reference book.
They are not related to the examples in the CORPDATA collection.

Department Table (CORPDATA.DEPARTMENT)


The department table describes each department in the enterprise and identifies its
manager and the department it reports to. The department table is created with the
following CREATE TABLE statement:
CREATE TABLE CORPDATA.DEPARTMENT
(DEPTNO CHAR(3) NOT NULL,
DEPTNAME VARCHAR(29) NOT NULL,
MGRNO CHAR(6) ,
ADMRDEPT CHAR(3) NOT NULL )

The following table shows the content of the columns:


Table 76. Columns of the Department Table
Column Name Description
DEPTNO Department number or ID.
DEPTNAME A name describing the general activities of the department.
MGRNO Employee number (EMPNO) of the department manager.
ADMRDEPT The department (DEPTNO) to which this department reports; the
department at the highest level reports to itself.

© Copyright IBM Corp. 1997, 1999 579


DEPARTMENT
DEPTNO DEPTNAME MGRNO ADMRDEPT
A00 SPIFFY COMPUTER SERVICE 000010 A00
DIV.
B01 PLANNING 000020 A00
C01 INFORMATION CENTER 000030 A00
D01 DEVELOPMENT CENTER ? A00
D11 MANUFACTURING SYSTEMS 000060 D01
D21 ADMINISTRATION SYSTEMS 000070 D01
E01 SUPPORT SERVICES 000050 A00
E11 OPERATIONS 000090 E01
E21 SOFTWARE SUPPORT 000100 E01

Employee Table (CORPDATA.EMPLOYEE)


The employee table identifies all employees by an employee number and lists basic
personnel information. The employee table is created with the following CREATE
TABLE statement:
CREATE TABLE CORPDATA.EMPLOYEE
(EMPNO CHAR(6) NOT NULL,
FIRSTNME VARCHAR(12) NOT NULL,
MIDINIT CHAR(1) NOT NULL,
LASTNAME VARCHAR(15) NOT NULL,
WORKDEPT CHAR(3) ,
PHONENO CHAR(4) ,
HIREDATE DATE ,
JOB CHAR(8) ,
EDLEVEL SMALLINT NOT NULL,
SEX CHAR(1) ,
BIRTHDATE DATE ,
SALARY DECIMAL(9,2) ,
BONUS DECIMAL(9,2) ,
COMM DECIMAL(9,2) )

The table below shows the content of the columns.

Column Name Description


EMPNO Employee number
FIRSTNME First name of employee
MIDINIT Middle initial of employee
LASTNAME Last name of employee
WORKDEPT ID of department in which the employee works
PHONENO Employee telephone number
HIREDATE Date of hire
JOB Job held by the employee
EDLEVEL Number of years of formal education
SEX Sex of the employee (M or F)
BIRTHDATE Date of birth
SALARY Yearly salary in dollars

580 DB2 UDB for AS/400 SQL Programming V4R4


Column Name Description
BONUS Yearly bonus in dollars
COMM Yearly commission in dollars

FIRST MID WORK PHONE ED SAL-


EMP NO NAME INIT LASTNAME DEPT NO HIRE DATE JOB LEVEL SEX BIRTH DATE ARY BONUS COMM
000010 CHRISTINE I HAAS A00 3978 1965-01-01 PRES 18 F 1933-08-24 52750 1000 4220
000020 MICHAEL L THOMPSON B01 3476 1973-10-10 MANAGER 18 M 1948-02-02 41250 800 3300
000030 SALLY A KWAN C01 4738 1975-04-05 MANAGER 20 F 1941-05-11 38250 800 3060
000050 JOHN B GEYER E01 6789 1949-08-17 MANAGER 16 M 1925-09-15 40175 800 3214
000060 IRVING F STERN D11 6423 1973-09-14 MANAGER 16 M 1945-07-07 32250 500 2580
000070 EVA D PULASKI D21 7831 1980-09-30 MANAGER 16 F 1953-05-26 36170 700 2893
000090 EILEEN W HENDERSON E11 5498 1970-08-15 MANAGER 16 F 1941-05-15 29750 600 2380
000100 THEODORE Q SPENSER E21 0972 1980-06-19 MANAGER 14 M 1956-12-18 26150 500 2092
000110 VINCENZO G LUCCHESSI A00 3490 1958-05-16 SALESREP 19 M 1929-11-05 46500 900 3720
000120 SEAN O'CONNELL A00 2167 1963-12-05 CLERK 14 M 1942-10-18 29250 600 2340
000130 DOLORES M QUINTANA C01 4578 1971-07-28 ANALYST 16 F 1925-09-15 23800 500 1904
000140 HEATHER A NICHOLLS C01 1793 1976-12-15 ANALYST 18 F 1946-01-19 28420 600 2274
000150 BRUCE ADAMSON D11 4510 1972-02-12 DESIGNER 16 M 1947-05-17 25280 500 2022
000160 ELIZABETH R PIANKA D11 3782 1977-10-11 DESIGNER 17 F 1955-04-12 22250 400 1780
000170 MASATOSHI J YOSHIMURA D11 2890 1978-09-15 DESIGNER 16 M 1951-01-05 24680 500 1974
000180 MARILYN S SCOUTTEN D11 1682 1973-07-07 DESIGNER 17 F 1949-02-21 21340 500 1707
000190 JAMES H WALKER D11 2986 1974-07-26 DESIGNER 16 M 1952-06-25 20450 400 1636
000200 DAVID BROWN D11 4501 1966-03-03 DESIGNER 16 M 1941-05-29 27740 600 2217
000210 WILLIAM T JONES D11 0942 1979-04-11 DESIGNER 17 M 1953-02-23 18270 400 1462
000220 JENNIFER K LUTZ D11 0672 1968-08-29 DESIGNER 18 F 1948-03-19 29840 600 2387
000230 JAMES J JEFFERSON D21 2094 1966-11-21 CLERK 14 M 1935-05-30 22180 400 1774
000240 SALVATORE M MARINO D21 3780 1979-12-05 CLERK 17 M 1954-03-31 28760 600 2301
000250 DANIEL S SMITH D21 0961 1969-10-30 CLERK 15 M 1939-11-12 19180 400 1534
000260 SYBIL P JOHNSON D21 8953 1975-09-11 CLERK 16 F 1936-10-05 17250 300 1380
000270 MARIA L PEREZ D21 9001 1980-09-30 CLERK 15 F 1953-05-26 27380 500 2190
000280 ETHEL R SCHNEIDER E11 8997 1967-03-24 OPERATOR 17 F 1936-03-28 26250 500 2100
000290 JOHN R PARKER E11 4502 1980-05-30 OPERATOR 12 M 1946-07-09 15340 300 1227
000300 PHILIP X SMITH E11 2095 1972-06-19 OPERATOR 14 M 1936-10-27 17750 400 1420
000310 MAUDE F SETRIGHT E11 3332 1964-09-12 OPERATOR 12 F 1931-04-21 15900 300 1272
000320 RAMLAL V MEHTA E21 9990 1965-07-07 FILEREP 16 M 1932-08-11 19950 400 1596
000330 WING LEE E21 2103 1976-02-23 FILEREP 14 M 1941-07-18 25370 500 2030
000340 JASON R GOUNOT E21 5698 1947-05-05 FILEREP 16 M 1926-05-17 23840 500 1907

Employee to Project Activity Table (CORPDATA.EMP_ACT)


The employee to project activity table identifies the employee who performs each
activity listed for each project. The employee’s level of involvement (full-time or
part-time) and schedule for activity are also in the table. The employee to project
activity table is created with the following CREATE TABLE statement:
CREATE TABLE CORPDATA.EMP_ACT
(EMPNO CHAR(6) NOT NULL,
PROJNO CHAR(6) NOT NULL,
ACTNO SMALLINT NOT NULL,
EMPTIME DECIMAL(5,2) ,
EMSTDATE DATE ,
EMENDATE DATE )

The table below shows the content of the columns.


Table 77. Columns of the Employee to Project Activity Table
Column Name Description
EMPNO Employee ID number
PROJNO PROJNO of the project to which the employee is assigned
ACTNO ID of an activity within a project to which an employee is
assigned
EMPTIME A proportion of the employee’s full time (between 0.00 and 1.00)
to be spent on the project from EMSTDATE to EMENDATE
EMSTDATE Start date of the activity

Appendix A. DB2 UDB for AS/400 Sample Tables 581


Table 77. Columns of the Employee to Project Activity Table (continued)
Column Name Description
EMENDATE Completion date of the activity

EMP_ACT
EMPNO PROJNO ACTNO EMPTIME EMSTDATE EMENDATE
000010 AD3100 10 .50 1982-01-01 1982-07-01
000070 AD3110 10 1.00 1982-01-01 1983-02-01
000230 AD3111 60 1.00 1982-01-01 1982-03-15
000230 AD3111 60 .50 1982-03-15 1982-04-15
000230 AD3111 70 .50 1982-03-15 1982-10-15
000230 AD3111 80 .50 1982-04-15 1982-10-15
000230 AD3111 180 1.00 1982-10-15 1983-01-01
000240 AD3111 70 1.00 1982-02-15 1982-09-15
000240 AD3111 80 1.00 1982-09-15 1983-01-01
000250 AD3112 60 1.00 1982-01-01 1982-02-01
000250 AD3112 60 .50 1982-02-01 1982-03-15
000250 AD3112 60 .50 1982-12-01 1983-01-01
000250 AD3112 60 1.00 1983-01-01 1983-02-01
000250 AD3112 70 .50 1982-02-01 1982-03-15
000250 AD3112 70 1.00 1982-03-15 1982-08-15
000250 AD3112 70 .25 1982-08-15 1982-10-15
000250 AD3112 80 .25 1982-08-15 1982-10-15
000250 AD3112 80 .50 1982-10-15 1982-12-01
000250 AD3112 180 .50 1982-08-15 1983-01-01
000260 AD3113 70 .50 1982-06-15 1982-07-01
000260 AD3113 70 1.00 1982-07-01 1983-02-01
000260 AD3113 80 1.00 1982-01-01 1982-03-01
000260 AD3113 80 .50 1982-03-01 1982-04-15
000260 AD3113 180 .50 1982-03-01 1982-04-15
000260 AD3113 180 1.00 1982-04-15 1982-06-01
000260 AD3113 180 .50 1982-06-01 1982-07-01
000270 AD3113 60 .50 1982-03-01 1982-04-01
000270 AD3113 60 1.00 1982-04-01 1982-09-01
000270 AD3113 60 .25 1982-09-01 1982-10-15
000270 AD3113 70 .75 1982-09-01 1982-10-15
000270 AD3113 70 1.00 1982-10-15 1983-02-01
000270 AD3113 80 1.00 1982-01-01 1982-03-01
000270 AD3113 80 .50 1982-03-01 1982-04-01
000030 IF1000 10 .50 1982-06-01 1983-01-01
000130 IF1000 90 1.00 1982-01-01 1982-10-01
000130 IF1000 100 .50 1982-10-01 1983-01-01

582 DB2 UDB for AS/400 SQL Programming V4R4


EMPNO PROJNO ACTNO EMPTIME EMSTDATE EMENDATE
000140 IF1000 90 .50 1982-10-01 1983-01-01
000030 IF2000 10 .50 1982-01-01 1983-01-01
000140 IF2000 100 1.00 1982-01-01 1982-03-01
000140 IF2000 100 .50 1982-03-01 1982-07-01
000140 IF2000 110 .50 1982-03-01 1982-07-01
000140 IF2000 110 .50 1982-10-01 1983-01-01
000010 MA2100 10 .50 1982-01-01 1982-11-01
000110 MA2100 20 1.00 1982-01-01 1982-03-01
000010 MA2110 10 1.00 1982-01-01 1983-02-01
000200 MA2111 50 1.00 1982-01-01 1982-06-15
000200 MA2111 60 1.00 1982-06-15 1983-02-01
000220 MA2111 40 1.00 1982-01-01 1983-02-01
000150 MA2112 60 1.00 1982-01-01 1982-07-15
000150 MA2112 180 1.00 1982-07-15 1983-02-01
000170 MA2112 60 1.00 1982-01-01 1983-06-01
000170 MA2112 70 1.00 1982-06-01 1983-02-01
000190 MA2112 70 1.00 1982-02-01 1982-10-01
000190 MA2112 80 1.00 1982-10-01 1983-10-01
000160 MA2113 60 1.00 1982-07-15 1983-02-01
000170 MA2113 80 1.00 1982-01-01 1983-02-01
000180 MA2113 70 1.00 1982-04-01 1982-06-15
000210 MA2113 80 .50 1982-10-01 1983-02-01
000210 MA2113 180 .50 1982-10-01 1983-02-01
000050 OP1000 10 .25 1982-01-01 1983-02-01
000090 OP1010 10 1.00 1982-01-01 1983-02-01
000280 OP1010 130 1.00 1982-01-01 1983-02-01
000290 OP1010 130 1.00 1982-01-01 1983-02-01
000300 OP1010 130 1.00 1982-01-01 1983-02-01
000310 OP1010 130 1.00 1982-01-01 1983-02-01
000050 OP2010 10 .75 1982-01-01 1983-02-01
000100 OP2010 10 1.00 1982-01-01 1983-02-01
000320 OP2011 140 .75 1982-01-01 1983-02-01
000320 OP2011 150 .25 1982-01-01 1983-02-01
000330 OP2012 140 .25 1982-01-01 1983-02-01
000330 OP2012 160 .75 1982-01-01 1983-02-01
000340 OP2013 140 .50 1982-01-01 1983-02-01
000340 OP2013 170 .50 1982-01-01 1983-02-01
000020 PL2100 30 1.00 1982-01-01 1982-09-15

Appendix A. DB2 UDB for AS/400 Sample Tables 583


Project Table (CORPDATA.PROJECT)
The project table describes each project that the business is currently undertaking.
Data contained in each row include the project number, name, person responsible,
and schedule dates. The project table is created with the following CREATE TABLE
statement:
CREATE TABLE CORPDATA.PROJECT
(PROJNO CHAR(6) NOT NULL,
PROJNAME VARCHAR(24) NOT NULL,
DEPTNO CHAR(3) NOT NULL,
RESPEMP CHAR(6) NOT NULL,
PRSTAFF DECIMAL(5,2) ,
PRSTDATE DATE ,
PRENDATE DATE ,
MAJPROJ CHAR(6) )

The table below shows the contents of the columns:

Column Name Description


PROJNO Project number
PROJNAME Project name
DEPTNO Department number of the department responsible for the
project
RESPEMP Employee number of the person responsible for the project
PRSTAFF Estimated mean staffing
PRSTDATE Estimated start date of the project
PRENDATE Estimated end date of the project
MAJPROJ Controlling project number for sub projects

PROJECT
PROJNO PROJNAME DEPTNO RESPEMP PRSTAFF PRSTDATE PRENDATE MAJPROJ
AD3100 ADMIN SERVICES D01 000010 6.5 1982-01-01 1983-02-01 ?
AD3110 GENERAL ADMIN D21 000070 6 1982-01-01 1983-02-01 AD3100
SYSTEMS
AD3111 PAYROLL D21 000230 2 1982-01-01 1983-02-01 AD3110
PROGRAMMING
AD3112 PERSONNEL D21 000250 1 1982-01-01 1983-02-01 AD3110
PROGRAMMING
AD3113 ACCOUNT D21 000270 2 1982-01-01 1983-02-01 AD3110
PROGRAMMING
IF1000 QUERY C01 000030 2 1982-01-01 1983-02-01 ?
SERVICES
IF2000 USER C01 000030 1 1982-01-01 1983-02-01 ?
EDUCATION
MA2100 WELD LINE D01 000010 12 1982-01-01 1983-02-01 ?
AUTOMATION
MA2110 WL D11 000060 9 1982-01-01 1983-02-01 MA2100
PROGRAMMING
MA2111 W L PROGRAM D11 000220 2 1982-01-01 1982-12-01 MA2110
DESIGN

584 DB2 UDB for AS/400 SQL Programming V4R4


PROJNO PROJNAME DEPTNO RESPEMP PRSTAFF PRSTDATE PRENDATE MAJPROJ
MA2112 W L ROBOT D11 000150 3 1982-01-01 1982-12-01 MA2110
DESIGN
MA2113 W L PROD CONT D11 000160 3 1982-02-15 1982-12-01 MA2110
PROGS
OP1000 OPERATION E01 000050 6 1982-01-01 1983-02-01 ?
SUPPORT
OP1010 OPERATION E11 000090 5 1982-01-01 1983-02-01 OP1000
OP2000 GEN SYSTEMS E01 000050 5 1982-01-01 1983-02-01 ?
SERVICES
OP2010 SYSTEMS E21 000100 4 1982-01-01 1983-02-01 OP2000
SUPPORT
OP2011 SCP SYSTEMS E21 000320 1 1982-01-01 1983-02-01 OP2010
SUPPORT
OP2012 APPLICATIONS E21 000330 1 1982-01-01 1983-02-01 OP2010
SUPPORT
OP2013 DB/DC SUPPORT E21 000340 1 1982-01-01 1983-02-01 OP2010
PL2100 WELD LINE B01 000020 1 1982-01-01 1982-09-15 MA2100
PLANNING

Class Schedule Table (CL_SCHED)


The class schedule table describes: each class, the start time for the class, the end
time for the class, and the class code. The class schedule table is created with the
following CREATE TABLE statement:
CREATE TABLE CL_SCHED
(CLASS_CODE CHAR(7),
DAY SMALLINT,
STARTING TIME,
ENDING TIME)

The table below gives the contents of the columns.

Column Name Description


CLASS_CODE Class code (room:teacher)
DAY Day number of 4 day schedule
STARTING Class start time
ENDING Class end time

Note: This table has no data.

In Tray Table (IN_TRAY)


The in tray table describes an electronic in-basket containing: a timestamp from
when the message was received, the user ID of the person sending the message,
and the message itself. The in tray table is created with the following CREATE
TABLE statement:

Appendix A. DB2 UDB for AS/400 Sample Tables 585


CREATE TABLE IN_TRAY
(RECEIVED TIMESTAMP,
SOURCE CHAR(8),
SUBJECT CHAR(64),
NOTE_TEXT VARCHAR(3000))

The table below gives the contents of the columns.

Column Name Description


RECEIVED Date and time received
SOURCE User ID of person sending the note
SUBJECT Brief description of the note
NOTE_TEXT The note

Note: This table has no data.

586 DB2 UDB for AS/400 SQL Programming V4R4


Appendix B. SQLCODEs and SQLSTATEs
SQL does not communicate directly with the end user but rather returns error codes
to the application program when an error occurs.

This appendix lists SQLCODEs and their associated SQLSTATEs. There are many
other SQL messages, but they are not listed here. Detailed descriptions of all DB2
UDB for AS/400 messages, including SQLCODEs, are available on-line and can be
displayed and printed from the Display Message Description display. You can
access this display by using the CL command Display Message Description
(DSPMSGD).

| If you wish, you can quickly reference “Positive SQLCODEs” on page 589 or
| “Negative SQLCODEs” on page 591.

SQLCODEs are returned in the SQLCA structure. SQLSTATE is an additional return


code that provides application programs with common return codes for common
error conditions found among the IBM relational database systems. SQLSTATEs are
particularly useful when handling errors in distributed SQL applications.

Every SQLCODE has a corresponding message in message file QSQLMSG in


library QSYS. The message ID for any SQLCODE is constructed by appending the
absolute value (5 digits) of the SQLCODE to SQ and changing the third character
to 'L' if the third character is a 0. For example, if the SQLCODE is 30070, the
message ID is SQ30070.

If SQL encounters an error while processing the statement, the first characters of
the SQLSTATE are not '00', '01' or '02', and the SQLCODE is a negative number. If
SQL encounters a warning but valid condition while processing your statement, the
SQLCODE is a positive number and bytes one and two of the SQLSTATE are '01'.
If your SQL statement is processed without encountering an error or warning
condition, the SQLCODE returned is 0 and SQLSTATE is '00000'.

When running in debug mode, SQL places a message corresponding to the


SQLCODE in the job log for each SQL statement run. If you are not running in
debug mode and get a negative SQLCODE, you will get a message in the job log
also.

An application can also send the SQL message corresponding to any SQLCODE to
the job log by specifying the message ID and the replacement text on the CL
commands Retrieve Message (RTVMSG), Send Program Message
(SNDPGMMSG), and Send User Message (SNDUSRMSG).

SQLSTATE values consist of a two-character class code, followed by a


three-character code. The class codes conform to ISO/ANSI standards. The class
codes are:
v 00 Unqualified Successful Completion
v 01 Warning
v 02 No Data
v 03 SQL Statement Not Yet Complete
v 07 Dynamic SQL Error
v 08 Connection Exception
v 09 Triggered Action Exception

© Copyright IBM Corp. 1997, 1999 587


v 0A Feature Not Supported
v 09 Invalid Token
v 20 Case Not Found for CASE Statement
v 21 Cardinality Violation
v 22 Data Exception
v 23 Constraint Violation
v 24 Invalid Cursor State
v 25 Invalid Transaction State
v 26 Invalid SQL Statement Identifier
v 27 Triggered Data Change Violation
v 28 Invalid Authorization Specification
v 2B Dependent Privilege Descriptors Still Exist
v 2C Invalid Character Set Name
v 2D Invalid Transaction Termination
v 2E Invalid Connection Name
v 2F SQL Function Exception
v 33 Invalid SQL Descriptor Name
v 34 Invalid Cursor Name
v 35 Invalid Condition Number
v 38 External Function Exception
v 39 External Function Call Exception
v 3C Ambiguous Cursor Name
v 3D Invalid Catalog Name
v 3F Invalid Collection (Schema) Name
v 40 Transaction Rollback
v 42 Syntax Error and Access Rule Violation
v 44 WITH CHECK OPTION Violation
v 51 Invalid Application State
v 53 Invalid Operand or Inconsistent Specification
v 54 SQL or Product Limit Exceeded
v 55 Object Not in Prerequisite State
v 56 Miscellaneous SQL or Product Error
v 57 Resource Not Available or Operator Intervention
v 58 System Error

For a list of SQLSTATEs that are used by the DB2 family of products, see IBM SQL
Reference, Version 2, SC26-8416. Also available on CD-ROM as a part of the
Transaction Processing Collection Kit CD-ROM, SK2T-0730-11.

When an SQLSTATE other than '00000' is returned from a non-DB2 UDB for
AS/400 application server, DB2 UDB for AS/400 attempts to map the SQLSTATE to
a DB2 UDB for AS/400 SQLCODE and message:
v If the SQLSTATE is not recognized by DB2 UDB for AS/400, the common
message for the class is issued.

588 DB2 UDB for AS/400 SQL Programming V4R4


v If the SQLSTATE and SQLCODE correspond to a single DB2 UDB for AS/400
SQLCODE, DB2 UDB for AS/400 attempts to convert the tokens returned in
SQLERRM to the replacement data expected by the SQL message. If an error
occurs while converting the tokens:
– The SQLCA is not changed.
– A common message for the class code of the SQLSTATE is issued.

SQLCODE and SQLSTATE Descriptions


In the following brief descriptions of the SQLCODEs (and their associated
SQLSTATEs) message data fields are identified by an ampersand (&); and a
number (for example, &1); The replacement text for these fields is stored in
SQLERRM in the SQLCA. More detailed cause and recovery information for any
SQLCODE can be found by using the Display Message Description (DSPMSGD)
CL command.

Positive SQLCODEs

N/A SQLCODE 0 SQL0088 SQLCODE +88 SQLSTATE 01504


Explanation: The SQL statement has run successfully. Explanation: No WHERE on UPDATE or DELETE.
If SQLWARN0 is blank, and SQLSTATE is '00000', the
statement was run successfully. Otherwise, a warning
SQL0100 SQLCODE +100 SQLSTATE 02000
condition exists. Check the other warning indicators or
SQLSTATE to determine the particular warning Explanation: Row not found for &1.
condition. For example, if SQLWARN1 is not blank, a
string has been truncated. The following warnings have
an SQLCODE of zero: SQL0114 SQLCODE +114 SQLSTATE 01536
v SQLWARN1 SQLSTATE 01004 Explanation: Relational database &1 not the same as
Explanation: The value of a string column was current server &2.
truncated when assigned to a host variable.
v SQLWARN2 SQLSTATE 01003 SQL0138 SQLCODE +138 SQLSTATE 01544
Explanation: Null values were eliminated from the Explanation: Argument &1 of SUBSTR function not
argument of a column function. valid.
v SQLWARN3 SQLSTATE 01503
Explanation: The number of result columns is larger SQL0177 SQLCODE +177 SQLSTATE 01009
than the number of host variables provided.
Explanation: CHECK condition text too long.
v SQLWARN4 SQLSTATE 01504
Explanation: The UPDATE or DELETE statement
does not include a WHERE clause. SQL0178 SQLCODE +178 SQLSTATE 0100A
v SQLWARN6 SQLSTATE 01506 Explanation: Query expression text for view &1 in &2
Explanation: An adjustment was made to a DATE or too long.
TIMESTAMP value to correct a date the was not
valid. The date resulted from an arithmetic operation. SQL0180 SQLCODE +180 SQLSTATE 01534
Explanation: Syntax of date, time, or timestamp value
SQL0012 SQLCODE +12 SQLSTATE 01545 not valid.
Explanation: Correlation without qualification occurred
for column &1 to table &2. SQL0181 SQLCODE +181 SQLSTATE 01534
Explanation: Value in date, time, or timestamp string
SQL0030 SQLCODE +30 SQLSTATE 01503 not valid.
Explanation: Number of INTO host-variable incorrect.

Appendix B. SQLCODEs and SQLSTATEs 589


SQL0183 SQLCODE +183 SQLSTATE 01535 SQL0445 SQLCODE +445 SQLSTATE 01004
Explanation: The result of a date or timestamp Explanation: Value of parameter &4 in procedure &1
expression not valid. in &2 too long.

SQL0191 SQLCODE +191 SQLSTATE 01547 SQL0460 SQLCODE +460 SQLSTATE 01593
Explanation: MIXED data not properly formed. Explanation: Truncation of data may have occurred
for ALTER TABLE in &1 of &2.
SQL0204 SQLCODE +204 SQLSTATE 01532
SQL0551 SQLCODE +551 SQLSTATE 01548
Explanation: Object &1 in &2 type *&3 not found.
Explanation: Not authorized to object &1 in &2 type
*&3.
| SQL0237 SQLCODE +237 SQLSTATE 01005
| Explanation: Not enough SQLVAR entries were
SQL0552 SQLCODE +552 SQLSTATE 01542
| provided in the SQLDA.
Explanation: Not authorized to &1.
| SQL0239 SQLCODE +239 SQLSTATE 01005
SQL0569 SQLCODE +569 SQLSTATE 01006
| Explanation: Not enough SQLVAR entries were
| provided in the SQLDA. Explanation: Not all requested privileges revoked from
object &1 in &2 type &3.
SQL0304 SQLCODE +304 SQLSTATE 01515,
01547, 01565 SQL0570 SQLCODE +570 SQLSTATE 01007
Explanation: Conversion error in assignment to host Explanation: Not all requested privileges to object &1
variable &2. in &2 type &3 granted.

SQL0326 SQLCODE +326 SQLSTATE 01557 SQL0595 SQLCODE +595 SQLSTATE 01526
Explanation: Too many host variables specified. Explanation: Commit level &1 escalated to &2 lock.

SQL0331 SQLCODE +331 SQLSTATE 01520 SQL0596 SQLCODE +596 SQLSTATE 01002
Explanation: Characters conversion cannot be Explanation: Error occurred during disconnect.
performed.
SQL0645 SQLCODE +645 SQLSTATE 01528
SQL0335 SQLCODE +335 SQLSTATE 01517
Explanation: WHERE NOT NULL clause ignored for
Explanation: Characters conversion has resulted in index &1 in &2.
substitution characters.
SQL0802 SQLCODE +802 SQLSTATE 01519,
| SQL0360 SQLCODE +360 SQLSTATE 01627 01547, 01564, 01565
| Explanation: Datalink in table &1 in &2 may not be Explanation: Data conversion or data mapping error.
| valid due to pending links.
SQL0863 SQLCODE +863 SQLSTATE 01539
SQL0403 SQLCODE +403 SQLSTATE 01522
Explanation: Mixed or DBCS CCSID not supported by
Explanation: Alias &1 in &2 created but table or view relational database &1.
not found.
SQL0990 SQLCODE +990 SQLSTATE 01587
SQL0420 SQLCODE +420 SQLSTATE 01565
Explanation: Outcome unknown for the unit of work.
Explanation: Character in CAST argument not valid.

590 DB2 UDB for AS/400 SQL Programming V4R4


SQL7905 SQLCODE +7905 SQLSTATE 01567
Explanation: Table &1 in &2 created but could not be
journaled.

Negative SQLCODEs
SQL0007 SQLCODE -07 SQLSTATE 42601 SQL0102 SQLCODE -102 SQLSTATE 54002
Explanation: Character &1 (HEX &2) not valid in SQL Explanation: String constant beginning with &1 too
statement. long.

SQL0010 SQLCODE -10 SQLSTATE 42603 SQL0103 SQLCODE -103 SQLSTATE 42604
Explanation: String constant beginning &1 not Explanation: Numeric constant &1 not valid.
delimited.
SQL0104 SQLCODE -104 SQLSTATE 42601
SQL0029 SQLCODE -29 SQLSTATE 42601
Explanation: Token &1 was not valid. Valid tokens:
Explanation: INTO clause missing from embedded &2.
SELECT statement.
SQL0105 SQLCODE -105 SQLSTATE 42604
SQL0051 SQLCODE -51 SQLSTATE 3C000
Explanation: Mixed or graphic string constant not
Explanation: Cursor or procedure &1 previously valid.
declared.
SQL0106 SQLCODE -106 SQLSTATE 42611
SQL0060 SQLCODE -60 SQLSTATE 42815
Explanation: Precision specified for FLOAT column
Explanation: Value &3 for argument &1 of &2 function not valid.
not valid.
SQL0107 SQLCODE -107 SQLSTATE 42622
SQL0080 SQLCODE -80 SQLSTATE 42978
Explanation: &1 too long. Maximum &2 characters.
Explanation: Indicator variable &1 not SMALLINT
type.
SQL0109 SQLCODE -109 SQLSTATE 42601
Explanation: &1 clause not allowed.
SQL0084 SQLCODE -84 SQLSTATE 42612
Explanation: SQL statement not allowed.
SQL0110 SQLCODE -110 SQLSTATE 42606
Explanation: Hexadecimal constant beginning with &1
SQL0090 SQLCODE -90 SQLSTATE 42618
not valid.
Explanation: Host variable not permitted here.
SQL0112 SQLCODE -112 SQLSTATE 42607
| SQL0097 SQLCODE -97 SQLSTATE 42601
Explanation: Argument of function &1 is another
| Explanation: Use of data type not valid. function.

SQL0099 SQLCODE -99 SQLSTATE 42992 SQL0113 SQLCODE -113 SQLSTATE 28000,
2E000, 42602
Explanation: Operator in join condition not valid.
Explanation: Name &1 not allowed.
SQL0101 SQLCODE -101 SQLSTATE 54001,
54010, 54011 SQL0114 SQLCODE -114 SQLSTATE 42961
Explanation: SQL statement too long or complex. Explanation: Relational database &1 not the same as
current server &2.

Appendix B. SQLCODEs and SQLSTATEs 591


SQL0115 SQLCODE -115 SQLSTATE 42601 SQL0132 SQLCODE -132 SQLSTATE 42824
Explanation: Comparison operator &1 not valid. Explanation: LIKE predicate not valid.

SQL0117 SQLCODE -117 SQLSTATE 42802 SQL0133 SQLCODE -133 SQLSTATE 42906
Explanation: Statement inserts wrong number of Explanation: Operator on correlated column in SQL
values. function not valid.

SQL0118 SQLCODE -118 SQLSTATE 42902 SQL0134 SQLCODE -134 SQLSTATE 42907
Explanation: Table &1 in &2 also specified in a FROM Explanation: Argument of function too long.
clause.
SQL0136 SQLCODE -136 SQLSTATE 54005
SQL0119 SQLCODE -119 SQLSTATE 42803
Explanation: ORDER BY or GROUP BY columns too
Explanation: Column &1 in HAVING clause not in long.
GROUP BY.
SQL0137 SQLCODE -137 SQLSTATE 54006
SQL0120 SQLCODE -120 SQLSTATE 42903
Explanation: Result too long.
Explanation: Use of column function &2 not valid.
SQL0138 SQLCODE -138 SQLSTATE 22011
SQL0121 SQLCODE -121 SQLSTATE 42701
Explanation: Argument &1 of SUBSTR function not
Explanation: Duplicate column name &1 in INSERT or valid.
UPDATE.
SQL0144 SQLCODE -144 SQLSTATE 58003
SQL0122 SQLCODE -122 SQLSTATE 42803
Explanation: Section number not valid.
Explanation: Column specified in SELECT list not
valid.
SQL0145 SQLCODE -145 SQLSTATE 55005
Explanation: Recursion not supported for an
SQL0125 SQLCODE -125 SQLSTATE 42805
application server other than the AS/400 system.
Explanation: ORDER BY column number &1 not
valid.
SQL0150 SQLCODE -150 SQLSTATE 42807
Explanation: View or logical file &1 in &2 read-only.
SQL0128 SQLCODE -128 SQLSTATE 42601
Explanation: Use of NULL is not valid.
SQL0151 SQLCODE -151 SQLSTATE 42808
Explanation: Column &1 in table &2 in &3 read-only.
SQL0129 SQLCODE -129 SQLSTATE 54004
Explanation: Too many tables in SQL statement.
SQL0152 SQLCODE -152 SQLSTATE 42809
Explanation: Constraint type not valid for constraint
SQL0130 SQLCODE -130 SQLSTATE 22019,
&1 in &2.
22025
Explanation: Escape character &1 or LIKE pattern not
SQL0153 SQLCODE -153 SQLSTATE 42908
valid.
Explanation: Column list required for CREATE VIEW.
SQL0131 SQLCODE -131 SQLSTATE 42818
SQL0154 SQLCODE -154 SQLSTATE 42909
Explanation: Operands of LIKE not compatible or not
valid. Explanation: UNION and UNION ALL for CREATE
VIEW not valid.

592 DB2 UDB for AS/400 SQL Programming V4R4


SQL0156 SQLCODE -156 SQLSTATE 42809 SQL0183 SQLCODE -183 SQLSTATE 22008
Explanation: &1 in &2 not a table. Explanation: The result of a date or timestamp
expression not valid.
SQL0157 SQLCODE -157 SQLSTATE 42810
SQL0184 SQLCODE -184 SQLSTATE 42610
Explanation: View &1 in &2 not valid in FOREIGN
KEY clause. Explanation: Parameter marker not valid in
expression.
SQL0158 SQLCODE -158 SQLSTATE 42811
SQL0187 SQLCODE -187 SQLSTATE 42816
Explanation: Number of columns specified not
consistent. Explanation: Use of labeled duration is not valid.

SQL0159 SQLCODE -159 SQLSTATE 42809 SQL0188 SQLCODE -188 SQLSTATE 22503,
28000, 2E000
Explanation: &1 in &2 not correct type.
Explanation: &1 is not a valid string representation of
an authorization name or a relational database name.
SQL0160 SQLCODE -160 SQLSTATE 42813
Explanation: WITH CHECK OPTION not allowed for
SQL0189 SQLCODE -189 SQLSTATE 22522
view &1 in &2.
Explanation: Coded Character Set Identifier &1 is not
valid.
SQL0161 SQLCODE -161 SQLSTATE 44000
Explanation: INSERT/UPDATE not allowed due to
SQL0190 SQLCODE -190 SQLSTATE 42837
WITH CHECK OPTION.
Explanation: Attributes of column &3 in &1 in &2 not
compatible.
SQL0170 SQLCODE -170 SQLSTATE 42605
Explanation: Number of arguments for function &1 not
SQL0191 SQLCODE -191 SQLSTATE 22504
valid.
Explanation: MIXED data not properly formed.
SQL0171 SQLCODE -171 SQLSTATE 42815
SQL0192 SQLCODE -192 SQLSTATE 42937
Explanation: Argument &1 of function &2 not valid.
Explanation: Argument of TRANSLATE function not
valid.
SQL0175 SQLCODE -175 SQLSTATE 58028
Explanation: COMMIT failed.
SQL0194 SQLCODE -194 SQLSTATE 42848
Explanation: KEEP LOCKS not allowed.
SQL0180 SQLCODE -180 SQLSTATE 22007
Explanation: Syntax of date, time, or timestamp value
SQL0195 SQLCODE -195 SQLSTATE 42814
not valid.
Explanation: Last column of &1 in &2 cannot be
dropped.
SQL0181 SQLCODE -181 SQLSTATE 22007
Explanation: Value in date, time, or timestamp string
SQL0196 SQLCODE -196 SQLSTATE 42817
not valid.
Explanation: Column &3 in &1 in &2 cannot be
dropped with RESTRICT.
SQL0182 SQLCODE -182 SQLSTATE 42816
Explanation: A date, time, or timestamp expression
SQL0197 SQLCODE -197 SQLSTATE 42877
not valid.
Explanation: Column &1 cannot be qualified.

Appendix B. SQLCODEs and SQLSTATEs 593


SQL0198 SQLCODE -198 SQLSTATE 42617 SQL0228 SQLCODE -228 SQLSTATE 42620
Explanation: SQL statement empty or blank. Explanation: FOR UPDATE OF clause not valid with
SCROLL for cursor &1.
SQL0199 SQLCODE -199 SQLSTATE 42601
SQL0231 SQLCODE -231 SQLSTATE 22006
Explanation: Keyword &1 not expected. Valid tokens:
&2. Explanation: Position of cursor &1 not valid for
FETCH of current row.
SQL0203 SQLCODE -203 SQLSTATE 42702
SQL0250 SQLCODE -250 SQLSTATE 42718
Explanation: Column &1 is ambiguous.
Explanation: Local relational database not defined in
the directory.
SQL0204 SQLCODE -204 SQLSTATE 42704
Explanation: &1 in &2 type *&3 not found.
SQL0251 SQLCODE -251 SQLSTATE 2E000,
42602
SQL0205 SQLCODE -205 SQLSTATE 42703
Explanation: Character in relational database name
Explanation: Column &1 not in table &2. &1 is not valid.

SQL0206 SQLCODE -206 SQLSTATE 42703 SQL0255 SQLCODE -255 SQLSTATE 42999

Explanation: Column &1 not in specified tables. Explanation: DB2 Multisystem query error.

SQL0208 SQLCODE -208 SQLSTATE 42707 SQL0256 SQLCODE -256 SQLSTATE 42998

Explanation: ORDER BY column &1 not in results Explanation: Constraint &1 in &2 not allowed on
table. distributed file.

SQL0212 SQLCODE -212 SQLSTATE 42712 SQL0270 SQLCODE -270 SQLSTATE 42997

Explanation: Duplicate table designator &1 not valid. Explanation: Unique index not allowed.

SQL0214 SQLCODE -214 SQLSTATE 42822 SQL0301 SQLCODE -301 SQLSTATE


07006,42895
Explanation: ORDER BY expression is not valid.
Explanation: Input host variable &2 or argument &1
not valid.
SQL0221 SQLCODE -221 SQLSTATE 42873
Explanation: Number of rows &2 not valid. SQL0302 SQLCODE -302 SQLSTATE 22001,
22003, 22023, 22024
SQL0225 SQLCODE -225 SQLSTATE 42872 Explanation: Conversion error on input host variable
Explanation: FETCH not valid; cursor &1 not declared &2.
with SCROLL.
SQL0303 SQLCODE -303 SQLSTATE 22001,
SQL0226 SQLCODE -226 SQLSTATE 24507 42806

Explanation: Current row deleted or moved for cursor Explanation: Host variable &1 not compatible with
&1. SELECT item.

SQL0227 SQLCODE -227 SQLSTATE 24513 SQL0304 SQLCODE -304 SQLSTATE 22003,
22023, 22504
Explanation: FETCH not valid, cursor &1 in unknown
position. Explanation: Conversion error in assignment to host
variable &2.

594 DB2 UDB for AS/400 SQL Programming V4R4


SQL0305 SQLCODE -305 SQLSTATE 22002 | SQL0340 SQLCODE -340 SQLSTATE 42726
Explanation: Indicator variable required. | Explanation: Duplicate name &1 for common table
| expression.
SQL0306 SQLCODE -306 SQLSTATE 42863
| SQL0341 SQLCODE -341 SQLSTATE 42835
Explanation: Undefined host variable in REXX.
| Explanation: Cyclic references between common
| table expressions.
SQL0311 SQLCODE -311 SQLSTATE 22501
Explanation: Length in a varying-length host variable
| SQL0346 SQLCODE -346 SQLSTATE 42836
not valid.
| Explanation: Recursion not allowed for common table
| expressions.
SQL0312 SQLCODE -312 SQLSTATE 42618
Explanation: Host variable &1 not defined or not
| SQL0350 SQLCODE -350 SQLSTATE 42962
usable.
| Explanation: Column &1 is not valid as key field for
| index or constraint.
SQL0313 SQLCODE -313 SQLSTATE 07001,
07004
SQL0351 SQLCODE -351 SQLSTATE 56084
Explanation: Number of host variables not valid.
| Explanation: The AR is not at the same level and
| DB2/400 cannot transform the data type to a compatible
SQL0328 SQLCODE -328 SQLSTATE 42996
| type.
Explanation: Column &1 not allowed in partitioning
key.
| SQL0352 SQLCODE -352 SQLSTATE 56084
| Explanation: The AS is not at the same level and
| SQL0329 SQLCODE -329 SQLSTATE 0E000
| DB2/400 cannot transform the data type to a compatible
| Explanation: The SET PATH name list is not valid. | type.

SQL0330 SQLCODE -330 SQLSTATE 22021 | SQL0357 SQLCODE -357 SQLSTATE 57050

Explanation: Character conversion cannot be | Explanation: File server &1 used in DataLink not
performed. | currently available.

SQL0331 SQLCODE -331 SQLSTATE 22021 | SQL0358 SQLCODE -358 SQLSTATE 428D1

Explanation: Character conversion cannot be | Explanation: Error &1 occurred using DataLink data
performed. | type.

SQL0332 SQLCODE -332 SQLSTATE 57017 | SQL0392 SQLCODE -392 SQLSTATE 42855

Explanation: Character conversion between CCSID | Explanation: Assignment of LOB to specified host
&1 and CCSID &2 not valid. | variable not allowed.

SQL0334 SQLCODE -334 SQLSTATE 22524 | SQL0398 SQLCODE -398 SQLSTATE 428D2

Explanation: Character conversion has resulted in | Explanation: AS LOCATOR cannot be specified for a
truncation. | non-LOB parameter.

SQL0338 SQLCODE -338 SQLSTATE 42972 SQL0401 SQLCODE -401 SQLSTATE 42818

Explanation: JOIN expression not valid. Explanation: Comparison operator &1 operands not
compatible.

Appendix B. SQLCODEs and SQLSTATEs 595


SQL0402 SQLCODE -402 SQLSTATE 42819 SQL0420 SQLCODE -420 SQLSTATE 22018
Explanation: &1 use not valid. Explanation: Character in CAST argument not valid.

SQL0404 SQLCODE -404 SQLSTATE 22001 SQL0421 SQLCODE -421 SQLSTATE 42826
Explanation: Value for column &1 too long. Explanation: Number of UNION operands not equal.

SQL0405 SQLCODE -405 SQLSTATE 42820 | SQL0423 SQLCODE -423 SQLSTATE 0F001
Explanation: Numeric constant &1 out of range. | Explanation: LOB locator &1 not valid.

SQL0406 SQLCODE -406 SQLSTATE 22003, SQL0428 SQLCODE -428 SQLSTATE 25501
22023, 22504
Explanation: SQL statement cannot be run.
Explanation: Conversion error on assignment to
column &2.
| SQL0429 SQLCODE -429 SQLSTATE 54028

SQL0407 SQLCODE -407 SQLSTATE 23502


| Explanation: The maximum number of concurrent
| LOB lcoators has been reached.
Explanation: Null values are not allowed in column
&1.
| SQL0432 SQLCODE -432 SQLSTATE 42841

SQL0408 SQLCODE -408 SQLSTATE 42821


| Explanation: A parameter marker cannot have the
| user-defined type name &1.
Explanation: INSERT or UPDATE value for column
&1 not compatible.
SQL0433 SQLCODE -433 SQLSTATE 22001
Explanation: Significant digits truncated during CAST
SQL0410 SQLCODE -410 SQLSTATE 42820
from numeric to character.
Explanation: Floating point literal &1 not valid.
SQL0440 SQLCODE -440 SQLSTATE 42884
SQL0412 SQLCODE -412 SQLSTATE 42823
Explanation: Number of arguments on CALL must
Explanation: Subquery with more than one result match procedure.
column not valid.
| SQL0441 SQLCODE -441 SQLSTATE 42601
SQL0414 SQLCODE -414 SQLSTATE 42824
| Explanation: Clause or keyword &1 not valid where
Explanation: Column &1 not valid in LIKE predicate. | specified.

SQL0415 SQLCODE -415 SQLSTATE 42825 SQL0442 SQLCODE -442 SQLSTATE 54023
Explanation: UNION operands not compatible. Explanation: Maximum # of parameters on CALL
exceeded.
SQL0417 SQLCODE -417 SQLSTATE 42609
SQL0443 SQLCODE -443 SQLSTATE 2Fxxx,
Explanation: Combination of parameter markers not
38501
valid.
Explanation: Trigger program or external procedure
detected on error.
SQL0418 SQLCODE -418 SQLSTATE 42610
Explanation: Use of parameter marker is not valid.
SQL0444 SQLCODE -444 SQLSTATE 42724
Explanation: External program &4 in &1 not found.
SQL0419 SQLCODE -419 SQLSTATE 42911
Explanation: Negative scale not valid.

596 DB2 UDB for AS/400 SQL Programming V4R4


SQL0446 SQLCODE -446 SQLSTATE 22003 | SQL0463 SQLCODE -463 SQLSTATE 39001
Explanation: Conversion error in assignment of | Explanation: SQLSTATE &4 returned from routine &1
argument &2. | in &2 not valid..

SQL0448 SQLCODE -448 SQLSTATE 54023 SQL0469 SQLCODE -469 SQLSTATE 42886
Explanation: Maximum parameters on DECLARE Explanation: IN, OUT, INOUT not valid for parameter
PROCEDURE exceeded. &4 in procedure &1 in &2.

SQL0449 SQLCODE -449 SQLSTATE 42878 SQL0470 SQLCODE -470 SQLSTATE 39002
Explanation: External program name for procedure &1 Explanation: NULL values not allowed for parameter
in &2 not valid. &4 in procedure.

SQL0451 SQLCODE -451 SQLSTATE 42815 | SQL0473 SQLCODE -473 SQLSTATE 42918
Explanation: Attributes of parameter &1 not valid for | Explanation: User-defined type &1 cannot be created.
procedure.
| SQL0475 SQLCODE -475 SQLSTATE 42866
| SQL0452 SQLCODE -452 SQLSTATE 428A1
| Explanation: RETURNS data type for function &3 in
| Explanation: Unable to access a file that is referred to | &4 not valid.
| by a file reference variable.
| SQL0476 SQLCODE -476 SQLSTATE 42725
| SQL0453 SQLCODE -453 SQLSTATE 42880
| Explanation: Function &1 in &2 not unique.
| Explanation: Return type for function &1 in &2 not
| compatible with CAST TO type.
| SQL0478 SQLCODE -478 SQLSTATE 42893

| SQL0454 SQLCODE -454 SQLSTATE 42723


| Explanation: Object &1 in &2 of type &3 cannot be
| dropped.
| Explanation: Function &1 in &2 with the same
| signature already exists.
| SQL0483 SQLCODE -483 SQLSTATE 42885

SQL0455 SQLCODE -455 SQLSTATE 42882


| Explanation: Parameters for function &1 in &2 not
| same as sourced function.
Explanation: Specific name not same as procedure
name.
| SQL0484 SQLCODE -484 SQLSTATE 42733
| Explanation: Routine &1 in &2 already exists.
| SQL0456 SQLCODE -456 SQLSTATE 42710
| Explanation: Specific name &3 in &2 already exists.
SQL0487 SQLCODE -487 SQLSTATE 38001
Explanation: SQL statements not allowed.
| SQL0457 SQLCODE -457 SQLSTATE 42939
| Explanation: Name &1 in &2 not allowed for function.
SQL0490 SQLCODE -490 SQLSTATE 428B7
Explanation: Numeric value &1 not valid.
| SQL0458 SQLCODE -458 SQLSTATE 42883
| Explanation: Function &1 in &2 not found with
| SQL0491 SQLCODE -491 SQLSTATE 42601
| matching signature.
| Explanation: RETURNS clause required on CREATE
SQL0461 SQLCODE -461 SQLSTATE 42846
| FUNCTION statement.

Explanation: Cast from &1 to &2 not supported.

Appendix B. SQLCODEs and SQLSTATEs 597


| SQL0492 SQLCODE -492 SQLSTATE 42879 SQL0517 SQLCODE -517 SQLSTATE 07005
| Explanation: Data type for function &1 in &2 not valid Explanation: Prepared statement &2 not SELECT
| for source type. statement.

SQL0501 SQLCODE -501 SQLSTATE 24501 SQL0518 SQLCODE -518 SQLSTATE 07003
Explanation: Cursor &1 not open. Explanation: Prepared statement &1 not found.

SQL0502 SQLCODE -502 SQLSTATE 24502 SQL0519 SQLCODE -519 SQLSTATE 24506
Explanation: Cursor &1 already open. Explanation: Prepared statement &2 in use.

SQL0503 SQLCODE -503 SQLSTATE 42912 SQL0520 SQLCODE -520 SQLSTATE 42828
Explanation: Column &3 cannot be updated. Explanation: Cannot UPDATE or DELETE on cursor
&1.
SQL0504 SQLCODE -504 SQLSTATE 34000
SQL0525 SQLCODE -525 SQLSTATE 51015
Explanation: Cursor &1 not declared.
Explanation: Statement not valid on application
server.
SQL0507 SQLCODE -507 SQLSTATE 24501
Explanation: Cursor &1 not open.
SQL0527 SQLCODE -527 SQLSTATE 42874
Explanation: ALWCPYDTA(*NO) specified but
SQL0508 SQLCODE -508 SQLSTATE 24504
temporary result required for &1.
Explanation: Cursor &1 not positioned on locked row.
SQL0530 SQLCODE -530 SQLSTATE 23503
SQL0509 SQLCODE -509 SQLSTATE 42827
Explanation: Insert or UPDATE value not allowed by
Explanation: Table &2 in &3 not same as table in referential constraint.
cursor &1.
SQL0531 SQLCODE -531 SQLSTATE 23001,
SQL0510 SQLCODE -510 SQLSTATE 42828 23504

Explanation: Cursor &1 for file &2 is read-only. Explanation: Update prevented by referential
constraint.

SQL0511 SQLCODE -511 SQLSTATE 42829


SQL0532 SQLCODE -532 SQLSTATE 23001,
Explanation: FOR UPDATE OF clause not valid. 23504
Explanation: Delete prevented by referential
SQL0513 SQLCODE -513 SQLSTATE 42924 constraint.
Explanation: Alias &1 in &2 cannot reference another
alias. SQL0536 SQLCODE -536 SQLSTATE 42914
Explanation: Delete not allowed because table
SQL0514 SQLCODE -514 SQLSTATE 26501 referenced in subquery can be affected.
Explanation: Prepared statement &2 not found.
SQL0537 SQLCODE -537 SQLSTATE 42709
SQL0516 SQLCODE -516 SQLSTATE 26501 Explanation: Duplicate column name in definition of
Explanation: Prepared statement &2 not found. key.

598 DB2 UDB for AS/400 SQL Programming V4R4


SQL0538 SQLCODE -538 SQLSTATE 42830 SQL0577 SQLCODE -577 SQLSTATE 38002,
2F002
Explanation: Foreign key attributes do not match
parent key. Explanation: Modifying SQL data not permitted.

SQL0539 SQLCODE -539 SQLSTATE 42888 SQL0579 SQLCODE -579 SQLSTATE 38004,
2F004
Explanation: Table does not have primary key.
Explanation: Reading SQL data not permitted.
SQL0541 SQLCODE -541 SQLSTATE 42891
SQL0580 SQLCODE -580 SQLSTATE 42625
Explanation: Duplicate UNIQUE constraint already
exists. Explanation: At least one result in CASE expression
must be not NULL.
SQL0543 SQLCODE -543 SQLSTATE 23511
SQL0581 SQLCODE -581 SQLSTATE 42804
Explanation: Constraint &1 conflicts with SET NULL
or SET DEFAULT rule. Explanation: The results in a CASE expression are
not compatible.
SQL0544 SQLCODE -544 SQLSTATE 23512
| SQL0583 SQLCODE -583 SQLSTATE 42845
Explanation: CHECK constraint &1 cannot be added.
| Explanation: Use of function &1 in &2 not valid.
SQL0545 SQLCODE -545 SQLSTATE 23513
| SQL0585 SQLCODE -585 SQLSTATE 42732
Explanation: INSERT or UPDATE not allowed by
CHECK constraint. | Explanation: Library &1 is used incorrectly on the
| SET PATH statement
SQL0546 SQLCODE -546 SQLSTATE 42621
SQL0590 SQLCODE -590 SQLSTATE 42734
Explanation: CHECK condition of constraint &1 not
valid. Explanation: Name &1 specified in &2 not unique.

SQL0551 SQLCODE -551 SQLSTATE 42501 SQL0601 SQLCODE -601 SQLSTATE 42710
Explanation: Not authorized to object &1 in &2 type Explanation: Object &1 in &2 type *&3 already exists.
*&3.
SQL0602 SQLCODE -602 SQLSTATE 54008
SQL0552 SQLCODE -552 SQLSTATE 42502
Explanation: More than 120 columns specified for
Explanation: Not authorized to &1. CREATE INDEX.

SQL0557 SQLCODE -557 SQLSTATE 42852 SQL0603 SQLCODE -603 SQLSTATE 23515
Explanation: Privilege not valid for table or view &1 in Explanation: Unique index cannot be created
&2. because of duplicate keys.

SQL0573 SQLCODE -573 SQLSTATE 42890 SQL0604 SQLCODE -604 SQLSTATE 42611
Explanation: Table does not have matching parent Explanation: Attributes of column not valid.
key.
SQL0607 SQLCODE -607 SQLSTATE 42832
SQL0574 SQLCODE -574 SQLSTATE 42894
Explanation: Operation not allowed on system table
Explanation: Default value not valid. &1 in &2.

Appendix B. SQLCODEs and SQLSTATEs 599


SQL0612 SQLCODE -612 SQLSTATE 42711 SQL0666 SQLCODE -666 SQLSTATE 57005
Explanation: &1 is a duplicate column name. Explanation: Estimated query processing time
exceeds limit.
SQL0613 SQLCODE -613 SQLSTATE 54008
SQL0667 SQLCODE -667 SQLSTATE 23520
Explanation: Primary or unique key constraint too
long. Explanation: Foreign key does not match a value in
the parent key.
SQL0614 SQLCODE -614 SQLSTATE 54008
SQL0675 SQLCODE -675 SQLSTATE 42892
Explanation: Length of columns for CREATE INDEX
too long. Explanation: Specified delete rule not allowed with
existing trigger.
SQL0615 SQLCODE -615 SQLSTATE 55006
SQL0679 SQLCODE -679 SQLSTATE 57006
Explanation: Object &1 in &2 type *&3 not dropped. It
is in use. Explanation: Object &1 in &2 type *&3 not created
due to pending operation.
SQL0616 SQLCODE -616 SQLSTATE 42893
SQL0683 SQLCODE -683 SQLSTATE 42842
Explanation: &1 in &2 type &3 cannot be dropped
with RESTRICT. Explanation: FOR DATA or CCSID clause not valid for
specified type.
SQL0624 SQLCODE -624 SQLSTATE 42889
| SQL0707 SQLCODE -707 SQLSTATE 42939
Explanation: Table already has primary key.
| Explanation: Name &1 in &2 not allowed for distinct
| type.
SQL0628 SQLCODE -628 SQLSTATE 42613
Explanation: Clauses are mutually exclusive.
| SQL0713 SQLCODE -713 SQLSTATE 42815
| Explanation: Host variable for &2 is NULL.
SQL0629 SQLCODE -629 SQLSTATE 42834
Explanation: SET NULL not allowed for referential
SQL0724 SQLCODE -724 SQLSTATE 54038
constraint.
Explanation: Too many cascaded trigger programs.
SQL0631 SQLCODE -631 SQLSTATE 54008
SQL0751 SQLCODE -751 SQLSTATE 42987
Explanation: Foreign key for referential constraint too
long. Explanation: SQL statement &1 not allowed in stored
procedure or trigger.
SQL0637 SQLCODE -637 SQLSTATE 42614
SQL0752 SQLCODE -752 SQLSTATE 0A001
Explanation: Duplicate &1 keyword.
Explanation: Connection cannot be changed. Reason
code is &1.
SQL0642 SQLCODE -642 SQLSTATE 54021
Explanation: Maximum number of constraints
SQL0773 SQLCODE -773 SQLSTATE 20000
exceeded.
Explanation: Case not found for CASE statement.
| SQL0658 SQLCODE -658 SQLSTATE 42917
SQL0774 SQLCODE -774 SQLSTATE 2D522
| Explanation: Function cannot be dropped.
Explanation: Statement cannot be executed within a
compound SQL statement.

600 DB2 UDB for AS/400 SQL Programming V4R4


SQL0775 SQLCODE -775 SQLSTATE 42910 SQL0803 SQLCODE -803 SQLSTATE 23505
Explanation: Statement not allowed in a compound Explanation: Duplicate key value specified.
SQL statement.
SQL0804 SQLCODE -804 SQLSTATE 07002
SQL0776 SQLCODE -776 SQLSTATE 428D4
Explanation: SQLDA not valid.
Explanation: Cursor &1 specified in FOR statement
not allowed.
SQL0805 SQLCODE -805 SQLSTATE 51002
Explanation: SQL package &1 in &2 not found.
SQL0777 SQLCODE -777 SQLSTATE 42919
Explanation: Nested compound statements not
SQL0811 SQLCODE -811 SQLSTATE 21000
allowed.
Explanation: Result of SELECT INTO or subquery
more than one row.
SQL0778 SQLCODE -778 SQLSTATE 428D5
Explanation: End label &1 not same as begin label.
SQL0818 SQLCODE -818 SQLSTATE 51003
Explanation: Consistency tokens do not match.
SQL0779 SQLCODE -779 SQLSTATE 42736
Explanation: Label &1 specified on LEAVE statement
SQL0822 SQLCODE -822 SQLSTATE 51004
not valid.
Explanation: Address in SQLDA not valid.
SQL0780 SQLCODE -780 SQLSTATE 428D6
SQL0827 SQLCODE -827 SQLSTATE 42862
Explanation: UNDO specified for a handler and
ATOMIC not specified. Explanation: &1 in &2 type *SQLPKG cannot be
accessed.
SQL0781 SQLCODE -781 SQLSTATE 42737
SQL0840 SQLCODE -840 SQLSTATE 54004
Explanation: Condition &1 specified in handler not
defined. Explanation: Number of selected items exceeds 8000.

SQL0782 SQLCODE -782 SQLSTATE 428D7 SQL0842 SQLCODE -842 SQLSTATE 08002
Explanation: Condition value &1 specified in handler Explanation: Connection already exists.
not valid.

SQL0843 SQLCODE -843 SQLSTATE 08003


SQL0783 SQLCODE -783 SQLSTATE 42738
Explanation: Connection does not exist.
Explanation: Select list for cursor &1 in FOR
statement not valid.
SQL0858 SQLCODE -858 SQLSTATE 08501

SQL0784 SQLCODE -784 SQLSTATE 42860 Explanation: Cannot disconnect relational database
due to LU 6.2 protected conversation.
Explanation: Check constraint &1 cannot be dropped.
SQL0862 SQLCODE -862 SQLSTATE 55029
SQL0785 SQLCODE -785 SQLSTATE 428D8
Explanation: Local program attempted to connect to a
Explanation: Use of SQLCODE or SQLSTATE not remote relational database.
valid.

SQL0871 SQLCODE -871 SQLSTATE 54019


SQL0802 SQLCODE -802 SQLSTATE 22003,
22012, 22023, 22504 Explanation: Too many CCSID values specified.

Explanation: Data conversion or data mapping error.

Appendix B. SQLCODEs and SQLSTATEs 601


SQL0900 SQLCODE -900 SQLSTATE 08003 SQL0971 SQLCODE -971 SQLSTATE 57011
Explanation: Application process not in a connected Explanation: Referential constraint &4 in check
state. pending state.

SQL0901 SQLCODE -901 SQLSTATE 58004 SQL5001 SQLCODE -5001 SQLSTATE 42703
Explanation: SQL system error. Explanation: Column qualifier &2 undefined.

SQL0904 SQLCODE -904 SQLSTATE 57011 SQL5002 SQLCODE -5002 SQLSTATE 42812
Explanation: Resource limit exceeded. Explanation: Collection must be specified for table &1.

SQL0906 SQLCODE -906 SQLSTATE 24514 SQL5003 SQLCODE -5003 SQLSTATE 42922
Explanation: Operation not performed because of Explanation: Cannot perform operation under
previous error. commitment control.

SQL0907 SQLCODE -907 SQLSTATE 27000 SQL5005 SQLCODE -5005 SQLSTATE 42815
Explanation: Attempt to change same row twice. Explanation: Operator &4 not consistent with
operands.
SQL0910 SQLCODE -910 SQLSTATE 57007
SQL5012 SQLCODE -5012 SQLSTATE 42618
Explanation: Object &1 in &2 type *&3 has a pending
change. Explanation: Host variable not a numeric with zero
scale.
SQL0913 SQLCODE -913 SQLSTATE 57033
SQL5016 SQLCODE -5016 SQLSTATE 42833
Explanation: Row or object &1 in &2 type *&3 in use.
Explanation: Object name &1 not valid for naming
option.
SQL0917 SQLCODE -917 SQLSTATE 42969
Explanation: Package not created.
SQL5021 SQLCODE -5021 SQLSTATE 42930
Explanation: FOR UPDATE OF column &1 also in
SQL0918 SQLCODE -918 SQLSTATE 51021
ORDER BY.
Explanation: Rollback required.
SQL5023 SQLCODE -5023 SQLSTATE 26510
SQL0950 SQLCODE -950 SQLSTATE 42705
Explanation: Duplicate statement name in DECLARE
Explanation: Relational database &1 not in relational CURSOR.
database directory.
SQL5024 SQLCODE -5024 SQLSTATE 42618
SQL0951 SQLCODE -951 SQLSTATE 55007
Explanation: Host variable &1 not character.
Explanation: Object &1 in &2 not altered. It is in use.
SQL5047 SQLCODE -5047 SQLSTATE 42616
SQL0952 SQLCODE -952 SQLSTATE 57014
Explanation: Error processing SRTSEQ or LANGID
Explanation: Processing of the SQL statement ended parameter.
by ENDRDBRQS command.
SQL5051 SQLCODE -5051 SQLSTATE 42875
SQL0969 SQLCODE -969 SQLSTATE 58033
Explanation: Incorrect qualifier.
Explanation: Unexpected client driver error.

602 DB2 UDB for AS/400 SQL Programming V4R4


SQL7001 SQLCODE -7001 SQLSTATE 42858 SQL7026 SQLCODE -7026 SQLSTATE 42896
Explanation: File &1 in &2 not database file. Explanation: Auxiliary storage pool not found.

SQL7002 SQLCODE -7002 SQLSTATE 42847 SQL7027 SQLCODE -7027 SQLSTATE 42984
Explanation: Override parameter not valid. Explanation: Unable to grant to a view.

SQL7003 SQLCODE -7003 SQLSTATE 42857 SQL7028 SQLCODE -7028 SQLSTATE 42944
Explanation: File &1 in &2 has more than one format. Explanation: Unable to CHGOBJOWN for primary
group.
SQL7006 SQLCODE -7006 SQLSTATE 55018
SQL7029 SQLCODE -7029 SQLSTATE 428B8
Explanation: Cannot drop collection &1.
Explanation: New name &3 is not valid.
SQL7007 SQLCODE -7007 SQLSTATE 51009
SQL7031 SQLCODE -7031 SQLSTATE 54044
Explanation: COMMIT or ROLLBACK not valid.
Explanation: Sort sequence table &1 too long.
SQL7008 SQLCODE -7008 SQLSTATE 55019
SQL7032 SQLCODE -7032 SQLSTATE 42904
Explanation: &1 in &2 not valid for operation.
Explanation: SQL procedure &1 in &2 not created.
SQL7010 SQLCODE -7010 SQLSTATE 42850
SQL7033 SQLCODE -7033 SQLSTATE 42923
Explanation: Logical file &1 in &2 not valid for
CREATE VIEW. Explanation: Alias name &1 in &2 not allowed.

SQL7011 SQLCODE -7011 SQLSTATE 42851 | SQL7034 SQLCODE -7034 SQLSTATE 42926
Explanation: &1 in &2 not table, view, or physical file. | Explanation: LOB locators are not allowed with
| COMMIT(*NONE).
SQL7017 SQLCODE -7017 SQLSTATE 42971
| SQL7037 SQLCODE -7037 SQLSTATE 42835
Explanation: Commitment control is already active to
a DDM target. | Explanation: Data in a distributed file &1 in &2 cannot
| be redistributed.
SQL7018 SQLCODE -7018 SQLSTATE 42970
SQL7941 SQLCODE -7941 SQLSTATE 42981
Explanation: COMMIT HOLD or ROLLBACK HOLD
not allowed. Explanation: Application process not at commit
boundary.
SQL7021 SQLCODE -7021 SQLSTATE 57043
SQL9012 SQLCODE -9012 SQLSTATE 42968
Explanation: Local program attempting to run on
application server. Explanation: DB2 UDB Query Manager and SQL
Development Kit not available.
SQL7022 SQLCODE -7022 SQLSTATE 42977
SQ30000 SQLCODE -30000 SQLSTATE 58008
Explanation: User &1 not the same as current user
&2 for connect to local relational database. Explanation: Distributed Relational Database
Architecture (DRDA) protocol error.
SQL7024 SQLCODE -7024 SQLSTATE 42876
SQ30001 SQLCODE -30001 SQLSTATE 57042
Explanation: Index cannot be created because of
CCSID incompatibility. Explanation: Call to distributed SQL program not
allowed.

Appendix B. SQLCODEs and SQLSTATEs 603


SQ30020 SQLCODE -30020 SQLSTATE 58009 SQ30072 SQLCODE -30072 SQLSTATE 58016
Explanation: Distributed Relational Database Explanation: Distributed Data Management (DDM)
Architecture (DRDA) protocol error. parameter &1 not supported.

SQ30021 SQLCODE -30021 SQLSTATE 58010 SQ30073 SQLCODE -30073 SQLSTATE 58017
Explanation: Distributed relational database not Explanation: Distributed Data Management (DDM)
supported by the remote system. parameter value &1 not supported.

SQ30040 SQLCODE -30040 SQLSTATE 57012 SQ30074 SQLCODE -30074 SQLSTATE 58018
Explanation: DDM resource &2 at relational database Explanation: Distributed Data Management (DDM)
&1 not available. reply message &1 not supported.

SQ30041 SQLCODE -30041 SQLSTATE 57013 SQ30080 SQLCODE -30080 SQLSTATE 08001
Explanation: DDM resources at relational database Explanation: Communication error occurred during
&1 not available. distributed database processing.

SQ30050 SQLCODE -30050 SQLSTATE 58011 SQ30089 SQLCODE -30089 SQLSTATE 08001
Explanation: DDM command &1 is not valid while Explanation: Communication error occurred during
bind process is in progress. DB2 Multisystem processing.

SQ30051 SQLCODE -30051 SQLSTATE 58012 SQ30090 SQLCODE -30090 SQLSTATE 25000,
2D528, 2D529
Explanation: Bind process for specified package
name and consistency token not active. Explanation: Change request not valid for read-only
application server.
SQ30052 SQLCODE -30052 SQLSTATE 42932
Explanation: Program preparation assumptions not
correct.

SQ30053 SQLCODE -30053 SQLSTATE 42506


Explanation: Not authorized to create package for
owner &1.

SQ30060 SQLCODE -30060 SQLSTATE 08004


Explanation: User not authorized to relational
database &1.

SQ30061 SQLCODE -30061 SQLSTATE 08004


Explanation: Relational database &1 not found.

SQ30070 SQLCODE -30070 SQLSTATE 58014


Explanation: Distributed Data Management (DDM)
command &1 not supported.

SQ30071 SQLCODE -30071 SQLSTATE 58015


Explanation: Distributed Data Management (DDM)
object &1 not supported.

604 DB2 UDB for AS/400 SQL Programming V4R4


Appendix C. Sample Programs Using DB2 UDB for AS/400
Statements
This appendix contains a sample application showing how to code SQL statements
in each of the languages supported by the DB2 UDB for AS/400 system: ILE C,
COBOL, ILE COBOL, PL/I, RPG for AS/400, ILE RPG for AS/400, and REXX.

Examples of programs that use SQL statements


The sample application gives raises based on commission.

Each sample program produces the same report, which is shown at the end of this
appendix. The first part of the report shows, by project, all employees working on
the project who received a raise. The second part of the report shows the new
salary expense for each project.

The following notes apply to all the sample programs:


SQL statements can be entered in upper or lowercase.
„1… This host language statement retrieves the external definitions for the SQL
table PROJECT. These definitions can be used as host variables or as a
host structure.
Notes:
1. In RPG for AS/400, field names in an externally described structure that
are longer than 6 characters must be renamed.
2. REXX does not support the retrieval of external definitions.
„2… The SQL INCLUDE SQLCA statement is used to include the SQLCA for
PL/I, C, and COBOL programs. For RPG programs, the SQL precompiler
automatically places the SQLCA data structure into the source at the end of
the Input specification section. For REXX, the SQLCA fields are maintained
in separate variables rather than in a contiguous data area mapped by the
SQLCA.
„3… This SQL WHENEVER statement defines the host language label to which
control is passed if an SQLERROR (SQLCODE < 0) occurs in an SQL
statement. This WHENEVER SQLERROR statement applies to all the
following SQL statements until the next WHENEVER SQLERROR
statement is encountered. REXX does not support the WHENEVER
statement. Instead, REXX uses the SIGNAL ON ERROR facility.
„4… This SQL UPDATE statement updates the SALARY column, which contains
the employee salary by the percentage in the host variable PERCENTAGE
(PERCNT for RPG). The updated rows are those that have employee
commissions greater than 2000. For REXX, this is PREPARE and
EXECUTE since UPDATE cannot be executed directly if there is a host
variable.
„5… This SQL COMMIT statement commits the changes made by the SQL
UPDATE statement. Record locks on all changed rows are released.

Note: The program was precompiled using COMMIT(*CHG). (For REXX,


*CHG. is the default.)
„6… This SQL DECLARE CURSOR statement defines cursor C1, which joins

© Copyright IBM Corp. 1997, 1999 605


two tables, EMPLOYEE and EMP_ACT, and returns rows for employees
who received a raise (commission > 2000). Rows are returned in ascending
order by project number and employee number (PROJNO and EMPNO
columns). For REXX, this is a PREPARE and DECLARE CURSOR since
the DECLARE CURSOR statement cannot be specified directly with a
statement string if it has host variables.
„7… This SQL OPEN statement opens cursor C1 so that the rows can be
fetched.
„8… This SQL WHENEVER statement defines the host language label to which
control is passed when all rows are fetched (SQLCODE = 100). For REXX,
the SQLCODE must be explicitly checked.
„9… This SQL FETCH statement returns all columns for cursor C1 and places
the returned values into the corresponding elements of the host structure.
„10… After all rows are fetched, control is passed to this label. The SQL CLOSE
statement closes cursor C1.
„11… This SQL DECLARE CURSOR statement defines cursor C2, which joins the
three tables, EMP_ACT, PROJECT, and EMPLOYEE. The results are
grouped by columns PROJNO and PROJNAME. The COUNT function
returns the number of rows in each group. The SUM function calculates the
new salary cost for each project. The ORDER BY 1 clause specifies that
rows are retrieved based on the contents of the final results column
(EMP_ACT.PROJNO). For REXX, this is a PREPARE and DECLARE
CURSOR since the DECLARE CURSOR statement cannot be specified
directly with a statement string if it has host variables.
„12… This SQL FETCH statement returns the results columns for cursor C2 and
places the returned values into the corresponding elements of the host
structure described by the program.
„13… This SQL WHENEVER statement with the CONTINUE option causes
processing to continue to the next statement regardless if an error occurs
on the SQL ROLLBACK statement. Errors are not expected on the SQL
ROLLBACK statement; however, this prevents the program from going into
a loop if an error does occur. SQL statements until the next WHENEVER
SQLERROR statement is encountered. REXX does not support the
WHENEVER statement. Instead, REXX uses the SIGNAL OFF ERROR
facility.
„14… This SQL ROLLBACK statement restores the table to its original condition if
an error occurred during the update.

SQL Statements in ILE C and C++ Programs


This sample program is written in the C programming language. The same program
would work in C++ if the following conditions are true:
v An SQL BEGIN DECLARE SECTION statement was added before line 18
v An SQL END DECLARE SECTION statement was added after line 42

606 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL ILE C Object CEX 04/01/98 15:52:26 Page 1
Source type...............C
Object name...............CORPDATA/CEX
Source file...............CORPDATA/SRC
Member....................CEX
To source file............QTEMP/QSQLTEMP
Options...................*XREF
Listing option............*PRINT
Target release............V4R4M0
INCLUDE file..............*LIBL/*SRCFILE
Commit....................*CHG
Allow copy of data........*YES
Close SQL cursor..........*ENDACTGRP
Allow blocking............*READ
Delay PREPARE.............*NO
Generation level..........10
Margins...................*SRCFILE
Printer file..............*LIBL/QSYSPRT
Date format...............*JOB
Date separator............*JOB
Time format...............*HMS
Time separator ...........*JOB
Replace...................*YES
Relational database.......*LOCAL
User .....................*CURRENT
RDB connect method........*DUW
Default Collection........*NONE
Package name..............*OBJLIB/*OBJ
Created object type.......*PGM
Debugging view............*NONE
Dynamic User Profile......*USER
User Profile..............*NAMING
Sort Sequence.............*JOB
Language ID...............*JOB
IBM SQL flagging..........*NOFLAG
ANS flagging..............*NONE
Text......................*SRCMBRTXT
Source file CCSID.........65535
Job CCSID.................65535
Source member changed on 04/01/98 17:15:17

Figure 39. Sample C Program Using SQL Statements (Part 1 of 7)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 607
5769ST1 V4R4M0 990521 Create SQL ILE C Object CEX 04/01/98 15:52:26 Page 2
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
1 #include "string.h" 100
2 #include "stdlib.h" 200
3 #include "stdio.h" 300
4 400
5 main() 500
6 { 600
7 /* A sample program which updates the salaries for those employees */ 700
8 /* whose current commission total is greater than or equal to the */ 800
9 /* value of 'commission'. The salaries of those who qualify are */ 900
10 /* increased by the value of 'percentage' retroactive to 'raise_date'*/ 1000
11 /* A report is generated showing the projects which these employees */ 1100
12 /* have contributed to ordered by project number and employee ID. */ 1200
13 /* A second report shows each project having an end date occurring */ 1300
14 /* after 'raise_date' (is potentially affected by the retroactive */ 1400
15 /* raises) with its total salary expenses and a count of employees */ 1500
16 /* who contributed to the project. */ 1600
17 1700
18 short work_days = 253; /* work days during in one year */ 1800
19 float commission = 2000.00; /* cutoff to qualify for raise */ 1900
20 float percentage = 1.04; /* raised salary as percentage */ 2000
21 char raise_date??(12??) = "1982-06-01"; /* effective raise date */ 2100
22 2200
23 /* File declaration for qprint */ 2300
24 FILE *qprint; 2400
25 2500
26 /* Structure for report 1 */ 2600
27 „1… #pragma mapinc ("project","CORPDATA/PROJECT(PROJECT)","both","p z") 2700
28 #include "project" 2800
29 struct { 2900
30 CORPDATA_PROJECT_PROJECT_both_t Proj_struct; 3000
31 char empno??(7??); 3100
32 char name??(30??); 3200
33 float salary; 3300
34 } rpt1; 3400
35 3500
36 /* Structure for report 2 */ 3600
37 struct { 3700
38 char projno??(7??); 3800
39 char project_name??(37??); 3900
40 short employee_count; 4000
41 double total_proj_cost; 4100
42 } rpt2; 4200
43 4300
44 „2… exec sql include SQLCA; 4400
45 4500
46 qprint=fopen("QPRINT","w"); 4600
47 4700
48 /* Update the selected projects by the new percentage. If an error */ 4800
49 /* occurs during the update, ROLLBACK the changes. */ 4900
50 „3… EXEC SQL WHENEVER SQLERROR GO TO update_error; 5000
51 „4… EXEC SQL 5100
52 UPDATE CORPDATA/EMPLOYEE 5200
53 SET SALARY = SALARY * :percentage 5300
54 WHERE COMM >= :commission ; 5400
55 5500
56 /* Commit changes */ 5600
57 „5… EXEC SQL 5700
58 COMMIT; 5800
59 EXEC SQL WHENEVER SQLERROR GO TO report_error; 5900
60 6000
61 /* Report the updated statistics for each employee assigned to the */ 6100
62 /* selected projects. */ 6200
63 6300
64 /* Write out the header for Report 1 */ 6400
65 fprintf(qprint," REPORT OF PROJECTS AFFECTED \ 6500

Figure 39. Sample C Program Using SQL Statements (Part 2 of 7)

608 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL ILE C Object CEX 04/01/98 15:52:26 Page 3
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
66 BY RAISES"); 6600
67 fprintf(qprint,"\n\nPROJECT EMPID EMPLOYEE NAME "); 6700
68 fprintf(qprint, " SALARY\n"); 6800
69 6900
70 „6… exec sql 7000
71 declare c1 cursor for 7100
72 select distinct projno, emp_act.empno, 7200
73 lastname||', '||firstnme, salary 7300
74 from corpdata/emp_act, corpdata/employee 7400
75 where emp_act.empno = employee.empno and comm >= :commission 7500
76 order by projno, empno; 7600
77 „7… EXEC SQL 7700
78 OPEN C1; 7800
79 7900
80 /* Fetch and write the rows to QPRINT */ 8000
81 „8… EXEC SQL WHENEVER NOT FOUND GO TO done1; 8100
82 8200
83 do { 8300
84 „10… EXEC SQL 8400
85 FETCH C1 INTO :Proj_struct.PROJNO, :rpt1.empno, 8500
86 :rpt1.name,:rpt1.salary; 8600
87 fprintf(qprint,"\n%6s %6s %-30s %8.2f", 8700
88 rpt1.Proj_struct.PROJNO,rpt1.empno, 8800
89 rpt1.name,rpt1.salary); 8900
90 } 9000
91 while (SQLCODE==0); 9100
92 9200
93 done1: 9300
94 EXEC SQL 9400
95 CLOSE C1; 9500
96 9600
97 /* For all projects ending at a date later than the 'raise_date' * / 9700
98 /* (i.e. those projects potentially affected by the salary raises) */ 9800
99 /* generate a report containing the project number, project name */ 9900
100 /* the count of employees participating in the project and the */ 10000
101 /* total salary cost of the project. */ 10100
102 10200
103 /* Write out the header for Report 2 */ 10300
104 fprintf(qprint,"\n\n\n ACCUMULATED STATISTICS\ 10400
105 BY PROJECT"); 10500
106 fprintf(qprint, "\n\nPROJECT \ 10600
107 NUMBER OF TOTAL"); 10700
108 fprintf(qprint, "\nNUMBER PROJECT NAME \ 10800
109 EMPLOYEES COST\n"); 10900
110 11000
111 „11… EXEC SQL 11100
112 DECLARE C2 CURSOR FOR 11200
113 SELECT EMP_ACT.PROJNO, PROJNAME, COUNT(*), 11300
114 SUM ( ( DAYS(EMENDATE) - DAYS(EMSTDATE) ) * EMPTIME * 11400
115 (DECIMAL( SALARY / :work_days ,8,2))) 11500
116 FROM CORPDATA/EMP_ACT, CORPDATA/PROJECT, CORPDATA/EMPLOYEE 11600
117 WHERE EMP_ACT.PROJNO=PROJECT.PROJNO and 11700
118 EMP_ACT.EMPNO =EMPLOYEE.EMPNO and 11800
119 PRENDATE > :raise_date 11900
120 GROUP BY EMP_ACT.PROJNO, PROJNAME 12000
121 ORDER BY 1; 12100
122 EXEC SQL 12200
123 OPEN C2; 12300
124 12400
125 /* Fetch and write the rows to QPRINT */ 12500
126 EXEC SQL WHENEVER NOT FOUND GO TO done2; 12600
127 12700
128 do { 12800
129 „12… EXEC SQL 12900
130 FETCH C2 INTO :rpt2; 13000

Figure 39. Sample C Program Using SQL Statements (Part 3 of 7)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 609
5769ST1 V4R4M0 990521 Create SQL ILE C Object CEX 04/01/98 15:52:26 Page 4
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
131 fprintf(qprint,"\n%6s %-36s %6d %9.2f", 13100
132 rpt2.projno,rpt2.project_name,rpt2.employee_count, 13200
133 rpt2.total_proj_cost); 13300
134 } 13400
135 while (SQLCODE==0); 13500
136 13600
137 done2: 13700
138 EXEC SQL 13800
139 CLOSE C2; 13900
140 goto finished; 14000
141 14100
142 /* Error occured while updating table. Inform user and rollback */ 14200
143 /* changes. */ 14300
144 update_error: 14400
145 „13… EXEC SQL WHENEVER SQLERROR CONTINUE; 14500
146 fprintf(qprint,"*** ERROR Occurred while updating table. SQLCODE=" 14600
147 "%5d\n",SQLCODE); 14700
148 „14… EXEC SQL 14800
149 ROLLBACK; 14900
150 goto finished; 15000
151 15100
152 /* Error occured while generating reports. Inform user and exit. */ 15200
153 report_error: 15300
154 fprintf(qprint,"*** ERROR Occurred while generating reports. " 15400
155 "SQLCODE=%5d\n",SQLCODE); 15500
156 goto finished; 15600
157 15700
158 /* All done */ 15800
159 finished: 15900
160 fclose(qprint); 16000
161 exit(0); 16100
162 16200
163 } 16300
* * * * * E N D O F S O U R C E * * * * *

Figure 39. Sample C Program Using SQL Statements (Part 4 of 7)

610 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL ILE C Object CEX 04/01/98 15:52:26 Page 5
CROSS REFERENCE
Data Names Define Reference
commission 19 FLOAT(24)
54 75
done1 **** LABEL
81
done2 **** LABEL
126
employee_count 40 SMALL INTEGER PRECISION(4,0) IN rpt2
empno 31 VARCHAR(7) IN rpt1
85
name 32 VARCHAR(30) IN rpt1
86
percentage 20 FLOAT(24)
53
project_name 39 VARCHAR(37) IN rpt2
projno 38 VARCHAR(7) IN rpt2
raise_date 21 VARCHAR(12)
119
report_error **** LABEL
59
rpt1 34
rpt2 42 STRUCTURE
130
salary 33 FLOAT(24) IN rpt1
86
total_proj_cost 41 FLOAT(53) IN rpt2
update_error **** LABEL
50
work_days 18 SMALL INTEGER PRECISION(4,0)
115
ACTNO 74 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
BIRTHDATE 74 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
BONUS 74 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
COMM **** COLUMN
54 75
COMM 74 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
CORPDATA **** COLLECTION
52 74 74 116 116 116
C1 71 CURSOR
78 85 95
C2 112 CURSOR
123 130 139
DEPTNO 27 VARCHAR(3) IN Proj_struct
DEPTNO 116 CHARACTER(3) COLUMN (NOT NULL) IN CORPDATA.PROJECT
EDLEVEL 74 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMENDATE 74 DATE(10) COLUMN IN CORPDATA.EMP_ACT
EMENDATE **** COLUMN
114
EMP_ACT **** TABLE
72 75 113 117 118 120
EMP_ACT **** TABLE IN CORPDATA
74 116

Figure 39. Sample C Program Using SQL Statements (Part 5 of 7)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 611
5769ST1 V4R4M0 990521 Create SQL ILE C Object CEX 04/01/98 15:52:26 Page 6
CROSS REFERENCE
EMPLOYEE **** TABLE IN CORPDATA
52 74 116
EMPLOYEE **** TABLE
75 118
EMPNO **** COLUMN IN EMP_ACT
72 75 76 118
EMPNO **** COLUMN IN EMPLOYEE
75 118
EMPNO 74 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
EMPNO 74 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMPTIME 74 DECIMAL(5,2) COLUMN IN CORPDATA.EMP_ACT
EMPTIME **** COLUMN
114
EMSTDATE 74 DATE(10) COLUMN IN CORPDATA.EMP_ACT
EMSTDATE **** COLUMN
114
FIRSTNME **** COLUMN
73
FIRSTNME 74 VARCHAR(12) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
HIREDATE 74 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
JOB 74 CHARACTER(8) COLUMN IN CORPDATA.EMPLOYEE
LASTNAME **** COLUMN
73
LASTNAME 74 VARCHAR(15) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
MAJPROJ 27 VARCHAR(6) IN Proj_struct
MAJPROJ 116 CHARACTER(6) COLUMN IN CORPDATA.PROJECT
MIDINIT 74 CHARACTER(1) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
Proj_struct 30 STRUCTURE IN rpt1
PHONENO 74 CHARACTER(4) COLUMN IN CORPDATA.EMPLOYEE
PRENDATE 27 DATE(10) IN Proj_struct
PRENDATE **** COLUMN
119
PRENDATE 116 DATE(10) COLUMN IN CORPDATA.PROJECT
PROJECT **** TABLE IN CORPDATA
116
PROJECT **** TABLE
117
PROJNAME 27 VARCHAR(24) IN Proj_struct
PROJNAME **** COLUMN
113 120
PROJNAME 116 VARCHAR(24) COLUMN (NOT NULL) IN CORPDATA.PROJECT
PROJNO 27 VARCHAR(6) IN Proj_struct
85
PROJNO **** COLUMN
72 76
PROJNO 74 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
PROJNO **** COLUMN IN EMP_ACT

Figure 39. Sample C Program Using SQL Statements (Part 6 of 7)

5769ST1 V4R4M0 990521 Create SQL ILE C Object CEX 04/01/98 15:52:26 Page 7
CROSS REFERENCE
113 117 120
PROJNO **** COLUMN IN PROJECT
117
PROJNO 116 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.PROJECT
PRSTAFF 27 DECIMAL(5,2) IN Proj_struct
PRSTAFF 116 DECIMAL(5,2) COLUMN IN CORPDATA.PROJECT
PRSTDATE 27 DATE(10) IN Proj_struct
PRSTDATE 116 DATE(10) COLUMN IN CORPDATA.PROJECT
RESPEMP 27 VARCHAR(6) IN Proj_struct
RESPEMP 116 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.PROJECT
SALARY **** COLUMN
53 53 73 115
SALARY 74 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
SEX 74 CHARACTER(1) COLUMN IN CORPDATA.EMPLOYEE
WORKDEPT 74 CHARACTER(3) COLUMN IN CORPDATA.EMPLOYEE
No errors found in source
163 Source records processed
* * * * * E N D O F L I S T I N G * * * * *

Figure 39. Sample C Program Using SQL Statements (Part 7 of 7)

612 DB2 UDB for AS/400 SQL Programming V4R4


SQL Statements in COBOL and ILE COBOL Programs

5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLEX 04/01/98 11:09:13 Page 1
Source type...............COBOL
Program name..............CORPDATA/CBLEX
Source file...............CORPDATA/SRC
Member....................CBLEX
To source file............QTEMP/QSQLTEMP
Options...................*SRC *XREF
Target release............V4R4M0
INCLUDE file..............*LIBL/*SRCFILE
Commit....................*CHG
Allow copy of data........*YES
Close SQL cursor..........*ENDPGM
Allow blocking............*READ
Delay PREPARE.............*NO
Generation level..........10
Printer file..............*LIBL/QSYSPRT
Date format...............*JOB
Date separator............*JOB
Time format...............*HMS
Time separator ...........*JOB
Replace...................*YES
Relational database.......*LOCAL
User .....................*CURRENT
RDB connect method........*DUW
Default Collection........*NONE
Package name..............*PGMLIB/*PGM
Dynamic User Profile......*USER
User Profile..............*NAMING
Sort Sequence.............*JOB
Language ID...............*JOB
IBM SQL flagging..........*NOFLAG
ANS flagging..............*NONE
Text......................*SRCMBRTXT
Source file CCSID.........65535
Job CCSID.................65535
Source member changed on 07/01/96 09:44:58

Figure 40. Sample COBOL Program Using SQL Statements (Part 1 of 9)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 613
5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLEX 04/01/98 11:09:13 Page 2
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
1
2 ****************************************************************
3 * A sample program which updates the salaries for those *
4 * employees whose current commission total is greater than or *
5 * equal to the value of COMMISSION. The salaries of those who *
6 * qualify are increased by the value of PERCENTAGE retroactive *
7 * to RAISE-DATE. A report is generated showing the projects *
8 * which these employees have contributed to ordered by the *
9 * project number and employee ID. A second report shows each *
10 * project having an end date occurring after RAISE-DATE *
11 * (i.e. potentially affected by the retroactive raises ) with *
12 * its total salary expenses and a count of employees who *
13 * contributed to the project. *
14 ****************************************************************
15
16
17 IDENTIFICATION DIVISION.
18
19 PROGRAM-ID. CBLEX.
20 ENVIRONMENT DIVISION.
21 CONFIGURATION SECTION.
22 SOURCE-COMPUTER. IBM-AS400.
23 OBJECT-COMPUTER. IBM-AS400.
24 INPUT-OUTPUT SECTION.
25
26 FILE-CONTROL.
27 SELECT PRINTFILE ASSIGN TO PRINTER-QPRINT
28 ORGANIZATION IS SEQUENTIAL.
29
30 DATA DIVISION.
31
32 FILE SECTION.
33
34 FD PRINTFILE
35 BLOCK CONTAINS 1 RECORDS
36 LABEL RECORDS ARE OMITTED.
37 01 PRINT-RECORD PIC X(132).
38
39 WORKING-STORAGE SECTION.
40 77 WORK-DAYS PIC S9(4) BINARY VALUE 253.
41 77 RAISE-DATE PIC X(11) VALUE "1982-06-01".
42 77 PERCENTAGE PIC S999V99 PACKED-DECIMAL.
43 77 COMMISSION PIC S99999V99 PACKED-DECIMAL VALUE 2000.00.
44
45 ***************************************************************
46 * Structure for report 1. *
47 ***************************************************************
48
49 „1… 01 RPT1.
50 COPY DDS-PROJECT OF CORPDATA-PROJECT.
51 05 EMPNO PIC X(6).
52 05 NAME PIC X(30).
53 05 SALARY PIC S9(6)V99 PACKED-DECIMAL.
54
55
56 ***************************************************************
57 * Structure for report 2. *
58 ***************************************************************
59
60 01 RPT2.
61 15 PROJNO PIC X(6).
62 15 PROJECT-NAME PIC X(36).
63 15 EMPLOYEE-COUNT PIC S9(4) BINARY.
64 15 TOTAL-PROJ-COST PIC S9(10)V99 PACKED-DECIMAL.
65

Figure 40. Sample COBOL Program Using SQL Statements (Part 2 of 9)

614 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLEX 04/01/98 11:09:13 Page 3
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
66 „2… EXEC SQL
67 INCLUDE SQLCA
68 END-EXEC.
69 77 CODE-EDIT PIC ---99.
70
71 ***************************************************************
72 * Headers for reports. *
73 ***************************************************************
74
75 01 RPT1-HEADERS.
76 05 RPT1-HEADER1.
77 10 FILLER PIC X(21) VALUE SPACES.
78 10 FILLER PIC X(111)
79 VALUE "REPORT OF PROJECTS AFFECTED BY RAISES".
80 05 RPT1-HEADER2.
81 10 FILLER PIC X(9) VALUE "PROJECT".
82 10 FILLER PIC X(10) VALUE "EMPID".
83 10 FILLER PIC X(35) VALUE "EMPLOYEE NAME".
84 10 FILLER PIC X(40) VALUE "SALARY".
85 01 RPT2-HEADERS.
86 05 RPT2-HEADER1.
87 10 FILLER PIC X(21) VALUE SPACES.
88 10 FILLER PIC X(111)
89 VALUE "ACCUMULATED STATISTICS BY PROJECT".
90 05 RPT2-HEADER2.
91 10 FILLER PIC X(9) VALUE "PROJECT".
92 10 FILLER PIC X(38) VALUE SPACES.
93 10 FILLER PIC X(16) VALUE "NUMBER OF".
94 10 FILLER PIC X(10) VALUE "TOTAL".
95 05 RPT2-HEADER3.
96 10 FILLER PIC X(9) VALUE "NUMBER".
97 10 FILLER PIC X(38) VALUE "PROJECT NAME".
98 10 FILLER PIC X(16) VALUE "EMPLOYEES".
99 10 FILLER PIC X(65) VALUE "COST".
100 01 RPT1-DATA.
101 05 PROJNO PIC X(6).
102 05 FILLER PIC XXX VALUE SPACES.
103 05 EMPNO PIC X(6).
104 05 FILLER PIC X(4) VALUE SPACES.
105 05 NAME PIC X(30).
106 05 FILLER PIC X(3) VALUE SPACES.
107 05 SALARY PIC ZZZZZ9.99.
108 05 FILLER PIC X(96) VALUE SPACES.
109 01 RPT2-DATA.
110 05 PROJNO PIC X(6).
111 05 FILLER PIC XXX VALUE SPACES.
112 05 PROJECT-NAME PIC X(36).
113 05 FILLER PIC X(4) VALUE SPACES.
114 05 EMPLOYEE-COUNT PIC ZZZ9.
115 05 FILLER PIC X(5) VALUE SPACES.
116 05 TOTAL-PROJ-COST PIC ZZZZZZZZ9.99.
117 05 FILLER PIC X(56) VALUE SPACES.
118
119 PROCEDURE DIVISION.
120
121 A000-MAIN.
122 MOVE 1.04 TO PERCENTAGE.
123 OPEN OUTPUT PRINTFILE.
124
125 ***************************************************************
126 * Update the selected employees by the new percentage. If an *
127 * error occurs during the update, ROLLBACK the changes, *
128 ***************************************************************
129
130 „3… EXEC SQL

Figure 40. Sample COBOL Program Using SQL Statements (Part 3 of 9)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 615
5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLEX 04/01/98 11:09:13 Page 4
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
131 WHENEVER SQLERROR GO TO E010-UPDATE-ERROR
132 END-EXEC.
133 „4… EXEC SQL
134 UPDATE CORPDATA/EMPLOYEE
135 SET SALARY = SALARY * :PERCENTAGE
136 WHERE COMM >= :COMMISSION
137 END-EXEC.
138
139 ***************************************************************
140 * Commit changes. *
141 ***************************************************************
142
143 „5… EXEC SQL
144 COMMIT
145 END-EXEC.
146
147 EXEC SQL
148 WHENEVER SQLERROR GO TO E020-REPORT-ERROR
149 END-EXEC.
150
151 ***************************************************************
152 * Report the updated statistics for each employee receiving *
153 * a raise and the projects that s/he participates in *
154 ***************************************************************
155
156 ***************************************************************
157 * Write out the header for Report 1. *
158 ***************************************************************
159
160 write print-record from rpt1-header1
161 before advancing 2 lines.
162 write print-record from rpt1-header2
163 before advancing 1 line.
164 „6… exec sql
165 declare c1 cursor for
166 SELECT DISTINCT projno, emp_act.empno,
167 lastname||", "||firstnme ,salary
168 from corpdata/emp_act, corpdata/employee
169 where emp_act.empno =employee.empno and
170 comm >= :commission
171 order by projno, empno
172 end-exec.
173 „7… EXEC SQL
174 OPEN C1
175 END-EXEC.
176
177 PERFORM B000-GENERATE-REPORT1 THRU B010-GENERATE-REPORT1-EXIT
178 UNTIL SQLCODE NOT EQUAL TO ZERO.
179
180 „10… A100-DONE1.
181 EXEC SQL
182 CLOSE C1
183 END-EXEC.
184
185 *************************************************************
186 * For all projects ending at a date later than the RAISE- *
187 * DATE ( i.e. those projects potentially affected by the *
188 * salary raises generate a report containing the project *
189 * project number, project name, the count of employees *
190 * participating in the project and the total salary cost *
191 * for the project *
192 *************************************************************
193
194
195 ***************************************************************

Note: „8… and „9… are located on Part 5 of this figure.

Figure 40. Sample COBOL Program Using SQL Statements (Part 4 of 9)

616 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLEX 04/01/98 11:09:13 Page 5
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
196 * Write out the header for Report 2. *
197 ***************************************************************
198
199 MOVE SPACES TO PRINT-RECORD.
200 WRITE PRINT-RECORD BEFORE ADVANCING 2 LINES.
201 WRITE PRINT-RECORD FROM RPT2-HEADER1
202 BEFORE ADVANCING 2 LINES.
203 WRITE PRINT-RECORD FROM RPT2-HEADER2
204 BEFORE ADVANCING 1 LINE.
205 WRITE PRINT-RECORD FROM RPT2-HEADER3
206 BEFORE ADVANCING 2 LINES.
207
208 EXEC SQL
209 „11… DECLARE C2 CURSOR FOR
210 SELECT EMP_ACT.PROJNO, PROJNAME, COUNT(*),
211 SUM ( (DAYS(EMENDATE)-DAYS(EMSTDATE)) *
212 EMPTIME * DECIMAL((SALARY / :WORK-DAYS),8,2))
213 FROM CORPDATA/EMP_ACT, CORPDATA/PROJECT,
214 CORPDATA/EMPLOYEE
215 WHERE EMP_ACT.PROJNO=PROJECT.PROJNO AND
216 EMP_ACT.EMPNO =EMPLOYEE.EMPNO AND
217 PRENDATE > :RAISE-DATE
218 GROUP BY EMP_ACT.PROJNO, PROJNAME
219 ORDER BY 1
220 END-EXEC.
221 EXEC SQL
222 OPEN C2
223 END-EXEC.
224
225 PERFORM C000-GENERATE-REPORT2 THRU C010-GENERATE-REPORT2-EXIT
226 UNTIL SQLCODE NOT EQUAL TO ZERO.
227
228 A200-DONE2.
229 EXEC SQL
230 CLOSE C2
231 END-EXEC
232
233 ***************************************************************
234 * All done. *
235 ***************************************************************
236
237 A900-MAIN-EXIT.
238 CLOSE PRINTFILE.
239 STOP RUN.
240
241 ***************************************************************
242 * Fetch and write the rows to PRINTFILE. *
243 ***************************************************************
244
245 B000-GENERATE-REPORT1.
246 „8… EXEC SQL
247 WHENEVER NOT FOUND GO TO A100-DONE1
248 END-EXEC.
249 „9… EXEC SQL
250 FETCH C1 INTO :PROJECT.PROJNO, :RPT1.EMPNO,
251 :RPT1.NAME, :RPT1.SALARY
252 END-EXEC.
253 MOVE CORRESPONDING RPT1 TO RPT1-DATA.
254 MOVE PROJNO OF RPT1 TO PROJNO OF RPT1-DATA.
255 WRITE PRINT-RECORD FROM RPT1-DATA
256 BEFORE ADVANCING 1 LINE.
257
258 B010-GENERATE-REPORT1-EXIT.
259 EXIT.
260

Figure 40. Sample COBOL Program Using SQL Statements (Part 5 of 9)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 617
5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLEX 04/01/98 11:09:13 Page 6
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
261 ***************************************************************
262 * Fetch and write the rows to PRINTFILE. *
263 ***************************************************************
264
265 C000-GENERATE-REPORT2.
266 EXEC SQL
267 WHENEVER NOT FOUND GO TO A200-DONE2
268 END-EXEC.
269 „12… EXEC SQL
270 FETCH C2 INTO :RPT2
271 END-EXEC.
272 MOVE CORRESPONDING RPT2 TO RPT2-DATA.
273 WRITE PRINT-RECORD FROM RPT2-DATA
274 BEFORE ADVANCING 1 LINE.
275
276 C010-GENERATE-REPORT2-EXIT.
277 EXIT.
278
279 ***************************************************************
280 * Error occured while updating table. Inform user and *
281 * rollback changes. *
282 ***************************************************************
283
284 E010-UPDATE-ERROR.
285 „13… EXEC SQL
286 WHENEVER SQLERROR CONTINUE
287 END-EXEC.
288 MOVE SQLCODE TO CODE-EDIT.
289 STRING "*** ERROR Occurred while updating table. SQLCODE="
290 CODE-EDIT DELIMITED BY SIZE INTO PRINT-RECORD.
291 WRITE PRINT-RECORD.
292 „14… EXEC SQL
293 ROLLBACK
294 END-EXEC.
295 STOP RUN.
296
297 ***************************************************************
298 * Error occured while generating reports. Inform user and *
299 * exit. *
300 ***************************************************************
301
302 E020-REPORT-ERROR.
303 MOVE SQLCODE TO CODE-EDIT.
304 STRING "*** ERROR Occurred while generating reports. SQLCODE
305 - "=" CODE-EDIT DELIMITED BY SIZE INTO PRINT-RECORD.
306 WRITE PRINT-RECORD.
307 STOP RUN.
* * * * * E N D O F S O U R C E * * * * *

Figure 40. Sample COBOL Program Using SQL Statements (Part 6 of 9)

618 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLEX 04/01/98 11:09:13 Page 7
CROSS REFERENCE
Data Names Define Reference
ACTNO 168 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
A100-DONE1 **** LABEL
247
A200-DONE2 **** LABEL
267
BIRTHDATE 134 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
BONUS 134 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
CODE-EDIT 69
COMM **** COLUMN
136 170
COMM 134 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
COMMISSION 43 DECIMAL(7,2)
136 170
CORPDATA **** COLLECTION
134 168 168 213 213 214
C1 165 CURSOR
174 182 250
C2 209 CURSOR
222 230 270
DEPTNO 50 CHARACTER(3) IN PROJECT
DEPTNO 213 CHARACTER(3) COLUMN (NOT NULL) IN CORPDATA.PROJECT
EDLEVEL 134 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMENDATE 168 DATE(10) COLUMN IN CORPDATA.EMP_ACT
EMENDATE **** COLUMN
211
EMP_ACT **** TABLE
166 169 210 215 216 218
EMP_ACT **** TABLE IN CORPDATA
168 213
EMPLOYEE **** TABLE IN CORPDATA
134 168 214
EMPLOYEE **** TABLE
169 216
EMPLOYEE-COUNT 63 SMALL INTEGER PRECISION(4,0) IN RPT2
EMPLOYEE-COUNT 114 IN RPT2-DATA
EMPNO 51 CHARACTER(6) IN RPT1
250
EMPNO 103 CHARACTER(6) IN RPT1-DATA
EMPNO 134 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMPNO **** COLUMN IN EMP_ACT
166 169 171 216
EMPNO **** COLUMN IN EMPLOYEE
169 216
EMPNO 168 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
EMPTIME 168 DECIMAL(5,2) COLUMN IN CORPDATA.EMP_ACT
EMPTIME **** COLUMN
212
EMSTDATE 168 DATE(10) COLUMN IN CORPDATA.EMP_ACT

Figure 40. Sample COBOL Program Using SQL Statements (Part 7 of 9)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 619
5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLEX 04/01/98 11:09:13 Page 8
CROSS REFERENCE
EMSTDATE **** COLUMN
211
E010-UPDATE-ERROR **** LABEL
131
E020-REPORT-ERROR **** LABEL
148
FIRSTNME 134 VARCHAR(12) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
FIRSTNME **** COLUMN
167
HIREDATE 134 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
JOB 134 CHARACTER(8) COLUMN IN CORPDATA.EMPLOYEE
LASTNAME 134 VARCHAR(15) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
LASTNAME **** COLUMN
167
MAJPROJ 50 CHARACTER(6) IN PROJECT
MAJPROJ 213 CHARACTER(6) COLUMN IN CORPDATA.PROJECT
MIDINIT 134 CHARACTER(1) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
NAME 52 CHARACTER(30) IN RPT1
251
NAME 105 CHARACTER(30) IN RPT1-DATA
PERCENTAGE 42 DECIMAL(5,2)
135
PHONENO 134 CHARACTER(4) COLUMN IN CORPDATA.EMPLOYEE
PRENDATE 50 DATE(10) IN PROJECT
PRENDATE **** COLUMN
217
PRENDATE 213 DATE(10) COLUMN IN CORPDATA.PROJECT
PRINT-RECORD 37 CHARACTER(132)
PROJECT 50 STRUCTURE IN RPT1
PROJECT **** TABLE IN CORPDATA
213
PROJECT **** TABLE
215
PROJECT-NAME 62 CHARACTER(36) IN RPT2
PROJECT-NAME 112 CHARACTER(36) IN RPT2-DATA
PROJNAME 50 VARCHAR(24) IN PROJECT
PROJNAME **** COLUMN
210 218
PROJNAME 213 VARCHAR(24) COLUMN (NOT NULL) IN CORPDATA.PROJECT
PROJNO 50 CHARACTER(6) IN PROJECT
250
PROJNO 61 CHARACTER(6) IN RPT2
PROJNO 101 CHARACTER(6) IN RPT1-DATA
PROJNO 110 CHARACTER(6) IN RPT2-DATA
PROJNO **** COLUMN

Figure 40. Sample COBOL Program Using SQL Statements (Part 8 of 9)

620 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL COBOL Program CBLEX 04/01/98 11:09:13 Page 9
CROSS REFERENCE
166 171
PROJNO 168 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
PROJNO **** COLUMN IN EMP_ACT
210 215 218
PROJNO **** COLUMN IN PROJECT
215
PROJNO 213 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.PROJECT
PRSTAFF 50 DECIMAL(5,2) IN PROJECT
PRSTAFF 213 DECIMAL(5,2) COLUMN IN CORPDATA.PROJECT
PRSTDATE 50 DATE(10) IN PROJECT
PRSTDATE 213 DATE(10) COLUMN IN CORPDATA.PROJECT
RAISE-DATE 41 CHARACTER(11)
217
RESPEMP 50 CHARACTER(6) IN PROJECT
RESPEMP 213 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.PROJECT
RPT1 49
RPT1-DATA 100
RPT1-HEADERS 75
RPT1-HEADER1 76 IN RPT1-HEADERS
RPT1-HEADER2 80 IN RPT1-HEADERS
RPT2 60 STRUCTURE
270
RPT2-DATA 109
RPT2-HEADERS 85
RPT2-HEADER1 86 IN RPT2-HEADERS
RPT2-HEADER2 90 IN RPT2-HEADERS
RPT2-HEADER3 95 IN RPT2-HEADERS
SALARY 53 DECIMAL(8,2) IN RPT1
251
SALARY 107 IN RPT1-DATA
SALARY **** COLUMN
135 135 167 212
SALARY 134 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
SEX 134 CHARACTER(1) COLUMN IN CORPDATA.EMPLOYEE
TOTAL-PROJ-COST 64 DECIMAL(12,2) IN RPT2
TOTAL-PROJ-COST 116 IN RPT2-DATA
WORK-DAYS 40 SMALL INTEGER PRECISION(4,0)
212
WORKDEPT 134 CHARACTER(3) COLUMN IN CORPDATA.EMPLOYEE
No errors found in source
307 Source records processed
* * * * * E N D O F L I S T I N G * * * * *

Figure 40. Sample COBOL Program Using SQL Statements (Part 9 of 9)

SQL Statements in PL/I

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 621
5769ST1 V4R4M0 990521 Create SQL PL/I Program PLIEX 04/01/98 12:53:36 Page 1
Source type...............PLI
Program name..............CORPDATA/PLIEX
Source file...............CORPDATA/SRC
Member....................PLIEX
To source file............QTEMP/QSQLTEMP
Options...................*SRC *XREF
Target release............V4R4M0
INCLUDE file..............*LIBL/*SRCFILE
Commit....................*CHG
Allow copy of data........*YES
Close SQL cursor..........*ENDPGM
Allow blocking............*READ
Delay PREPARE.............*NO
Generation level..........10
Margins...................*SRCFILE
Printer file..............*LIBL/QSYSPRT
Date format...............*JOB
Date separator............*JOB
Time format...............*HMS
Time separator ...........*JOB
Replace...................*YES
Relational database.......*LOCAL
User .....................*CURRENT
RDB connect method........*DUW
Default Collection........*NONE
Package name..............*PGMLIB/*PGM
Dynamic User Profile......*USER
User Profile..............*NAMING
Sort Sequence.............*JOB
Language ID...............*JOB
IBM SQL flagging..........*NOFLAG
ANS flagging..............*NONE
Text......................*SRCMBRTXT
Source file CCSID.........65535
Job CCSID.................65535
Source member changed on 07/01/96 12:53:08

Figure 41. Sample PL/I Program Using SQL Statements (Part 1 of 7)

622 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL PL/I Program PLIEX 04/01/98 12:53:36 Page 2
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
1 /* A sample program which updates the salaries for those employees */ 100
2 /* whose current commission total is greater than or equal to the */ 200
3 /* value of COMMISSION. The salaries of those who qualify are */ 300
4 /* increased by the value of PERCENTAGE, retroactive to RAISE_DATE. */ 400
5 /* A report is generated showing the projects which these employees */ 500
6 /* have contributed to, ordered by project number and employee ID. */ 600
7 /* A second report shows each project having an end date occurring */ 700
8 /* after RAISE_DATE (i.e. is potentially affected by the retroactive */ 800
9 /* raises) with its total salary expenses and a count of employees */ 900
10 /* who contributed to the project. */ 1000
11 /*********************************************************************/ 1100
12 1200
13 1300
14 PLIEX: PROC; 1400
15 1500
16 DCL RAISE_DATE CHAR(10); 1600
17 DCL WORK_DAYS FIXED BIN(15); 1700
18 DCL COMMISSION FIXED DECIMAL(8,2); 1800
19 DCL PERCENTAGE FIXED DECIMAL(5,2); 1900
20 2000
21 /* File declaration for sysprint */ 2100
22 DCL SYSPRINT FILE EXTERNAL OUTPUT STREAM PRINT; 2200
23 2300
24 /* Structure for report 1 */ 2400
25 DCL 1 RPT1, 2500
26 „1…%INCLUDE PROJECT (PROJECT, RECORD,,COMMA); 2600
27 15 EMPNO CHAR(6), 2700
28 15 NAME CHAR(30), 2800
29 15 SALARY FIXED DECIMAL(8,2); 2900
30 3000
31 /* Structure for report 2 */ 3100
32 DCL 1 RPT2, 3200
33 15 PROJNO CHAR(6), 3300
34 15 PROJECT_NAME CHAR(36), 3400
35 15 EMPLOYEE_COUNT FIXED BIN(15), 3500
36 15 TOTL_PROJ_COST FIXED DECIMAL(10,2); 3600
37 3700
38 „2… EXEC SQL INCLUDE SQLCA; 3800
39 3900
40 COMMISSION = 2000.00; 4000
41 PERCENTAGE = 1.04; 4100
42 RAISE_DATE = '1982-06-01'; 4200
43 WORK_DAYS = 253; 4300
44 OPEN FILE(SYSPRINT); 4400
45 4500
46 /* Update the selected employee's salaries by the new percentage. */ 4600
47 /* If an error occurs during the update, ROLLBACK the changes. */ 4700
48 „3… EXEC SQL WHENEVER SQLERROR GO TO UPDATE_ERROR; 4800
49 „4… EXEC SQL 4900
50 UPDATE CORPDATA/EMPLOYEE 5000
51 SET SALARY = SALARY * :PERCENTAGE 5100
52 WHERE COMM >= :COMMISSION ; 5200
53 5300
54 /* Commit changes */ 5400
55 „5… EXEC SQL 5500
56 COMMIT; 5600
57 EXEC SQL WHENEVER SQLERROR GO TO REPORT_ERROR; 5700
58 5800
59 /* Report the updated statistics for each project supported by one */ 5900
60 /* of the selected employees. */ 6000
61 6100
62 /* Write out the header for Report 1 */ 6200
63 put file(sysprint) 6300
64 edit('REPORT OF PROJECTS AFFECTED BY EMPLOYEE RAISES') 6400
65 (col(22),a); 6500

Figure 41. Sample PL/I Program Using SQL Statements (Part 2 of 7)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 623
5769ST1 V4R4M0 990521 Create SQL PL/I Program PLIEX 04/01/98 12:53:36 Page 3
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
66 put file(sysprint) 6600
67 edit('PROJECT','EMPID','EMPLOYEE NAME','SALARY') 6700
68 (skip(2),col(1),a,col(10),a,col(20),a,col(55),a); 6800
69 6900
70 „6… exec sql 7000
71 declare c1 cursor for 7100
72 select DISTINCT projno, EMP_ACT.empno, 7200
73 lastname||', '||firstnme, salary 7300
74 from CORPDATA/EMP_ACT, CORPDATA/EMPLOYEE 7400
75 where EMP_ACT.empno = EMPLOYEE.empno and 7500
76 comm >= :COMMISSION 7600
77 order by projno, empno; 7700
78 „7… EXEC SQL 7800
79 OPEN C1; 7900
80 8000
81 /* Fetch and write the rows to SYSPRINT */ 8100
82 „8… EXEC SQL WHENEVER NOT FOUND GO TO DONE1; 8200
83 8300
84 DO UNTIL (SQLCODE |= 0); 8400
85 „9… EXEC SQL 8500
86 FETCH C1 INTO :RPT1.PROJNO, :rpt1.EMPNO, :RPT1.NAME, 8600
87 :RPT1.SALARY; 8700
88 PUT FILE(SYSPRINT) 8800
89 EDIT(RPT1.PROJNO,RPT1.EMPNO,RPT1.NAME,RPT1.SALARY) 8900
90 (SKIP,COL(1),A,COL(10),A,COL(20),A,COL(54),F(8,2)); 9000
91 END; 9100
92 9200
93 DONE1: 9300
94 „10… EXEC SQL 9400
95 CLOSE C1; 9500
96 9600
97 /* For all projects ending at a date later than 'raise_date' */ 9700
98 /* (i.e. those projects potentially affected by the salary raises) */ 9800
99 /* generate a report containing the project number, project name */ 9900
100 /* the count of employees participating in the project and the */ 10000
101 /* total salary cost of the project. */ 10100
102 10200
103 /* Write out the header for Report 2 */ 10300
104 PUT FILE(SYSPRINT) EDIT('ACCUMULATED STATISTICS BY PROJECT') 10400
105 (SKIP(3),COL(22),A); 10500
106 PUT FILE(SYSPRINT) 10600
107 EDIT('PROJECT','NUMBER OF','TOTAL') 10700
108 (SKIP(2),COL(1),A,COL(48),A,COL(63),A); 10800
109 PUT FILE(SYSPRINT) 10900
110 EDIT('NUMBER','PROJECT NAME','EMPLOYEES','COST') 11000
111 (SKIP,COL(1),A,COL(10),A,COL(48),A,COL(63),A,SKIP); 11100
112 11200
113 „11… EXEC SQL 11300
114 DECLARE C2 CURSOR FOR 11400
115 SELECT EMP_ACT.PROJNO, PROJNAME, COUNT(*), 11500
116 SUM( (DAYS(EMENDATE) - DAYS(EMSTDATE)) * EMPTIME * 11600
117 DECIMAL(( SALARY / :WORK_DAYS ),8,2) ) 11700
118 FROM CORPDATA/EMP_ACT, CORPDATA/PROJECT, CORPDATA/EMPLOYEE 11800
119 WHERE EMP_ACT.PROJNO=PROJECT.PROJNO AND 11900
120 EMP_ACT.EMPNO =EMPLOYEE.EMPNO AND 12000
121 PRENDATE > :RAISE_DATE 12100
122 GROUP BY EMP_ACT.PROJNO, PROJNAME 12200
123 ORDER BY 1; 12300
124 EXEC SQL 12400
125 OPEN C2; 12500
126 12600
127 /* Fetch and write the rows to SYSPRINT */ 12700
128 EXEC SQL WHENEVER NOT FOUND GO TO DONE2; 12800
129 12900
130 DO UNTIL (SQLCODE |= 0); 13000

Figure 41. Sample PL/I Program Using SQL Statements (Part 3 of 7)

624 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL PL/I Program PLIEX 04/01/98 12:53:36 Page 4
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
131 „12… EXEC SQL 13100
132 FETCH C2 INTO :RPT2; 13200
133 PUT FILE(SYSPRINT) 13300
134 EDIT(RPT2.PROJNO,RPT2.PROJECT_NAME,EMPLOYEE_COUNT, 13400
135 TOTL_PROJ_COST) 13500
136 (SKIP,COL(1),A,COL(10),A,COL(50),F(4),COL(62),F(8,2)); 13600
137 END; 13700
138 13800
139 DONE2: 13900
140 EXEC SQL 14000
141 CLOSE C2; 14100
142 GO TO FINISHED; 14200
143 14300
144 /* Error occured while updating table. Inform user and rollback */ 14400
145 /* changes. */ 14500
146 UPDATE_ERROR: 14600
147 „13… EXEC SQL WHENEVER SQLERROR CONTINUE; 14700
148 PUT FILE(SYSPRINT) EDIT('*** ERROR Occurred while updating table.'|| 14800
149 ' SQLCODE=',SQLCODE)(A,F(5)); 14900
150 „14… EXEC SQL 15000
151 ROLLBACK; 15100
152 GO TO FINISHED; 15200
153 15300
154 /* Error occured while generating reports. Inform user and exit. */ 15400
155 REPORT_ERROR: 15500
156 PUT FILE(SYSPRINT) EDIT('*** ERROR Occurred while generating '|| 15600
157 'reports. SQLCODE=',SQLCODE)(A,F(5)); 15700
158 GO TO FINISHED; 15800
159 15900
160 /* All done */ 16000
161 FINISHED: 16100
162 CLOSE FILE(SYSPRINT); 16200
163 RETURN; 16300
164 16400
165 END PLIEX; 16500
* * * * * E N D O F S O U R C E * * * * *

Figure 41. Sample PL/I Program Using SQL Statements (Part 4 of 7)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 625
5769ST1 V4R4M0 990521 Create SQL PL/I Program PLIEX 04/01/98 12:53:36 Page 5
CROSS REFERENCE
Data Names Define Reference
ACTNO 74 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
BIRTHDATE 74 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
BONUS 74 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
COMM **** COLUMN
52 76
COMM 74 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
COMMISSION 18 DECIMAL(8,2)
52 76
CORPDATA **** COLLECTION
50 74 74 118 118 118
C1 71 CURSOR
79 86 95
C2 114 CURSOR
125 132 141
DEPTNO 26 CHARACTER(3) IN RPT1
DEPTNO 118 CHARACTER(3) COLUMN (NOT NULL) IN CORPDATA.PROJECT
DONE1 **** LABEL
82
DONE2 **** LABEL
128
EDLEVEL 74 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMENDATE 74 DATE(10) COLUMN IN CORPDATA.EMP_ACT
EMENDATE **** COLUMN
116
EMP_ACT **** TABLE
72 75 115 119 120 122
EMP_ACT **** TABLE IN CORPDATA
74 118
EMPLOYEE **** TABLE IN CORPDATA
50 74 118
EMPLOYEE **** TABLE
75 120
EMPLOYEE_COUNT 35 SMALL INTEGER PRECISION(4,0) IN RPT2
EMPNO 27 CHARACTER(6) IN RPT1
86
EMPNO **** COLUMN IN EMP_ACT
72 75 77 120
EMPNO **** COLUMN IN EMPLOYEE
75 120
EMPNO 74 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
EMPNO 74 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMPTIME 74 DECIMAL(5,2) COLUMN IN CORPDATA.EMP_ACT
EMPTIME **** COLUMN
116
EMSTDATE 74 DATE(10) COLUMN IN CORPDATA.EMP_ACT
EMSTDATE **** COLUMN
116
FIRSTNME **** COLUMN
73
FIRSTNME 74 VARCHAR(12) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE

Figure 41. Sample PL/I Program Using SQL Statements (Part 5 of 7)

626 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL PL/I Program PLIEX 04/01/98 12:53:36 Page 6
CROSS REFERENCE
HIREDATE 74 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
JOB 74 CHARACTER(8) COLUMN IN CORPDATA.EMPLOYEE
LASTNAME **** COLUMN
73
LASTNAME 74 VARCHAR(15) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
MAJPROJ 26 CHARACTER(6) IN RPT1
MAJPROJ 118 CHARACTER(6) COLUMN IN CORPDATA.PROJECT
MIDINIT 74 CHARACTER(1) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
NAME 28 CHARACTER(30) IN RPT1
86
PERCENTAGE 19 DECIMAL(5,2)
51
PHONENO 74 CHARACTER(4) COLUMN IN CORPDATA.EMPLOYEE
PRENDATE 26 DATE(10) IN RPT1
PRENDATE **** COLUMN
121
PRENDATE 118 DATE(10) COLUMN IN CORPDATA.PROJECT
PROJECT **** TABLE IN CORPDATA
118
PROJECT **** TABLE
119
PROJECT_NAME 34 CHARACTER(36) IN RPT2
PROJNAME 26 VARCHAR(24) IN RPT1
PROJNAME **** COLUMN
115 122
PROJNAME 118 VARCHAR(24) COLUMN (NOT NULL) IN CORPDATA.PROJECT
PROJNO 26 CHARACTER(6) IN RPT1
86
PROJNO 33 CHARACTER(6) IN RPT2
PROJNO **** COLUMN
72 77
PROJNO 74 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
PROJNO **** COLUMN IN EMP_ACT
115 119 122
PROJNO **** COLUMN IN PROJECT
119
PROJNO 118 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.PROJECT
PRSTAFF 26 DECIMAL(5,2) IN RPT1
PRSTAFF 118 DECIMAL(5,2) COLUMN IN CORPDATA.PROJECT
PRSTDATE 26 DATE(10) IN RPT1
PRSTDATE 118 DATE(10) COLUMN IN CORPDATA.PROJECT
RAISE_DATE 16 CHARACTER(10)
121
REPORT_ERROR **** LABEL
57

Figure 41. Sample PL/I Program Using SQL Statements (Part 6 of 7)

5769ST1 V4R4M0 990521 Create SQL PL/I Program PLIEX 04/01/98 12:53:36 Page 7
CROSS REFERENCE
RESPEMP 26 CHARACTER(6) IN RPT1
RESPEMP 118 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.PROJECT
RPT1 25 STRUCTURE
RPT2 32 STRUCTURE
132
SALARY 29 DECIMAL(8,2) IN RPT1
87
SALARY **** COLUMN
51 51 73 117
SALARY 74 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
SEX 74 CHARACTER(1) COLUMN IN CORPDATA.EMPLOYEE
SYSPRINT 22
TOTL_PROJ_COST 36 DECIMAL(10,2) IN RPT2
UPDATE_ERROR **** LABEL
48
WORK_DAYS 17 SMALL INTEGER PRECISION(4,0)
117
WORKDEPT 74 CHARACTER(3) COLUMN IN CORPDATA.EMPLOYEE
No errors found in source
165 Source records processed
* * * * * E N D O F L I S T I N G * * * * *

Figure 41. Sample PL/I Program Using SQL Statements (Part 7 of 7)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 627
SQL Statements in RPG for AS/400 Programs

5769ST1 V4R4M0 990521 Create SQL RPG Program RPGEX 04/01/98 12:55:22 Page 1
Source type...............RPG
Program name..............CORPDATA/RPGEX
Source file...............CORPDATA/SRC
Member....................RPGEX
To source file............QTEMP/QSQLTEMP
Options...................*SRC *XREF
Target release............V4R4M0
INCLUDE file..............*LIBL/*SRCFILE
Commit....................*CHG
Allow copy of data........*YES
Close SQL cursor..........*ENDPGM
Allow blocking............*READ
Delay PREPARE.............*NO
Generation level..........10
Printer file..............*LIBL/QSYSPRT
Date format...............*JOB
Date separator............*JOB
Time format...............*HMS
Time separator ...........*JOB
Replace...................*YES
Relational database.......*LOCAL
User .....................*CURRENT
RDB connect method........*DUW
Default Collection........*NONE
Package name..............*PGMLIB/*PGM
Dynamic User Profile......*USER
User Profile...............*NAMING
Sort Sequence.............*JOB
Language ID...............*JOB
IBM SQL flagging..........*NOFLAG
ANS flagging..............*NONE
Text......................*SRCMBRTXT
Source file CCSID.........65535
Job CCSID.................65535
Source member changed on 07/01/96 17:06:17

Figure 42. Sample RPG for AS/400 Program Using SQL Statements (Part 1 of 8)

628 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL RPG Program RPGEX 04/01/98 12:55:22 Page 2
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
1 H 100
2 F* File declaration for QPRINT 200
3 F* 300
4 FQPRINT O F 132 PRINTER 400
5 I* 500
6 I* Structure for report 1. 600
7 I* 700
8 „1… IRPT1 E DSPROJECT 800
9 I PROJNAME PROJNM 900
10 I RESPEMP RESEM 1000
11 I PRSTAFF STAFF 1100
12 I PRSTDATE PRSTD 1200
13 I PRENDATE PREND 1300
14 I MAJPROJ MAJPRJ 1400
15 I* 1500
16 I DS 1600
17 I 1 6 EMPNO 1700
18 I 7 36 NAME 1800
19 I P 37 412SALARY 1900
20 I* 2000
21 I* Structure for report 2. 2100
22 I* 2200
23 IRPT2 DS 2300
24 I 1 6 PRJNUM 2400
25 I 7 42 PNAME 2500
26 I B 43 440EMPCNT 2600
27 I P 45 492PRCOST 2700
28 I* 2800
29 I DS 2900
30 I B 1 20WRKDAY 3000
31 I P 3 62COMMI 3100
32 I 7 16 RDATE 3200
33 I P 17 202PERCNT 3300
34 „2… C* 3400
35 C Z-ADD253 WRKDAY 3500
36 C Z-ADD2000.00 COMMI 3600
37 C Z-ADD1.04 PERCNT 3700
38 C MOVEL'1982-06-'RDATE 3800
39 C MOVE '01' RDATE 3900
40 C SETON LR 3901 02/03/93
41 C* 4000
42 C* Update the selected projects by the new percentage. If an 4100
43 C* error occurs during the update, ROLLBACK the changes. 4200
44 C* 4300
45 „3… C/EXEC SQL WHENEVER SQLERROR GOTO UPDERR 4400
46 C/END-EXEC 4500
47 C* 4600
48 „4… C/EXEC SQL 4700
49 C+ UPDATE CORPDATA/EMPLOYEE 4800
50 C+ SET SALARY = SALARY * :PERCNT 4900
51 C+ WHERE COMM >= :COMMI 5000
52 C/END-EXEC 5100
53 C* 5200
54 C* Commit changes. 5300
55 C* 5400
56 „5… C/EXEC SQL COMMIT 5500
57 C/END-EXEC 5600
58 C* 5700
59 C/EXEC SQL WHENEVER SQLERROR GO TO RPTERR 5800
60 C/END-EXEC 5900
61 C* 6000
62 C* Report the updated statistics for each employee assigned to 6100
63 C* selected projects. 6200
64 C* 6300
65 C* Write out the header for report 1. 6400

Figure 42. Sample RPG for AS/400 Program Using SQL Statements (Part 2 of 8)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 629
5769ST1 V4R4M0 990521 Create SQL RPG Program RPGEX 04/01/98 12:55:22 Page 3
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
66 C* 6500
67 C EXCPTRECA 6600
68 „6… C/EXEC SQL DECLARE C1 CURSOR FOR 6700 02/03/93
69 C+ SELECT DISTINCT PROJNO, EMP_ACT.EMPNO, 6800 02/03/93
70 C+ LASTNAME||', '||FIRSTNME, SALARY 6900 02/03/93
71 C+ FROM CORPDATA/EMP_ACT, CORPDATA/EMPLOYEE 7000 02/03/93
72 C+ WHERE EMP_ACT.EMPNO = EMPLOYEE.EMPNO AND 7100 02/03/93
73 C+ COMM >= :COMMI 7200 02/03/93
74 C+ ORDER BY PROJNO, EMPNO 7300 02/03/93
75 C/END-EXEC 7400
76 C* 7500
77 „7… C/EXEC SQL 7600
78 C+ OPEN C1 7700
79 C/END-EXEC 7800
80 C* 7900
81 C* Fetch and write the rows to QPRINT. 8000
82 C* 8100
83 „8… C/EXEC SQL WHENEVER NOT FOUND GO TO DONE1 8200
84 C/END-EXEC 8300
85 C SQLCOD DOUNE0 8400
86 C/EXEC SQL 8500
87 „9… C+ FETCH C1 INTO :PROJNO, :EMPNO, :NAME, :SALARY 8600
88 C/END-EXEC 8700
89 C EXCPTRECB 8800
90 C END 8900
91 C DONE1 TAG 9000
92 C/EXEC SQL 9100
93 „10… C+ CLOSE C1 9200
94 C/END-EXEC 9300
95 C* 9400
96 C* For all project ending at a date later than the raise date 9500
97 C* (i.e. those projects potentially affected by the salary raises) 9600
98 C* generate a report containing the project number, project name, 9700
99 C* the count of employees participating in the project and the 9800
100 C* total salary cost of the project. 9900
101 C* 10000
102 C* Write out the header for report 2. 10100
103 C* 10200
104 C EXCPTRECC 10300
105 „11… C/EXEC SQL 10400
106 C+ DECLARE C2 CURSOR FOR 10500
107 C+ SELECT EMP_ACT.PROJNO, PROJNAME, COUNT(*), 10600
108 C+ SUM((DAYS(EMENDATE) - DAYS(EMSTDATE)) * EMPTIME * 10700
109 C+ DECIMAL((SALARY/:WRKDAY),8,2)) 10800
110 C+ FROM CORPDATA/EMP_ACT, CORPDATA/PROJECT, CORPDATA/EMPLOYEE 10900
111 C+ WHERE EMP_ACT.PROJNO = PROJECT.PROJNO AND 11000
112 C+ EMP_ACT.EMPNO = EMPLOYEE.EMPNO AND 11100
113 C+ PRENDATE > :RDATE 11200
114 C+ GROUP BY EMP_ACT.PROJNO, PROJNAME 11300
115 C+ ORDER BY 1 11400
116 C/END-EXEC 11500
117 C* 11600
118 C/EXEC SQL OPEN C2 11700
119 C/END-EXEC 11800
120 C* 11900
121 C* Fetch and write the rows to QPRINT. 12000
122 C* 12100
123 C/EXEC SQL WHENEVER NOT FOUND GO TO DONE2 12200
124 C/END-EXEC 12300
125 C SQLCOD DOUNE0 12400
126 C/EXEC SQL 12500
127 „12… C+ FETCH C2 INTO :RPT2 12600
128 C/END-EXEC 12700
129 C EXCPTRECD 12800
130 C END 12900

Figure 42. Sample RPG for AS/400 Program Using SQL Statements (Part 3 of 8)

630 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL RPG Program RPGEX 04/01/98 12:55:22 Page 4
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
131 C DONE2 TAG 13000
132 C/EXEC SQL CLOSE C2 13100
133 C/END-EXEC 13200
134 C RETRN 13300 02/03/93
135 C* 13400
136 C* Error occured while updating table. Inform user and rollback 13500
137 C* changes. 13600
138 C* 13700
139 C UPDERR TAG 13800
140 C EXCPTRECE 13900
141 „13… C/EXEC SQL WHENEVER SQLERROR CONTINUE 14000
142 C/END-EXEC 14100
143 C* 14200
144 „14… C/EXEC SQL 14300
145 C+ ROLLBACK 14400
146 C/END-EXEC 14500
147 C RETRN 14600 02/03/93
148 C* 14700
149 C* Error occured while generating reports. Inform user and exit. 14800
150 C* 14900
151 C RPTERR TAG 15000
152 C EXCPTRECF 15100
153 C* 15200
154 C* All done. 15300
155 C* 15400
156 C FINISH TAG 15500
157 OQPRINT E 0201 RECA 15700
158 O 45 'REPORT OF PROJECTS AFFEC' 15800
159 O 64 'TED BY EMPLOYEE RAISES' 15900
160 O E 01 RECA 16000
161 O 7 'PROJECT' 16100
162 O 17 'EMPLOYEE' 16200
163 O 32 'EMPLOYEE NAME' 16300
164 O 60 'SALARY' 16400
165 O E 01 RECB 16500
166 O PROJNO 6 16600
167 O EMPNO 15 16700
168 O NAME 50 16800
169 O SALARYL 61 16900
170 O E 22 RECC 17000
171 O 42 'ACCUMULATED STATISTIC' 17100
172 O 54 'S BY PROJECT' 17200
173 O E 01 RECC 17300
174 O 7 'PROJECT' 17400
175 O 56 'NUMBER OF' 17500
176 O 67 'TOTAL' 17600
177 O E 02 RECC 17700
178 O 6 'NUMBER' 17800
179 O 21 'PROJECT NAME' 17900
180 O 56 'EMPLOYEES' 18000
181 O 66 'COST' 18100
182 O E 01 RECD 18200
195 O 57 'CODE=' 19500
183 O PRJNUM 6 18300
184 O PNAME 45 18400
185 O EMPCNTL 54 18500
186 O PRCOSTL 70 18600
187 O E 01 RECE 18700
188 O 28 '*** ERROR Occurred while' 18800
189 O 52 ' updating table. SQLCODE' 18900
190 O 53 '=' 19000
191 O SQLCODL 62 19100
192 O E 01 RECF 19200
193 O 28 '*** ERROR Occurred while' 19300
194 O 52 ' generating reports. SQL' 19400

Figure 42. Sample RPG for AS/400 Program Using SQL Statements (Part 4 of 8)

5769ST1 V4R4M0 990521 Create SQL RPG Program RPGEX 04/01/98 12:55:22 Page 5
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change
196 O SQLCODL 67 19600
* * * * * E N D O F S O U R C E * * * * *

Figure 42. Sample RPG for AS/400 Program Using SQL Statements (Part 5 of 8)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 631
5769ST1 V4R4M0 990521 Create SQL RPG Program RPGEX 04/01/98 12:55:22 Page 6
CROSS REFERENCE
Data Names Define Reference
ACTNO 68 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
BIRTHDATE 48 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
BONUS 48 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
COMM **** COLUMN
48 68
COMM 48 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
COMMI 31 DECIMAL(7,2)
48 68
CORPDATA **** COLLECTION
48 68 68 105 105 105
C1 68 CURSOR
77 86 92
C2 105 CURSOR
118 126 132
DEPTNO 8 CHARACTER(3) IN RPT1
DEPTNO 105 CHARACTER(3) COLUMN (NOT NULL) IN CORPDATA.PROJECT
DONE1 91 LABEL
83
DONE2 131 LABEL
123
EDLEVEL 48 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMENDATE 68 DATE(10) COLUMN IN CORPDATA.EMP_ACT
EMENDATE **** COLUMN
105
EMP_ACT **** TABLE
68 68 105 105 105 105
EMP_ACT **** TABLE IN CORPDATA
68 105
EMPCNT 26 SMALL INTEGER PRECISION(4,0) IN RPT2
EMPLOYEE **** TABLE IN CORPDATA
48 68 105
EMPLOYEE **** TABLE
68 105
EMPNO 17 CHARACTER(6)
86
EMPNO 48 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMPNO **** COLUMN IN EMP_ACT
68 68 68 105
EMPNO **** COLUMN IN EMPLOYEE
68 105
EMPNO 68 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
EMPTIME 68 DECIMAL(5,2) COLUMN IN CORPDATA.EMP_ACT
EMPTIME **** COLUMN
105
EMSTDATE 68 DATE(10) COLUMN IN CORPDATA.EMP_ACT
EMSTDATE **** COLUMN
105
FINISH 156 LABEL
FIRSTNME 48 VARCHAR(12) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE

Figure 42. Sample RPG for AS/400 Program Using SQL Statements (Part 6 of 8)

632 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL RPG Program RPGEX 04/01/98 12:55:22 Page 7
CROSS REFERENCE
FIRSTNME **** COLUMN
68
HIREDATE 48 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
JOB 48 CHARACTER(8) COLUMN IN CORPDATA.EMPLOYEE
LASTNAME 48 VARCHAR(15) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
LASTNAME **** COLUMN
68
MAJPRJ 8 CHARACTER(6) IN RPT1
MAJPROJ 105 CHARACTER(6) COLUMN IN CORPDATA.PROJECT
MIDINIT 48 CHARACTER(1) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
NAME 18 CHARACTER(30)
86
PERCNT 33 DECIMAL(7,2)
48
PHONENO 48 CHARACTER(4) COLUMN IN CORPDATA.EMPLOYEE
PNAME 25 CHARACTER(36) IN RPT2
PRCOST 27 DECIMAL(9,2) IN RPT2
PREND 8 DATE(10) IN RPT1
PRENDATE **** COLUMN
105
PRENDATE 105 DATE(10) COLUMN IN CORPDATA.PROJECT
PRJNUM 24 CHARACTER(6) IN RPT2
PROJECT **** TABLE IN CORPDATA
105
PROJECT **** TABLE
105
PROJNAME **** COLUMN
105 105
PROJNAME 105 VARCHAR(24) COLUMN (NOT NULL) IN CORPDATA.PROJECT
PROJNM 8 VARCHAR(24) IN RPT1
PROJNO 8 CHARACTER(6) IN RPT1
86
PROJNO **** COLUMN
68 68
PROJNO 68 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
PROJNO **** COLUMN IN EMP_ACT
105 105 105
PROJNO **** COLUMN IN PROJECT
105
PROJNO 105 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.PROJECT
PRSTAFF 105 DECIMAL(5,2) COLUMN IN CORPDATA.PROJECT
PRSTD 8 DATE(10) IN RPT1
PRSTDATE 105 DATE(10) COLUMN IN CORPDATA.PROJECT
RDATE 32 CHARACTER(10)
105

Figure 42. Sample RPG for AS/400 Program Using SQL Statements (Part 7 of 8)

5769ST1 V4R4M0 990521 Create SQL RPG Program RPGEX 04/01/98 12:55:22 Page 8
CROSS REFERENCE
RESEM 8 CHARACTER(6) IN RPT1
RESPEMP 105 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.PROJECT
RPTERR 151 LABEL
59
RPT1 8 STRUCTURE
RPT2 23 STRUCTURE
126
SALARY 19 DECIMAL(9,2)
86
SALARY **** COLUMN
48 48 68 105
SALARY 48 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
SEX 48 CHARACTER(1) COLUMN IN CORPDATA.EMPLOYEE
STAFF 8 DECIMAL(5,2) IN RPT1
UPDERR 139 LABEL
45
WORKDEPT 48 CHARACTER(3) COLUMN IN CORPDATA.EMPLOYEE
WRKDAY 30 SMALL INTEGER PRECISION(4,0)
105
No errors found in source
196 Source records processed
* * * * * E N D O F L I S T I N G * * * * *

Figure 42. Sample RPG for AS/400 Program Using SQL Statements (Part 8 of 8)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 633
SQL Statements in ILE RPG for AS/400 Programs

5769ST1 V4R4M0 990521 Create SQL ILE RPG Object RPGLEEX 04/01/98 16:03:02 Page 1
Source type...............RPG
Object name...............CORPDATA/RPGLEEX
Source file...............CORPDATA/SRC
Member....................*OBJ
To source file............QTEMP/QSQLTEMP1
Options...................*XREF
Listing option............*PRINT
Target release............V4R4M0
INCLUDE file..............*LIBL/*SRCFILE
Commit....................*CHG
Allow copy of data........*YES
Close SQL cursor..........*ENDMOD
Allow blocking............*READ
Delay PREPARE.............*NO
Generation level..........10
Printer file..............*LIBL/QSYSPRT
Date format...............*JOB
Date separator............*JOB
Time format...............*HMS
Time separator ...........*JOB
Replace...................*YES
Relational database.......*LOCAL
User .....................*CURRENT
RDB connect method........*DUW
Default Collection........*NONE
Package name..............*OBJLIB/*OBJ
Created object type.......*PGM
Debugging view............*NONE
Dynamic User Profile......*USER
User Profile..............*NAMING
Sort Sequence.............*JOB
Language ID...............*JOB
IBM SQL flagging..........*NOFLAG
ANS flagging..............*NONE
Text......................*SRCMBRTXT
Source file CCSID.........65535
Job CCSID.................65535
Source member changed on 07/01/96 15:55:32

Figure 43. Sample ILE RPG for AS/400 Program Using SQL Statements (Part 1 of 7)

634 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL ILE RPG Object RPGLEEX 04/01/98 16:03:02 Page 2
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change Comments
1 H 100
2 F* File declaration for QPRINT 200
3 F* 300
4 FQPRINT O F 132 PRINTER 400
5 D* 500
6 D* Structure for report 1. 600
7 D* 700
8 „1… DRPT1 E DS EXTNAME(PROJECT) 800
9 D* 900
10 D DS 1000
11 D EMPNO 1 6 1100
12 D NAME 7 36 1200
13 D SALARY 37 41P 2 1300
14 D* 1400
15 D* Structure for report 2. 1500
16 D* 1600
17 DRPT2 DS 1700
18 D PRJNUM 1 6 1800
19 D PNAME 7 42 1900
20 D EMPCNT 43 44B 0 2000
21 D PRCOST 45 49P 2 2100
22 D* 2200
23 D DS 2300
24 D WRKDAY 1 2B 0 2400
25 D COMMI 3 6P 2 2500
26 D RDATE 7 16 2600
27 D PERCNT 17 20P 2 2700
28 * 2800
29 „2… C Z-ADD 253 WRKDAY 2900
30 C Z-ADD 2000.00 COMMI 3000
31 C Z-ADD 1.04 PERCNT 3100
32 C MOVEL '1982-06-' RDATE 3200
33 C MOVE '01' RDATE 3300
34 C SETON LR 3400
35 C* 3500
36 C* Update the selected projects by the new percentage. If an 3600
37 C* error occurs during the update, ROLLBACK the changes. 3700
38 C* 3800
39 „3… C/EXEC SQL WHENEVER SQLERROR GOTO UPDERR 3900
40 C/END-EXEC 4000
41 C* 4100
42 C/EXEC SQL 4200
43 „4… C+ UPDATE CORPDATA/EMPLOYEE 4300
44 C+ SET SALARY = SALARY * :PERCNT 4400
45 C+ WHERE COMM >= :COMMI 4500
46 C/END-EXEC 4600
47 C* 4700
48 C* Commit changes. 4800
49 C* 4900
50 „5… C/EXEC SQL COMMIT 5000
51 C/END-EXEC 5100
52 C* 5200
53 C/EXEC SQL WHENEVER SQLERROR GO TO RPTERR 5300
54 C/END-EXEC 5400
55 C* 5500
56 C* Report the updated statistics for each employee assigned to 5600
57 C* selected projects. 5700
58 C* 5800
59 C* Write out the header for report 1. 5900
60 C* 6000
61 C EXCEPT RECA 6100
62 „6… C/EXEC SQL DECLARE C1 CURSOR FOR 6200
63 C+ SELECT DISTINCT PROJNO, EMP_ACT.EMPNO, 6300
64 C+ LASTNAME||', '||FIRSTNME, SALARY 6400
65 C+ FROM CORPDATA/EMP_ACT, CORPDATA/EMPLOYEE 6500

Figure 43. Sample ILE RPG for AS/400 Program Using SQL Statements (Part 2 of 7)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 635
5769ST1 V4R4M0 990521 Create SQL ILE RPG Object RPGLEEX 04/01/98 16:03:02 Page 3
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change Comments
66 C+ WHERE EMP_ACT.EMPNO = EMPLOYEE.EMPNO AND 6600
67 C+ COMM >= :COMMI 6700
68 C+ ORDER BY PROJNO, EMPNO 6800
69 C/END-EXEC 6900
70 C* 7000
71 „7… C/EXEC SQL 7100
72 C+ OPEN C1 7200
73 C/END-EXEC 7300
74 C* 7400
75 C* Fetch and write the rows to QPRINT. 7500
76 C* 7600
77 „8… C/EXEC SQL WHENEVER NOT FOUND GO TO DONE1 7700
78 C/END-EXEC 7800
79 C SQLCOD DOUNE 0 7900
80 C/EXEC SQL 8000
81 „9… C+ FETCH C1 INTO :PROJNO, :EMPNO, :NAME, :SALARY 8100
82 C/END-EXEC 8200
83 C EXCEPT RECB 8300
84 C END 8400
85 C DONE1 TAG 8500
86 C/EXEC SQL 8600
87 „10… C+ CLOSE C1 8700
88 C/END-EXEC 8800
89 C* 8900
90 C* For all project ending at a date later than the raise date 9000
91 C* (i.e. those projects potentially affected by the salary raises) 9100
92 C* generate a report containing the project number, project name, 9200
93 C* the count of employees participating in the project and the 9300
94 C* total salary cost of the project. 9400
95 C* 9500
96 C* Write out the header for report 2. 9600
97 C* 9700
98 C EXCEPT RECC 9800
99 C/EXEC SQL 9900
100 „11… C+ DECLARE C2 CURSOR FOR 10000
101 C+ SELECT EMP_ACT.PROJNO, PROJNAME, COUNT(*), 10100
102 C+ SUM((DAYS(EMENDATE) - DAYS(EMSTDATE)) * EMPTIME * 10200
103 C+ DECIMAL((SALARY/:WRKDAY),8,2)) 10300
104 C+ FROM CORPDATA/EMP_ACT, CORPDATA/PROJECT, CORPDATA/EMPLOYEE 10400
105 C+ WHERE EMP_ACT.PROJNO = PROJECT.PROJNO AND 10500
106 C+ EMP_ACT.EMPNO = EMPLOYEE.EMPNO AND 10600
107 C+ PRENDATE > :RDATE 10700
108 C+ GROUP BY EMP_ACT.PROJNO, PROJNAME 10800
109 C+ ORDER BY 1 10900
110 C/END-EXEC 11000
111 C* 11100
112 C/EXEC SQL OPEN C2 11200
113 C/END-EXEC 11300
114 C* 11400
115 C* Fetch and write the rows to QPRINT. 11500
116 C* 11600
117 C/EXEC SQL WHENEVER NOT FOUND GO TO DONE2 11700
118 C/END-EXEC 11800
119 C SQLCOD DOUNE 0 11900
120 C/EXEC SQL 12000
121 „12… C+ FETCH C2 INTO :RPT2 12100
122 C/END-EXEC 12200
123 C EXCEPT RECD 12300
124 C END 12400
125 C DONE2 TAG 12500
126 C/EXEC SQL CLOSE C2 12600
127 C/END-EXEC 12700
128 C RETURN 12800
129 C* 12900
130 C* Error occured while updating table. Inform user and rollback 13000

Figure 43. Sample ILE RPG for AS/400 Program Using SQL Statements (Part 3 of 7)

636 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL ILE RPG Object RPGLEEX 04/01/98 16:03:02 Page 4
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 SEQNBR Last change Comments
131 C* changes. 13100
132 C* 13200
133 C UPDERR TAG 13300
134 C EXCEPT RECE 13400
135 „13… C/EXEC SQL WHENEVER SQLERROR CONTINUE 13500
136 C/END-EXEC 13600
137 C* 13700
138 „14… C/EXEC SQL 13800
139 C+ ROLLBACK 13900
140 C/END-EXEC 14000
141 C RETURN 14100
142 C* 14200
143 C* Error occured while generating reports. Inform user and exit. 14300
144 C* 14400
145 C RPTERR TAG 14500
146 C EXCEPT RECF 14600
147 C* 14700
148 C* All done. 14800
149 C* 14900
150 C FINISH TAG 15000
151 OQPRINT E RECA 0 2 01 15100
152 O 42 'REPORT OF PROJECTS AFFEC' 15200
153 O 64 'TED BY EMPLOYEE RAISES' 15300
154 O E RECA 0 1 15400
155 O 7 'PROJECT' 15500
156 O 17 'EMPLOYEE' 15600
157 O 32 'EMPLOYEE NAME' 15700
158 O 60 'SALARY' 15800
159 O E RECB 0 1 15900
160 O PROJNO 6 16000
161 O EMPNO 15 16100
162 O NAME 50 16200
163 O SALARY L 61 16300
164 O E RECC 2 2 16400
165 O 42 'ACCUMULATED STATISTIC' 16500
166 O 54 'S BY PROJECT' 16600
167 O E RECC 0 1 16700
168 O 7 'PROJECT' 16800
169 O 56 'NUMBER OF' 16900
170 O 67 'TOTAL' 17000
171 O E RECC 0 2 17100
172 O 6 'NUMBER' 17200
173 O 21 'PROJECT NAME' 17300
174 O 56 'EMPLOYEES' 17400
175 O 66 'COST' 17500
176 O E RECD 0 1 17600
177 O PRJNUM 6 17700
178 O PNAME 45 17800
179 O EMPCNT L 54 17900
180 O PRCOST L 70 18000
181 O E RECE 0 1 18100
182 O 28 '*** ERROR Occurred while' 18200
183 O 52 ' updating table. SQLCODE' 18300
184 O 53 '=' 18400
185 O SQLCOD L 62 18500
186 O E RECF 0 1 18600
187 O 28 '*** ERROR Occurred while' 18700
188 O 52 ' generating reports. SQL' 18800
189 O 57 'CODE=' 18900
190 O SQLCOD L 67 19000
* * * * * E N D O F S O U R C E * * * * *

Figure 43. Sample ILE RPG for AS/400 Program Using SQL Statements (Part 4 of 7)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 637
5769ST1 V4R4M0 990521 Create SQL ILE RPG Object RPGLEEX 04/01/98 16:03:02 Page 5
CROSS REFERENCE
Data Names Define Reference
ACTNO 62 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
BIRTHDATE 42 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
BONUS 42 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
COMM **** COLUMN
42 62
COMM 42 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
COMMI 25 DECIMAL(7,2)
42 62
CORPDATA **** COLLECTION
42 62 62 99 99 99
C1 62 CURSOR
71 80 86
C2 99 CURSOR
112 120 126
DEPTNO 8 CHARACTER(3) IN RPT1
DEPTNO 99 CHARACTER(3) COLUMN (NOT NULL) IN CORPDATA.PROJECT
DONE1 85
DONE1 **** LABEL
77
DONE2 125
DONE2 **** LABEL
117
EDLEVEL 42 SMALL INTEGER PRECISION(4,0) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMENDATE 62 DATE(10) COLUMN IN CORPDATA.EMP_ACT
EMENDATE **** COLUMN
99
EMP_ACT **** TABLE
62 62 99 99 99 99
EMP_ACT **** TABLE IN CORPDATA
62 99
EMPCNT 20 SMALL INTEGER PRECISION(4,0) IN RPT2
EMPLOYEE **** TABLE IN CORPDATA
42 62 99
EMPLOYEE **** TABLE
62 99
EMPNO 11 CHARACTER(6) DBCS-open
80
EMPNO 42 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
EMPNO **** COLUMN IN EMP_ACT
62 62 62 99
EMPNO **** COLUMN IN EMPLOYEE
62 99
EMPNO 62 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
EMPTIME 62 DECIMAL(5,2) COLUMN IN CORPDATA.EMP_ACT
EMPTIME **** COLUMN
99
EMSTDATE 62 DATE(10) COLUMN IN CORPDATA.EMP_ACT
EMSTDATE **** COLUMN
99
FINISH 150

Figure 43. Sample ILE RPG for AS/400 Program Using SQL Statements (Part 5 of 7)

638 DB2 UDB for AS/400 SQL Programming V4R4


5769ST1 V4R4M0 990521 Create SQL ILE RPG Object RPGLEEX 04/01/98 16:03:02 Page 6
CROSS REFERENCE
FIRSTNME 42 VARCHAR(12) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
FIRSTNME **** COLUMN
62
HIREDATE 42 DATE(10) COLUMN IN CORPDATA.EMPLOYEE
JOB 42 CHARACTER(8) COLUMN IN CORPDATA.EMPLOYEE
LASTNAME 42 VARCHAR(15) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
LASTNAME **** COLUMN
62
MAJPROJ 8 CHARACTER(6) IN RPT1
MAJPROJ 99 CHARACTER(6) COLUMN IN CORPDATA.PROJECT
MIDINIT 42 CHARACTER(1) COLUMN (NOT NULL) IN CORPDATA.EMPLOYEE
NAME 12 CHARACTER(30) DBCS-open
80
PERCNT 27 DECIMAL(7,2)
42
PHONENO 42 CHARACTER(4) COLUMN IN CORPDATA.EMPLOYEE
PNAME 19 CHARACTER(36) DBCS-open IN RPT2
PRCOST 21 DECIMAL(9,2) IN RPT2
PRENDATE 8 DATE(8) IN RPT1
PRENDATE **** COLUMN
99
PRENDATE 99 DATE(10) COLUMN IN CORPDATA.PROJECT
PRJNUM 18 CHARACTER(6) DBCS-open IN RPT2
PROJECT **** TABLE IN CORPDATA
99
PROJECT **** TABLE
99
PROJNAME 8 VARCHAR(24) IN RPT1
PROJNAME **** COLUMN
99 99
PROJNAME 99 VARCHAR(24) COLUMN (NOT NULL) IN CORPDATA.PROJECT
PROJNO 8 CHARACTER(6) IN RPT1
80
PROJNO **** COLUMN
62 62
PROJNO 62 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.EMP_ACT
PROJNO **** COLUMN IN EMP_ACT
99 99 99
PROJNO **** COLUMN IN PROJECT
99
PROJNO 99 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.PROJECT
PRSTAFF 8 DECIMAL(5,2) IN RPT1
PRSTAFF 99 DECIMAL(5,2) COLUMN IN CORPDATA.PROJECT
PRSTDATE 8 DATE(8) IN RPT1
PRSTDATE 99 DATE(10) COLUMN IN CORPDATA.PROJECT

Figure 43. Sample ILE RPG for AS/400 Program Using SQL Statements (Part 6 of 7)

5769ST1 V4R4M0 990521 Create SQL ILE RPG Object RPGLEEX 04/01/98 16:03:02 Page 7
CROSS REFERENCE
RDATE 26 CHARACTER(10) DBCS-open
99
RESPEMP 8 CHARACTER(6) IN RPT1
RESPEMP 99 CHARACTER(6) COLUMN (NOT NULL) IN CORPDATA.PROJECT
RPTERR 145
RPTERR **** LABEL
53
RPT1 8 STRUCTURE
RPT2 17 STRUCTURE
120
SALARY 13 DECIMAL(9,2)
80
SALARY **** COLUMN
42 42 62 99
SALARY 42 DECIMAL(9,2) COLUMN IN CORPDATA.EMPLOYEE
SEX 42 CHARACTER(1) COLUMN IN CORPDATA.EMPLOYEE
UPDERR 133
UPDERR **** LABEL
39
WORKDEPT 42 CHARACTER(3) COLUMN IN CORPDATA.EMPLOYEE
WRKDAY 24 SMALL INTEGER PRECISION(4,0)
99
No errors found in source
190 Source records processed
* * * * * E N D O F L I S T I N G * * * * *

Figure 43. Sample ILE RPG for AS/400 Program Using SQL Statements (Part 7 of 7)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 639
SQL Statements in REXX Programs

Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8


1 /*********************************************************************/
2 /* A sample program which updates the salaries for those employees */
3 /* whose current commission total is greater than or equal to the */
4 /* value of COMMISSION. The salaries of those who qualify are */
5 /* increased by the value of PERCENTAGE, retroactive to RAISE_DATE. */
6 /* A report is generated and dumped to the display which shows the */
7 /* projects which these employees have contributed to, ordered by */
8 /* project number and employee ID. A second report shows each */
9 /* project having an end date occurring after RAISE DATE (i.e. is */
10 /* potentially affected by the retroactive raises) with its total */
11 /* salary expenses and a count of employees who contributed to the */
12 /* project. */
13 /*********************************************************************/
14
15
16 /* Initialize RC variable */
17 RC = 0
18
19 /* Initialize HV for program usage */
20 COMMISSION = 2000.00;
21 PERCENTAGE = 1.04;
22 RAISE_DATE = '1982-06-01';
23 WORK_DAYS = 253;
24
25 /* Create the output file to dump the 2 reports. Perform an OVRDBF */
26 /* to allow us to use the SAY REXX command to write to the output */
27 /* file. */
28 ADDRESS '*COMMAND',
29 'DLTF FILE(CORPDATA/REPORTFILE)'
30 ADDRESS '*COMMAND',
31 'CRTPF FILE(CORPDATA/REPORTFILE) RCDLEN(80)'
32 ADDRESS '*COMMAND',
33 'OVRDBF FILE(STDOUT) TOFILE(CORPDATA/REPORTFILE) MBR(REPORTFILE)'
34
35 /* Update the selected employee's salaries by the new percentage. */
36 /* If an error occurs during the update, ROLLBACK the changes. */
37 „3…SIGNAL ON ERROR
38 ERRLOC = 'UPDATE_ERROR'
39 UPDATE_STMT = 'UPDATE CORPDATA/EMPLOYEE ',
40 'SET SALARY = SALARY * ? ',
41 'WHERE COMM >= ? '
42 EXECSQL,
43 'PREPARE S1 FROM :UPDATE_STMT'
44 „4…EXECSQL,
45 'EXECUTE S1 USING :PERCENTAGE,',
46 ' :COMMISSION '
47 /* Commit changes */
48 „5…EXECSQL,
49 'COMMIT'

Figure 44. Sample REXX Procedure Using SQL Statements (Part 1 of 4)

640 DB2 UDB for AS/400 SQL Programming V4R4


Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8
50 ERRLOC = 'REPORT_ERROR'
51
52 /* Report the updated statistics for each project supported by one */
53 /* of the selected employees. */
54
55 /* Write out the header for Report 1 */
56 SAY ' '
57 SAY ' '
58 SAY ' '
59 SAY ' REPORT OF PROJECTS AFFECTED BY EMPLOYEE RAISES'
60 SAY ' '
61 SAY 'PROJECT EMPID EMPLOYEE NAME SALARY'
62 SAY '------- ----- ------------- ------'
63 SAY ' '
64
65 SELECT_STMT = 'SELECT DISTINCT PROJNO, EMP_ACT.EMPNO, ',
66 ' LASTNAME||'', ''||FIRSTNME, SALARY ',
67 'FROM CORPDATA/EMP_ACT, CORPDATA/EMPLOYEE ',
68 'WHERE EMP_ACT.EMPNO = EMPLOYEE.EMPNO AND ',
69 ' COMM >= ? ',
70 'ORDER BY PROJNO, EMPNO '
71 EXECSQL,
72 'PREPARE S2 FROM :SELECT_STMT'
73 „6…EXECSQL,
74 'DECLARE C1 CURSOR FOR S2'
75 „7…EXECSQL,
76 'OPEN C1 USING :COMMISSION'
77
78 /* Handle the FETCH errors and warnings inline */
79 SIGNAL OFF ERROR
80
81 /* Fetch all of the rows */
82 DO UNTIL (SQLCODE <> 0)
83 „9…EXECSQL,
84 'FETCH C1 INTO :RPT1.PROJNO, :RPT1.EMPNO,',
85 ' :RPT1.NAME, :RPT1.SALARY '
86
87 /* Process any errors that may have occurred. Continue so that */
88 /* we close the cursor for any warnings. */
89 IF SQLCODE < 0 THEN
90 SIGNAL ERROR
91
92 /* Stop the loop when we hit the EOF. Don't try to print out the */
93 /* fetched values. */
94 „8…IF SQLCODE = 100 THEN
95 LEAVE
96
97 /* Print out the fetched row */
98 SAY RPT1.PROJNO ' ' RPT1.EMPNO ' ' RPT1.NAME ' ' RPT1.SALARY
99 END;
100
101 „10…EXECSQL,
102 'CLOSE C1'
103
104 /* For all projects ending at a date later than 'raise_date' */
105 /* (i.e. those projects potentially affected by the salary raises) */
106 /* generate a report containing the project number, project name */
107 /* the count of employees participating in the project and the */
108 /* total salary cost of the project. */
109
110 /* Write out the header for Report 2 */
111 SAY ' '
112 SAY ' '
113 SAY ' '
114 SAY ' ACCUMULATED STATISTICS BY PROJECT'
115 SAY ' '
116 SAY 'PROJECT PROJECT NAME NUMBER OF TOTAL'
117 SAY 'NUMBER EMPLOYEES COST'
118 SAY '------- ------------ --------- -----'
119 SAY ' '
120

Figure 44. Sample REXX Procedure Using SQL Statements (Part 2 of 4)

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 641
Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8
121
122 /* Go to the common error handler */
123 SIGNAL ON ERROR
124
125 SELECT_STMT = 'SELECT EMP_ACT.PROJNO, PROJNAME, COUNT(*), ',
126 ' SUM( (DAYS(EMENDATE) - DAYS(EMSTDATE)) * EMPTIME * ',
127 ' DECIMAL(( SALARY / ? ),8,2) ) ',
128 'FROM CORPDATA/EMP_ACT, CORPDATA/PROJECT, CORPDATA/EMPLOYEE',
129 'WHERE EMP_ACT.PROJNO = PROJECT.PROJNO AND ',
130 ' EMP_ACT.EMPNO = EMPLOYEE.EMPNO AND ',
131 ' PRENDATE > ? ',
132 'GROUP BY EMP_ACT.PROJNO, PROJNAME ',
133 'ORDER BY 1 '
134 EXECSQL,
135 'PREPARE S3 FROM :SELECT_STMT'
136 „11…EXECSQL,
137 'DECLARE C2 CURSOR FOR S3'
138 EXECSQL,
139 'OPEN C2 USING :WORK_DAYS, :RAISE_DATE'
140
141 /* Handle the FETCH errors and warnings inline */
142 SIGNAL OFF ERROR
143
144 /* Fetch all of the rows */
145 DO UNTIL (SQLCODE <> 0)
146 „12…EXECSQL,
147 'FETCH C2 INTO :RPT2.PROJNO, :RPT2.PROJNAME, ',
148 ' :RPT2.EMPCOUNT, :RPT2.TOTAL_COST '
149
150 /* Process any errors that may have occurred. Continue so that */
151 /* we close the cursor for any warnings. */
152 IF SQLCODE < 0 THEN
153 SIGNAL ERROR
154
155 /* Stop the loop when we hit the EOF. Don't try to print out the */
156 /* fetched values. */
157 IF SQLCODE = 100 THEN
158 LEAVE
159
160 /* Print out the fetched row */
161 SAY RPT2.PROJNO ' ' RPT2.PROJNAME ' ' ,
162 RPT2.EMPCOUNT ' ' RPT2.TOTAL_COST
163 END;
164
165 EXECSQL,
166 'CLOSE C2'
167
168 /* Delete the OVRDBF so that we will continue writing to the output */
169 /* display. */
170 ADDRESS '*COMMAND',
171 'DLTOVR FILE(STDOUT)'
172
173 /* Leave procedure with a successful or warning RC */
174 EXIT RC
175
176
177 /* Error occurred while updating the table or generating the */
178 /* reports. If the error occurred on the UPDATE, rollback all of */
179 /* the changes. If it occurred on the report generation, display the */
180 /* REXX RC variable and the SQLCODE and exit the procedure. */
181 ERROR:
182
183 „13…SIGNAL OFF ERROR
184
185 /* Determine the error location */
186 SELECT
187 /* When the error occurred on the UPDATE statement */
188 WHEN ERRLOC = 'UPDATE_ERROR' THEN
190 DO
191 SAY '*** ERROR Occurred while updating table.',
192 'SQLCODE = ' SQLCODE
193 „14…EXECSQL,
194 'ROLLBACK'
195 END

Figure 44. Sample REXX Procedure Using SQL Statements (Part 3 of 4)

642 DB2 UDB for AS/400 SQL Programming V4R4


196 /* When the error occurred during the report generation */
197 WHEN ERRLOC = 'REPORT_ERROR' THEN
198 SAY '*** ERROR Occurred while generating reports. ',
199 'SQLCODE = ' SQLCODE
200 OTHERWISE
201 SAY '*** Application procedure logic error occurred '
202 END
203
204 /* Delete the OVRDBF so that we will continue writing to the */
205 /* output display. */
206 ADDRESS '*COMMAND',
207 'DLTOVR FILE(STDOUT)'
208
209 /* Return the error RC received from SQL. */
210 EXIT RC
211 * * * * * E N D O F S O U R C E * * * * *

Figure 44. Sample REXX Procedure Using SQL Statements (Part 4 of 4)

Report Produced by Sample Programs


The following report is produced by each of the preceding sample programs.
REPORT OF PROJECTS AFFECTED BY RAISES

PROJECT EMPID EMPLOYEE NAME SALARY

AD3100 000010 HAAS, CHRISTINE 54860.00


AD3110 000070 PULASKI, EVA 37616.80
AD3111 000240 MARINO, SALVATORE 29910.40
AD3113 000270 PEREZ, MARIA 28475.20
IF1000 000030 KWAN, SALLY 39780.00
IF1000 000140 NICHOLLS, HEATHER 29556.80
IF2000 000030 KWAN, SALLY 39780.00
IF2000 000140 NICHOLLS, HEATHER 29556.80
MA2100 000010 HAAS, CHRISTINE 54860.00
MA2100 000110 LUCCHESSI, VICENZO 48360.00
MA2110 000010 HAAS, CHRISTINE 54860.00
MA2111 000200 BROWN, DAVID 28849.60
MA2111 000220 LUTZ, JENNIFER 31033.60
MA2112 000150 ADAMSON, BRUCE 26291.20
OP1000 000050 GEYER, JOHN 41782.00
OP1010 000090 HENDERSON, EILEEN 30940.00
OP1010 000280 SCHNEIDER, ETHEL 27300.00
OP2010 000050 GEYER, JOHN 41782.00
OP2010 000100 SPENSER, THEODORE 27196.00
OP2012 000330 LEE, WING 26384.80
PL2100 000020 THOMPSON, MICHAEL 42900.00

ACCUMULATED STATISTICS BY PROJECT

PROJECT NUMBER OF TOTAL


NUMBER PROJECT NAME EMPLOYEES COST

AD3100 ADMIN SERVICES 1 19623.11


AD3110 GENERAL ADMIN SYSTEMS 1 58877.28
AD3111 PAYROLL PROGRAMMING 8 72806.74
AD3112 PERSONNEL PROGRAMMING 9 28845.70
AD3113 ACCOUNT PROGRAMMING 14 72114.52
IF1000 QUERY SERVICES 4 52205.66
IF2000 USER EDUCATION 5 55212.61
MA2100 WELD LINE AUTOMATION 2 114001.52
MA2110 W L PROGRAMMING 1 85864.68
MA2111 W L PROGRAM DESIGN 3 93729.24
MA2112 W L ROBOT DESIGN 6 166945.84

Appendix C. Sample Programs Using DB2 UDB for AS/400 Statements 643
MA2113 W L PROD CONT PROGS 5 71509.11
OP1000 OPERATION SUPPORT 1 16348.86
OP1010 OPERATION 5 167828.76
OP2010 SYSTEMS SUPPORT 2 91612.62
OP2011 SCP SYSTEMS SUPPORT 2 31224.60
OP2012 APPLICATIONS SUPPORT 2 41294.88
OP2013 DB/DC SUPPORT 2 37311.12
PL2100 WELD LINE PLANNING 1 43576.92

644 DB2 UDB for AS/400 SQL Programming V4R4


Appendix D. DB2 UDB for AS/400 CL Command Descriptions
This appendix contains the syntax diagrams referred to and used in this guide and
the DB2 UDB for AS/400 SQL Reference book.

CRTSQLCBL (Create Structured Query Language COBOL) Command


Job: B,I Pgm: B,I REXX: B,I Exec

*CURLIB/
ÊÊ CRTSQLCBL PGM( program-name ) Ê
library-name/

Ê Ê
*LIBL/ QLBLSRC
SRCFILE( source-file-name )
*CURLIB/
library-name/

(1)
Ê Ê
*PGM
SRCMBR( source-file-member-name )

Ê Ê
OPTION( OPTION Details ) *CURRENT
TGTRLS( *PRV )
VxRxMx

Ê Ê
*LIBL/ *SRCFILE
INCFILE( source-file-name )
*CURLIB/
library-name/

Ê Ê
*UR *ENDPGM
*CHG CLOSQLCSR( *ENDSQL )
COMMIT( *ALL ) *ENDJOB
*RS
*CS
*NONE
*NC
*RR

Ê Ê
*OPTIMIZE *ALLREAD
ALWCPYDTA( *YES ) ALWBLK( *NONE )
*NO *READ

© Copyright IBM Corp. 1997, 1999 645


CRTSQLCBL
Ê Ê
*NO 10
DLYPRP( *YES ) GENLVL( severity-level )

Ê Ê
*JOB *JOB
DATFMT( *USA ) DATSEP( '/' )
*ISO '.'
*EUR ','
*JIS '-'
*MDY ' '
*DMY *BLANK
*YMD
*JUL

Ê Ê
*HMS *JOB
TIMFMT( *USA ) TIMSEP( ':' )
*ISO '.'
*EUR ','
*JIS ' '
*BLANK

Ê Ê
*YES
REPLACE( *NO )

Ê Ê
*LOCAL *CURRENT
RDB( relational-database-name ) USER( user-name )
*NONE

Ê Ê
*NONE *DUW
PASSWORD( password ) RDBCNNMTH( *RUW )

Ê Ê
*NONE *NO
DFTRDBCOL( collection-name ) DYNDFTCOL( *YES )

Ê Ê
*PGMLIB/ *PGM
SQLPKG( package-name )
library-name/

646 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBL
Ê Ê
*NAMING
SQLPATH( *LIBL )

· collection-name

Ê Ê
*NOFLAG *NONE
SAAFLAG( *FLAG ) FLAGSTD( *ANS )

Ê Ê
*LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

Ê Ê
*JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

Ê Ê
*JOB *NAMING
LANGID( *JOBRUN ) USRPRF( *OWNER )
language-ID *USER

Ê Ê
*USER
DYNUSRPRF( *OWNER )

Ê Ê
QTEMP/ QSQLTEMP
TOSRCFILE( source-file-name )
*LIBL/
*CURLIB/
library-name/

Ê ÊÍ
*SRCMBRTXT
TEXT( *BLANK )
'description'

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 647


CRTSQLCBL
OPTION Details:

*NOSRC
*NOSOURCE *NOXREF *GEN *JOB *QUOTESQL
Ê
*SOURCE *XREF *NOGEN *PERIOD *APOSTSQL
*SRC *SYSVAL
*COMMA

*QUOTE *SYS *NOSECLVL *NOLSTDBG


Ê
*APOST *SQL *SECLVL *LSTDBG

Notes:
1. All parameters preceding this point can be specified in positional form.

Purpose
The Create Structured Query Language COBOL (CRTSQLCBL) command calls the
Structured Query Language (SQL) precompiler, which precompiles COBOL source
containing SQL statements, produces a temporary source member, and then
optionally calls the COBOL compiler to compile the program.

Parameters
PGM
Specifies the qualified name of the compiled program.

The name of the compiled COBOL program can be qualified by one of the
following library values:
*CURLIB The compiled COBOL program is created in the current library for
the job. If no library is specified as the current library for the job, the QGPL
library is used.
library name: Specify the name of the library where the compiled COBOL
program is created.

program-name: Specify the name of the compiled COBOL program.


SRCFILE
Specifies the qualified name of the source file that contains the COBOL source
with SQL statements.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QLBLSRC: If a COBOL source file name is not specified, the IBM-supplied


source file QLBLSRC contains the COBOL source.

648 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBL
source-file-name: Specify the name of the source file that contains the COBOL
source. This source file should have a record length of 92 bytes. The source file
can be a database file, device file, or an inline data file.
SRCMBR
Specifies the name of the source file member that contains the COBOL source.
This parameter is specified only if the source file name in the SRCFILE
parameter is a database file. If this parameter is not specified, the PGM name
specified on the PGM parameter is used.

*PGM: Specifies that the COBOL source is in the member of the source file that
has the same name as that specified on the PGM parameter.

source-file-member-name: Specify the name of the member that contains the


COBOL source.
OPTION
Specifies whether one or more of the following options are used when the
COBOL source is precompiled. If an option is specified more than once, or if
two options conflict, the last option specified is used.

Element 1: Source Listing Options

*NOSOURCE or *NOSRC: A source printout is not produced by the precompiler


unless errors are detected during precompile or create package.

*SOURCE or *SRC: The precompiler produces a source printout consisting of


COBOL source input.

Element 2: Cross-Reference Options

*NOXREF: The precompiler does not cross-reference names.

*XREF: The precompiler cross-references items in the program to the statement


numbers in the program that refer to those items.

Element 3: Program Creation Options

*GEN: The compiler creates a program that can run after the program is
compiled. An SQL package object is created if a relational database name is
specified on the RDB parameter.

*NOGEN: The precompiler does not call the COBOL compiler, and a program
and SQL package are not created.

Element 4: Decimal Point Options

*JOB: The value used as the decimal point for numeric constants in SQL is the
representation of decimal point specified for the job at precompile time.

*SYSVAL: The value used as the decimal point for numeric constants in SQL
statements is the QDECFMT system value.

Note: If QDECFMT specifies that the value used as the decimal point is a
comma, any numeric constants in lists (such as in the SELECT clause or
the VALUES clause) must be separated by a comma followed by a

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 649


CRTSQLCBL
blank. For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) in which the decimal point is a period.

*PERIOD: The value used as the decimal point for numeric constants in SQL
statements is a period.

*COMMA: The value used as the decimal point for numeric constants in SQL
statements is a comma.

Note: Any numeric constants in lists (such as in the SELECT clause or the
VALUES clause) must be separated by a comma followed by a blank.
For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) where the decimal point is a period.

Element 5: String Delimiter Options

*QUOTESQL: A double quote (") is the string delimiter in the SQL statements.

*APOSTSQL: An apostrophe (') is the string delimiter in the SQL statements.

Element 6: Literal Options

*QUOTE: A double quote (") is used for non-numeric literals and Boolean
literals in the COBOL statements.

*APOST: An apostrophe (') is used for non-numeric literals and Boolean literals
in the COBOL statements.

Element 7: Naming Convention Option

*SYS: The system naming convention (library-name/file-name) is used.

*SQL: The SQL naming convention (collection-name.table-name) is used. When


creating a program on a remote database other than an AS/400 system, *SQL
must be specified as the naming convention.

Element 8: Second-Level Message Text Option

*NOSECLVL: Second-level text descriptions are not added to the listing.

*SECLVL: Second-level text with replacement data is added for all messages
on the listing.

Element 9: Debug Listing View

*NOLSTDBG: Error and debug information is not generated.

*LSTDBG: The SQL precompiler generates a listing view, and error and debug
information required for this view. You can use *LSTDBG only if you are using
the CODE/400 product to compile your program.
TGTRLS
Specifies the release of the operating system on which the user intends to use
the object being created.

650 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBL
In the examples given for the *CURRENT and *PRV values, and when
specifying the release-level value, the format VxRxMx is used to specify the
release, where Vx is the version, Rx is the release, and Mx is the modification
level. For example, V2R3M0 is version 2, release 3, modification level 0.

*CURRENT: The object is to be used on the release of the operating system


currently running on the user’s system. For example, if V2R3M5 is running on
the system, *CURRENT means the user intends to use the object on a system
with V2R3M5 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

Note: If V2R3M5 is running on the system, and the object is to be used on a


system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
TGTRLS(*CURRENT).
*PRV: The object is to be used on the previous release with modification level 0
of the operating system. For example, if V2R3M5 is running on the user’s
system, *PRV means the user intends to use the object on a system with
V2R2M0 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

release-level: Specify the release in the format VxRxMx. The object can be
used on a system with the specified release or with any subsequent release of
the operating system installed.

Valid values depend on the current version, release, and modification level, and
they change with each new release. If you specify a release-level which is
earlier than the earliest release level supported by this command, an error
message is sent indicating the earliest supported release.
INCFILE
Specifies the qualified name of the source file that contains members included
in the program with any SQL INCLUDE statement.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

*SRCFILE: The qualified source file specified in the SRCFILE parameter


contains the source file member(s) specified on any SQL INCLUDE statement.

source-file-name: Specify the name of the source file that contains the source
file member(s) specified on any SQL INCLUDE statement. The record length of
the source file specified here must be no less than the record length of the
source file specified for the SRCFILE parameter.
COMMIT
Specifies whether SQL statements in the compiled program are run under
commitment control. Files referred to in the host language source are not
affected by this option. Only SQL tables, SQL views, and SQL packages
referred to in SQL statements are affected.

Note: Files referenced in the COBOL source are not affected by this option.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 651


CRTSQLCBL
*CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,
COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows updated, deleted, and inserted are locked
until the end of the unit of work (transaction). Uncommitted changes in other
jobs can be seen.

*ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows selected, updated, deleted, and inserted are
locked until the end of the unit of work (transaction). Uncommitted changes in
other jobs cannot be seen.

*CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows updated, deleted, and inserted are locked until the end of the unit of
work (transaction). A row that is selected, but not updated, is locked until the
next row is selected. Uncommitted changes in other jobs cannot be seen.

*NONE or *NC: Specifies that commitment control is not used. Uncommitted


changes in other jobs can be seen. If the SQL DROP COLLECTION statement
is included in the program, *NONE or *NC must be used. If a relational
database is specified on the RDB parameter and the relational database is on a
system that is not on an AS/400, *NONE or *NC cannot be specified.

*RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows selected, updated, deleted, and inserted are locked until the end of the
unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
are locked exclusively until the end of the unit of work (transaction).
CLOSQLCSR
Specifies when SQL cursors are implicitly closed, SQL prepared statements are
implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
HOLD) SQL statements.

*ENDPGM: SQL cursors are closed and SQL prepared statements are
discarded when the program ends. LOCK TABLE locks are released when the
first SQL program on the call stack ends.

*ENDSQL: SQL cursors remain open between calls and can be fetched without
running another SQL OPEN. One of the programs higher on the call stack must
have run at least one SQL statement. SQL cursors are closed, SQL prepared
statements are discarded, and LOCK TABLE locks are released when the first
SQL program on the call stack ends. If *ENDSQL is specified for a program that
is the first SQL program called (the first SQL program on the call stack), the
program is treated as if *ENDPGM was specified.

*ENDJOB: SQL cursors remain open between calls and can be fetched without
running another SQL OPEN. The programs higher on the call stack do not need
to have run SQL statements. SQL cursors are left open, SQL prepared
statements are preserved, and LOCK TABLE locks are held when the first SQL
program on the call stack ends. SQL cursors are closed, SQL prepared
statements are discarded, and LOCK TABLE locks are released when the job
ends.

652 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBL
| ALWCPYDTA
| Specifies whether a copy of the data can be used in a SELECT statement.

| *OPTIMIZE: The system determines whether to use the data retrieved directly
| from the database or to use a copy of the data. The decision is based on which
| method provides the best performance. If COMMIT is *CHG or *CS and
| ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
| data is used only when it is necessary to run a query.

| *YES: A copy of the data is used only when necessary.

| *NO: A copy of the data is not allowed. If a temporary copy of the data is
| required to perform the query, an error message is returned.
| ALWBLK
| Specifies whether the database manager can use record blocking, and the
| extent to which blocking can be used for read-only cursors.

| *ALLREAD: Rows are blocked for read-only cursors if *NONE or *CHG is


| specified on the COMMIT parameter. All cursors in a program that are not
| explicitly able to be updated are opened for read-only processing even though
| EXECUTE or EXECUTE IMMEDIATE statements may be in the program.

| Specifying *ALLREAD:
| v Allows record blocking under commitment control level *CHG in addition to
| the blocking allowed for *READ.
| v Can improve the performance of almost all read-only cursors in programs,
| but limits queries in the following ways:
| – The Rollback (ROLLBACK) command, a ROLLBACK statement in host
| languages, or the ROLLBACK HOLD SQL statement does not reposition a
| read-only cursor when *ALLREAD is specified.
| – Dynamic running of a positioned UPDATE or DELETE statement (for
| example, using EXECUTE IMMEDIATE), cannot be used to update a row
| in a cursor unless the DECLARE statement for the cursor includes the
| FOR UPDATE clause.

| *NONE: Rows are not blocked for retrieval of data for cursors.

| Specifying *NONE:
| v Guarantees that the data retrieved is current.
| v May reduce the amount of time required to retrieve the first row of data for a
| query.
| v Stops the database manager from retrieving a block of data rows that is not
| used by the program when only the first few rows of a query are retrieved
| before the query is closed.
| v Can degrade the overall performance of a query that retrieves a large
| number of rows.

| *READ: Records are blocked for read-only retrieval of data for cursors when:
| v *NONE is specified on the COMMIT parameter, which indicates that
| commitment control is not used.
| v The cursor is declared with a FOR READ ONLY clause or there are no
| dynamic statements that could run a positioned UPDATE or DELETE
| statement for the cursor.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 653


CRTSQLCBL
| Specifying *READ can improve the overall performance of queries that meet the
| above conditions and retrieve a large number of records.
DLYPRP
Specifies whether the dynamic statement validation for a PREPARE statement
is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
validation improves performance by eliminating redundant validation.

*NO: Dynamic statement validation is not delayed. When the dynamic


statement is prepared, the access plan is validated. When the dynamic
statement is used in an OPEN or EXECUTE statement, the access plan is
revalidated. Because the authority or the existence of objects referred to by the
dynamic statement may change, you must still check the SQLCODE or
SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
dynamic statement is still valid.

*YES: Dynamic statement validation is delayed until the dynamic statement is


used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
dynamic statement is used, the validation is completed and an access plan is
built. If you specify *YES on this parameter, you should check the SQLCODE
and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
ensure that the dynamic statement is valid.

Note: If you specify *YES, performance is not improved if the INTO clause is
used on the PREPARE statement or if a DESCRIBE statement uses the
dynamic statement before an OPEN is issued for the statement.
GENLVL
Specifies the severity level at which the create operation fails. If errors occur
that have a severity level greater than or equal to this value, the operation
ends.

10: The default severity level is 10.

severity-level: Specify a value ranging from 0 through 40.


DATFMT
Specifies the format used when accessing date result columns. All output date
fields are returned in the specified format. For input date strings, the specified
value is used to determine whether the date is specified in a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not an AS/400 system, then *USA, *ISO,
*EUR, or *JIS must be specified.

*JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
command to determine the current date format for the job.

*USA: The United States date format (mm/dd/yyyy) is used.

*ISO: The International Organization for Standardization (ISO) date format


(yyyy-mm-dd) is used.

*EUR: The European date format (dd.mm.yyyy) is used.

654 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBL
*JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

*MDY: The date format (mm/dd/yy) is used.

*DMY: The date format (dd/mm/yy) is used.

*YMD: The date format (yy/mm/dd) is used.

*JUL: The Julian date format (yy/ddd) is used.


DATSEP
Specifies the separator used when accessing date result columns.

Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
specified on the DATFMT parameter.

*JOB: The date separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’/’: A slash (/) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’-’: A dash (-) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


TIMFMT
Specifies the format used when accessing time result columns. For input time
strings, the specified value is used to determine whether the time is specified in
a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not another AS/400 system, the time
format must be *USA, *ISO, *EUR, *JIS, or *HMS with a time separator
of colon or period.

*HMS: The (hh:mm:ss) format is used.

*USA: The United States time format (hh:mm xx) is used, where xx is AM or
PM.

*ISO: The International Organization for Standardization (ISO) time format


(hh.mm.ss) is used.

*EUR: The European time format (hh.mm.ss) is used.

*JIS: The Japanese Industrial Standard time format (hh:mm:ss) is used.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 655


CRTSQLCBL
TIMSEP
Specifies the separator used when accessing time result columns.

Note: This parameter applies only when *HMS is specified on the TIMFMT
parameter.

*JOB: The time separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’:’: A colon (:) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


REPLACE
Specifies whether a new program or SQL package is created when a program
or SQL package of the same name exists in the same library. The value of this
parameter is passed to the CRTCBLPGM command. More information on this
parameter is in Appendix A, ″Expanded Parameter Descriptions″ in the CL
Reference (Abridged) book.

*YES: A new program or SQL package is created, and any existing program or
SQL package of the same name and type in the specified library is moved to
QRPLOBJ.

*NO: A new program or SQL package is not created if an object of the same
name and type already exists in the specified library.
RDB
Specifies the name of the relational database where the SQL package object is
created.

*LOCAL: The program is created as a distributed SQL program. The SQL


statements will access the local database. An SQL package object is not
created as part of the precompile process. The Create Structured Query
Language Package (CRTSQLPKG) command can be used.

relational-database-name: Specify the name of the relational database where


the new SQL package object is to be created. When the name of the local
relational database is specified, the program created is still a distributed SQL
program. The SQL statements will access the local database.

*NONE: An SQL package object is not created. The program object is not a
distributed program and the Create Structured Query Language Package
(CRTSQLPKG) command cannot be used.
USER
Specifies the user name sent to the remote system when starting the
conversation. This parameter is valid only when RDB is specified.

*CURRENT: The user profile under which the current job is running is used.

656 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBL
user-name: Specify the user name to be used for the application server job.
PASSWORD
Specifies the password to be used on the remote system. This parameter is
valid only if RDB is specified.

*NONE: No password is sent. If this value is specified, USER(*CURRENT)


must also be specified.

password: Specify the password of the user name specified on the USER
parameter.
RDBCNNMTH
Specifies the semantics used for CONNECT statements. Refer to the SQL
Reference book for more information.

*DUW: CONNECT (Type 2) semantics are used to support distributed unit of


work. Consecutive CONNECT statements to additional relational databases do
not result in disconnection of previous connections.

*RUW: CONNECT (Type 1) semantics are used to support remote unit of work.
Consecutive CONNECT statements result in the previous connection being
disconnected before a new connection is established.
DFTRDBCOL
Specifies the collection name used for the unqualified names of tables, views,
indexes, and SQL packages. This parameter applies only to static SQL
statements.

*NONE: The naming convention defined on the OPTION parameter is used.

collection-name: Specify the name of the collection identifier. This value is used
instead of the naming convention specified on the OPTION parameter.
| DYNDFTCOL
| Specifies whether the default collection name specified for the DFTRDBCOL
| parameter is also used for dynamic statements.

| *NO: Do not use the value specified on the DFTRDBCOL parameter for
| unqualified names of tables, views, indexes, and SQL packages for dynamic
| SQL statements. The naming convention specified on the OPTION parameter is
| used.

| *YES: The collection name specified on the DFTRDBCOL parameter will be


| used for the unqualified names of the tables, views, indexes, and SQL
| packages in dynamic SQL statements.
SQLPKG
Specifies the qualified name of the SQL package created on the relational
database specified on the RDB parameter of this command.

The library values are:


*PGMLIB: The package is created in the library with the same name as the
library containing the program.
library-name: Specify the name of the library where the package is created.

*PGM: The package name is the same as the program name.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 657


CRTSQLCBL
package-name: Specify the name of the package created on the remote
database specified on the RDB parameter.
| SQLPATH
| Specifies the path to be used to find procedures, functions, and user defined
| types in static SQL statements.

| *NAMING: The path used depends on the naming convention specified on the
| OPTION parameter.

| For *SYS naming, the path used is *LIBL, the current library list at runtime.

| For *SQL naming, the path used is ″QSYS″, ″QSYS2″, ″userid″, where ″userid″
| is the value of the USER special register. If a collection-name is specified on
| the DFTRDBCOL parameter, the collection-name takes the place of userid.

| *LIBL: The path used is the library list at runtime.

| collection-name: Specify a list of one or more collection names. A maximum of


| 43 individual collections may be specified.
SAAFLAG
Specifies the IBM SQL flagging function. This parameter flags SQL statements
to verify whether they conform to IBM SQL syntax More information about
which IBM database products IBM SQL syntax is in the DRDA IBM SQL
Reference, SC26-3255-00.

*NOFLAG: The precompiler does not check to see whether SQL statements
conform to IBM SQL syntax.

*FLAG: The precompiler checks to see whether SQL statements conform to


IBM SQL syntax.
FLAGSTD
Specifies the American National Standards Institute (ANSI) flagging function.
This parameter flags SQL statements to verify whether they conform to the
following standards.
ANSI X3.135-1992 entry
ISO 9075-1992 entry
FIPS 127.2 entry

*NONE: The precompiler does not check to see whether SQL statements
conform to ANSI standards.

*ANS: The precompiler checks to see whether SQL statements conform to


ANSI standards.
PRTFILE
Specifies the qualified name of the printer device file to which the listing is
directed. The file must have a minimum record length of 132 bytes or
information is lost.

The name of the printer file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.

658 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBL
QSYSPRT: If a file name is not specified, the precompiler printout is directed to
the IBM-supplied printer file QSYSPRT.

printer-file-name: Specify the name of the printer device file to which the
precompiler printout is directed.
SRTSEQ
Specifies the sort sequence table to be used for string comparisons in SQL
statements.

Note: *HEX must be specified for this parameter on distributed applications


where the application server is not on an AS/400 system or the release
level is prior to V2R3M0.

*JOB: The SRTSEQ value for the job is retrieved during the precompile.

*JOBRUN: The SRTSEQ value for the job is retrieved when the program is run.
For distributed applications, SRTSEQ(*JOBRUN) is valid only when
LANGID(*JOBRUN) is also specified.

*LANGIDUNQ: The unique-weight sort table for the language specified on the
LANGID parameter is used.

*LANGIDSHR: The shared-weight sort table for the language specified on the
LANGID parameter is used.

*HEX: A sort sequence table is not used. The hexadecimal values of the
characters are used to determine the sort sequence.

The name of the sort sequence table can be qualified by one of the following
library values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

table-name: Specify the name of the sort sequence table to be used.


LANGID
Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
SRTSEQ(*LANGIDSHR) is specified.

*JOB: The LANGID value for the job is retrieved during the precompile.

*JOBRUN: The LANGID value for the job is retrieved when the program is run.
For distributed applications, LANGID(*JOBRUN) is valid only when
SRTSEQ(*JOBRUN) is also specified.

language-id: Specify a language identifier to be used by the program.


USRPRF
Specifies the user profile that is used when the compiled program object is run,
including the authority that the program object has for each object in static SQL
statements. The profile of either the program owner or the program user is used
to control which objects can be used by the program object.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 659


CRTSQLCBL
*NAMING: The user profile is determined by the naming convention. If the
naming convention is *SQL, USRPRF(*OWNER) is used. If the naming
convention is *SYS, USRPRF(*USER) is used.

*USER: The profile of the user running the program object is used.

*OWNER: The user profiles of both the program owner and the program user
are used when the program is run.
DYNUSRPRF
Specifies the user profile used for dynamic SQL statements.

*USER: Local dynamic SQL statements are run under the user profile of the
job. Distributed dynamic SQL statements are run under the user profile of the
application server job.

*OWNER: Local dynamic SQL statements are run under the user profile of the
program’s owner. Distributed dynamic SQL statements are run under the user
profile of the SQL package’s owner.
| TOSRCFILE
| Specifies the qualified name of the source file that is to contain the output
| source member that has been processed by the SQL precompiler. If the
| specified source file is not found, it will be created. The output member will
| have the same name as the name that is specified for the SRCMBR parameter.

| The possible library values are:


| QTEMP: The library QTEMP will be used.
| *LIBL: The job’s library list is searched for the specified file. If the file is not
| found in any library in the library list, the file will be created in the current
| library.
| *CURLIB: The current library for the job will be used. If no library is
| specified as the current library for the job, the QGPL library will be used.
| library-name: Specify the name of the library that is to contain the output
| source file.

| QSQLTEMP: The source file QSQLTEMP will be used.

| source-file-name: Specify the name of the source file to contain the output
| source member.
TEXT
Specifies the text that briefly describes the program and its function. More
information on this parameter is in Appendix A, ″Expanded Parameter
Descriptions″ in the CL Reference (Abridged) book.

*SRCMBRTXT: The text is taken from the source file member being used to
create the COBOL program. Text for a database source member can be added
or changed by using the Start Source Entry Utility (STRSEU) command, or by
using either the Add Physical File Member (ADDPFM) or Change Physical File
Member (CHGPFM) command. If the source file is an inline file or a device file,
the text is blank.

*BLANK: Text is not specified.

660 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBL
’description’: Specify no more than 50 characters of text, enclosed in
apostrophes.

Example
CRTSQLCBL PGM(ACCTS/STATS) SRCFILE(ACCTS/ACTIVE)
TEXT('Statistical analysis program for
active accounts')

This command runs the SQL precompiler which precompiles the source and stores
the changed source in the member STATS in file QSQLTEMP in library QTEMP.
The COBOL compiler is called to create program STATS in library ACCTS using the
source member created by the SQL precompiler.

CRTSQLCBLI (Create SQL ILE COBOL Object) Command


Job: B,I Pgm: B,I REXX: B,I Exec

*CURLIB/
ÊÊ CRTSQLCBLI OBJ( object-name ) Ê
library-name/

Ê Ê
*LIBL/ QCBLLESRC
SRCFILE( source-file-name )
*CURLIB/
library-name/

(1)
Ê Ê
*OBJ
SRCMBR( source-file-member-name )

Ê Ê
OPTION( OPTION Details ) *CURRENT
TGTRLS( *PRV )
VxRxMx

Ê Ê
*PGM
OBJTYPE( *MODULE )
*SRVPGM

Ê Ê
*LIBL/ *SRCFILE
INCFILE( source-file-name )
*CURLIB/
library-name/

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 661


CRTSQLCBLI
Ê Ê
*UR *ENDACTGRP
*CHG CLOSQLCSR( *ENDMOD )
COMMIT( *ALL )
*RS
*CS
*NONE
*NC
*RR

Ê Ê
*OPTIMIZE *ALLREAD
ALWCPYDTA( *YES ) ALWBLK( *NONE )
*NO *READ

Ê Ê
*NO 10
DLYPRP( *YES ) GENLVL( severity-level )

Ê Ê
*JOB *JOB
DATFMT( *USA ) DATSEP( '/' )
*ISO '.'
*EUR ','
*JIS '-'
*MDY ' '
*DMY *BLANK
*YMD
*JUL

Ê Ê
*HMS *JOB
TIMFMT( *USA ) TIMSEP( ':' )
*ISO '.'
*EUR ','
*JIS ' '
*BLANK

Ê Ê
*YES *LOCAL
REPLACE( *NO ) RDB( relational-database-name )
*NONE

Ê Ê
*CURRENT *NONE
USER( user-name ) PASSWORD( password )

Ê Ê
*DUW *NONE
RDBCNNMTH( *RUW ) DFTRDBCOL( collection-name )

662 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBLI
Ê Ê
*NO
DYNDFTCOL( *YES )

Ê Ê
*OBJLIB/ *OBJ
SQLPKG( package-name )
library-name/

Ê Ê
*NAMING
SQLPATH( *LIBL )

· collection-name

Ê Ê
*NOFLAG *NONE
SAAFLAG( *FLAG ) FLAGSTD( *ANS )

Ê Ê
*NONE *NAMING
DBGVIEW( *SOURCE ) USRPRF( *OWNER )
*USER

Ê Ê
*USER
DYNUSRPRF( *OWNER )

Ê Ê
*JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

Ê Ê
*JOB *NONE
LANGID( *JOBRUN ) OUTPUT( *PRINT )
language-identifier

Ê Ê
*LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 663


CRTSQLCBLI
Ê Ê
QTEMP/ QSQLTEMP
TOSRCFILE( source-file-name )
*LIBL/
*CURLIB/
library-name/

Ê ÊÍ
*SRCMBRTXT
TEXT( *BLANK )
'description'

OPTION Details:

*XREF *GEN *JOB *SYS *NOSECLVL


Ê
*NOXREF *NOGEN *SYSVAL *SQL *SECLVL
*PERIOD
*COMMA

*QUOTESQL *QUOTE *NOEVENTF *OPTLOB


Ê
*APOSTSQL *APOST *EVENTF *NOOPTLOB

Notes:
1. All parameters preceding this point can be specified in positional form.

Purpose
The Create Structured Query Language ILE COBOL Object (CRTSQLCBLI)
command calls the Structured Query Language (SQL) precompiler which
precompiles COBOL source containing SQL statements, produces a temporary
source member, and then optionally calls the ILE COBOL compiler to create a
module, a program, or a service program.

Parameters
OBJ
Specifies the qualified name of the object being created.

*CURLIB: The new object is created in the current library for the job. If no
library is specified as the current library for the job, the QGPL library is used.

library-name: Specify the name of the library where the object is created.

object-name: Specify the name of the object that is being created.


SRCFILE
Specifies the qualified name of the source file that contains the COBOL source
with SQL statements.

The name of the source file can be qualified by one of the following library
values:

664 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBLI
*LIBL All libraries in the job’s library list are searched until the first match is
found.
*CURLIB The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QCBLLESRC: If the source file name is not specified, the source file
QCBLLESRC contains the COBOL source.

source-file-name: Specify the name of the source file that contains the COBOL
source.
SRCMBR
Specifies the name of the source file member that contains the COBOL source.
This parameter is specified only if the source file name in the SRCFILE
parameter is a database file. If this parameter is not specified, the OBJ name
specified on the OBJ parameter is used.

*OBJ: Specifies that the COBOL source is in the member of the source file that
has the same name as that specified on the OBJ parameter.

source-file-member-name: Specify the name of the member that contains the


COBOL source.
OPTION
Specifies whether one or more of the following options are used when the
COBOL source is precompiled. If an option is specified more than once, or if
two options conflict, the last option specified is used.

Element 1: Cross-Reference Options

*XREF: The precompiler cross-references items in the program to the statement


numbers in the program that refer to those items.

*NOXREF: The precompiler does not cross-reference names.

Element 2: Program Creation Options

*GEN: The precompiler creates the object that is specified by the OBJTYPE
parameter.

*NOGEN: The precompiler does not call the ILE COBOL compiler, and a
module, program, service program, or SQL package are not created.

Element 3: Decimal Point Options

*JOB: The value used as the decimal point for numeric constants in SQL is the
representation of decimal point specified for the job at precompile time.

*SYSVAL: The value used as the decimal point for numeric constants in SQL
statements is the QDECFMT system value.

*PERIOD: The value used as the decimal point for numeric constants in SQL
statements is a period (.).

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 665


CRTSQLCBLI
Note: If QDECFMT specifies that the value used as the decimal point is a
comma (,), any numeric constants in lists (such as in the SELECT clause
or the VALUES clause) must be separated by a comma (,) followed by a
blank ( ). For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) in which the decimal point is a period (.).

*COMMA: The value used as the decimal point for numeric constants in SQL
statements is a comma (,).

Note: Any numeric constants in lists (such as in the SELECT clause or the
VALUES clause) must be separated by a comma (,) followed by a blank(
). For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) where the decimal point is a period(.).

Element 4: Naming Convention Options

*SYS: The system naming convention (library-name/file-name) is used.

*SQL: The SQL naming convention is used (collection-name.table-name).

When creating a program on a remote database other than an AS/400 system,


*SQL must be specified as the naming convention.

Element 5: Second-Level Message Text Option

*NOSECLVL: Second-level text descriptions are not added to the listing.

*SECLVL: Second-level text with replacement data is added for all messages
on the listing.

Element 6: String Delimiter Options

*QUOTESQL: A double quote (") is the string delimiter in the SQL statements.

*APOSTSQL: An apostrophe (') is the string delimiter in the SQL statements.

Element 7: Literal Options

*QUOTE: A double quote (") is used for literals which are not numeric and
Boolean literals in the COBOL statements.

*APOST: An apostrophe (') is used for literals which are not numeric and
Boolean literals in the COBOL statements.

Element 8: Event File Creation

*NOEVENTF: The compiler will not produce an event file for use by
CoOperative Development Environment/400 (CODE/400).

*EVENTF: The compiler produces an event file for use by CoOperative


Development Environment/400 (CODE/400). The event file will be created as a
member in the file EVFEVENT in your source library. CODE/400 uses this file to
offer error feedback integrated with the CODE/400 editor. This option is
normally specified by CODE/400 on your behalf.

| Element 9: Large Object Optimization for DRDA

666 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBLI
*OPTLOB: The first FETCH for a cursor derermines how the cursor will be
used for LOBs (Large Objects) on all subsequent FETCHes. This option
remains in effect until the cursor is closed.

If the first FETCH uses a LOB locator to access a LOB column, no subsequent
FETCH for that cursor can fetch that LOB column into a LOB host variable.

If the first FETCH places the LOB column into a LOB host variable, no
subsequent FETCH for that cursor can use a LOB locator for that column.

*NOOPTLOB:There is no restriction on whether a column is retrieved into a


LOB locator or into a LOB host variable. This option can cause performance to
degrade.
TGTRLS
Specifies the release of the operating system on which the user intends to use
the object being created.

In the examples given for the *CURRENT and *PRV values, and when
specifying the release-level value, the format VxRxMx is used to specify the
release, where Vx is the version, Rx is the release, and Mx is the modification
level. For example, V2R3M0 is version 2, release 3, modification level 0.

*CURRENT: The object is to be used on the release of the operating system


currently running on the user’s system. For example, if V2R3M5 is running on
the system, *CURRENT means the user intends to use the object on a system
with V2R3M5 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

Note: If V2R3M5 is running on the system, and the object is to be used on a


system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
TGTRLS(*CURRENT).
*PRV: The object is to be used on the previous release with modification level 0
of the operating system. For example, if V2R3M5 is running on the user’s
system, *PRV means the user intends to use the object on a system with
V2R2M0 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

release-level: Specify the release in the format VxRxMx. The object can be
used on a system with the specified release or with any subsequent release of
the operating system installed.

Valid values depend on the current version, release, and modification level, and
they change with each new release. If you specify a release-level which is
earlier than the earliest release level supported by this command, an error
message is sent indicating the earliest supported release.
OBJTYPE
Specifies the type of object being created.

*PGM: The SQL precompiler issues the CRTBNDCBL command to create the
bound program.

*MODULE: The SQL precompiler issues the CRTCBLMOD command to create


the module.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 667


CRTSQLCBLI
*SRVPGM: The SQL precompiler issues the CRTCBLMOD and CRTSRVPGM
commands to create the service program.
Notes:
1. When OBJTYPE(*PGM) or OBJTYPE(*SRVPGM) is specified and the RDB
parameter is also specified, the CRTSQLPKG command is issued by the
SQL precompiler after the program has been created. When
OBJTYPE(*MODULE) is specified, an SQL package is not created and you
must issue the CRTSQLPKG command after the CRTPGM or
CRTSRVPGM command has created the program.
2. If *NOGEN is specified, only the SQL temporary source member is
generated and a module, program, service program, or SQL package are
not created.
INCFILE
Specifies the qualified name of the source file that contains members included
in the program with any SQL INCLUDE statement.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

*SRCFILE: The qualified source file specified in the SRCFILE parameter


contains the source file members specified on any SQL INCLUDE statement.

source-file-name: Specify the name of the source file that contains the source
file members specified on any SQL INCLUDE statement. The record length of
the source file specified here must be no less than the record length of the
source file specified on the SRCFILE parameter.
COMMIT
Specifies whether SQL statements in the compiled unit are run under
commitment control. Files referred to in the host language source are not
affected by this option. Only SQL tables, SQL views, and SQL packages
referred to in SQL statements are affected.

*CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows updated, deleted, and inserted are locked
until the end of the unit of work (transaction). Uncommitted changes in other
jobs can be seen.

*ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows selected, updated, deleted, and inserted are
locked until the end of the unit of work (transaction). Uncommitted changes in
other jobs cannot be seen.

*CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows updated, deleted, and inserted are locked until the end of the unit of

668 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBLI
work (transaction). A row that is selected, but not updated, is locked until the
next row is selected. Uncommitted changes in other jobs cannot be seen.

*NONE or *NC: Specifies that commitment control is not used. Uncommitted


changes in other jobs can be seen. If the SQL DROP COLLECTION statement
is included in the program, *NONE or *NC must be used. If a relational
database is specified on the RDB parameter and the relational database is on a
system that is not on an AS/400, *NONE or *NC cannot be specified.

*RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows selected, updated, deleted, and inserted are locked until the end of the
unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
are locked exclusively until the end of the unit of work (transaction).
CLOSQLCSR
Specifies when SQL cursors are implicitly closed, SQL prepared statements are
implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
HOLD) SQL statements.

*ENDACTGRP: SQL cursors are closed, SQL prepared statements are implicitly
discarded, and LOCK TABLE locks are released when the activation group
ends.

*ENDMOD: SQL cursors are closed and SQL prepared statements are implicitly
discarded when the module is exited. LOCK TABLE locks are released when
the activation group ends.
| ALWCPYDTA
| Specifies whether a copy of the data can be used in a SELECT statement.

| *OPTIMIZE: The system determines whether to use the data retrieved directly
| from the database or to use a copy of the data. The decision is based on which
| method provides the best performance. If COMMIT is *CHG or *CS and
| ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
| data is used only when it is necessary to run a query.

| *YES: A copy of the data is used only when necessary.

| *NO: A copy of the data is not allowed. If a temporary copy of the data is
| required to perform the query, an error message is returned.
| ALWBLK
| Specifies whether the database manager can use record blocking, and the
| extent to which blocking can be used for read-only cursors.

| *ALLREAD: Rows are blocked for read-only cursors if *NONE or *CHG is


| specified on the COMMIT parameter. All cursors in a program that are not
| explicitly able to be updated are opened for read-only processing even though
| EXECUTE or EXECUTE IMMEDIATE statements may be in the program.

| Specifying *ALLREAD:
| v Allows record blocking under commitment control level *CHG in addition to
| the blocking allowed for *READ.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 669


CRTSQLCBLI
| v Can improve the performance of almost all read-only cursors in programs,
| but limits queries in the following ways:
| – The Rollback (ROLLBACK) command, a ROLLBACK statement in host
| languages, or the ROLLBACK HOLD SQL statement does not reposition a
| read-only cursor when *ALLREAD is specified.
| – Dynamic running of a positioned UPDATE or DELETE statement (for
| example, using EXECUTE IMMEDIATE), cannot be used to update a row
| in a cursor unless the DECLARE statement for the cursor includes the
| FOR UPDATE clause.

| *NONE: Rows are not blocked for retrieval of data for cursors.

| Specifying *NONE:
| v Guarantees that the data retrieved is current.
| v May reduce the amount of time required to retrieve the first row of data for a
| query.
| v Stops the database manager from retrieving a block of data rows that is not
| used by the program when only the first few rows of a query are retrieved
| before the query is closed.
| v Can degrade the overall performance of a query that retrieves a large
| number of rows.

| *READ: Records are blocked for read-only retrieval of data for cursors when:
| v *NONE is specified on the COMMIT parameter, which indicates that
| commitment control is not used.
| v The cursor is declared with a FOR READ ONLY clause or there are no
| dynamic statements that could run a positioned UPDATE or DELETE
| statement for the cursor.

| Specifying *READ can improve the overall performance of queries that meet the
| above conditions and retrieve a large number of records.
DLYPRP
Specifies whether the dynamic statement validation for a PREPARE statement
is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
validation improves performance by eliminating redundant validation.

*NO: Dynamic statement validation is not delayed. When the dynamic


statement is prepared, the access plan is validated. When the dynamic
statement is used in an OPEN or EXECUTE statement, the access plan is
revalidated. Because the authority or the existence of objects referred to by the
dynamic statement may change, you must still check the SQLCODE or
SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
dynamic statement is still valid.

*YES: Dynamic statement validation is delayed until the dynamic statement is


used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
dynamic statement is used, the validation is completed and an access plan is
built. If you specify *YES on this parameter, you should check the SQLCODE
and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
ensure that the dynamic statement is valid.

670 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBLI
Note: If you specify *YES, performance is not improved if the INTO clause is
used on the PREPARE statement or if a DESCRIBE statement uses the
dynamic statement before an OPEN is issued for the statement.
GENLVL
Specifies the severity level at which the create operation fails. If errors occur
that have a severity level greater than this value, the operation ends.

10: The default severity level is 10.

severity-level: Specify a value ranging from 0 through 40.


DATFMT
Specifies the format used when accessing date result columns. All output date
fields are returned in the specified format. For input date strings, the specified
value is used to determine whether the date is specified in a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not an AS/400 system, then *USA, *ISO,
*EUR, or *JIS must be specified.

*JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
command to determine the current date format for the job.

*USA: The United States date format (mm/dd/yyyy) is used.

*ISO: The International Organization for Standardization (ISO) date format


(yyyy-mm-dd) is used.

*EUR: The European date format (dd.mm.yyyy) is used.

*JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

*MDY: The date format (mm/dd/yy) is used.

*DMY: The date format (dd/mm/yy) is used.

*YMD: The date format (yy/mm/dd) is used.

*JUL: The Julian date format (yy/ddd) is used.


DATSEP
Specifies the separator used when accessing date result columns.

Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
specified on the DATFMT parameter.

*JOB: The date separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’/’: A slash (/) is used.

’.’: A period (.) is used.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 671


CRTSQLCBLI
’,’: A comma (,) is used.

’-’: A dash (-) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


TIMFMT
Specifies the format used when accessing time result columns. For input time
strings, the specified value is used to determine whether the time is specified in
a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not another AS/400 system, the time
format must be *USA, *ISO, *EUR, *JIS, or *HMS with a time separator
of a colon or period.

*HMS: The hh:mm:ss format is used.

*USA: The United States time format hh:mm xx is used, where xx is AM or


PM.

*ISO: The International Organization for Standardization (ISO) time format


hh.mm.ss is used.

*EUR: The European time format hh.mm.ss is used.

*JIS: The Japanese Industrial Standard time format hh:mm:ss is used.


TIMSEP
Specifies the separator used when accessing time result columns.

Note: This parameter applies only when *HMS is specified on the TIMFMT
parameter.

*JOB: The time separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’:’: A colon (:) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


REPLACE
Specifies if a SQL module, program, service program or package is created
when there is an existing SQL module, program, service program, or package

672 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBLI
of the same name and type in the same library. The value of this parameter is
passed to the CRTCBLMOD, CRTBNDCBL, CRTSRVPGM, and CRTSQLPKG
commands.

*YES: A new SQL module, program, service program, or package is created,


any existing SQL object of the same name and type in the specified library is
moved to QRPLOBJ.

*NO: A new SQL module, program, service program, or package is not created
if an SQL object of the same name and type already exists in the specified
library.
RDB
Specifies the name of the relational database where the SQL package object is
created.

*LOCAL: The program is created as a distributed SQL program. The SQL


statements will access the local database. An SQL package object is not
created as part of the precompile process. The Create Structured Query
Language Package (CRTSQLPKG) command can be used.

relational-database-name: Specify the name of the relational database where


the new SQL package object is to be created. When the name of the local
relational database is specified, the program created is still a distributed SQL
program. The SQL statements will access the local database.

*NONE: An SQL package object is not created. The program object is not a
distributed program and the Create Structured Query Language Package
(CRTSQLPKG) command cannot be used.
USER
Specifies the user name sent to the remote system when starting the
conversation. This parameter is valid only when RDB is specified.

*CURRENT: The user profile under which the current job is running is used.

user-name: Specify the user name being used for the application server job.
PASSWORD
Specifies the password to be used on the remote system. This parameter is
valid only if RDB is specified.

*NONE: No password is sent. If this value is specified, USER(*CURRENT)


must also be specified.

password: Specify the password of the user name specified on the USER
parameter.
RDBCNNMTH
Specifies the semantics used for CONNECT statements. Refer to the SQL
Reference book for more information.

*DUW: CONNECT (Type 2) semantics are used to support distributed unit of


work. Consecutive CONNECT statements to additional relational databases do
not result in disconnection of previous connections.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 673


CRTSQLCBLI
*RUW: CONNECT (Type 1) semantics are used to support remote unit of work.
Consecutive CONNECT statements result in the previous connection being
disconnected before a new connection is established.
DFTRDBCOL
Specifies the collection name used for the unqualified names of tables, views,
indexes, and SQL packages. This parameter applies only to static SQL
statements.

*NONE: The naming convention defined on the OPTION parameter is used.

collection-name: Specify the name of the collection identifier. This value is used
instead of the naming convention specified on the OPTION parameter.
| DYNDFTCOL
| Specifies whether the default collection name specified for the DFTRDBCOL
| parameter is also used for dynamic statements.

| *NO: Do not use the value specified on the DFTRDBCOL parameter for
| unqualified names of tables, views, indexes, and SQL packages for dynamic
| SQL statements. The naming convention specified on the OPTION parameter is
| used.

| *YES: The collection name specified on the DFTRDBCOL parameter will be


| used for the unqualified names of the tables, views, indexes, and SQL
| packages in dynamic SQL statements.
SQLPKG
Specifies the qualified name of the SQL package created on the relational
database specified on the RDB parameter of this command.

The possible library values are:


*OBJLIB: The package is created in the library with the same name as the
library specified on the OBJ parameter.
library-name: Specify the name of the library where the package is created.

*OBJ: The name of the SQL package is the same as the object name specified
on the OBJ parameter.

package-name: Specify the name of the SQL package. If the remote system is
not an AS/400 system, no more than 8 characters can be specified.
| SQLPATH
| Specifies the path to be used to find procedures, functions, and user defined
| types in static SQL statements.

| *NAMING: The path used depends on the naming convention specified on the
| OPTION parameter.

| For *SYS naming, the path used is *LIBL, the current library list at runtime.

| For *SQL naming, the path used is ″QSYS″, ″QSYS2″, ″userid″, where ″userid″
| is the value of the USER special register. If a collection-name is specified on
| the DFTRDBCOL parameter, the collection-name takes the place of userid.

| *LIBL: The path used is the library list at runtime.

674 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBLI
| collection-name: Specify a list of one or more collection names. A maximum of
| 43 individual collections may be specified.
SAAFLAG
Specifies the IBM SQL flagging function. This parameter flags SQL statements
to verify whether they conform to IBM SQL syntax More information about
which IBM database products IBM SQL syntax is in the DRDA IBM SQL
Reference, SC26-3255-00.

*NOFLAG: The precompiler does not check to see whether SQL statements
conform to IBM SQL syntax.

*FLAG: The precompiler checks to see whether SQL statements conform to


IBM SQL syntax.
FLAGSTD
Specifies the American National Standards Institute (ANSI) flagging function.
This parameter flags SQL statements to verify whether they conform to the
following standards.
ANSI X3.135-1992 entry
ISO 9075-1992 entry
FIPS 127.2 entry

*NONE: The precompiler does not check to see whether SQL statements
conform to ANSI standards.

*ANS: The precompiler checks to see whether SQL statements conform to


ANSI standards.
DBGVIEW
Specifies the type of source debug information to be provided by the SQL
precompiler.

*NONE: The source view is not generated.

*SOURCE: The SQL precompiler provides the source views for the root and if
necessary, SQL INCLUDE statements. A view is provided which contains the
statements generated by the precompiler.
USRPRF
Specifies the user profile that is used when the compiled program object is run,
including the authority that the program object has for each object in static SQL
statements. The profile of either the program owner or the program user is used
to control which objects can be used by the program object.

*NAMING: The user profile is determined by the naming convention. If the


naming convention is *SQL, USRPRF(*OWNER) is used. If the naming
convention is *SYS, USRPRF(*USER) is used.

*USER: The profile of the user running the program object is used.

*OWNER: The user profiles of both the program owner and the program user
are used when the program is run.
DYNUSRPRF
Specifies the user profile to be used for dynamic SQL statements.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 675


CRTSQLCBLI
*USER: For local programs, dynamic SQL statements run under the profile of
the program’s user. For distributed programs, dynamic SQL statements run
under the profile of the SQL package’s user.

*OWNER: For local programs, dynamic SQL statements run under the profile of
the program’s owner. For distributed programs, dynamic SQL statements run
under the profile of the SQL package’s owner.
SRTSEQ
Specifies the sort sequence table to be used for string comparisons in SQL
statements.

Note: *HEX must be specified for this parameter on distributed applications


where the application server is not on an AS/400 system or the release level is
prior to V2R3M0.

*JOB: The SRTSEQ value for the job is retrieved during the precompile.

*JOBRUN: The SRTSEQ value for the job is retrieved when the program is run.
For distributed applications, SRTSEQ(*JOBRUN) is valid only when
LANGID(*JOBRUN) is also specified.

*LANGIDUNQ: The unique-weight sort table for the language specified on the
LANGID parameter is used.

The name of the table name can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

*LANGIDSHR: The sort sequence table uses the same weight for multiple
characters, and is the shared-weight sort sequence table associated with the
language specified on the LANGID parameter.

*HEX: A sort sequence is not used. The hexadecimal values of the characters
are used to determine the sort sequence.

table-name: Specify the name of the sort sequence table to be used.


LANGID
Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
SRTSEQ(*LANGIDSHR) is specified.

*JOB: The LANGID value for the job is retrieved during the precompile.

*JOBRUN: The LANGID value for the job is retrieved when the program is run.
For distributed applications, LANGID(*JOBRUN) is valid only when
SRTSEQ(*JOBRUN) is also specified.

language-identifier: Specify a language identifier.


OUTPUT
Specifies whether the precompiler listing is generated.

676 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCBLI
*NONE: The precompiler listing is not generated.

*PRINT: The precompiler listing is generated.


PRTFILE
Specifies the qualified name of the printer device file to which the precompiler
printout is directed. The file must have a minimum length of 132 bytes. If a file
with a record length of less than 132 bytes is specified, information is lost.

The name of the printer file can be qualified by one of the following library
values:
*LIBL All libraries in the job’s library list are searched until the first match is
found.
*CURLIB The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QSYSPRT: If a file name is not specified, the precompiler printout is directed to


the IBM-supplied printer file QSYSPRT.

printer-file-name: Specify the name of the printer device file to which the
precompiler printout is directed.
| TOSRCFILE
| Specifies the qualified name of the source file that is to contain the output
| source member that has been processed by the SQL precompiler. If the
| specified source file is not found, it will be created. The output member will
| have the same name as the name that is specified for the SRCMBR parameter.

| The possible library values are:


| QTEMP: The library QTEMP will be used.
| *LIBL: The job’s library list is searched for the specified file. If the file is not
| found in any library in the library list, the file will be created in the current
| library.
| *CURLIB: The current library for the job will be used. If no library is
| specified as the current library for the job, the QGPL library will be used.
| library-name: Specify the name of the library that is to contain the output
| source file.

| QSQLTEMP: The source file QSQLTEMP will be used.

| source-file-name: Specify the name of the source file to contain the output
| source member.
TEXT
Specifies the text that briefly describes the printer file. More information on this
parameter is in Appendix A, ″Expanded Parameter Descriptions″ in the CL
Reference (Abridged) book.

*SRCMBRTXT: The text is taken from the source file member being used to
create the COBOL program. Text can be added or changed for a database
source member by using the Start Source Entry Utility (STRSEU) command, or
by using either the Add Physical File Member (ADDPFM) or Change Physical
File Member (CHGPFM) command. If the source file is an inline file or a device
file, the text is blank.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 677


CRTSQLCBLI
*BLANK: Text is not specified.

’description’: Specify no more than 50 characters of text, enclosed in


apostrophes.

Example
CRTSQLCBLI PAYROLL OBJTYPE(*MODULE) TEXT('Payroll Program')

This command runs the SQL precompiler which precompiles the source and stores
the changed source in member PAYROLL in file QSQLTEMP in library QTEMP. The
ILE COBOL compiler is called to create module PAYROLL in the current library by
using the source member created by the SQL precompiler.

CRTSQLCI (Create Structured Query Language ILE C Object)


Command
Job: B,I Pgm: B,I REXX: B,I Exec

*CURLIB/
ÊÊ CRTSQLCI OBJ( object-name ) Ê
library-name/

Ê Ê
*LIBL/ QCSRC
SRCFILE( source-file-name )
*CURLIB/
library-name/

(1)
Ê Ê
*OBJ
SRCMBR( source-file-member-name )

Ê Ê
OPTION( OPTION Details ) *CURRENT
TGTRLS( *PRV )
VxRxMx

Ê Ê
*MODULE
OBJTYPE( *PGM )
*SRVPGM

Ê Ê
*LIBL/ *SRCFILE
INCFILE( source-file-name )
*CURLIB/
library-name/

678 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCI
Ê Ê
*UR *ENDACTGRP
*CHG CLOSQLCSR( *ENDMOD )
COMMIT( *ALL )
*RS
*CS
*NONE
*NC
*RR

Ê Ê
*OPTIMIZE *ALLREAD
ALWCPYDTA( *YES ) ALWBLK( *NONE )
*NO *READ

Ê Ê
*NO 10
DLYPRP( *YES ) GENLVL( severity-level )

Ê Ê
*SRCFILE *JOB
MARGINS( left-right ) DATFMT( *USA )
*ISO
*EUR
*JIS
*MDY
*DMY
*YMD
*JUL

Ê Ê
*JOB *HMS
DATSEP( '/' ) TIMFMT( *USA )
'.' *ISO
',' *EUR
'-' *JIS
' '
*BLANK

Ê Ê
*JOB *YES
TIMSEP( ':' ) REPLACE( *NO )
'.'
','
' '
*BLANK

Ê Ê
*LOCAL *CURRENT
RDB( relational-database-name ) USER( user-name )
*NONE

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 679


CRTSQLCI
Ê Ê
*NONE *DUW
PASSWORD( password ) RDBCNNMTH( *RUW )

Ê Ê
*NONE *NO
DFTRDBCOL( collection-name ) DYNDFTCOL( *YES )

Ê Ê
*OBJ
SQLPKG( package-name )

Ê Ê
*NAMING
SQLPATH( *LIBL )

· collection-name

Ê Ê
*NOFLAG *NONE
SAAFLAG( *FLAG ) FLAGSTD( *ANS )

Ê Ê
*NONE *NAMING
DBGVIEW( *SOURCE ) USRPRF( *OWNER )
*USER

Ê Ê
*USER
DYNUSRPRF( *OWNER )

Ê Ê
*JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

Ê Ê
*JOB *NONE
LANGID( *JOBRUN ) OUTPUT( *PRINT )
language-identifier

680 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCI
Ê Ê
*LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

Ê Ê
QTEMP/ QSQLTEMP
TOSRCFILE( source-file-name )
*LIBL/
*CURLIB/
library-name/

Ê ÊÍ
*SRCMBRTXT
TEXT( *BLANK )
'description'

OPTION Details:

*XREF *GEN *PERIOD *SYS *NOSECLVL


Ê
*NOXREF *NOGEN *JOB *SQL *SECLVL
*SYSVAL
*COMMA

*NOCNULRQD *NOEVENTF *OPTLOB


Ê
*CNULRQD *EVENTF *NOOPTLOB

Notes:
1. All parameters preceding this point can be specified in positional form.

Purpose
The Create Structured Query Language ILE C Object (CRTSQLCI) command calls
the Structured Query Language (SQL) precompiler that precompiles C source
containing SQL statements, produces a temporary source member, and then
optionally calls the ILE C compiler to create a module, create a program, or create
a service program.

Parameters
OBJ
Specifies the qualified name of the object being created.

The name of the object can be qualified by one of the following library values:
*CURLIB: The object is created in the current library for the job. If no library
is specified as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library where the object is created.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 681


CRTSQLCI
object-name: Specify the name of the object that is being created.
SRCFILE
Specifies the qualified name of the source file that contains the C source with
SQL statements.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QCSRC: If the source file name is not specified, the IBM-supplied source file
QCSRC contains the C source.

source-file-name: Specify the name of the source file that contains the C
source.
SRCMBR
Specifies the name of the source file member that contains the C source. This
parameter is only specified if the source file name in the SRCFILE parameter is
a database file. If this parameter is not specified, the OBJ name specified on
the OBJ parameter is used.

*OBJ: Specifies that the C source is in the member of the source file that has
the same name as that specified on the OBJ parameter.

source-file-member-name: Specify the name of the member that contains the C


source.
OPTION
Specifies whether one or more of the following options are used when the C
source is precompiled. If an option is specified more than once, or if two options
conflict, the last option specified is used.

Element 1: Cross-Reference Options

*XREF: The precompiler cross-references items in the program to the statement


numbers in the program that refer to those items.

*NOXREF: The precompiler does not cross-reference names.

Element 2: Program Creation Options

*GEN: The precompiler creates the object that is specified by the OBJTYPE
parameter.

*NOGEN: The precompiler does not call the C compiler, and a module,
program, service program, or SQL package is not created.

Element 3: Decimal Point Options

*PERIOD: The value used as the decimal point for numeric constants in SQL
statements is a period.

682 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCI
*JOB: The value used as the decimal point for numeric constants in SQL is the
representation of decimal point specified for the job at precompile time.

*SYSVAL: The value used as the decimal point for numeric constants in SQL
statements is the QDECFMT system value.

Note: If QDECFMT specifies that the value used as the decimal point is a
comma, any numeric constants in lists (such as in the SELECT clause or
the VALUES clause) must be separated by a comma followed by a
blank. For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) in which the decimal point is a period.

*COMMA: The value used as the decimal point for numeric constants in SQL
statements is a comma.

Note: Any numeric constants in lists (such as in the SELECT clause or the
VALUES clause) must be separated by a comma followed by a blank.
For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) where the decimal point is a period.

Element 4: Naming Convention Options

*SYS: The system naming convention (library-name/file-name) is used.

*SQL: The SQL naming convention is used (collection-name.table-name). When


creating a package on a remote database other than an AS/400 system, *SQL
must be specified as the naming convention.

Element 5: Second-Level Message Text Option

*NOSECLVL: Second-level text descriptions are not added to the listing.

*SECLVL: Second-level text with replacement data is added for all messages
on the listing.

Element 6: NUL Required Options

*NOCNULRQD: For output character and graphic host variables, the


NUL-terminator is not returned when the host variable is exactly the same
length as the data. Input character and graphic host variables do not require a
NUL-terminator.

*CNULRQD: Output character and graphic host variables always contain the
NUL-terminator. If there is not enough space for the NUL-terminator, the data is
truncated and the NUL-terminator is added. Input character and graphic host
variables require a NUL-terminator.

Element 7: Event File Creation

*NOEVENTF: The compiler will not produce an event file for use by
CoOperative Development Environment/400 (CODE/400).

*EVENTF: The compiler produces an event file for use by CoOperative


Development Environment/400 (CODE/400). The event file will be created as a
member in the file EVFEVENT in your source library. CODE/400 uses this file to

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 683


CRTSQLCI
offer error feedback integrated with the CODE/400 editor. This option is
normally specified by CODE/400 on your behalf.

| Element 8: Large Object Optimization for DRDA

| *OPTLOB: The first FETCH for a cursor derermines how the cursor will be
| used for LOBs (Large Objects) on all subsequent FETCHes. This option
| remains in effect until the cursor is closed.

If the first FETCH uses a LOB locator to access a LOB column, no subsequent
FETCH for that cursor can fetch that LOB column into a LOB host variable.

If the first FETCH places the LOB column into a LOB host variable, no
subsequent FETCH for that cursor can use a LOB locator for that column.

| *NOOPTLOB: There is no restriction on whether a column is retrieved into a


| LOB locator or into a LOB host variable. This option can cause performance to
| degrade.
TGTRLS
Specifies the release of the operating system on which the user intends to use
the object being created.

In the examples given for the *CURRENT and *PRV values, and when
specifying the release-level value, the format VxRxMx is used to specify the
release, where Vx is the version, Rx is the release, and Mx is the modification
level. For example, V2R3M0 is version 2, release 3, modification level 0.

*CURRENT: The object is to be used on the release of the operating system


currently running on the user’s system. For example, if V2R3M5 is running on
the system, *CURRENT means the user intends to use the object on a system
with V2R3M5 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

Note: If V2R3M5 is running on the system, and the object is to be used on a


system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
TGTRLS(*CURRENT).
*PRV: The object is to be used on the previous release with modification level 0
of the operating system. For example, if V2R3M5 is running on the user’s
system, *PRV means the user intends to use the object on a system with
V2R2M0 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

release-level: Specify the release in the format VxRxMx. The object can be
used on a system with the specified release or with any subsequent release of
the operating system installed.

Valid values depend on the current version, release, and modification level, and
they change with each new release. If you specify a release-level which is
earlier than the earliest release level supported by this command, an error
message is sent indicating the earliest supported release.
OBJTYPE
Specifies the type of object being created.

*MODULE: The SQL precompiler issues the CRTCMOD command to create the
module.

684 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCI
*PGM: The SQL precompiler issues the CRTBNDC command to create the
bound program.

*SRVPGM: The SQL precompiler issues the CRTCMOD and CRTSRVPGM


commands to create the service program.

The user must create a source member in QSRVSRC that has the same name
as the name specified on the OBJ parameter. The source member must contain
the export information for the module. More information on the export file is in
the Integrated Language Environment*C/400 Programmers Guide.
Notes:
1. When OBJTYPE(*PGM) or OBJTYPE(*SRVPGM) is specified and the RDB
parameter is also specified, the CRTSQLPKG command is issued by the
SQL precompiler after the program has been created. When
OBJTYPE(*MODULE) is specified, an SQL package is not created and the
user must issue the CRTSQLPKG command after the CRTPGM or
CRTSRVPGM command has created the program.
2. If *NOGEN is specified, only the SQL temporary source member is
generated and a module, program, service program, or SQL package is not
created.
INCFILE
Specifies the qualified name of the source file that contains members included
in the program with any SQL INCLUDE statement.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

*SRCFILE: The qualified source file specified in the SRCFILE parameter


contains the source file members specified on any SQL INCLUDE statement.

source-file-name: Specify the name of the source file that contains the source
file members specified on any SQL INCLUDE statement. The record length of
the source file specified here must be no less than the record length of the
source file specified on the SRCFILE parameter.
COMMIT
Specifies whether SQL statements in the compiled unit are run under
commitment control. Files referred to in the host language source are not
affected by this option. Only SQL tables, SQL views, and SQL packages
referred to in SQL statements are affected.

*CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows updated, deleted, and inserted are locked
until the end of the unit of work (transaction). Uncommitted changes in other
jobs can be seen.

*ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 685


CRTSQLCI
REVOKE statements and the rows selected, updated, deleted, and inserted are
locked until the end of the unit of work (transaction). Uncommitted changes in
other jobs cannot be seen.

*CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows updated, deleted, and inserted are locked until the end of the unit of
work (transaction). A row that is selected, but not updated, is locked until the
next row is selected. Uncommitted changes in other jobs cannot be seen.

*NONE or *NC: Specifies that commitment control is not used. Uncommitted


changes in other jobs can be seen. If the SQL DROP COLLECTION statement
is included in the program, *NONE or *NC must be used. If a relational
database is specified on the RDB parameter and the relational database is on a
system that is not on an AS/400, *NONE or *NC cannot be specified.

*RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows selected, updated, deleted, and inserted are locked until the end of the
unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
are locked exclusively until the end of the unit of work (transaction).
CLOSQLCSR
Specifies when SQL cursors are implicitly closed, SQL prepared statements are
implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
HOLD) SQL statements.

*ENDACTGRP: SQL cursors are closed, SQL prepared statements are implicitly
discarded, and LOCK TABLE locks are released when the activation group
ends.

*ENDMOD: SQL cursors are closed and SQL prepared statements are implicitly
discarded when the module is exited. LOCK TABLE locks are released when
the first SQL program on the call stack ends.
| ALWCPYDTA
| Specifies whether a copy of the data can be used in a SELECT statement.

| *OPTIMIZE: The system determines whether to use the data retrieved directly
| from the database or to use a copy of the data. The decision is based on which
| method provides the best performance. If COMMIT is *CHG or *CS and
| ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
| data is used only when it is necessary to run a query.

| *YES: A copy of the data is used only when necessary.

| *NO: A copy of the data is not allowed. If a temporary copy of the data is
| required to perform the query, an error message is returned.
| ALWBLK
| Specifies whether the database manager can use record blocking, and the
| extent to which blocking can be used for read-only cursors.

| *ALLREAD: Rows are blocked for read-only cursors if *NONE or *CHG is


| specified on the COMMIT parameter. All cursors in a program that are not

686 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCI
| explicitly able to be updated are opened for read-only processing even though
| EXECUTE or EXECUTE IMMEDIATE statements may be in the program.

| Specifying *ALLREAD:
| v Allows record blocking under commitment control level *CHG in addition to
| the blocking allowed for *READ.
| v Can improve the performance of almost all read-only cursors in programs,
| but limits queries in the following ways:
| – The Rollback (ROLLBACK) command, a ROLLBACK statement in host
| languages, or the ROLLBACK HOLD SQL statement does not reposition a
| read-only cursor when *ALLREAD is specified.
| – Dynamic running of a positioned UPDATE or DELETE statement (for
| example, using EXECUTE IMMEDIATE), cannot be used to update a row
| in a cursor unless the DECLARE statement for the cursor includes the
| FOR UPDATE clause.

| *NONE: Rows are not blocked for retrieval of data for cursors.

| Specifying *NONE:
| v Guarantees that the data retrieved is current.
| v May reduce the amount of time required to retrieve the first row of data for a
| query.
| v Stops the database manager from retrieving a block of data rows that is not
| used by the program when only the first few rows of a query are retrieved
| before the query is closed.
| v Can degrade the overall performance of a query that retrieves a large
| number of rows.

| *READ: Records are blocked for read-only retrieval of data for cursors when:
| v *NONE is specified on the COMMIT parameter, which indicates that
| commitment control is not used.
| v The cursor is declared with a FOR READ ONLY clause or there are no
| dynamic statements that could run a positioned UPDATE or DELETE
| statement for the cursor.

| Specifying *READ can improve the overall performance of queries that meet the
| above conditions and retrieve a large number of records.
DLYPRP
Specifies whether the dynamic statement validation for a PREPARE statement
is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
validation improves performance by eliminating redundant validation.

*NO: Dynamic statement validation is not delayed. When the dynamic


statement is prepared, the access plan is validated. When the dynamic
statement is used in an OPEN or EXECUTE statement, the access plan is
revalidated. Because the authority or the existence of objects referred to by the
dynamic statement may change, you must still check the SQLCODE or
SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
dynamic statement is still valid.

*YES: Dynamic statement validation is delayed until the dynamic statement is


used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
dynamic statement is used, the validation is completed and an access plan is

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 687


CRTSQLCI
built. If you specify *YES on this parameter, you should check the SQLCODE
and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
ensure that the dynamic statement is valid.

Note: If you specify *YES, performance is not improved if the INTO clause is
used on the PREPARE statement or if a DESCRIBE statement uses the
dynamic statement before an OPEN is issued for the statement.
GENLVL
Specifies the severity level at which the create operation fails. If errors occur
that have a severity level greater than this value, the operation ends.

10: The default severity level is 10.

severity-level: Specify a value ranging from 0 through 40.


MARGINS
Specifies the part of the precompiler input record that contains source text.

| *SRCFILE: The precompiler uses file member margin values that are specified
| by the user on the SRCMBR parameter. The margin values default to 1 and 80.

Element 1: Left Margin

left: Specify the beginning position for the statements. Valid values range from 1
through 80.

Element 2: Right Margin

right: Specify the ending position for the statements. Valid values range from 1
through 80.
DATFMT
Specifies the format used when accessing date result columns. All output date
fields are returned in the specified format. For input date strings, the specified
value is used to determine whether the date is specified in a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not an AS/400 system, then *USA, *ISO,
*EUR, or *JIS must be specified.

*JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
command to determine the current date format for the job.

*USA: The United States date format (mm/dd/yyyy) is used.

*ISO: The International Organization for Standardization (ISO) date format


(yyyy-mm-dd) is used.

*EUR: The European date format (dd.mm.yyyy) is used.

*JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

*MDY: The date format (mm/dd/yy) is used.

688 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCI
*DMY: The date format (dd/mm/yy) is used.

*YMD: The date format (yy/mm/dd) is used.

*JUL: The Julian date format (yy/ddd) is used.


DATSEP
Specifies the separator used when accessing date result columns.

Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
specified on the DATFMT parameter.

*JOB:The date separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’/’: A slash (/) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’-’: A dash (-) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


TIMFMT
Specifies the format used when accessing time result columns. For input time
strings, the specified value is used to determine whether the time is specified in
a valid format.

Note: An input time string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not another AS/400 system, the time
format must be *USA, *ISO, *EUR, *JIS, or *HMS with a time separator
of colon or period.

*HMS: The hh:mm:ss format is used.

*USA: The United States time format hh:mm xx is used, where xx is AM or


PM.

*ISO: The International Organization for Standardization (ISO) time format


hh.mm.ss is used.

*EUR: The European time format hh.mm.ss is used.

*JIS: The Japanese Industrial Standard time format hh:mm:ss is used.


TIMSEP
Specifies the separator used when accessing time result columns.

Note: This parameter applies only when *HMS is specified on the TIMFMT
parameter.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 689


CRTSQLCI
*JOB: The time separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’:’: A colon (:) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


REPLACE
Specifies if a SQL module, program, service program or package is created
when there is an existing SQL module, program, service program, or package
of the same name and type in the same library. The value of this parameter is
passed to the CRTCMOD, CRTBNDC, CRTSRVPGM, and CRTSQLPKG
commands.

*YES: A new SQL module, program, service program, or package is created,


and any existing object of the same name and type in the specified library is
moved to QRPLOBJ.

*NO: A new SQL module, program, service program, or package is not created
if an object of the same name and type already exists in the specified library.
RDB
Specifies the name of the relational database where the SQL package object is
created.

*LOCAL: The program is created as a distributed SQL program. The SQL


statements will access the local database. An SQL package object is not
created as part of the precompile process. The Create Structured Query
Language Package (CRTSQLPKG) command can be used.

relational-database-name: Specify the name of the relational database where


the new SQL package object is to be created. When the name of the local
relational database is specified, the program created is still a distributed SQL
program. The SQL statements will access the local database.

*NONE: An SQL package object is not created. The program object is not a
distributed program and the Create Structured Query Language Package
(CRTSQLPKG) command cannot be used.
USER
Specifies the user name sent to the remote system when starting the
conversation. This parameter is valid only when RDB is specified.

*CURRENT: The user profile under which the current job is running is used.

user-name: Specify the user name being used for the application server job.
PASSWORD
Specifies the password to be used on the remote system. This parameter is
valid only if RDB is specified.

690 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCI
*NONE: No password is sent. If this value is specified, USER(*CURRENT)
must also be specified.

password: Specify the password of the user name specified on the USER
parameter.
RDBCNNMTH
Specifies the semantics used for CONNECT statements. Refer to the SQL
Reference, SC41-3612 book for more information.

*DUW: CONNECT (Type 2) semantics are used to support distributed unit of


work. Consecutive CONNECT statements to additional relational databases do
not result in disconnection of previous connections.

*RUW: CONNECT (Type 1) semantics are used to support remote unit of work.
Consecutive CONNECT statements result in the previous connection being
disconnected before a new connection is established.
DFTRDBCOL
Specifies the collection name used for the unqualified names of tables, views,
indexes, and SQL packages. This parameter applies only to static SQL
statements.

*NONE: The naming convention defined on the OPTION parameter is used.

collection-name: Specify the name of the collection identifier. This value is used
instead of the naming convention specified on the OPTION parameter.
| DYNDFTCOL
| Specifies whether the default collection name specified for the DFTRDBCOL
| parameter is also used for dynamic statements.

| *NO: Do not use the value specified on the DFTRDBCOL parameter for
| unqualified names of tables, views, indexes, and SQL packages for dynamic
| SQL statements. The naming convention specified on the OPTION parameter is
| used.

| *YES: The collection name specified on the DFTRDBCOL parameter will be


| used for the unqualified names of the tables, views, indexes, and SQL
| packages in dynamic SQL statements.
SQLPKG
Specifies the qualified name of the SQL package created on the relational
database specified on the RDB parameter of this command.

The possible library values are:


*OBJLIB: The package is created in the library with the same name as the
library specified on the OBJ parameter.
library-name: Specify the name of the library where the package is created.

*OBJ: The name of the SQL package is the same as the object name specified
on the OBJ parameter.

package-name: Specify the name of the SQL package. If the remote system is
not an AS/400 system, no more than 8 characters can be specified.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 691


CRTSQLCI
| SQLPATH
| Specifies the path to be used to find procedures, functions, and user defined
| types in static SQL statements.

| *NAMING: The path used depends on the naming convention specified on the
| OPTION parameter.

| For *SYS naming, the path used is *LIBL, the current library list at runtime.

| For *SQL naming, the path used is ″QSYS″, ″QSYS2″, ″userid″, where ″userid″
| is the value of the USER special register. If a collection-name is specified on
| the DFTRDBCOL parameter, the collection-name takes the place of userid.

| *LIBL: The path used is the library list at runtime.

| collection-name: Specify a list of one or more collection names. A maximum of


| 43 individual collections may be specified.
SAAFLAG
Specifies the IBM SQL flagging function. This parameter flags SQL statements
to verify whether they conform to IBM SQL syntax More information about
which IBM database products IBM SQL syntax is in the DRDA IBM SQL
Reference, SC26-3255-00.

*NOFLAG: The precompiler does not check to see whether SQL statements
conform to IBM SQL syntax.

*FLAG: The precompiler checks to see whether SQL statements conform to


IBM SQL syntax
FLAGSTD
Specifies the American National Standards Institute (ANSI) flagging function.
This parameter flags SQL statements to verify whether they conform to the
following standards.
ANSI X3.135-1992 entry
ISO 9075-1992 entry
FIPS 127.2 entry

*NONE: The precompiler does not check to see whether SQL statements
conform to ANSI standards.

*ANS: The precompiler checks to see whether SQL statements conform to


ANSI standards.
DBGVIEW
This parameter specifies the type of source debug information to be provided by
the SQL precompiler.

*NONE: The source view will not be generated.

*SOURCE: The SQL precompiler provides the source views for the root and if
necessary, SQL INCLUDE statements. A view is provided that contains the
statements generated by the precompiler.
USRPRF
Specifies the user profile that is used when the compiled program object is run,
including the authority that the program object has for each object in static SQL

692 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCI
statements. The profile of either the program owner or the program user is used
to control which objects can be used by the program object.

*NAMING: The user profile is determined by the naming convention. If the


naming convention is *SQL, USRPRF(*OWNER) is used. If the naming
convention is *SYS, USRPRF(*USER) is used.

*USER: The profile of the user running the program object is used.

*OWNER: The user profiles of both the program owner and the program user
are used when the program is run.
DYNUSRPRF
Specifies the user profile to be used for dynamic SQL statements.

*USER: Local dynamic SQL statements are run under the profile of the
program’s user. Distributed dynamic SQL statements are run under the profile
of the SQL package’s user.

*OWNER: Local dynamic SQL statements are run under the profile of the
program’s owner. Distributed dynamic SQL statements are run under the profile
of the SQL package’s owner.
SRTSEQ
Specifies the sort sequence table to be used for string comparisons in SQL
statements.

Note: *HEX must be specified for this parameter on distributed applications


where the application server is not on an AS/400 system or the release
level is prior to V2R3M0.

*JOB: The SRTSEQ value for the job is retrieved during the precompile.

*JOBRUN: The SRTSEQ value for the job is retrieved when the program is run.
For distributed applications, SRTSEQ(*JOBRUN) is valid only when
LANGID(*JOBRUN) is also specified.

*HEX: A sort sequence table is not used. The hexadecimal values of the
characters are used to determine the sort sequence.

*LANGIDSHR: The sort sequence table uses the same weight for multiple
characters, and is the shared-weight sort sequence table associated with the
language specified on the LANGID parameter.

*LANGIDUNQ: The unique-weight sort table for the language specified on the
LANGID parameter is used.

The name of the table name can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of hte library to be searched.

table-name: Specify the name of the sort sequence table to be used.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 693


CRTSQLCI
LANGID
Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
SRTSEQ(*LANGIDSHR) is specified.

*JOB: The LANGID value for the job is retrieved during the precompile.

*JOBRUN: The LANGID value for the job is retrieved when the program is run.
For distributed applications, LANGID(*JOBRUN) is valid only when
SRTSEQ(*JOBRUN) is also specified.

language-identifier: Specify a language identifier.


OUTPUT
Specifies whether the precompiler listing is generated.

*NONE: The precompiler listing is not generated.

*PRINT: The precompiler listing is generated.


PRTFILE
Specifies the qualified name of the printer device file to which the precompiler
printout is directed. The file must have a minimum length of 132 bytes. If a file
with a record length of less than 132 bytes is specified, information is lost.

The name of the printer file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QSYSPRT: If a file name is not specified, the precompiler printout is directed to


the IBM-supplied printer file QSYSPRT.

printer-file-name: Specify the name of the printer device file to which the
precompiler printout is directed.
| TOSRCFILE
| Specifies the qualified name of the source file that is to contain the output
| source member that the SQL precompiler has processed. If the precompiler
| cannot find the specified source file, it creates the file. The output member will
| have the same name as the name that is specified for the SRCMBR parameter.

| The possible library values are:


| QTEMP: The library QTEMP will be used.
| *LIBL: The job’s library list is searched for the specified file. If the file is not
| found in any library in the library list, the file will be created in the current
| library.
| *CURLIB: The current library for the job will be used. If no library is
| specified as the current library for the job, the QGPL library will be used.
| library-name: Specify the name of the library that is to contain the output
| source file.

| QSQLTEMP: The source file QSQLTEMP will be used.

694 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCI
| source-file-name: Specify the name of the source file to contain the output
| source member.
TEXT
Specifies the text that briefly describes the program and the function. More
information on this parameter is in Appendix A, ″Expanded Parameter
Descriptions″ in the CL Reference book.

*SRCMBRTXT: The text is taken from the source file member being used to
create the C program. Text can be added or changed for a database source
member by using the Start Source Entry Utility (STRSEU) command, or by
using either the Add Physical File Member (ADDPFM) command or the Change
Physical File Member (CHGPFM) command. If the source file is an inline file or
a device file, the text is blank.

*BLANK: Text is not specified.

’description’: Specify no more than 50 characters of text, enclosed in


apostrophes.

Example
CRTSQLCI PAYROLL OBJTYPE(*MODULE)
TEXT('Payroll Program')

This command runs the SQL precompiler which precompiles the source and stores
the changed source in member PAYROLL in file QSQLTEMP in library QTEMP. The
ILE C for AS/400 compiler is called to create module PAYROLL in the current library
| by using the source member created by the SQL precompiler.
|
| CRTSQLCPPI (Create Structured Query Language C++ Object)
| Command
| Job: B,I Pgm: B,I REXX: B,I Exec

| *CURLIB/
| ÊÊ CRTSQLCPPI OBJ( object-name ) Ê
library-name/

| Ê Ê
| *LIBL/ QCSRC
SRCFILE( source-file-name )
*CURLIB/
library-name/

| (1)
| Ê Ê
*OBJ
SRCMBR( source-file-member-name )

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 695


CRTSQLCPPI
| Ê Ê
| OPTION( OPTION Details ) *CURRENT
TGTRLS( VxRxMx )

| Ê Ê
| *LIBL/ *SRCFILE
INCFILE( source-file-name )
*CURLIB/
library-name/

| Ê Ê
| *UR *ENDACTGRP
*CHG CLOSQLCSR( *ENDMOD )
COMMIT( *ALL )
*RS
*CS
*NONE
*NC
*RR

| Ê Ê
| *OPTIMIZE *ALLREAD
ALWCPYDTA( *YES ) ALWBLK( *NONE )
*NO *READ

| Ê Ê
| *NO 10
DLYPRP( *YES ) GENLVL( severity-level )

| Ê Ê
| *SRCFILE *JOB
MARGINS( left-right ) DATFMT( *USA )
*ISO
*EUR
*JIS
*MDY
*DMY
*YMD
*JUL

| Ê Ê
| *JOB *HMS
DATSEP( '/' ) TIMFMT( *USA )
'.' *ISO
',' *EUR
'-' *JIS
' '
*BLANK

696 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCPPI
| Ê Ê
*JOB
TIMSEP( ':' )
'.'
','
' '
*BLANK

|
| Ê Ê
| *YES *LOCAL
REPLACE( *NO ) RDB( relational-database-name )
*NONE

| Ê Ê
| *CURRENT *NONE
USER( user-name ) PASSWORD( password )

| Ê Ê
| *DUW *NONE
RDBCNNMTH( *RUW ) DFTRDBCOL( collection-name )

| Ê Ê
| *NO
DYNDFTCOL( *YES )

| Ê Ê
| *OBJLIB/ *OBJ
SQLPKG( package-name )
library-name/

| Ê Ê
| *NAMING
SQLPATH( *LIBL )

· collection-name

| Ê Ê
| *NOFLAG *NONE
SAAFLAG( *FLAG ) FLAGSTD( *ANS )

| Ê Ê
| *NONE *NAMING
DBGVIEW( *SOURCE ) USRPRF( *OWNER )
*USER

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 697


CRTSQLCPPI
| Ê Ê
| *USER
DYNUSRPRF( *OWNER )

| Ê Ê
| *JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

| Ê Ê
| *JOB *NONE
LANGID( *JOBRUN ) OUTPUT( *PRINT )
language-identifier

| Ê Ê
| *LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

|
| Ê Ê
| QTEMP/ QSQLTEMP
TOSRCFILE( source-file-name )
*LIBL/
*CURLIB/
library-name/

| Ê ÊÍ
| *SRCMBRTXT
TEXT( *BLANK )
'description'

| OPTION Details:

| *XREF *GEN *JOB *SYS *NOSECLVL


| Ê
*NOXREF *NOGEN *PERIOD *SQL *SECLVL
*SYSVAL
*COMMA

| *NOCNULRQD *NOEVENTF *OPTLOB


| Ê
*CNULRQD *EVENTF *NOOPTLOB

698 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCPPI
| Notes:
| 1. All parameters preceding this point can be specified in positional form.

| Purpose
| The Create Structured Query Language C++ Object (CRTSQLCPPI) command calls
| the Structured Query Language (SQL) precompiler. The SQL precompiler
| precompiles C++ source containing SQL statements, produces a temporary source
| member, and then optionally calls the C++ compiler to create a module.

| To precompile for the VisualAge C++ for OS/400 compiler, use the CVTSQLCPP
| command.

| Parameters
| OBJ
| Specifies the qualified name of the object that the precompiler creates.

| One of the following library values can qualify the name of the object:
| *CURLIB The object is created in the current library for the job. If you do not
| specify a library as the current library for the job, the precompiler uses
| QGPL library.
| library-name: Specify the name of the library where the object is created.

| object-name: Specify the name of the object that the precompiler creates.
| SRCFILE
| Specifies the qualified name of the source file that contains the C++ source with
| SQL statements.

| One of the following library values can qualify the name of the source file:
| *LIBL: The precompiler searches all libraries in the job’s library list until it
| finds the first match.
| *CURLIB: The precompiler searches the current library for the job. If you do
| not specify a library as the current library for the job, it uses the QGPL
| library.
| library-name: Specify the name of the library that the precompiler searches.

| QCSRC: If you do not specify the source file name, the IBM-supplied source file
| QCSRC contains the C++ source.

| source-file-name: Specify the name of the source file that contains the C++
| source.
| SRCMBR
| Specifies the name of the source file member that contains the C++ source.
| Specify this parameter only if the source file name in the SRCFILE parameter is
| a database file. If you do not specify this parameter, the precompiler uses the
| OBJ name that is specified on the OBJ parameter.

| *OBJ: Specifies that the C++ source is in the member of the source file that
| has the same name as the file specified on the OBJ parameter.

| source-file-member-name: Specify the name of the member that contains the


| C++ source.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 699


CRTSQLCPPI
| OPTION
| Specifies whether one or more of the following options are used when the C++
| source is precompiled. If an option is specified more than once, or if two options
| conflict, the last option specified is used.

| Element 1: Cross-Reference Options

| *XREF: The precompiler cross-references items in the program to the statement


| numbers in the program that refer to those items.

| *NOXREF: The precompiler does not cross-reference names.

| Element 2: Program Creation Options

| *GEN: The precompiler creates the module object.

| *NOGEN: The precompiler does not call the C++ compiler, and does not create
| a module.

| Element 3: Decimal Point Options

| *JOB: The value used as the decimal point for numeric constants in SQL is the
| representation of decimal point that is specified for the job at precompile time.

| Note: If the job specifies that the value used as the decimal point is a comma,
| any numeric constants in lists (such as in the SELECT clause or the
| VALUES clause) must be separated by a comma followed by a blank.
| For example, VALUES(1,1, 2,23, 4,1) is equivalent to
| VALUES(1.1,2.23,4.1) in which the decimal point is a period.

| *PERIOD:The value used as the decimal point for numeric constants in SQL
| statements is a period.

| *COMMA: The value used as the decimal point for numeric constants in SQL
| statements is a comma.

| Note: Any numeric constants in lists (such as in the SELECT clause or the
| VALUES clause) must be separated by a comma followed by a blank.
| For example, VALUES(1,1, 2,23, 4,1) is equivalent to
| VALUES(1.1,2.23,4.1) where the decimal point is a period.

| Element 4: Naming Convention Options

| *SYS: The system naming convention (library-name/file-name) is used.

| *SQL: The SQL naming convention is used (collection-name.table-name). When


| creating a package on a remote database other than an AS/400 system, you
| must specify *SQL as the naming convention.

| Element 5: Second-Level Message Text Option

| *NOSECLVL: Second-level text descriptions are not added to the listing.

| *SECLVL: Second-level text with replacement data is added for all messages
| on the listing.

700 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCPPI
| Element 6: NUL Required Options

| *NOCNULRQD: For output character and graphic host variables, the


| NUL-terminator is not returned when the host variable is exactly the same
| length as the data. Input character and graphic host variables do not require a
| NUL-terminator.

| *CNULRQD: Output character and graphic host variables always contain the
| NUL-terminator. If there is not enough space for the NUL-terminator, the data is
| truncated, and the NUL-terminator is added. Input character and graphic host
| variables require a NUL-terminator.

| Element 7: Event File Creation

| *NOEVENTF: The compiler will not produce an event file for use by
| CoOperative Development Environment/400 (CODE/400).

| *EVENTF: The compiler produces an event file for use by CoOperative


| Development Environment/400 (CODE/400). It creates the event file as a
| member in the file EVFEVENT in your source library. CODE/400 uses this file to
| offer error feedback that is integrated with the CODE/400 editor. CODE/400
| normally specifies this option on your behalf.

| Element 8: Large Object Optimization for DRDA

| *OPTLOB: The first FETCH for a cursor derermines how the cursor will be
| used for LOBs (Large Objects) on all subsequent FETCHes. This option
| remains in effect until the cursor is closed.

| If the first FETCH uses a LOB locator to access a LOB column, no subsequent
| FETCH for that cursor can fetch that LOB column into a LOB host variable.

| If the first FETCH places the LOB column into a LOB host variable, no
| subsequent FETCH for that cursor can use a LOB locator for that column.

| *NOOPTLOB: There is no restriction on whether a column is retrieved into a


| LOB locator or into a LOB host variable. This option can cause performance to
| degrade.
| TGTRLS
| Specifies the release of the operating system on which the user intends to use
| the object that is being created.

| The examples given for the *CURRENT value, as well as the release-level
| value, use the format VxRxMx to specify the release. In this format, Vx is the
| version, Rx is the release, and Mx is the modification level. For example,
| V2R3M0 is version 2, release 3, modification level 0.

| *CURRENT: The object is to be used on the release of the operating system


| that is currently running on the user’s system. For example, if V2R3M5 is
| running on the system, *CURRENT means that the user intends to use the
| object on a system with V2R3M5 installed. The user can also use the object on
| a system with any subsequent release of the operating system installed.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 701


CRTSQLCPPI
| Note: If V2R3M5 is running on the system, and the object is to be used on a
| system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
| TGTRLS(*CURRENT).

| release-level: Specify the release in the format VxRxMx. The object can be
| used on a system with the specified release or with any subsequent release of
| the operating system installed.

| Valid values depend on the current version, release, and modification level, and
| they change with each new release. If you specify a release-level which is
| earlier than the earliest release level that is supported by this command, an
| error message is sent indicating the earliest supported release.
| INCFILE
| Specifies the qualified name of the source file that contains members that are
| included in the program with any SQL INCLUDE statement.

| One of the following library values can qualify the name of the source file:
| *LIBL: All libraries in the job’s library list are searched until the first match is
| found.
| *CURLIB: The current library for the job is searched. If no library is specified
| as the current library for the job, the QGPL library is used.
| library-name: Specify the name of the library to be searched.

| *SRCFILE: The qualified source file specified in the SRCFILE parameter


| contains the source file members that are specified on any SQL INCLUDE
| statement.

| source-file-name: Specify the name of the source file that contains the source
| file members that are specified on any SQL INCLUDE statement. The record
| length of the source file that is specified here must be no less than the record
| length of the source file specified on the SRCFILE parameter.
| COMMIT
| Specifies whether SQL statements in the compiled unit are run under
| commitment control. Files referred to in the host language source are not
| affected by this option. Only SQL tables, SQL views, and SQL packages
| referred to in SQL statements are affected.

| *CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,


| COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
| REVOKE statements and the rows updated, deleted, and inserted are locked
| until the end of the unit of work (transaction). Uncommitted changes in other
| jobs can be seen.

| *ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


| COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
| REVOKE statements and the rows selected, updated, deleted, and inserted are
| locked until the end of the unit of work (transaction). Uncommitted changes in
| other jobs cannot be seen.

| *CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
| CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
| the rows updated, deleted, and inserted are locked until the end of the unit of
| work (transaction). A row that is selected, but not updated, is locked until the
| next row is selected. Uncommitted changes in other jobs cannot be seen.

702 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCPPI
| *NONE or *NC: Specifies that commitment control is not used. Uncommitted
| changes in other jobs can be seen. If the SQL DROP COLLECTION statement
| is included in the program, *NONE or *NC must be used. If a relational
| database is specified on the RDB parameter and the relational database is on a
| system that is not on an AS/400, *NONE or *NC cannot be specified.

| *RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
| CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
| the rows selected, updated, deleted, and inserted are locked until the end of the
| unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
| All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
| are locked exclusively until the end of the unit of work (transaction).
| CLOSQLCSR
| Specifies when SQL cursors are implicitly closed, SQL prepared statements are
| implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
| explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
| HOLD) SQL statements.

| *ENDACTGRP: SQL cursors are closed, SQL prepared statements are implicitly
| discarded, and LOCK TABLE locks are released when the activation group
| ends.

| *ENDMOD: SQL cursors are closed, and SQL prepared statements are
| implicitly discarded when the module is exited. LOCK TABLE locks are released
| when the first SQL program on the call stack ends.
| ALWCPYDTA
| Specifies whether a copy of the data can be used in a SELECT statement.

| *OPTIMIZE: The system determines whether to use the data retrieved directly
| from the database or to use a copy of the data. The decision is based on which
| method provides the best performance. If COMMIT is *CHG or *CS and
| ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
| data is used only when it is necessary to run a query.

| *YES: A copy of the data is used only when necessary.

| *NO: A copy of the data is not allowed. If a temporary copy of the data is
| required to perform the query, an error message is returned.
| ALWBLK
| Specifies whether the database manager can use record blocking, and the
| extent to which blocking can be used for read-only cursors.

| *ALLREAD: Rows are blocked for read-only cursors if *NONE or *CHG is


| specified on the COMMIT parameter. All cursors in a program that are not
| explicitly able to be updated are opened for read-only processing even though
| EXECUTE or EXECUTE IMMEDIATE statements may be in the program.

| Specifying *ALLREAD:
| v Allows record blocking under commitment control level *CHG in addition to
| the blocking allowed for *READ.
| v Can improve the performance of almost all read-only cursors in programs,
| but limits queries in the following ways:

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 703


CRTSQLCPPI
| – The Rollback (ROLLBACK) command, a ROLLBACK statement in host
| languages, or the ROLLBACK HOLD SQL statement does not reposition a
| read-only cursor when *ALLREAD is specified.
| – Dynamic running of a positioned UPDATE or DELETE statement (for
| example, using EXECUTE IMMEDIATE), cannot be used to update a row
| in a cursor unless the DECLARE statement for the cursor includes the
| FOR UPDATE clause.

| *NONE: Rows are not blocked for retrieval of data for cursors.

| Specifying *NONE:
| v Guarantees that the data retrieved is current.
| v May reduce the amount of time required to retrieve the first row of data for a
| query.
| v Stops the database manager from retrieving a block of data rows that is not
| used by the program when only the first few rows of a query are retrieved
| before the query is closed.
| v Can degrade the overall performance of a query that retrieves a large
| number of rows.

| *READ: Records are blocked for read-only retrieval of data for cursors when:
| v *NONE is specified on the COMMIT parameter, which indicates that
| commitment control is not used.
| v The cursor is declared with a FOR READ ONLY clause or there are no
| dynamic statements that could run a positioned UPDATE or DELETE
| statement for the cursor.

| Specifying *READ can improve the overall performance of queries that meet the
| above conditions and retrieve a large number of records.
| DLYPRP
| Specifies whether the dynamic statement validation for a PREPARE statement
| is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
| validation improves performance by eliminating redundant validation.

| *NO: Dynamic statement validation is not delayed. When the dynamic


| statement is prepared, the access plan is validated. When the dynamic
| statement is used in an OPEN or EXECUTE statement, the access plan is
| revalidated. Because the authority or the existence of objects referred to by the
| dynamic statement may change, you must still check the SQLCODE or
| SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
| dynamic statement is still valid.

| *YES: Dynamic statement validation is delayed until the dynamic statement is


| used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
| dynamic statement is used, the validation is completed, and an access plan is
| built. If you specify *YES on this parameter, you should check the SQLCODE
| and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
| ensure that the dynamic statement is valid.

| Note: If you specify *YES, performance is not improved if the INTO clause is
| used on the PREPARE statement or if a DESCRIBE statement uses the
| dynamic statement before an OPEN is issued for the statement.

704 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCPPI
| GENLVL
| Specifies the severity level at which the create operation fails. If errors occur
| that have a severity level greater than this value, the operation ends.

| 10: The default severity level is 10.

| severity-level: Specify a value ranging from 0 through 40.


| MARGINS
| Specifies the part of the precompiler input record that contains source text.

| *SRCFILE: The file member margin values specified by the user on the
| SRCMBR parameter are used. If the member is of SQLCLE, SQLC, C, or CLE
| source type, the margin values are the values that are specified on the SEU
| services display. If the member is a different source type, the margin values are
| the default values of 1 and 80.

| Element 1: Left Margin

| left: Specify the beginning position for the statements. Valid values range from 1
| through 80.

| Element 2: Right Margin

| right: Specify the ending position for the statements. Valid values range from 1
| through 80.
| DATFMT
| Specifies the format used when accessing date result columns. All output date
| fields are returned in the specified format. For input date strings, the specified
| value is used to determine whether the date is specified in a valid format.

| Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
| always valid.

| If a relational database is specified on the RDB parameter and the


| database is on a system that is not an AS/400 system, then *USA, *ISO,
| *EUR, or *JIS must be specified.

| *JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
| command to determine the current date format for the job.

| *USA: The United States date format (mm/dd/yyyy) is used.

| *ISO: The International Organization for Standardization (ISO) date format


| (yyyy-mm-dd) is used.

| *EUR: The European date format (dd.mm.yyyy) is used.

| *JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

| *MDY: The date format (mm/dd/yy) is used.

| *DMY: The date format (dd/mm/yy) is used.

| *YMD: The date format (yy/mm/dd) is used.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 705


CRTSQLCPPI
| *JUL: The Julian date format (yy/ddd) is used.
| DATSEP
| Specifies the separator used when accessing date result columns.

| Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
| specified on the DATFMT parameter.

| *JOB:The date separator specified for the job at precompile time is used. Use
| the Display Job (DSPJOB) command to determine the current value for the job.

| ’/’: A slash (/) is used.

| ’.’: A period (.) is used.

| ’,’: A comma (,) is used.

| ’-’: A dash (-) is used.

| ’ ’: A blank ( ) is used.

| *BLANK: A blank ( ) is used.


| TIMFMT
| Specifies the format used when accessing time result columns. For input time
| strings, the specified value is used to determine whether the time is specified in
| a valid format.

| Note: An input time string that uses the format *USA, *ISO, *EUR, or *JIS is
| always valid.

| If a relational database is specified on the RDB parameter and the


| database is on a system that is not another AS/400 system, the time
| format must be *USA, *ISO, *EUR, *JIS, or *HMS with a time separator
| of colon or period.

| *HMS: The hh:mm:ss format is used.

| *USA: The United States time format hh:mm xx is used, where xx is AM or


| PM.

| *ISO: The International Organization for Standardization (ISO) time format


| hh.mm.ss is used.

| *EUR: The European time format hh.mm.ss is used.

| *JIS: The Japanese Industrial Standard time format hh:mm:ss is used.


| TIMSEP
| Specifies the separator used when accessing time result columns.

| Note: This parameter applies only when *HMS is specified on the TIMFMT
| parameter.

| *JOB: The time separator specified for the job at precompile time is used. Use
| the Display Job (DSPJOB) command to determine the current value for the job.

706 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCPPI
| ’:’: A colon (:) is used.

| ’.’: A period (.) is used.

| ’,’: A comma (,) is used.

| ’ ’: A blank ( ) is used.

| *BLANK: A blank ( ) is used.


| REPLACE
| Specifies if an SQL module is created when there is an existing SQL module of
| the same name in the same library. The value of this parameter is passed to
| the CRTCPPMOD command.

| *YES: A new SQL module is created, and any existing object of the same name
| in the specified library is moved to QRPLOBJ.

| *NO: A new SQL module is not created if an object of the same name already
| exists in the specified library.
| RDB
| Specifies the name of the relational database where the SQL package object is
| created.

| *LOCAL: The program is created as a distributed SQL program. The SQL


| statements will access the local database. An SQL package object is not
| created as part of the precompile process. The Create Structured Query
| Language Package (CRTSQLPKG) command can be used.

| relational-database-name: Specify the name of the relational database where


| the new SQL package object is to be created. When the name of the local
| relational database is specified, the program created is still a distributed SQL
| program. The SQL statements will access the local database.

| *NONE: An SQL package object is not created. The program object is not a
| distributed program and the Create Structured Query Language Package
| (CRTSQLPKG) command cannot be used.
| USER
| Specifies the user name sent to the remote system when starting the
| conversation. This parameter is valid only when RDB is specified.

| *CURRENT: The user profile under which the current job is running is used.

| user-name: Specify the user name being used for the application server job.
| PASSWORD
| Specifies the password to be used on the remote system. This parameter is
| valid only if RDB is specified.

| *NONE: No password is sent. If this value is specified, USER(*CURRENT)


| must also be specified.

| password: Specify the password of the user name that is specified on the
| USER parameter.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 707


CRTSQLCPPI
| RDBCNNMTH
| Specifies the semantics used for CONNECT statements. Refer to the SQL
| Reference, SC41-3612 book for more information.

| *DUW: CONNECT (Type 2) semantics are used to support distributed unit of


| work. Consecutive CONNECT statements to additional relational databases do
| not result in disconnection of previous connections.

| *RUW: CONNECT (Type 1) semantics are used to support remote unit of work.
| Consecutive CONNECT statements result in the previous connection being
| disconnected before a new connection is established.
| DFTRDBCOL
| Specifies the collection name used for the unqualified names of tables, views,
| indexes, and SQL packages. This parameter applies only to static SQL
| statements.

| *NONE: The naming convention defined on the OPTION parameter is used.

| collection-name: Specify the name of the collection identifier. This value is used
| instead of the naming convention that is specified on the OPTION parameter.
| DYNDFTCOL
| Specifies whether the default collection name specified for the DFTRDBCOL
| parameter is also used for dynamic statements.

| *NO: Do not use the value specified on the DFTRDBCOL parameter for
| unqualified names of tables, views, indexes, and SQL packages for dynamic
| SQL statements. The naming convention specified on the OPTION parameter is
| used.

| *YES: The collection name specified on the DFTRDBCOL parameter will be


| used for the unqualified names of the tables, views, indexes, and SQL
| packages in dynamic SQL statements.
| SQLPKG
| Specifies the qualified name of the SQL package created on the relational
| database specified on the RDB parameter of this command.

| The possible library values are:


| *OBJLIB: The package is created in the library with the same name as the
| library specified on the OBJ parameter.
| library-name: Specify the name of the library where the package is created.

| *OBJ: The name of the SQL package is the same as the object name specified
| on the OBJ parameter.

| package-name: Specify the name of the SQL package. If the remote system is
| not an AS/400 system, no more than 8 characters can be specified.
| SQLPATH
| Specifies the path to be used to find procedures, functions, and user defined
| types in static SQL statements.

| *NAMING: The path used depends on the naming convention specified on the
| OPTION parameter.

708 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCPPI
| For *SYS naming, the path used is *LIBL, the current library list at runtime.

| For *SQL naming, the path used is ″QSYS″, ″QSYS2″, ″userid″, where ″userid″
| is the value of the USER special register. If a collection-name is specified on
| the DFTRDBCOL parameter, the collection-name takes the place of userid.

| *LIBL: The path used is the library list at runtime.

| collection-name: Specify a list of one or more collection names. A maximum of


| 43 individual collections may be specified.
| SAAFLAG
| Specifies the IBM SQL flagging function. This parameter flags SQL statements
| to verify whether they conform to IBM SQL syntax More information about
| which IBM database products IBM SQL syntax is in the DRDA IBM SQL
| Reference, SC26-3255-00.

| *NOFLAG: The precompiler does not check to see whether SQL statements
| conform to IBM SQL syntax.

| *FLAG: The precompiler checks to see whether SQL statements conform to


| IBM SQL syntax.
| FLAGSTD
| Specifies the American National Standards Institute (ANSI) flagging function.
| This parameter flags SQL statements to verify whether they conform to the
| following standards.
| ANSI X3.135-1992 entry
| ISO 9075-1992 entry
| FIPS 127.2 entry

| *NONE: The precompiler does not check to see whether SQL statements
| conform to ANSI standards.

| *ANS: The precompiler checks to see whether SQL statements conform to


| ANSI standards.
| DBGVIEW
| This parameter specifies the type of source debug information to be provided by
| the SQL precompiler.

| *NONE: The source view will not be generated.

| *SOURCE: The SQL precompiler provides the source views for the root and if
| necessary, SQL INCLUDE statements. A view is provided that contains the
| statements generated by the precompiler.
| USRPRF
| Specifies the user profile that is used when the compiled program object is run,
| including the authority that the program object has for each object in static SQL
| statements. The profile of either the program owner or the program user is used
| to control which objects can be used by the program object.

| *NAMING: The user profile is determined by the naming convention. If the


| naming convention is *SQL, USRPRF(*OWNER) is used. If the naming
| convention is *SYS, USRPRF(*USER) is used.

| *USER: The profile of the user running the program object is used.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 709


CRTSQLCPPI
| *OWNER: The user profiles of both the program owner and the program user
| are used when the program is run.
| DYNUSRPRF
| Specifies the user profile to be used for dynamic SQL statements.

| *USER: Local dynamic SQL statements are run under the profile of the
| program’s user. Distributed dynamic SQL statements are run under the profile
| of the SQL package’s user.

| *OWNER: Local dynamic SQL statements are run under the profile of the
| program’s owner. Distributed dynamic SQL statements are run under the profile
| of the SQL package’s owner.
| SRTSEQ
| Specifies the sort sequence table to be used for string comparisons in SQL
| statements.

| Note: *HEX must be specified for this parameter on distributed applications


| where the application server is not on an AS/400 system or the release
| level is prior to V2R3M0.

| *JOB: The SRTSEQ value for the job is retrieved during the precompile.

| *JOBRUN: The SRTSEQ value for the job is retrieved when the program is run.
| For distributed applications, SRTSEQ(*JOBRUN) is valid only when
| LANGID(*JOBRUN) is also specified.

| *HEX: A sort sequence table is not used. The hexadecimal values of the
| characters are used to determine the sort sequence.

| *LANGIDSHR: The sort sequence table uses the same weight for multiple
| characters, and is the shared-weight sort sequence table associated with the
| language specified on the LANGID parameter.

| *LANGIDUNQ: The unique-weight sort table for the language that is specified
| on the LANGID parameter is used.

| The name of the table name can be qualified by one of the following library
| values:
| *LIBL: All libraries in the job’s library list are searched until the first match is
| found.
| *CURLIB: The current library for the job is searched. If no library is specified
| as the current library for the job, the QGPL library is used.
| library-name: Specify the name of hte library to be searched.

| table-name: Specify the name of the sort sequence table to be used.


| LANGID
| Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
| SRTSEQ(*LANGIDSHR) is specified.

| *JOB: The LANGID value for the job is retrieved during the precompile.

| *JOBRUN: The LANGID value for the job is retrieved when the program is run.
| For distributed applications, LANGID(*JOBRUN) is valid only when
| SRTSEQ(*JOBRUN) is also specified.

710 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLCPPI
| language-identifier: Specify a language identifier.
| OUTPUT
| Specifies whether the precompiler listing is generated.

| *NONE: The precompiler listing is not generated.

| *PRINT: The precompiler listing is generated.


| PRTFILE
| Specifies the qualified name of the printer device file to which the precompiler
| printout is directed. The file must have a minimum length of 132 bytes. If a file
| with a record length of less than 132 bytes is specified, information is lost.

| The name of the printer file can be qualified by one of the following library
| values:
| *LIBL: All libraries in the job’s library list are searched until the first match is
| found.
| *CURLIB: The current library for the job is searched. If no library is specified
| as the current library for the job, the QGPL library is used.
| library-name: Specify the name of the library to be searched.

| QSYSPRT: If a file name is not specified, the precompiler printout is directed to


| the IBM-supplied printer file QSYSPRT.

| printer-file-name: Specify the name of the printer device file to which the
| precompiler printout is directed.
| TOSRCFILE
| Specifies the qualified name of the source file that is to contain the output
| source member that has been processed by the SQL precompiler. If the
| specified source file is not found, it will be created. The output member will
| have the same name as the name that is specified for the SRCMBR parameter.

| The possible library values are:


| QTEMP: The library QTEMP will be used.
| *LIBL: The job’s library list is searched for the specified file. If the file is not
| found in any library in the library list, the file will be created in the current
| library.
| *CURLIB: The current library for the job will be used. If no library is
| specified as the current library for the job, the QGPL library will be used.
| library-name: Specify the name of the library that is to contain the output
| source file.

| QSQLTEMP: The source file QSQLTEMP will be used.

| source-file-name: Specify the name of the source file to contain the output
| source member.
| TEXT
| Specifies the text that briefly describes the program and the function. More
| information on this parameter is in Appendix A, ″Expanded Parameter
| Descriptions″ in the CL Reference book.

| *SRCMBRTXT: The text is taken from the source file member being used to
| create the C++ program. You can add or change text for a database source

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 711


CRTSQLCPPI
| member by using the Start Source Entry Utility (STRSEU) command. You can
| also use either the Add Physical File Member (ADDPFM) command or the
| Change Physical File Member (CHGPFM) command. If the source file is an
| inline file or a device file, the text is blank.

| *BLANK: Text is not specified.

| ’description’: Specify no more than 50 characters of text, enclosed in


| apostrophes.

| Example
| CRTSQLCPPI PAYROLL OBJTYPE(*MODULE)
| TEXT('Payroll Program')

| This command runs the SQL precompiler which precompiles the source and stores
| the changed source in member PAYROLL in file QSQLTEMP in library QTEMP. The
| command calls the ILE C++ compiler to create module PAYROLL in the current
| library by using the source member that is created by the SQL precompiler.

CRTSQLPLI (Create Structured Query Language PL/I) Command


Job: B,I Pgm: B,I REXX: B,I Exec

*CURLIB/
ÊÊ CRTSQLPLI PGM( program-name ) Ê
library-name/

Ê Ê
*LIBL/ QPLISRC
SRCFILE( source-file-name )
*CURLIB/
library-name/

(1)
Ê Ê
*PGM
SRCMBR( source-file-member-name )

Ê Ê
OPTION( Option Details *CURRENT
TGTRLS( *PRV )
VxRxMx

Ê Ê
*LIBL/ *SRCFILE
INCFILE( source-file-name )
*CURLIB/
library-name/

712 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLPLI
Ê Ê
*UR *ENDPGM
*CHG CLOSQLCSR( *ENDSQL )
COMMIT( *ALL ) *ENDJOB
*RS
*CS
*NONE
*NC
*RR

Ê Ê
*OPTIMIZE *ALLREAD
ALWCPYDTA( *YES ) ALWBLK( *NONE )
*NO *READ

Ê Ê
*NO 10
DLYPRP( *YES ) GENLVL( severity-level )

Ê Ê
*SRCFILE *JOB
MARGINS( left-right ) DATFMT( *USA )
*ISO
*EUR
*JIS
*MDY
*DMY
*YMD
*JUL

Ê Ê
*JOB *HMS
DATSEP( '/' ) TIMFMT( *USA )
'.' *ISO
',' *EUR
'-' *JIS
' '
*BLANK

Ê Ê
*JOB
TIMSEP( ':' )
'.'
','
' '
*BLANK

Ê Ê
*YES *LOCAL
REPLACE( *NO ) RDB( relational-database-name )
*NONE

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 713


CRTSQLPLI
Ê Ê
*CURRENT *NONE
USER( user-name ) PASSWORD( password )

Ê Ê
*DUW *NONE
RDBCNNMTH( *RUW ) DFTRDBCOL( collection-name )

Ê Ê
*NO
DYNDFTCOL( *YES )

Ê Ê
*PGMLIB/ *PGM
SQLPKG( package-name )
library-name/

Ê Ê
*NAMING
SQLPATH( *LIBL )

· collection-name

Ê Ê
*NOFLAG *NONE
SAAFLAG( *FLAG ) FLAGSTD( *ANS )

Ê Ê
*LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

Ê Ê
*JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

Ê Ê
*JOB *NAMING
LANGID( *JOBRUN ) USRPRF( *OWNER )
language-ID *USER

714 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLPLI
Ê Ê
*USER
DYNUSRPRF( *OWNER )

Ê Ê
QTEMP/ QSQLTEMP
TOSRCFILE( source-file-name )
*LIBL/
*CURLIB/
library-name/

Ê ÊÍ
*SCRMBRTXT
TEXT( *BLANK )
'description'

Option Details:

*NOSRC
*NOSOURCE *NOXREF *GEN *JOB *SYS
Ê
*SRC *XREF *NOGEN *PERIOD *SQL
*SOURCE *SYSVAL
*COMMA

*NOSECLVL *OPTLOB
Ê )
*SECLVL *NOOPTLOB

Notes:
1. All parameters preceding this point can be specified in positional form.

Purpose
The Create Structured Query Language PL/I (CRTSQLPLI) command calls a
Structured Query Language (SQL) precompiler, which precompiles PL/I source
containing SQL statements, produces a temporary source member, and optionally
calls the PL/I compiler to compile the program.

Parameters
PGM
Specifies the qualified name of the compiled program.

The name of the compiled PL/I program can be qualified by one of the following
library values:
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library where the compiled PL/I
program is created.

program-name: Specify the name of the compiled program.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 715


CRTSQLPLI
SRCFILE
Specifies the qualified name of the source file that contains the PL/I source with
SQL statements.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QPLISRC: If the source file name is not specified, the IBM-supplied source file
QPLISRC contains the PL/I source.

source-file-name: Specify the name of the source file that contains the PL/I
source.
SRCMBR
Specifies the name of the source file member that contains the PL/I source.
This parameter is specified only if the source file name in the SRCFILE
parameter is a database file. If this parameter is not specified, the PGM name
specified on the PGM parameter is used.

*PGM: Specifies that the PL/I source is in the member of the source file that
has the same name as that specified on the PGM parameter.

source-file-member-name: Specify the name of the member that contains the


PL/I source.
OPTION
Specifies whether one or more of the following options are used when the PL/I
source is precompiled. If an option is specified more than once, or if two options
conflict, the last option specified is used.

Element 1: Source Listing Options

*NOSOURCE: or *NOSRC: A source printout is not produced by the


precompiler unless errors are detected during precompile or create package.

*SOURCE or *SRC: The precompiler produces a source printout consisting of


PL/I source input.

Element 2: Cross-Reference Options

*NOXREF: The precompiler does not cross-reference names.

*XREF: The precompiler cross-references items in the program to the statement


numbers in the program that refer to those items.

Element 3: Program Creation Options

*GEN: The compiler creates a program that can run after the program is
compiled. An SQL package object is created if a relational database name is
specified on the RDB parameter.

716 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLPLI
*NOGEN: The precompiler does not call the C compiler, and a program and
SQL package are not created.

Element 4: Decimal Point Options

*JOB: The value used as the decimal point for numeric constants in SQL is the
representation of decimal point specified for the job at precompile time.

*PERIOD: The value used as the decimal point for numeric constants used in
SQL statements is a period.

*SYSVAL: The value used as the decimal point for numeric constants in SQL
statements is the QDECFMT system value.

Note: If QDECFMT specifies that the value used as the decimal point is a
comma, any numeric constants in lists (such as in the SELECT clause or
the VALUES clause) must be separated by a comma followed by a
blank. For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) in which the decimal point is a period.

*COMMA: The value used as the decimal point for numeric constants in SQL
statements is a comma.

Note: Any numeric constants in lists (such as in the SELECT clause or the
VALUES clause) must be separated by a comma followed by a blank.
For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) where the decimal point is a period.

Element 5: Naming Convention Options

*SYS: The system naming convention (library-name/file-name) is used.

*SQL: The SQL naming convention is used (collection-name.table-name). When


creating a program on a remote database other than an AS/400 system, *SQL
must be specified as the naming convention.

Element 6: Second-Level Message Text Option

*NOSECLVL: Second-level text descriptions are not added to the listing.

*SECLVL: Second-level text with replacement data is added to the printout for
all messages on the listing.

Element 7: Large Object Optimization for DRDA Option

*OPTLOB: The first FETCH for a cursor determines how the cursor will be used
for LOBs (Large Objects) on all subsequent FETCHes. This option remains in
effect until the cursor is closed.

If the first FETCH uses a LOB locator to access a LOB column, no subsequent
FETCH for that cursor can fetch that LOB column into a LOB host variable.

If the first FETCH places the LOB column into a LOB host variable, no
subsequent FETCH for that cursor can use a LOB locator for that column.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 717


CRTSQLPLI
*NOOPTLOB: There is no restriction on whether a column is retrieved into a
LOB locator or into a LOB host variable. This option can cause performance to
degrade.
TGTRLS
Specifies the release of the operating system on which the user intends to use
the object being created.

In the examples given for the *CURRENT and *PRV values, and when
specifying the release-level value, the format VxRxMx is used to specify the
release, where Vx is the version, Rx is the release, and Mx is the modification
level. For example, V2R3M0 is version 2, release 3, modification level 0.

*CURRENT: The object is to be used on the release of the operating system


currently running on the user’s system. For example, if V2R3M5 is running on
the system, *CURRENT means the user intends to use the object on a system
with V2R3M5 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

Note: If V2R3M5 is running on the system, and the object is to be used on a


system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
TGTRLS(*CURRENT).
*PRV: The object is to be used on the previous release with modification level 0
of the operating system. For example, if V2R3M5 is running on the user’s
system, *PRV means the user intends to use the object on a system with
V2R2M0 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

release-level: Specify the release in the format VxRxMx. The object can be
used on a system with the specified release or with any subsequent release of
the operating system installed.

Valid values depend on the current version, release, and modification level, and
they change with each new release. If you specify a release-level which is
earlier than the earliest release level supported by this command, an error
message is sent indicating the earliest supported release.
INCFILE
Specifies the qualified name of the source file that contains members included
in the program with any SQL INCLUDE statement.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

*SRCFILE: The qualified source file specified in the SRCFILE parameter


contains the source file members specified on any SQL INCLUDE statement.

source-file-name: Specify the name of the source file that contains the source
file members specified on any SQL INCLUDE statement. The record length of
the source file specified must be no less than the record length of the source
file specified for the SRCFILE parameter.

718 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLPLI
COMMIT
Specifies whether SQL statements in the compiled program are run under
commitment control. Files referred to in the host language source are not
affected by this option. Only SQL tables, SQL views, and SQL packages
referred to in SQL statements are affected.

*CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows updated, deleted, and inserted are locked
until the end of the unit of work (transaction). Uncommitted changes in other
jobs can be seen.

*ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows selected, updated, deleted, and inserted are
locked until the end of the unit of work (transaction). Uncommitted changes in
other jobs cannot be seen.

*CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows updated, deleted, and inserted are locked until the end of the unit of
work (transaction). A row that is selected, but not updated, is locked until the
next row is selected. Uncommitted changes in other jobs cannot be seen.

*NONE or *NC: Specifies that commitment control is not used. Uncommitted


changes in other jobs can be seen. If the SQL DROP COLLECTION statement
is included in the program, *NONE or *NC must be used. If a relational
database is specified on the RDB parameter and the relational database is on a
system that is not on an AS/400, *NONE or *NC cannot be specified.

*RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows selected, updated, deleted, and inserted are locked until the end of the
unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
are locked exclusively until the end of the unit of work (transaction).
CLOSQLCSR
Specifies when SQL cursors are implicitly closed, SQL prepared statements are
implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
HOLD) SQL statements.

*ENDPGM: SQL cursors are closed and SQL prepared statements are
discarded when the program ends. LOCK TABLE locks are released when the
first SQL program on the call stack ends.

*ENDSQL: SQL cursors remain open between calls and can be fetched without
running another SQL OPEN. One of the programs higher on the call stack must
have run at least one SQL statement. SQL cursors are closed, SQL prepared
statements are discarded, and LOCK TABLE locks are released when the first
SQL program on the call stack ends. If *ENDSQL is specified for a program that
is the first SQL program called (the first SQL program on the call stack), the
program is treated as if *ENDPGM was specified.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 719


CRTSQLPLI
*ENDJOB: SQL cursors remain open between calls and can be fetched without
running another SQL OPEN. The programs higher on the call stack do not need
to have run SQL statements. SQL cursors are left open, SQL prepared
statements are preserved, and LOCK TABLE locks are held when the first SQL
program on the call stack ends. SQL cursors are closed, SQL prepared
statements are discarded, and LOCK TABLE locks are released when the job
ends.
| ALWCPYDTA
| Specifies whether a copy of the data can be used in a SELECT statement.

| *OPTIMIZE: The system determines whether to use the data retrieved directly
| from the database or to use a copy of the data. The decision is based on which
| method provides the best performance. If COMMIT is *CHG or *CS and
| ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
| data is used only when it is necessary to run a query.

| *YES: A copy of the data is used only when necessary.

| *NO: A copy of the data is not allowed. If a temporary copy of the data is
| required to perform the query, an error message is returned.
| ALWBLK
| Specifies whether the database manager can use record blocking, and the
| extent to which blocking can be used for read-only cursors.

| *ALLREAD: Rows are blocked for read-only cursors if *NONE or *CHG is


| specified on the COMMIT parameter. All cursors in a program that are not
| explicitly able to be updated are opened for read-only processing even though
| EXECUTE or EXECUTE IMMEDIATE statements may be in the program.

| Specifying *ALLREAD:
| v Allows record blocking under commitment control level *CHG in addition to
| the blocking allowed for *READ.
| v Can improve the performance of almost all read-only cursors in programs,
| but limits queries in the following ways:
| – The Rollback (ROLLBACK) command, a ROLLBACK statement in host
| languages, or the ROLLBACK HOLD SQL statement does not reposition a
| read-only cursor when *ALLREAD is specified.
| – Dynamic running of a positioned UPDATE or DELETE statement (for
| example, using EXECUTE IMMEDIATE), cannot be used to update a row
| in a cursor unless the DECLARE statement for the cursor includes the
| FOR UPDATE clause.

| *NONE: Rows are not blocked for retrieval of data for cursors.

| Specifying *NONE:
| v Guarantees that the data retrieved is current.
| v May reduce the amount of time required to retrieve the first row of data for a
| query.
| v Stops the database manager from retrieving a block of data rows that is not
| used by the program when only the first few rows of a query are retrieved
| before the query is closed.
| v Can degrade the overall performance of a query that retrieves a large
| number of rows.

720 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLPLI
| *READ: Records are blocked for read-only retrieval of data for cursors when:
| v *NONE is specified on the COMMIT parameter, which indicates that
| commitment control is not used.
| v The cursor is declared with a FOR READ ONLY clause or there are no
| dynamic statements that could run a positioned UPDATE or DELETE
| statement for the cursor.

| Specifying *READ can improve the overall performance of queries that meet the
| above conditions and retrieve a large number of records.
DLYPRP
Specifies whether the dynamic statement validation for a PREPARE statement
is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
validation improves performance by eliminating redundant validation.

*NO: Dynamic statement validation is not delayed. When the dynamic


statement is prepared, the access plan is validated. When the dynamic
statement is used in an OPEN or EXECUTE statement, the access plan is
revalidated. Because the authority or the existence of objects referred to by the
dynamic statement may change, you must still check the SQLCODE or
SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
dynamic statement is still valid.

*YES: Dynamic statement validation is delayed until the dynamic statement is


used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
dynamic statement is used, the validation is completed and an access plan is
built. If you specify *YES on this parameter, you should check the SQLCODE
and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
ensure that the dynamic statement is valid.

Note: If you specify *YES, performance is not improved if the INTO clause is
used on the PREPARE statement or if a DESCRIBE statement uses the
dynamic statement before an OPEN is issued for the statement.
GENLVL
Specifies the severity level at which the create operation fails. If errors occur
that have a severity level greater than or equal to this value, the operation
ends.

10: The default severity level is 10.

severity-level: Specify a value ranging from 0 through 40.


MARGINS
Specifies the part of the precompiler input record that contains source text.

*SRCFILE: The file member margin values specified by the user on the
SRCMBR parameter are used. If the member is a SQLPLI source type, the
margin values are the values specified on the SEU services display. If the
member is a different source type, the margin values are the default values of 2
and 72.

Element 1: Left Margin

left: Specify the beginning position for the statements. Valid values range from 1
through 80.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 721


CRTSQLPLI
Element 2: Right Margin

right: Specify the ending position for the statements. Valid values range from 1
through 80.
DATFMT
Specifies the format used when accessing date result columns. All output date
fields are returned in the specified format. For input date strings, the specified
value is used to determine whether the date is specified in a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not an AS/400 system, then *USA, *ISO,
*EUR, or *JIS must be specified.

*JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
command to determine the current date format for the job.

*USA: The United States date format (mm/dd/yyyy) is used.

*ISO: The International Organization for Standardization (ISO) date format


(yyyy-mm-dd) is used.

*EUR: The European date format (dd.mm.yyyy) is used.

*JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

*MDY: The date format (mm/dd/yy) is used.

*DMY: The date format (dd/mm/yy) is used.

*YMD: The date format (yy/mm/dd) is used.

*JUL: The Julian date format (yy/ddd) is used.


DATSEP
Specifies the separator used when accessing date result columns.

Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
specified on the DATFMT parameter.

*JOB: The date separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’/’: A slash (/) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’-’: A dash (-) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.

722 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLPLI
TIMFMT
Specifies the format used when accessing time result columns. For input time
strings, the specified value is used to determine whether the time is specified in
a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not another AS/400 system, the time
format must be *USA, *ISO, *EUR, *JIS, or *HMS with a time separator
of colon or period.

*HMS: The (hh:mm:ss) format is used.

*USA: The United States time format (hh:mm xx) is used, where xx is AM or
PM.

*ISO: The International Organization for Standardization (ISO) time format


(hh.mm.ss) is used.

*EUR: The European time format (hh.mm.ss) is used.

*JIS: The Japanese Industrial Standard time format (hh:mm:ss) is used.


TIMSEP
Specifies the separator used when accessing time result columns.

Note: This parameter applies only when *HMS is specified on the TIMFMT
parameter.

*JOB: The time separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’:’: A colon (:) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


REPLACE
Specifies whether a new program or SQL package is created when a program
or SQL package of the same name exists in the same library. The value of this
parameter is passed to the CRTPLIPGM command. More information on this
parameter is in Appendix A, ″Expanded Parameter Descriptions″ in the CL
Reference (Abridged) book.

*YES: A new program or SQL package is created, and any existing program or
SQL package of the same name and type in the specified library is moved to
QRPLOBJ.

*NO: A new program or SQL package is not created if an object of the same
name and type already exists in the specified library.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 723


CRTSQLPLI
RDB
Specifies the name of the relational database where the SQL package object is
created.

*LOCAL: The program is created as a distributed SQL program. The SQL


statements will access the local database. An SQL package object is not
created as part of the precompile process. The Create Structured Query
Language Package (CRTSQLPKG) command can be used.

relational-database-name: Specify the name of the relational database where


the new SQL package object is to be created. When the name of the local
relational database is specified, the program created is still a distributed SQL
program. The SQL statements will access the local database.

*NONE: An SQL package object is not created. The program object is not a
distributed program and the Create Structured Query Language Package
(CRTSQLPKG) command cannot be used.
USER
Specifies the user name sent to the remote system when starting the
conversation. This parameter is valid only when RDB is specified.

*CURRENT: The user profile under which the current job is running is used.

user-name: Specify the user name being used for the application server job.
PASSWORD
Specifies the password to be used on the remote system. This parameter is
valid only if RDB is specified.

*NONE: No password is sent. If this value is specified, USER(*CURRENT)


must also be specified.

password: Specify the password of the user name specified on the USER
parameter.
RDBCNNMTH
Specifies the semantics used for CONNECT statements. Refer to the SQL
Reference book for more information.

*DUW: CONNECT (Type 2) semantics are used to support distributed unit of


work. Consecutive CONNECT statements to additional relational databases do
not result in disconnection of previous connections.

*RUW: CONNECT (Type 1) semantics are used to support remote unit of work.
Consecutive CONNECT statements result in the previous connection being
disconnected before a new connection is established.
DFTRDBCOL
Specifies the collection name used for the unqualified names of tables, views,
indexes, and SQL packages. This parameter applies only to static SQL
statements.

*NONE: The naming convention defined on the OPTION parameter is used.

collection-name: Specify the name of the collection identifier. This value is used
instead of the naming convention specified on the OPTION parameter.

724 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLPLI
| DYNDFTCOL
| Specifies whether the default collection name specified for the DFTRDBCOL
| parameter is also used for dynamic statements.

| *NO: Do not use the value specified on the DFTRDBCOL parameter for
| unqualified names of tables, views, indexes, and SQL packages for dynamic
| SQL statements. The naming convention specified on the OPTION parameter is
| used.

| *YES: The collection name specified on the DFTRDBCOL parameter will be


| used for the unqualified names of the tables, views, indexes, and SQL
| packages in dynamic SQL statements.
SQLPKG
Specifies the qualified name of the SQL package created on the relational
database specified on the RDB parameter of this command.

The possible library values are:


*PGMLIB: The package is created in the library with the same name as the
library containing the program.
library-name: Specify the name of the library where the package is created.

*PGM: The package name is the same as the program name.

package-name: Specify the name of the package created on the remote


database specified on the RDBNAME parameter.
| SQLPATH
| Specifies the path to be used to find procedures, functions, and user defined
| types in static SQL statements.

| *NAMING: The path used depends on the naming convention specified on the
| OPTION parameter.

| For *SYS naming, the path used is *LIBL, the current library list at runtime.

| For *SQL naming, the path used is ″QSYS″, ″QSYS2″, ″userid″, where ″userid″
| is the value of the USER special register. If a collection-name is specified on
| the DFTRDBCOL parameter, the collection-name takes the place of userid.

| *LIBL: The path used is the library list at runtime.

| collection-name: Specify a list of one or more collection names. A maximum of


| 43 individual collections may be specified.
SAAFLAG
Specifies the IBM SQL flagging function. This parameter flags SQL statements
to verify whether they conform to IBM SQL syntax More information about
which IBM database products IBM SQL syntax is in the DRDA IBM SQL
Reference, SC26-3255-00.

*NOFLAG: The precompiler does not check to see whether SQL statements
conform to IBM SQL syntax.

*FLAG: The precompiler checks to see whether SQL statements conform to


IBM SQL syntax.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 725


CRTSQLPLI
FLAGSTD
Specifies the American National Standards Institute (ANSI) flagging function.
This parameter flags SQL statements to verify whether they conform to the
following standards.
ANSI X3.135-1992 entry
ISO 9075-1992 entry
FIPS 127.2 entry

Specifies the American National Standards Institute (ANSI) flagging function.


This parameter flags SQL statements to verify whether they conform to the
following standards.
ANSI X3.135-1992 entry
ISO 9075-1992 entry
FIPS 127.2 entry

*NONE: The precompiler does not check to see whether SQL statements
conform to ANSI standards.

*ANS: The precompiler checks to see whether SQL statements conform to


ANSI standards.
PRTFILE
Specifies the qualified name of the printer device file to which the listing is
directed. The file must have a minimum record length of 132 bytes or
information is lost.

The name of the printer file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QSYSPRT: If a file name is not specified, the precompiler printout is directed to


the IBM-supplied printer file QSYSPRT.

printer-file-name: Specify the name of the printer device file to which the
precompiler printout is directed.
SRTSEQ
Specifies the sort sequence table to be used for string comparisons in SQL
statements.

Note: *HEX must be specified for this parameter on distributed applications


where the application server is not on an AS/400 system or the release
level is prior to V2R3M0.

*JOB: The SRTSEQ value for the job is retrieved during the precompile.

*JOBRUN: The SRTSEQ value for the job is retrieved when the program is run.
For distributed applications, SRTSEQ(*JOBRUN) is valid only when
LANGID(*JOBRUN) is also specified.

*LANGIDUNQ: The unique-weight sort table for the language specified on the
LANGID parameter is used.

726 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLPLI
*LANGIDSHR: The shared-weight sort table for the language specified on the
LANGID parameter is used.

*HEX: A sort sequence table is not used. The hexadecimal values of the
characters are used to determine the sort sequence.

The name of the sort sequence table can be qualified by one of hte following
library values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

table-name: Specify the name of the sort sequence table to be used.


LANGID
Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
SRTSEQ(*LANGIDSHR) is specified.

*JOB: The LANGID value for the job is retrieved during the precompile.

*JOBRUN: The LANGID value for the job is retrieved when the program is run.
For distributed applications, LANGID(*JOBRUN) is valid only when
SRTSEQ(*JOBRUN) is also specified.

language-id: Specify a language identifier to be used by the program.


USRPRF
Specifies the user profile that is used when the compiled program object is run,
including the authority that the program object has for each object in static SQL
statements. The profile of either the program owner or the program user is used
to control which objects can be used by the program object.

*NAMING: The user profile is determined by the naming convention. If the


naming convention is *SQL, USRPRF(*OWNER) is used. If the naming
convention is *SYS, USRPRF(*USER) is used.

*USER: The profile of the user running the program object is used.

*OWNER: The user profiles of both the program owner and the program user
are used when the program is run.
DYNUSRPRF
Specifies the user profile used for dynamic SQL statements.

*USER: Local dynamic SQL statements are run under the user profile of the
job. Distributed dynamic SQL statements are run under the user profile of the
application server job.

*OWNER: Local dynamic SQL statements are run under the user profile of the
program’s owner. Distributed dynamic SQL statements are run under the user
profile of the SQL package’s owner.
| TOSRCFILE
| Specifies the qualified name of the source file that is to contain the output
| source member that has been processed by the SQL precompiler. If the

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 727


CRTSQLPLI
| specified source file is not found, it will be created. The output member will
| have the same name as the name that is specified for the SRCMBR parameter.

| The possible library values are:


| QTEMP: The library QTEMP will be used.
| *LIBL: The job’s library list is searched for the specified file. If the file is not
| found in any library in the library list, the file will be created in the current
| library.
| *CURLIB: The current library for the job will be used. If no library is
| specified as the current library for the job, the QGPL library will be used.
| library-name: Specify the name of the library that is to contain the output
| source file.

| QSQLTEMP: The source file QSQLTEMP will be used.

| source-file-name: Specify the name of the source file to contain the output
| source member.
TEXT
Specifies the text that briefly describes the program and its function. More
information on this parameter is in Appendix A, ″Expanded Parameter
Descriptions″ in the CL Reference (Abridged) book.

*SCRMBRTXT: The text is taken from the source file member being used to
create the PL/I program. The user can add or change text for a database
source member by using the Start Source Entry Utility (STRSEU) command, or
by using either the Add Physical File Member (ADDPFM) or Change Physical
File Member (CHGPFM) command. If the source file is an inline file or a device
file, the text is blank.

*BLANK: Text is not specified.

’description’: Specify no more than 50 characters of text, enclosed in


apostrophes.

Example
CRTSQLPLI PAYROLL TEXT('Payroll Program')

This command runs the SQL precompiler, which precompiles the source and stores
the changed source in member PAYROLL in file QSQLTEMP in library QTEMP. The
PL/I compiler is called to create program PAYROLL in the current library using the
source member created by the SQL precompiler.

CRTSQLRPG (Create Structured Query Language RPG) Command


Job: B,I Pgm: B,I REXX: B,I Exec

*CURLIB/
ÊÊ CRTSQLRPG PGM( program-name ) Ê
library-name/

728 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPG
Ê Ê
*LIBL/ QRPGSRC
SRCFILE( source-file-name )
*CURLIB/
library-name/

(1)
Ê Ê
*PGM
SRCMBR( source-file-member-name )

Ê Ê
OPTION( OPTION DETAILS ) *CURRENT
TGTRLS( *PRV )
VxRxMx

Ê Ê
*LIBL/ *SRCFILE
INCFILE( source-file-name )
*CURLIB/
library-name/

Ê Ê
*UR *ENDPGM
*CHG CLOSQLCSR( *ENDSQL )
COMMIT( *ALL ) *ENDJOB
*RS
*CS
*NONE
*NC
*RR

Ê Ê
*OPTIMIZE *ALLREAD
ALWCPYDTA( *YES ) ALWBLK( *NONE )
*NO *READ

Ê Ê
*NO 10
DLYPRP( *YES ) GENLVL( severity-level )

Ê Ê
*JOB *JOB
DATFMT( *USA ) DATSEP( '/' )
*ISO '.'
*EUR ','
*JIS '-'
*MDY ' '
*DMY *BLANK
*YMD
*JUL

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 729


CRTSQLRPG
Ê Ê
*HMS *JOB
TIMFMT( *USA ) TIMSEP( ':' )
*ISO '.'
*EUR ','
*JIS ' '
*BLANK

Ê Ê
*YES
REPLACE( *NO )

Ê Ê
*LOCAL *CURRENT
RDB( relational-database-name ) USER( user-name )
*NONE

Ê Ê
*NONE *DUW
PASSWORD( password ) RDBCNNMTH( *RUW )

Ê Ê
*NONE *NO
DFTRDBCOL( collection-name ) DYNDFTCOL( *YES )

Ê Ê
*PGMLIB/ *PGM
SQLPKG( package-name )
library-name/

Ê Ê
*NAMING
SQLPATH( *LIBL )

· collection-name

Ê Ê
*NOFLAG *NONE
SAAFLAG( *FLAG ) FLAGSTD( *ANS )

Ê Ê
*LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

730 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPG
Ê Ê
*JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

Ê Ê
*JOB *NAMING
LANGID( *JOBRUN ) USRPRF( *OWNER )
language-ID *USER

Ê Ê
*USER
DYNUSRPRF( *OWNER )

Ê Ê
QTEMP/ QSQLTEMP
TOSRCFILE( source-file-name )
*LIBL/
*CURLIB/
library-name/

Ê ÊÍ
*SRCMBRTXT
TEXT( *BLANK )
'description'

OPTION Details:

*NOSRC
*NOSOURCE *NOXREF *GEN *JOB *SYS
Ê
*SOURCE *XREF *NOGEN *SYSVAL *SQL
*SRC *PERIOD
*COMMA

*NOSECLVL *NOSEQSRC *NOLSTDBG


Ê
*SECLVL *SEQSRC *LSTDBG

Notes:
1. All parameters preceding this point can be specified in positional form.

Purpose
The Create Structured Query Language RPG (CRTSQLRPG) command calls the
Structured Query Language (SQL) precompiler which precompiles the RPG source

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 731


CRTSQLRPG
containing the SQL statements, produces a temporary source member, and then
optionally calls the RPG compiler to compile the program.

Parameters
PGM
Specifies the qualified name of the compiled program.

The name of the compiled RPG can be qualified by one of the following library
values:
*CURLIB: The compiled RPG program is created in the current library for
the job. If no library is specified as the current library for the job, the QGPL
library is used.
library-name: Specify the name of hte library where the compiled RPG
program is created.

program-name: Specify the name of the compiled program.


SRCFILE
Specifies the qualified name of the source file that contains the RPG source
with SQL statements.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QRPGSRC: If the source file name is not specified, the IBM-supplied source file
QRPGSRC contains the RPG source.

source-file-name: Specify the name of the source file that contains the RPG
source.
SRCMBR
Specifies the name of hte source file member that contains the RPG source.
This parameter is specified only if the source file name in the SRCFILE
parameter is a database file. If this parameter is not specified, the PGM name
specified on the PGM parameter is used.

*PGM: Specifies that the RPG source is in the member of the source file that
has the same name as that specified on the PGM parameter.

source-file-member-name: Specify the name of the member that contains the


RPG source.
OPTION
Specifies whether one or more of the following options are used when the RPG
source is precompiled. If an option is specified more than once, or if two options
conflict, the last option specified is used.

Element 1: Source Listing Options

732 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPG
*NOSOURCE or *NOSRC: A source printout is not produced by the precompiler
unless errors are detected during precompile or create package.

*SOURCE or *SRC: The precompiler produces a source printout, consisting of


RPG source input.

Element 2: Cross-Reference Options

*NOXREF: The precompiler does not cross-reference names.

*XREF: The precompiler cross-references items in the program to the statement


numbers in the program that refer to those items.

Element 3: Program Creation Options

*GEN: The compiler creates a program that can run after the program is
compiled. An SQL package object is created if a relational database name is
specified on the RDB parameter.

*NOGEN: The precompiler does not call the RPG compiler, and a program and
SQL package are not created.

Element 4: Decimal Point Options

*JOB: The value used as the decimal point for numeric constants in SQL is the
representation of decimal point specified for the job at precompile time.

*SYSVAL: The value used as the decimal point for numeric constants in SQL
statements is the QDECFMT system value.

Note: If QDECFMT specifies that the value used as the decimal point is a
comma, any numeric constants in lists (such as in the SELECT clause,
VALUES clause, and so on.) must be separated by a comma followed by
a blank. For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) where the decimal point is a period.

*PERIOD: The value used as the decimal point for numeric constants used in
SQL statements is a period.

*COMMA: The value used as the decimal point for numeric constants in SQL
statements is a comma.

Note: Any numeric constants in lists (such as in the SELECT clause, VALUES
clause, and so on.) must be separated by a comma followed by a blank.
For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) where the decimal point is a period.

Element 5: Naming Convention Options

*SYS: The system naming convention (library-name/file-name) is used.

*SQL: The SQL naming convention is used (collection-name.table-name). When


creating a program on a remote database other than an AS/400 system, *SQL
must be specified as the naming convention.

Element 6: Second-Level Message Text Option

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 733


CRTSQLRPG
*NOSECLVL: Second-level text descriptions are not added to the listing.

*SECLVL: Second-level text with replacement data is added for all messages
on the listing.

Element 7: Source Sequence Number Option

*NOSEQSRC: Source sequence numbers from the input source files are used
when creating the new source member in QSQLTEMP.

*SEQSRC: Source records written to the new source member in QSQLTEMP


are numbered starting at 000001.

Element 8: Debug Listing View Option

*NOLSTDBG: Error and debug information is not generated.

*LSTDBG: The SQL precompiler generates a listing view and error and debug
information required for this view. You can use *LSTDBG only if you are using
the CODE/400 product to compile your program.
TGTRLS
Specifies the release of the operating system on which the user intends to use
the object being created.

In the examples given for the *CURRENT and *PRV values, and when
specifying the release-level value, the format VxRxMx is used to specify the
release, where Vx is the version, Rx is the release, and Mx is the modification
level. For example, V2R3M0 is version 2, release 3, modification level 0.

*CURRENT: The object is to be used on the release of the operating system


currently running on the user’s system. For example, if V2R3M5 is running on
the system, *CURRENT means the user intends to use the object on a system
with V2R3M5 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

Note: If V2R3M5 is running on the system, and the object is to be used on a


system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
TGTRLS(*CURRENT).
*PRV: The object is to be used on the previous release with modification level 0
of the operating system. For example, if V2R3M5 is running on the user’s
system, *PRV means the user intends to use the object on a system with
V2R2M0 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

release-level: Specify the release in the format VxRxMx. The object can be
used on a system with the specified release or with any subsequent release of
the operating system installed.

Valid values depend on the current version, release, and modification level, and
they change with each new release. If you specify a release-level which is
earlier than the earliest release level supported by this command, an error
message is sent indicating the earliest supported release.
INCFILE
Specifies the qualified name of the source file that contains members included
in the program with any SQL INCLUDE statement.

734 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPG
The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

*SRCFILE: The qualified source file specified in the SRCFILE parameter


contains the source file members specified on any SQL INCLUDE statement.

source-file-name: Specify the name of the source file that contains the source
file members specified on any SQL INCLUDE statement. The record length of
the source file specified here must be no less than the record length of the
source file specified for the SRCFILE parameter.
COMMIT
Specifies whether SQL statements in the compiled program are run under
commitment control. Files referred to in the host language source are not
affected by this option. Only SQL tables, SQL views, and SQL packages
referred to in SQL statements are affected.

Note: Files referenced in the RPG source are not affected by this option.

*CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows updated, deleted, and inserted are locked
until the end of the unit of work (transaction). Uncommitted changes in other
jobs can be seen.

*ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows selected, updated, deleted, and inserted are
locked until the end of the unit of work (transaction). Uncommitted changes in
other jobs cannot be seen.

*CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows updated, deleted, and inserted are locked until the end of the unit of
work (transaction). A row that is selected, but not updated, is locked until the
next row is selected. Uncommitted changes in other jobs cannot be seen.

*NONE or *NC: Specifies that commitment control is not used. Uncommitted


changes in other jobs can be seen. If the SQL DROP COLLECTION statement
is included in the program, *NONE or *NC must be used. If a relational
database is specified on the RDB parameter and the relational database is on a
system that is not on an AS/400, *NONE or *NC cannot be specified.

*RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows selected, updated, deleted, and inserted are locked until the end of the
unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
are locked exclusively until the end of the unit of work (transaction).

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 735


CRTSQLRPG
CLOSQLCSR
Specifies when SQL cursors are implicitly closed, SQL prepared statements are
implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
HOLD) SQL statements.

*ENDPGM: SQL cursors are closed and SQL prepared statements are
discarded when the program ends. LOCK TABLE locks are released when the
first SQL program on the call stack ends.

*ENDSQL: SQL cursors remain open between calls and can be fetched without
running another SQL OPEN. One of the programs higher on the call stack must
have run at least one SQL statement. SQL cursors are closed, SQL prepared
statements are discarded, and LOCK TABLE locks are released when the first
SQL program on the call stack ends. If *ENDSQL is specified for a program that
is the first SQL program called (the first SQL program on the call stack), the
program is treated as if *ENDPGM was specified.

*ENDJOB: SQL cursors remain open between calls and can be fetched without
running another SQL OPEN. The programs higher on the call stack do not need
to have run SQL statements. SQL cursors are left open, SQL prepared
statements are preserved, and LOCK TABLE locks are held when the first SQL
program on the call stack ends. SQL cursors are closed, SQL prepared
statements are discarded, and LOCK TABLE locks are released when the job
ends.
| ALWCPYDTA
| Specifies whether a copy of the data can be used in a SELECT statement.

| *OPTIMIZE: The system determines whether to use the data retrieved directly
| from the database or to use a copy of the data. The decision is based on which
| method provides the best performance. If COMMIT is *CHG or *CS and
| ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
| data is used only when it is necessary to run a query.

| *YES: A copy of the data is used only when necessary.

| *NO: A copy of the data is not allowed. If a temporary copy of the data is
| required to perform the query, an error message is returned.
| ALWBLK
| Specifies whether the database manager can use record blocking, and the
| extent to which blocking can be used for read-only cursors.

| *ALLREAD: Rows are blocked for read-only cursors if *NONE or *CHG is


| specified on the COMMIT parameter. All cursors in a program that are not
| explicitly able to be updated are opened for read-only processing even though
| EXECUTE or EXECUTE IMMEDIATE statements may be in the program.

| Specifying *ALLREAD:
| v Allows record blocking under commitment control level *CHG in addition to
| the blocking allowed for *READ.
| v Can improve the performance of almost all read-only cursors in programs,
| but limits queries in the following ways:

736 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPG
| – The Rollback (ROLLBACK) command, a ROLLBACK statement in host
| languages, or the ROLLBACK HOLD SQL statement does not reposition a
| read-only cursor when *ALLREAD is specified.
| – Dynamic running of a positioned UPDATE or DELETE statement (for
| example, using EXECUTE IMMEDIATE), cannot be used to update a row
| in a cursor unless the DECLARE statement for the cursor includes the
| FOR UPDATE clause.

| *NONE: Rows are not blocked for retrieval of data for cursors.

| Specifying *NONE:
| v Guarantees that the data retrieved is current.
| v May reduce the amount of time required to retrieve the first row of data for a
| query.
| v Stops the database manager from retrieving a block of data rows that is not
| used by the program when only the first few rows of a query are retrieved
| before the query is closed.
| v Can degrade the overall performance of a query that retrieves a large
| number of rows.

| *READ: Records are blocked for read-only retrieval of data for cursors when:
| v *NONE is specified on the COMMIT parameter, which indicates that
| commitment control is not used.
| v The cursor is declared with a FOR READ ONLY clause or there are no
| dynamic statements that could run a positioned UPDATE or DELETE
| statement for the cursor.

| Specifying *READ can improve the overall performance of queries that meet the
| above conditions and retrieve a large number of records.
DLYPRP
Specifies whether the dynamic statement validation for a PREPARE statement
is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
validation improves performance by eliminating redundant validation.

*NO: Dynamic statement validation is not delayed. When the dynamic


statement is prepared, the access plan is validated. When the dynamic
statement is used in an OPEN or EXECUTE statement, the access plan is
revalidated. Because the authority or the existence of objects referred to by the
dynamic statement may change, you must still check the SQLCODE or
SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
dynamic statement is still valid.

*YES: Dynamic statement validation is delayed until the dynamic statement is


used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
dynamic statement is used, the validation is completed and an access plan is
built. If you specify *YES on this parameter, you should check the SQLCODE
and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
ensure that the dynamic statement is valid.

Note: If you specify *YES, performance is not improved if the INTO clause is
used on the PREPARE statement or if a DESCRIBE statement uses the
dynamic statement before an OPEN is issued for the statement.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 737


CRTSQLRPG
GENLVL
Specifies the severity level at which the create operation fails. If errors occur
that have a severity level greater than or equal to this value, the operation
ends.

10: The default severity level is 10.

severity-level: Specify a value ranging from 0 through 40.


DATFMT
Specifies the format used when accessing date result columns. All output date
fields are returned in the specified format. For input date strings, the specified
value is used to determine whether the date is specified in a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not an AS/400 system, then *USA, *ISO,
*EUR, or *JIS must be specified.

*JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
command to determine the current date format for the job.

*USA: The United States date format (mm/dd/yyyy) is used.

*ISO: The International Organization for Standardization (ISO) date format


(yyyy-mm-dd) is used.

*EUR: The European date format (dd.mm.yyyy) is used.

*JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

*MDY: The date format (mm/dd/yy) is used.

*DMY: The date format (dd/mm/yy) is used.

*YMD: The date format (yy/mm/dd) is used.

*JUL: The Julian date format (yy/ddd) is used.


DATSEP
Specifies the separator used when accessing date result columns.

Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
specified on the DATFMT parameter.

*JOB: The date separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’/’: A slash (/) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’-’: A dash (-) is used.

738 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPG
’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


TIMFMT
Specifies the format used when accessing time result columns. For input time
strings, the specified value is used to determine whether the time is specified in
a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not another AS/400 system, the time
format must be *USA, *ISO, *EUR, *JIS, or *HMS with a time separator
of colon or period.

*HMS: The (hh:mm:ss) format is used.

*USA: The United States time format (hh:mm xx) is used, where xx is AM or
PM.

*ISO: The International Organization for Standardization (ISO) time format


(hh.mm.ss) is used.

*EUR: The European time format (hh.mm.ss) is used.

*JIS: The Japanese Industrial Standard time format (hh:mm:ss) is used.


TIMSEP
Specifies the separator used when accessing time result columns.

Note: This parameter applies only when *HMS is specified on the TIMFMT
parameter.

*JOB: The time separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’:’: A colon (:) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


REPLACE
Specifies whether a new program or SQL package is created when a program
or SQL package of the same name exists in the same library. The value of this
parameter is passed to the C command.More information on this parameter is
in Appendix A, ″Expanded Parameter Descriptions″ in the CL Reference
(Abridged) book.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 739


CRTSQLRPG
*YES: A new program or SQL package is created, and any existing program or
SQL package of the same name and type in the specified library is moved to
QRPLOBJ.

*NO: A new program or SQL package is not created if an object of the same
name and type already exists in the specified library.
RDB
Specifies the name of the relational database where the SQL package object is
created.

*LOCAL: The program is created as a distributed SQL program. The SQL


statements will access the local database. An SQL package object is not
created as part of the precompile process. The Create Structured Query
Language Package (CRTSQLPKG) command can be used.

relational-database-name: Specify the name of the relational database where


the new SQL package object is to be created. When the name of the local
relational database is specified, the program created is still a distributed SQL
program. The SQL statements will access the local database.

*NONE: An SQL package object is not created. The program object is not a
distributed program and the Create Structured Query Language Package
(CRTSQLPKG) command cannot be used.
USER
Specifies the user name sent to the remote system when starting the
conversation. This parameter is valid only when RDB is specified.

*CURRENT: The user profile under which the current job is running is used.

user-name: Specify the user name being used for the application requester job.
PASSWORD
Specifies the password to be used on the remote system. This parameter is
valid only if RDB is specified.

*NONE: No password is sent. If this value is specified, USER(*CURRENT)


must also be specified.

password: Specify the password of the user name specified on the USER
parameter.
RDBCNNMTH
Specifies the semantics used for CONNECT statements. Refer to the SQL
Reference, SC41-3612 book for more information.

*DUW: CONNECT (Type 2) semantics are used to support distributed unit of


work. Consecutive CONNECT statements to additional relational databases do
not result in disconnection of previous connections.

*RUW: CONNECT (Type 1) semantics are used to support remote unit of work.
Consecutive CONNECT statements result in the previous connection being
disconnected before a new connection is established.

740 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPG
DFTRDBCOL
Specifies the collection name used for the unqualified names of tables, views,
indexes, and SQL packages. This parameter applies only to static SQL
statements.

*NONE: The naming convention defined on the OPTION parameter is used.

collection-name: Specify the name of the collection identifier. This value is used
instead of the naming convention specified on the OPTION parameter.
| DYNDFTCOL
| Specifies whether the default collection name specified for the DFTRDBCOL
| parameter is also used for dynamic statements.

| *NO: Do not use the value specified on the DFTRDBCOL parameter for
| unqualified names of tables, views, indexes, and SQL packages for dynamic
| SQL statements. The naming convention specified on the OPTION parameter is
| used.

| *YES: The collection name specified on the DFTRDBCOL parameter will be


| used for the unqualified names of the tables, views, indexes, and SQL
| packages in dynamic SQL statements.
SQLPKG
Specifies the qualified name of the SQL package created on the relational
database specified on the RDB parameter of this command.

The possible library values are:


*PGMLIB: The package is created in the library with the same name as the
library containing the program.
library-name: Specify the name of the library where the package is created.

*PGM: The package name is the same as the program name.

package-name: Specify the name of the package created on the remote


database specified on the RDBNAME parameter.
| SQLPATH
| Specifies the path to be used to find procedures, functions, and user defined
| types in static SQL statements.

| *NAMING: The path used depends on the naming convention specified on the
| OPTION parameter.

| For *SYS naming, the path used is *LIBL, the current library list at runtime.

| For *SQL naming, the path used is ″QSYS″, ″QSYS2″, ″userid″, where ″userid″
| is the value of the USER special register. If a collection-name is specified on
| the DFTRDBCOL parameter, the collection-name takes the place of userid.

| *LIBL: The path used is the library list at runtime.

| collection-name: Specify a list of one or more collection names. A maximum of


| 43 individual collections may be specified.
SAAFLAG
Specifies the IBM SQL flagging function. This parameter flags SQL statements

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 741


CRTSQLRPG
to verify whether they conform to IBM SQL syntax More information about
which IBM database products IBM SQL syntax is in the DRDA IBM SQL
Reference, SC26-3255-00.

*NOFLAG: The precompiler does not check to see whether SQL statements
conform to IBM SQL syntax.

*FLAG: The precompiler checks to see whether SQL statements conform to


IBM SQL syntax.
FLAGSTD
Specifies the American National Standards Institute (ANSI) flagging function.
This parameter flags SQL statements to verify whether they conform to the
following standards.
ANSI X3.135-1992 entry
ISO 9075-1992 entry
FIPS 127.2 entry

*NONE: The precompiler does not check to see whether SQL statements
conform to ANSI standards.

*ANS: The precompiler checks to see whether SQL statements conform to


ANSI standards.
PRTFILE
Specifies the qualified name of the printer device file to which the listing is
directed. The file must have a minimum record length of 132 bytes or
information is lost.

The name of the printer file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the printer device file to which the
compiler printout is directed.

QSYSPRT: If a file name is not specified, the precompiler printout is directed to


the IBM-supplied printer file QSYSPRT.

printer-file-name: Specify the name of the printer device file to which the
compiler printout is directed.
SRTSEQ
Specifies the sort sequence table to be used for string comparisons in SQL
statements.

Note: *HEX must be specified for this parameter on distributed applications


where the application server is not on an AS/400 system or the release
level is prior to V2R3M0.

*JOB: The SRTSEQ value for the job is retrieved during the precompile.

*JOBRUN: The SRTSEQ value for the job is retrieved when the program is run.
For distributed applications, SRTSEQ(*JOBRUN) is valid only when
LANGID(*JOBRUN) is also specified.

742 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPG
*LANGIDUNQ: The unique-weight sort table for the language specified on the
LANGID parameter is used.

*LANGIDSHR: The shared-weight sort table for the language specified on the
LANGID parameter is used.

*HEX: A sort sequence table is not used. The hexadecimal values of the
characters are used to determine the sort sequence.

The name of the sort sequence table can be qualified by one of the following
library values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

table-name: Specify the name of the sort sequence table to be used.


LANGID
Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
SRTSEQ(*LANGIDSHR) is specified.

*JOB: The LANGID value for hte job is retrieved during the precompile.

*JOBRUN: The LANGID value for the job is retrieved when the program is run.
For distributed applications, LANGID(*JOBRUN) is valid only when
SRTSEQ(*JOBRUN) is also specified.

language-id: Specify a language identifier to be used by the program.


USRPRF
Specifies the user profile that is used when the compiled program object is run,
including the authority that the program object has for each object in static SQL
statements. The profile of either the program owner or the program user is used
to control which objects can be used by the program object.

*NAMING: The user profile is determined by the naming convention. If the


naming convention is *SQL, USRPRF(*OWNER) is used. If the naming
convention is *SYS, USRPRF(*USER) is used.

*USER: The profile of the user running the program object is used.

*OWNER: The user profiles of both the program owner and the program user
are used when the program is run.
DYNUSRPRF
Specifies the user profile used for dynamic SQL statements.

*USER: Local dynamic SQL statements are run under the user profile of the
job. Distributed dynamic SQL statements are run under the user profile of the
application server job.

*OWNER: Local dynamic SQL statements are run under the user profile of the
program’s owner. Distributed dynamic SQL statements are run under the user
profile of the SQL package’s owner.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 743


CRTSQLRPG
| TOSRCFILE
| Specifies the qualified name of the source file that is to contain the output
| source member that has been processed by the SQL precompiler. If the
| specified source file is not found, it will be created. The output member will
| have the same name as the name that is specified for the SRCMBR parameter.

| The possible library values are:


| QTEMP: The library QTEMP will be used.
| *LIBL: The job’s library list is searched for the specified file. If the file is not
| found in any library in the library list, the file will be created in the current
| library.
| *CURLIB: The current library for the job will be used. If no library is
| specified as the current library for the job, the QGPL library will be used.
| library-name: Specify the name of the library that is to contain the output
| source file.

| QSQLTEMP: The source file QSQLTEMP will be used.

| source-file-name: Specify the name of the source file to contain the output
| source member.
TEXT
Specifies text that briefly describes the program and its function. More
information on this parameter is in Appendix A, ″Expanded Parameter
Descriptions″ in the CL Reference book.

*SRCMBRTXT: The text is taken from the source file member being used to
create the RPG program. Text for a database source member can be added or
changed by using the Start Source Entry Utility (STRSEU) command, or by
using either the Add Physical File Member (ADDPFM) command or the Change
Physical File Member (CHGPFM) command. If the source file is an inline file or
a device file, the text is blank.

*BLANK: Text is not specified.

’description’: Specify no more than 50 characters of text, enclosed in


apostrophes.

Example
CRTSQLRPG PGM(JONES/ARBR5)
TEXT('Accounts Receivable Branch 5')

This command runs the SQL precompiler which precompiles the source and stores
the changed source in member ARBR5 in file QSQLTEMP in library QTEMP. The
RPG compiler is called to create program ARBR5 in library JONES by using the
source member created by the SQL precompiler.

CRTSQLRPGI (Create SQL ILE RPG Object) Command


Job: B,I Pgm: B,I REXX: B,I Exec

*CURLIB/
ÊÊ CRTSQLRPGI OBJ( object-name ) Ê
library-name/

744 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPGI
Ê Ê
*LIBL/ QRPGLESRC
SRCFILE( source-file-name )
*CURLIB/
library-name/

(1)
Ê Ê
*OBJ
SRCMBR( source-file-member-name )

Ê Ê
OPTION( OPTION Details ) *CURRENT
TGTRLS( *PRV )
VxRxMx

Ê Ê
*PGM
OBJTYPE( *MODULE )
*SRVPGM

Ê Ê
*LIBL/ *SRCFILE
INCFILE( source-file-name )
*CURLIB/
library-name/

Ê Ê
*UR *ENDACTGRP
*CHG CLOSQLCSR( *ENDMOD )
COMMIT( *ALL )
*RS
*CS
*NONE
*NC
*RR

Ê Ê
*OPTIMIZE *ALLREAD
ALWCPYDTA( *YES ) ALWBLK( *NONE )
*NO *READ

Ê Ê
*NO 10
DLYPRP( *YES ) GENLVL( severity-level )

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 745


CRTSQLRPGI
Ê Ê
*JOB *JOB
DATFMT( *USA ) DATSEP( '/' )
*ISO '.'
*EUR ','
*JIS '-'
*MDY ' '
*DMY *BLANK
*YMD
*JUL

Ê Ê
*HMS *JOB
TIMFMT( *USA ) TIMSEP( ':' )
*ISO '.'
*EUR ','
*JIS ' '
*BLANK

Ê Ê
*YES *LOCAL
REPLACE( *NO ) RDB( relational-database-name )
*NONE

Ê Ê
*CURRENT *NONE
USER( user-name ) PASSWORD( password )

Ê Ê
*DUW *NONE
RDBCNNMTH( *RUW ) DFTRDBCOL( collection-name )

Ê Ê
*NO
DYNDFTCOL( *YES )

Ê Ê
*OBJLIB/ *OBJ
SQLPKG( package-name )
library-name/

Ê Ê
*NAMING
SQLPATH( *LIBL )

· collection-name

746 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPGI
Ê Ê
*NOFLAG *NONE
SAAFLAG( *FLAG ) FLAGSTD( *ANS )

Ê Ê
*NONE *NAMING
DBGVIEW( *SOURCE ) USRPRF( *OWNER )
*USER

Ê Ê
*USER
DYNUSRPRF( *OWNER )

Ê Ê
*JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

Ê Ê
*JOB *NONE
LANGID( *JOBRUN ) OUTPUT( *PRINT )
language-identifier

Ê Ê
*LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

Ê Ê
QTEMP/ QSQLTEMP1
TOSRCFILE( source-file-name )
*LIBL/
*CURLIB/
library-name/

Ê ÊÍ
*SRCMBRTXT
TEXT( *BLANK )
'description'

OPTION Details:

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 747


CRTSQLRPGI
*XREF *GEN *JOB *SYS *NOSECLVL
Ê
*NOXREF *NOGEN *SYSVAL *SQL *SECLVL
*PERIOD
*COMMA

*NOSEQSRC *NOEVENTF *OPTLOB


Ê
*SEQSRC *EVENTF *NOOPTLOB

Notes:
1. All parameters preceding this point can be specified in positional form.

Purpose
The Create Structured Query Language ILE RPG Object (CRTSQLRPGI) command
calls the Structured Query Language (SQL) precompiler which precompiles RPG
source containing SQL statements, produces a temporary source member, and then
optionally calls the ILE RPG compiler to create a module, create a program, or
create a service program.

Parameters
OBJ
Specifies the qualified name of the object being created.
*CURLIB: The new object is created in the current library for the job. If no
library is specified as the current library for the job, the QGPL library is
used.
library-name: Specify the name of the library where the object is created.

object-name: Specify the name of the object being created.


SRCFILE
Specifies the qualified name of the source file that contains the RPG source
with SQL statements.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QRPGLESRC: If the source file name is not specified, the IBM-supplied source
file QRPGLESRC contains the RPG source.

source-file-name: Specify the name of the source file that contains the RPG
source.
SRCMBR
Specifies the name of the source file member that contains the RPG source.
This parameter is specified only if the source file name in the SRCFILE

748 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPGI
parameter is a database file. If this parameter is not specified, the PGM name
specified on the OBJ parameter is used.

*OBJ: Specifies that the RPG source is in the member of the source file that
has the same name as that specified on the OBJ parameter.

source-file-member-name: Specify the name of the member that contains the


RPG source.
OPTION
Specifies whether one or more of the following options are used when the RPG
source is precompiled. If an option is specified more than once, or if two options
conflict, the last option specified is used.

Element 1: Cross-Reference Options

*XREF: The precompiler cross-references items in the program to the statement


numbers in the program that refer to those items.

*NOXREF: The precompiler does not cross-reference names.

Element 2: Program Creation Options

*GEN: The precompiler creates the object that is specified by the OBJTYPE
parameter.

*NOGEN: The precompiler does not call the RPG compiler, and a module,
program, service program, or SQL package is not created.

Element 3: Decimal Point Options

*JOB: The value used as the decimal point for numeric constants in SQL is the
representation of decimal point specified for the job at precompile time.

*SYSVAL: The value used as the decimal point for numeric constants in SQL
statements is the QDECFMT system value.

Note: If QDECFMT specifies that the value used as the decimal point is a
comma(,), any numeric constants in lists (such as in the SELECT clause
or the VALUES clause) must be separated by a comma (,) followed by a
blank ( ). For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) in which the decimal point is a period (.).

*PERIOD: The value used as the decimal point for numeric constants in SQL
statements is a period (.).

*COMMA: The value used as the decimal point for numeric constants in SQL
statements is a comma (,).

Note: Any numeric constants in lists (such as in the SELECT clause or the
VALUES clause) must be separated by a comma (,) followed by a blank(
). For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) where the decimal point is a period (.).

Element 4: Naming Convention Options

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 749


CRTSQLRPGI
*SYS: The system naming convention (library-name/file-name) is used.

*SQL: The SQL naming convention is used (collection-name.table-name). When


creating a program on a remote database other than an AS/400 system, *SQL
must be specified as the naming convention.

Element 5: Second-Level Message Text Option

*NOSECLVL: Second-level text descriptions are not added to the listing.

*SECLVL: Second-level text with replacement data is added for all messages
on the listing.

Element 6: Sequence source

*NOSEQSRC: The source file member created into QSQLTEMP1 has the same
sequence numbers as the original source read by the precompiler.

*SEQSRC: The source file member created into QSQLTEMP1 contains


sequence numbers starting at 000001 and incremented by 000001.

Element 7: Event File Creation

*NOEVENTF: The compiler will not produce an Event File for use by
CoOperative Development Environment/400 (CODE/400).

*EVENTF: The compiler produces an event file for use by CoOperative


Development Environment/400 (CODE/400). The event file will be created as a
member in the file EVFEVENT in your source library. CODE/400 uses this file to
offer error feedback integrated with the CODE/400 editor. This option is
normally specified by CODE/400 on your behalf.

Element 8: Date Conversion

*NOCVTDT: Date, time and timestamp data types which are retrieved from
externally-described files are to be processed using the native RPG language.

*CVTDT: Date, time and timestamp data types which are retrieved from
externally-described files are to be processed as fixed-length character.

| Element 9: Large Object Optimization for DRDA

*OPTLOB: The first FETCH for a cursor determines how the cursor will be used
for LOBs (Large Objects) on all subsequent FETCHes. This option remains in
effect until the cursor is closed.

If the first FETCH uses a LOB locator to access a LOB column, no subsequent
FETCH for that cursor can fetch that LOB column into a LOB host variable.

If the first FETCH places the LOB column into a LOB host variable, no
subsequent FETCH for that cursor can use a LOB locator for that column.

*NOOPTLOB: There is no restriction on whether a column is retrieved into a


LOB locator or into a LOB host variable. This option can cause performance to
degrade.

750 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPGI
TGTRLS
Specifies the release of the operating system on which the user intends to use
the object being created.

In the examples given for the *CURRENT and *PRV values, and when
specifying the release-level value, the format VxRxMx is used to specify the
release, where Vx is the version, Rx is the release, and Mx is the modification
level. For example, V2R3M0 is version 2, release 3, modification level 0.

*CURRENT: The object is to be used on the release of the operating system


currently running on the user’s system. For example, if V2R3M5 is running on
the system, *CURRENT means the user intends to use the object on a system
with V2R3M5 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

Note: If V2R3M5 is running on the system, and the object is to be used on a


system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
TGTRLS(*CURRENT).
*PRV: The object is to be used on the previous release with modification level 0
of the operating system. For example, if V2R3M5 is running on the user’s
system, *PRV means the user intends to use the object on a system with
V2R2M0 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

release-level: Specify the release in the format VxRxMx. The object can be
used on a system with the specified release or with any subsequent release of
the operating system installed.

Valid values depend on the current version, release, and modification level, and
they change with each new release. If you specify a release-level which is
earlier than the earliest release level supported by this command, an error
message is sent indicating the earliest supported release.
OBJTYPE
Specifies the type of object being created.

*PGM: The SQL precompiler issues the CRTBNDRPG command to create the
bound program.

*MODULE: The SQL precompiler issues the CRTRPGMOD command to create


the module.

*SRVPGM: The SQL precompiler issues the CRTRPGMOD and CRTSRVPGM


commands to create the service program.
Notes:
1. When OBJTYPE(*PGM) or OBJTYPE(*SRVPGM) is specified and the RDB
parameter is also specified, the CRTSQLPKG command is issued by the
SQL precompiler after the program has been created. When
OBJTYPE(*MODULE) is specified, an SQL package is not created and you
must issue the CRTSQLPKG command after the CRTPGM or
CRTSRVPGM command has created the program.
2. If *NOGEN is specified, only the SQL temporary source member is
generated and a module, program, service program, and SQL package are
not created.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 751


CRTSQLRPGI
INCFILE
Specifies the qualified name of the source file that contains members included
in the program with any SQL INCLUDE statement.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

*SRCFILE: The qualified source file specified in the SRCFILE parameter


contains the source file members specified on any SQL INCLUDE statement.

source-file-name: Specify the name of the source file that contains the source
file members specified on any SQL INCLUDE statement. The record length of
the source file specified here must be no less than the record length of the
source file specified on the SRCFILE parameter.
COMMIT
Specifies whether SQL statements in the compiled unit are run under
commitment control. Files referred to in the host language source are not
affected by this option. Only SQL tables, SQL views, and SQL packages
referred to in SQL statements are affected.

*CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows updated, deleted, and inserted are locked
until the end of the unit of work (transaction). Uncommitted changes in other
jobs can be seen.

*ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows selected, updated, deleted, and inserted are
locked until the end of the unit of work (transaction). Uncommitted changes in
other jobs cannot be seen.

*CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows updated, deleted, and inserted are locked until the end of the unit of
work (transaction). A row that is selected, but not updated, is locked until the
next row is selected. Uncommitted changes in other jobs cannot be seen.

*NONE or *NC: Specifies that commitment control is not used. Uncommitted


changes in other jobs can be seen. If the SQL DROP COLLECTION statement
is included in the program, *NONE or *NC must be used. If a relational
database is specified on the RDB parameter and the relational database is on a
system that is not on an AS/400, *NONE or *NC cannot be specified.

*RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows selected, updated, deleted, and inserted are locked until the end of the
unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
are locked exclusively until the end of the unit of work (transaction).

752 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPGI
CLOSQLCSR
Specifies when SQL cursors are implicitly closed, SQL prepared statements are
implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
HOLD) SQL statements.

*ENDACTGRP: SQL cursors are closed, SQL prepared statements are implicitly
discarded, and LOCK TABLE locks are released when the activation group
ends.

*ENDMOD: SQL cursors are closed and SQL prepared statements are implicitly
discarded when the module is exited. LOCK TABLE locks are released when
the first SQL program on the call stack ends.
| ALWCPYDTA
| Specifies whether a copy of the data can be used in a SELECT statement.

| *OPTIMIZE: The system determines whether to use the data retrieved directly
| from the database or to use a copy of the data. The decision is based on which
| method provides the best performance. If COMMIT is *CHG or *CS and
| ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
| data is used only when it is necessary to run a query.

| *YES: A copy of the data is used only when necessary.

| *NO: A copy of the data is not allowed. If a temporary copy of the data is
| required to perform the query, an error message is returned.
| ALWBLK
| Specifies whether the database manager can use record blocking, and the
| extent to which blocking can be used for read-only cursors.

| *ALLREAD: Rows are blocked for read-only cursors if *NONE or *CHG is


| specified on the COMMIT parameter. All cursors in a program that are not
| explicitly able to be updated are opened for read-only processing even though
| EXECUTE or EXECUTE IMMEDIATE statements may be in the program.

| Specifying *ALLREAD:
| v Allows record blocking under commitment control level *CHG in addition to
| the blocking allowed for *READ.
| v Can improve the performance of almost all read-only cursors in programs,
| but limits queries in the following ways:
| – The Rollback (ROLLBACK) command, a ROLLBACK statement in host
| languages, or the ROLLBACK HOLD SQL statement does not reposition a
| read-only cursor when *ALLREAD is specified.
| – Dynamic running of a positioned UPDATE or DELETE statement (for
| example, using EXECUTE IMMEDIATE), cannot be used to update a row
| in a cursor unless the DECLARE statement for the cursor includes the
| FOR UPDATE clause.

| *NONE: Rows are not blocked for retrieval of data for cursors.

| Specifying *NONE:
| v Guarantees that the data retrieved is current.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 753


CRTSQLRPGI
| v May reduce the amount of time required to retrieve the first row of data for a
| query.
| v Stops the database manager from retrieving a block of data rows that is not
| used by the program when only the first few rows of a query are retrieved
| before the query is closed.
| v Can degrade the overall performance of a query that retrieves a large
| number of rows.

| *READ: Records are blocked for read-only retrieval of data for cursors when:
| v *NONE is specified on the COMMIT parameter, which indicates that
| commitment control is not used.
| v The cursor is declared with a FOR READ ONLY clause or there are no
| dynamic statements that could run a positioned UPDATE or DELETE
| statement for the cursor.

| Specifying *READ can improve the overall performance of queries that meet the
| above conditions and retrieve a large number of records.
DLYPRP
Specifies whether the dynamic statement validation for a PREPARE statement
is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
validation improves performance by eliminating redundant validation.

*NO: Dynamic statement validation is not delayed. When the dynamic


statement is prepared, the access plan is validated. When the dynamic
statement is used in an OPEN or EXECUTE statement, the access plan is
revalidated. Because the authority or the existence of objects referred to by the
dynamic statement may change, you must still check the SQLCODE or
SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
dynamic statement is still valid.

*YES: Dynamic statement validation is delayed until the dynamic statement is


used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
dynamic statement is used, the validation is completed and an access plan is
built. If you specify *YES on this parameter, you should check the SQLCODE
and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
ensure that the dynamic statement is valid.

Note: If you specify *YES, performance is not improved if the INTO clause is
used on the PREPARE statement or if a DESCRIBE statement uses the
dynamic statement before an OPEN is issued for the statement.
GENLVL
Specifies the severity level at which the create operation fails. If errors occur
that have a severity level greater than this value, the operation ends.

10: The default severity level is 10.

severity-level: Specify a value ranging from 0 through 40.


DATFMT
Specifies the format used when accessing date result columns. All output date
fields are returned in the specified format. For input date strings, the specified
value is used to determine whether the date is specified in a valid format.

754 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPGI
Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not an AS/400 system, then *USA, *ISO,
*EUR, or *JIS must be specified.

*JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
command to determine the current date format for the job.

*USA: The United States date format (mm/dd/yyyy) is used.

*ISO: The International Organization for Standardization (ISO) date format


(yyyy-mm-dd) is used.

*EUR: The European date format (dd.mm.yyyy) is used.

*JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

*MDY: The date format (mm/dd/yy) is used.

*DMY: The date format (dd/mm/yy) is used.

*YMD: The date format (yy/mm/dd) is used.

*JUL: The Julian date format (yy/ddd) is used.


DATSEP
Specifies the separator used when accessing date result columns.

Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
specified on the DATFMT parameter.

*JOB: The date separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’/’: A slash (/) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’-’: A dash (-) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


TIMFMT
Specifies the format used when accessing time result columns. For input time
strings, the specified value is used to determine whether the time is specified in
a valid format.

Note: An input time string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 755


CRTSQLRPGI
If a relational database is specified on the RDB parameter and the
database is on a system that is not another AS/400 system, the time
format must be *USA, *ISO, *EUR, *JIS, or *HMS with a time separator
of a colon or period.

*HMS: The hh:mm:ss format is used.

*USA: The United States time format hh:mm xx is used, where xx is AM or


PM.

*ISO: The International Organization for Standardization (ISO) time format


hh.mm.ss is used.

*EUR: The European time format hh.mm.ss is used.

*JIS: The Japanese Industrial Standard time format hh:mm:ss is used.


TIMSEP
Specifies the separator used when accessing time result columns.

Note: This parameter applies only when *HMS is specified on the TIMFMT
parameter.

*JOB: The time separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’:’: A colon (:) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


REPLACE
Specifies if a SQL module, program, service program or package is created
when there is an existing SQL module, program, service program, or package
of the same name and type in the same library. The value of this parameter is
passed to the CRTRPGMOD, CRTBNDRPG, CRTSRVPGM, and CRTSQLPKG
commands.

*YES: A new SQL module, program, service program, or package is created,


any existing SQL object of the same name and type in the specified library is
moved to QRPLOBJ.

*NO: A new SQL module, program, service program, or package is not created
if an SQL object of the same name and type already exists in the specified
library.
RDB
Specifies the name of the relational database where the SQL package object is
created.

*LOCAL: The program is created as a distributed SQL program. The SQL


statements will access the local database. An SQL package object is not

756 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPGI
created as part of the precompile process. The Create Structured Query
Language Package (CRTSQLPKG) command can be used.

relational-database-name: Specify the name of the relational database where


the new SQL package object is to be created. When the name of the local
relational database is specified, the program created is still a distributed SQL
program. The SQL statements will access the local database.

*NONE: An SQL package object is not created. The program object is not a
distributed program and the Create Structured Query Language Package
(CRTSQLPKG) command cannot be used.
USER
Specifies the user name sent to the remote system when starting the
conversation. This parameter is valid only when RDB is specified.

*CURRENT: The user profile under which the current job is running is used.

user-name: Specify the user name being used for the application server job.
PASSWORD
Specifies the password to be used on the remote system. This parameter is
valid only if RDB is specified.

*NONE: No password is sent. If this value is specified, USER(*CURRENT)


must also be specified.

password: Specify the password of the user name specified on the USER
parameter.
RDBCNNMTH
Specifies the semantics used for CONNECT statements. Refer to the SQL
Reference, SC41-3612 book for more information.

*DUW: CONNECT (Type 2) semantics are used to support distributed unit of


work. Consecutive CONNECT statements to additional relational databases do
not result in disconnection of previous connections.

*RUW: CONNECT (Type 1) semantics are used to support remote unit of work.
Consecutive CONNECT statements result in the previous connection being
disconnected before a new connection is established.
DFTRDBCOL
Specifies the collection name used for the unqualified names of tables, views,
indexes, and SQL packages. This parameter applies only to static SQL
statements.

*NONE: The naming convention defined on the OPTION parameter is used.

collection-name: Specify the name of the collection identifier. This value is used
instead of the naming convention specified on the OPTION parameter.
| DYNDFTCOL
| Specifies whether the default collection name specified for the DFTRDBCOL
| parameter is also used for dynamic statements.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 757


CRTSQLRPGI
| *NO: Do not use the value specified on the DFTRDBCOL parameter for
| unqualified names of tables, views, indexes, and SQL packages for dynamic
| SQL statements. The naming convention specified on the OPTION parameter is
| used.

| *YES: The collection name specified on the DFTRDBCOL parameter will be


| used for the unqualified names of the tables, views, indexes, and SQL
| packages in dynamic SQL statements.
SQLPKG
Specifies the qualified name of the SQL package created on the relational
database specified on the RDB parameter of this command.

The possible library values are:


*OBJLIB: The package is created in the library with the same name as the
library specified on the OBJ parameter.
library-name: Specify the name of the library where the package is created.

*OBJ: The name of the SQL package is the same as the object name specified
on the OBJ parameter.

package-name: Specify the name of the SQL package. If the remote system is
not an AS/400 system, no more than 8 characters can be specified.
| SQLPATH
| Specifies the path to be used to find procedures, functions, and user defined
| types in static SQL statements.

| *NAMING: The path used depends on the naming convention specified on the
| OPTION parameter.

| For *SYS naming, the path used is *LIBL, the current library list at runtime.

| For *SQL naming, the path used is ″QSYS″, ″QSYS2″, ″userid″, where ″userid″
| is the value of the USER special register. If a collection-name is specified on
| the DFTRDBCOL parameter, the collection-name takes the place of userid.

| *LIBL: The path used is the library list at runtime.

| collection-name: Specify a list of one or more collection names. A maximum of


| 43 individual collections may be specified.
SAAFLAG
Specifies the IBM SQL flagging function. This parameter flags SQL statements
to verify whether they conform to IBM SQL syntax. More information about IBM
SQL syntax found in IBM database products can be found in the DRDA IBM
SQL Reference, SC26–3255–00.

*NOFLAG: The precompiler does not check to see whether SQL statements
conform to IBM SQL syntax.

*FLAG: The precompiler checks to see whether SQL statements conform to


IBM SQL syntax.

758 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPGI
FLAGSTD
Specifies the American National Standards Institute (ANSI) flagging function.
This parameter flags SQL statements to verify whether they conform to the
following standards.
ANSI X3.135-1992 entry
ISO 9075-1992 entry
FIPS 127.2 entry

*NONE: The precompiler does not check to see whether SQL statements
conform to ANSI standards.

*ANS: The precompiler checks to see whether SQL statements conform to


ANSI standards.
DBGVIEW
Specifies the type of source debug information to be provided by the SQL
precompiler.

*NONE: The source view will not be generated.

*SOURCE: The SQL precompiler will provide the source views for the root and
if necessary, SQL INCLUDE statements. A view will be provided which contains
the statements generated by the precompiler.
USRPRF
Specifies the user profile that is used when the compiled program object is run,
including the authority that the program object has for each object in static SQL
statements. The profile of either the program owner or the program user is used
to control which objects can be used by the program object.

*NAMING: The user profile is determined by the naming convention. If the


naming convention is *SQL, USRPRF(*OWNER) is used. If the naming
convention is *SYS, USRPRF(*USER) is used.

*USER: The profile of the user running the program object is used.

*OWNER: The user profiles of both the program owner and the program user
are used when the program is run.
DYNUSRPRF
Specifies the user profile to be used for dynamic SQL statements.

*USER: For local, dynamic SQL statements run under the user of the program’s
user. For distributed, dynamic SQL statements run under the profile of the SQL
package’s user.

*OWNER: For local, dynamic SQL statements run under the profile of the
program’s owner. For distributed, dynamic SQL statements run under the profile
of the SQL package’s owner.
SRTSEQ
Specifies the sort sequence table to be used for string comparisons in SQL
statements.

Note: *HEX must be specified for this parameter on distributed applications


where the application server is not on an AS/400 system or the release
level is prior to V2R3M0.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 759


CRTSQLRPGI
*JOB: The SRTSEQ value for the job is retrieved during the precompile.

*JOBRUN: The SRTSEQ value for the job is retrieved when the program is run.
For distributed applications, SRTSEQ(*JOBRUN) is valid only when
LANGID(*JOBRUN) is also specified.

*LANGIDUNQ: The unique-weight sort table for the language specified on the
LANGID parameter is used.

*LANGIDSHR: The sort sequence table uses the same weight for multiple
characters, and is the shared-weight sort sequence table associated with the
language specified on the LANGID parameter.

*HEX: A sort sequence table is not used. The hexadecimal values of the
characters are used to determine the sort sequence.

The name of the sort sequence table can be qualified by one of the following
library values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.
table-name: Specify the name of the sort sequence table to be used.
LANGID
Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
SRTSEQ(*LANGIDSHR) is specified.

*JOB: The LANGID value for the job is retrieved during the precompile.

*JOBRUN: The LANGID value for the job is retrieved when the program is run.
For distributed applications, LANGID(*JOBRUN) is valid only when
SRTSEQ(*JOBRUN) is also specified.

language-identifier: Specify a language identifier.


OUTPUT
Specifies whether the precompiler listing is generated.

*NONE: The precompiler listing is not generated.

*PRINT: The precompiler listing is generated.


PRTFILE
Specifies the qualified name of the printer device file to which the precompiler
printout is directed. The file must have a minimum length of 132 bytes. If a file
with a record length of less than 132 bytes is specified, information is lost.

The name of the printer file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

760 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLRPGI
QSYSPRT: If a file name is not specified, the precompiler printout is directed to
the IBM-supplied printer file QSYSPRT.

printer-file-name: Specify the name of the printer device file to which the
precompiler printout is directed.
| TOSRCFILE
| Specifies the qualified name of the source file that is to contain the output
| source member that has been processed by the SQL precompiler. If the
| specified source file is not found, it will be created. The output member will
| have the same name as the name that is specified for the SRCMBR parameter.

| The possible library values are:


| QTEMP: The library QTEMP will be used.
| *LIBL: The job’s library list is searched for the specified file. If the file is not
| found in any library in the library list, the file will be created in the current
| library.
| *CURLIB: The current library for the job will be used. If no library is
| specified as the current library for the job, the QGPL library will be used.
| library-name: Specify the name of the library that is to contain the output
| source file.

| QSQLTEMP1: The source file QSQLTEMP1 will be used.

| source-file-name: Specify the name of the source file to contain the output
| source member.
TEXT
Specifies the text that briefly describes the function. More information on this
parameter is located in Appendix A, ″Expanded Parameter Descriptions″ in the
CL Reference book.

*SRCMBRTXT: The text is taken from the source file member being used to
create the RPG program. Text can be added or changed for a database source
member by using the Start Source Entry Utility (STRSEU) command, or by
using either the Add Physical File Member (ADDPFM) or Change Physical File
Member (CHGPFM) command. If the source file is an inline file or a device file,
the text is blank.

*BLANK: Text is not specified.

’description’: Specify no more than 50 characters of text, enclosed in


apostrophes.

Example
CRTSQLRPGI PAYROLL OBJTYPE(*PGM) TEXT('Payroll Program')

This command runs the SQL precompiler which precompiles the source and stores
the changed source in member PAYROLL in file QSQLTEMP1 in library QTEMP.
The ILE RPG compiler is called to create program PAYROLL in the current library
by using the source member created by the SQL precompiler.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 761


CRTSQLPKG

CRTSQLPKG (Create Structured Query Language Package) Command


Job: B,I Pgm: B,I REXX: B,I Exec

*LIBL/
ÊÊ CRTSQLPKG PGM( program-name ) Ê
*CURLIB/
library-name/

(1)
Ê Ê
*PGM
RDB( relational-database-name )

Ê Ê
*CURRENT *NONE
USER( user-name ) PASSWORD( password )

Ê Ê
10 *YES
GENLVL( severity-level ) REPLACE( *NO )

Ê Ê
*PGM
DFTRDBCOL( *NONE )
collection-name

Ê Ê
*LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

Ê Ê
*PGM
OBJTYPE( *SRVPGM )

Ê Ê
*ALL

(2)
MODULE( · module-name )

Ê ÊÍ
*PGMTXT
TEXT( *BLANK )
'description'

762 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLPKG
Notes:
1. All parameters preceding this point can be specified in positional form.
2. A maximum of 256 modules may be specified.

Purpose
The Create Structured Query Language Package (CRTSQLPKG) command is used
to create (or re-create) an SQL package on a relational database from an existing
distributed SQL program. A distributed SQL program is a program created by
specifying the RDB parameter on a CRTSQLxxx (where xxx = C, CI, CBL, CBLI,
FTN, PLI, or RPG or RPGI) command.

Parameters
PGM
Specifies the qualified name of the program for which the SQL package is being
created. The program must be a distributed SQL program.

The name of the program can be qualified by one of the following library values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

program-name: Specify the name of the program for which the package is being
created.
RDB
Specifies the name of the relational database where the SQL package is being
created.

*PGM: The relational database name specified for the SQL program is used.
The relational database name is specified on the RDB parameter of the
distributed SQL program.

relational-database-name: Specify the name of the relational database where


the SQL package is to be created. Use the Work with Relational Database
Directory Entry (WRKRDBDIRE) command to show the relational database
names that are valid on this parameter.
USER
Specifies the user name sent to the remote system when starting the
conversation.

*CURRENT: The user name associated with the current job is used.

user-name: Specify the user name being used for the application server job.
PASSWORD
Specifies the password to be used on the remote system.

*NONE: No password is sent. If this value is specified, USER(*CURRENT)


must also be specified.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 763


CRTSQLPKG
password: Specify the password of the user name specified on the USER
parameter.
GENLVL
Specifies the maximum severity level allowed for errors detected during SQL
package creation. If errors occur at a level that exceeds the specified level, the
SQL package is not created.

10: The default severity-level is 10.

severity-level: Specify the maximum severity level. Valid values range from 0
through 40.
REPLACE
Specifies whether an existing package is being replaced with the new package.
More information on this parameter is in Appendix A, ″Expanded Parameter
Descriptions″ in the CL Reference book.

*YES: An existing SQL package of the same name is replaced by the new SQL
package.

*NO: An existing SQL package of the same name is not replaced; a new SQL
package is not created if the package already exists in the specified library.
DFTRDBCOL
Specifies the collection name to be used for unqualified names of tables, views,
indexes, and SQL packages. This parameter applies only to static SQL
statements in the package.

*PGM: The collection name specified for the SQL program is used. The default
relational database collection name is specified on the DFTRDBCOL parameter
of the distributed SQL program.

*NONE: Unqualified names for tables, views, indexes, and SQL packages use
the search conventions specified on the OPTION parameter of the CRTSQLxxx
command used to create the program.

collection-name: Specify the collection name that is used for unqualified tables,
views, indexes, and SQL packages.
PRTFILE
Specifies the qualified name of the printer device file to which the create SQL
package error listing is directed. If no errors are detected during the creation of
the SQL package, no listing is produced.

The name of the printer file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QSYSPRT: If a file name is not specified, the create SQL package error listing
is directed to the IBM-supplied printer file QSYSPRT.

764 DB2 UDB for AS/400 SQL Programming V4R4


CRTSQLPKG
printer-file-name: Specify the name of the printer device file to which the create
SQL package error listing is directed.
OBJTYPE
Specifies the type of program for which an SQL package is created.

*PGM: Create an SQL package from the program specified on the PGM
parameter.

*SRVPGM: Create an SQL package from the service program specified on the
PGM parameter.
MODULE
Specifies a list of modules in a bound program.

*ALL: An SQL package is created for each module in the program. An error
message is sent if none of the modules in the program contain SQL statements
or none of the modules is a distributed module.

Note: CRTSQLPKG can process programs that do not contain more than 1024
modules.

module-name: Specify the names of up to 256 modules in the program for


which an SQL package is to be created. If more than 256 modules exist that
need to have an SQL package created, multiple CRTSQLPKG commands must
be used.

Duplicate module names in the same program are allowed. This command
looks at each module in the program and if *ALL or the module name is
specified on the MODULE parameter, processing continues to determine
whether an SQL package should be created. If the module is created using
SQL and the RDB parameter is specified on the precompile command, an SQL
package is created for the module. The SQL package is associated with the
module of the bound program.
TEXT
Specifies text that briefly describes the SQL package and its function.

*PGMTXT: The text from the program for which the SQL package is being
created is used.

*BLANK: No text is specified.

’description’: Specify a maximum of 50 characters of text, enclosed in


apostrophes.

Example
CRTSQLPKG PAYROLL RDB(SYSTEMA)
TEXT('Payroll Program')

This command creates an SQL package from the distributed SQL program
| PAYROLL on relational database SYSTEMA.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 765


CVTSQLCPP
|
| CVTSQLCPP (Convert Structured Query Language C++ Source)
| Command
| Job: B,I Pgm: B,I REXX: B,I Exec

| *LIBL/
| ÊÊ CVTSQLCPP SRCFILE( source-file-name ) Ê
*CURLIB/
library-name/

| *OBJ (1)
| Ê SRCMBR( source-file-member-name ) Ê

| Ê Ê
| *LIBL/ QSQLTEMP
TOSRCFILE( source-file-name )
*CURLIB/
library-name/

| Ê Ê
| OPTION( OPTION Details ) *CURRENT
TGTRLS( VxRxMx )

| Ê Ê
| *LIBL/ *SRCFILE
INCFILE( source-file-name )
*CURLIB/
library-name/

| Ê Ê
| *UR *ENDACTGRP
*CHG CLOSQLCSR( *ENDMOD )
COMMIT( *ALL )
*RS
*CS
*NONE
*NC
*RR

| Ê Ê
| *OPTIMIZE *ALLREAD
ALWCPYDTA( *YES ) ALWBLK( *NONE )
*NO *READ

| Ê Ê
| *NO 10
DLYPRP( *YES ) GENLVL( severity-level )

766 DB2 UDB for AS/400 SQL Programming V4R4


CVTSQLCPP
| Ê Ê
| *SRCFILE *JOB
MARGINS( left-right ) DATFMT( *USA )
*ISO
*EUR
*JIS
*MDY
*DMY
*YMD
*JUL

| Ê Ê
| *JOB *HMS
DATSEP( '/' ) TIMFMT( *USA )
'.' *ISO
',' *EUR
'-' *JIS
' '
*BLANK

| Ê Ê
| *JOB
TIMSEP( ':' )
'.'
','
' '
*BLANK

|
| Ê Ê
| *LOCAL *CURRENT
RDB( relational-database-name ) USER( user-name )
*NONE

| Ê Ê
| *NONE *DUW
PASSWORD( password ) RDBCNNMTH( *RUW )

| Ê Ê
| *NONE *NO
DFTRDBCOL( collection-name ) DYNDFTCOL( *YES )

| Ê Ê
| *OBJLIB/ *OBJ
SQLPKG( package-name )
library-name/

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 767


CVTSQLCPP
| Ê Ê
| *NAMING
SQLPATH( *LIBL )

· collection-name

| Ê Ê
| *NOFLAG *NONE
SAAFLAG( *FLAG ) FLAGSTD( *ANS )

| Ê Ê
| *NONE *NAMING
DBGVIEW( *SOURCE ) USRPRF( *OWNER )
*USER

| Ê Ê
| *USER
DYNUSRPRF( *OWNER )

| Ê Ê
| *JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

| Ê Ê
| *JOB *NONE
LANGID( *JOBRUN ) OUTPUT( *PRINT )
language-identifier

| Ê Ê
| *LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

| Ê ÊÍ
| *SRCMBRTXT
TEXT( *BLANK )
'description'

| OPTION Details:

768 DB2 UDB for AS/400 SQL Programming V4R4


CVTSQLCPP
| *XREF *JOB *SYS *NOSECLVL *NOCNULRQD
| Ê
*NOXREF *SYSVAL *SQL *SECLVL *CNULRQD
*PERIOD
*COMMA

| *NOEVENTF *OPTLOB
| Ê
*EVENTF *NOOPTLOB

|
| Notes:
| 1. All parameters preceding this point can be specified in positional form.

| Purpose
| The Convert Structured Query Language C++ Source (CVTSQLCPP) command
| calls the Structured Query Language (SQL) precompiler. The precompiler
| precompiles C++ source that contains SQL statements, and produces a temporary
| source member. This source member can then be provided as input to the
| VisualAge C++ for OS/400 compiler.

| Parameters
| SRCFILE
| Specifies the qualified name of the source file that contains the C++ source with
| SQL statements.

| One of the following library values can qualify the name of the source file:
| *LIBL: All libraries in the job’s library list are searched until the first match is
| found.
| *CURLIB: The current library for the job is searched. If no library is specified
| as the current library for the job, the QGPL library is used.
| library-name: Specify the name of the library to be searched.

| source-file-name: Specify the name of the source file that contains the C++
| source with SQL statements.
| SRCMBR
| Specifies the name of the source file member that contains the C++ source.
| TOSRCFILE
| Specifies the qualified name of the source file that is to contain the output C++
| source member that has been processed by the SQL C++ precompiler. If the
| specified source file is not found, it will be created. The output member will
| have the same name as the name specified for the SRCMBR parameter.

| The name of the source file can be qualified by one of the following library
| values:
| *LIBL: The job’s library list is searched for the specified file. If the file is not
| found in any library in the library list, the file will be created in the current
| library.
| *CURLIB: The current library for the job will be used. If no library is
| specified as the current library for the job, the QGPL library is used.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 769


CVTSQLCPP
| library-name: Specify the name of the library that is to contain the output
| source file.
| OPTION
| Specifies whether one or more of the following options are used when the C++
| source is precompiled. If an option is specified more than once, or if two options
| conflict, the last option specified is used.

| Element 1: Cross-Reference Options

| *XREF: The precompiler cross-references items in the program to the statement


| numbers in the program that refer to those items.

| *NOXREF: The precompiler does not cross-reference names.

| Element 2: Decimal Point Options

| *JOB: The value used as the decimal point for numeric constants in SQL is the
| representation of decimal point specified for the job at precompile time.

| Note: If the job decimal point value specifies that the value used as the
| decimal point is a comma, any numeric constants in lists (such as in the
| SELECT clause or the VALUES clause) must be separated by a comma
| followed by a blank. For example, VALUES(1,1, 2,23, 4,1) is equivalent
| to VALUES(1.1,2.23,4.1) in which the decimal point is a period.

| *PERIOD:The value used as the decimal point for numeric constants in SQL
| statements is a period.

| *COMMA: The value used as the decimal point for numeric constants in SQL
| statements is a comma.

| Note: Any numeric constants in lists (such as in the SELECT clause or the
| VALUES clause) must be separated by a comma followed by a blank.
| For example, VALUES(1,1, 2,23, 4,1) is equivalent to
| VALUES(1.1,2.23,4.1) where the decimal point is a period.

| Element 3: Naming Convention Options

| *SYS: The system naming convention (library-name/file-name) is used.

| *SQL: The SQL naming convention is used (collection-name.table-name). When


| creating a package on a remote database other than an AS/400 system, *SQL
| must be specified as the naming convention.

| Element 4: Second-Level Message Text Option

| *NOSECLVL: Second-level text descriptions are not added to the listing.

| *SECLVL: Second-level text with replacement data is added for all messages
| on the listing.

| Element 5: NUL Required Options

770 DB2 UDB for AS/400 SQL Programming V4R4


CVTSQLCPP
| *NOCNULRQD: For output character and graphic host variables, the
| NUL-terminator is not returned when the host variable is exactly the same
| length as the data. Input character and graphic host variables do not require a
| NUL-terminator.

| *CNULRQD: Output character and graphic host variables always contain the
| NUL-terminator. If there is not enough space for the NUL-terminator, the data is
| truncated and the NUL-terminator is added. Input character and graphic host
| variables require a NUL-terminator.

| Element 6: Event File Creation

| *NOEVENTF: The compiler will not produce an event file for use by
| CoOperative Development Environment/400 (CODE/400).

| *EVENTF: The compiler produces an event file for use by CoOperative


| Development Environment/400 (CODE/400). The event file will be created as a
| member in the file EVFEVENT in your source library. CODE/400 uses this file to
| offer error feedback integrated with the CODE/400 editor. This option is
| normally specified by CODE/400 on your behalf.

| Element 7: Large Object Optimization for DRDA

| *OPTLOB: The first FETCH for a cursor determines how the cursor will be used
| for LOBs (Large Objects) on all subsequent FETCHes. This option remains in
| effect until the cursor is closed.

| If the first FETCH uses a LOB locator to access a LOB column, no subsequent
| FETCH for that cursor can fetch that LOB column into a LOB host variable.

| If the first FETCH places the LOB column into a LOB host variable, no
| subsequent FETCH for that cursor can use a LOB locator for that column.

| *NOOPTLOB: There is no restriction on whether a column is retrieved into a


| LOB locator or into a LOB host variable. This option can cause performance to
| degrade.
| TGTRLS
| Specifies the release of the operating system on which the user intends to use
| the object being created.

| In the examples given for the *CURRENT and *PRV values, and when
| specifying the release-level value, the format VxRxMx is used to specify the
| release, where Vx is the version, Rx is the release, and Mx is the modification
| level. For example, V2R3M0 is version 2, release 3, modification level 0.

| *CURRENT: The object is to be used on the release of the operating system


| currently running on the user’s system. For example, if V2R3M5 is running on
| the system, *CURRENT means the user intends to use the object on a system
| with V2R3M5 installed. The user can also use the object on a system with any
| subsequent release of the operating system installed.

| Note: If V2R3M5 is running on the system, and the object is to be used on a


| system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
| TGTRLS(*CURRENT).

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 771


CVTSQLCPP
| release-level: Specify the release in the format VxRxMx. The object can be
| used on a system with the specified release or with any subsequent release of
| the operating system installed.

| Valid values depend on the current version, release, and modification level, and
| they change with each new release. If you specify a release-level which is
| earlier than the earliest release level supported by this command, an error
| message is sent indicating the earliest supported release.
| INCFILE
| Specifies the qualified name of the source file that contains members included
| in the program with any SQL INCLUDE statement.

| The name of the source file can be qualified by one of the following library
| values:
| *LIBL: All libraries in the job’s library list are searched until the first match is
| found.
| *CURLIB: The current library for the job is searched. If no library is specified
| as the current library for the job, the QGPL library is used.
| library-name: Specify the name of the library to be searched.

| *SRCFILE: The qualified source file specified in the SRCFILE parameter


| contains the source file members specified on any SQL INCLUDE statement.

| source-file-name: Specify the name of the source file that contains the source
| file members specified on any SQL INCLUDE statement. The record length of
| the source file specified here must be no less than the record length of the
| source file specified on the SRCFILE parameter.
| COMMIT
| Specifies whether SQL statements in the compiled unit are run under
| commitment control. Files referred to in the host language source are not
| affected by this option. Only SQL tables, SQL views, and SQL packages
| referred to in SQL statements are affected.

| *CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,


| COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
| REVOKE statements and the rows updated, deleted, and inserted are locked
| until the end of the unit of work (transaction). Uncommitted changes in other
| jobs can be seen.

| *ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


| COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
| REVOKE statements and the rows selected, updated, deleted, and inserted are
| locked until the end of the unit of work (transaction). Uncommitted changes in
| other jobs cannot be seen.

| *CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
| CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
| the rows updated, deleted, and inserted are locked until the end of the unit of
| work (transaction). A row that is selected, but not updated, is locked until the
| next row is selected. Uncommitted changes in other jobs cannot be seen.

| *NONE or *NC: Specifies that commitment control is not used. Uncommitted


| changes in other jobs can be seen. If the SQL DROP COLLECTION statement
| is included in the program, *NONE or *NC must be used. If a relational

772 DB2 UDB for AS/400 SQL Programming V4R4


CVTSQLCPP
| database is specified on the RDB parameter and the relational database is on a
| system that is not on an AS/400, *NONE or *NC cannot be specified.

| *RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
| CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
| the rows selected, updated, deleted, and inserted are locked until the end of the
| unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
| All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
| are locked exclusively until the end of the unit of work (transaction).
| CLOSQLCSR
| Specifies when SQL cursors are implicitly closed, SQL prepared statements are
| implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
| explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
| HOLD) SQL statements.

| *ENDACTGRP: SQL cursors are closed, SQL prepared statements are implicitly
| discarded, and LOCK TABLE locks are released when the activation group
| ends.

| *ENDMOD: SQL cursors are closed and SQL prepared statements are implicitly
| discarded when the module is exited. LOCK TABLE locks are released when
| the first SQL program on the call stack ends.
| ALWCPYDTA
| Specifies whether a copy of the data can be used in a SELECT statement.

| *OPTIMIZE: The system determines whether to use the data retrieved directly
| from the database or to use a copy of the data. The decision is based on which
| method provides the best performance. If COMMIT is *CHG or *CS and
| ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
| data is used only when it is necessary to run a query.

| *YES: A copy of the data is used only when necessary.

| *NO: A copy of the data is not allowed. If a temporary copy of the data is
| required to perform the query, an error message is returned.
| ALWBLK
| Specifies whether the database manager can use record blocking, and the
| extent to which blocking can be used for read-only cursors.

| *ALLREAD: Rows are blocked for read-only cursors if *NONE or *CHG is


| specified on the COMMIT parameter. All cursors in a program that are not
| explicitly able to be updated are opened for read-only processing even though
| EXECUTE or EXECUTE IMMEDIATE statements may be in the program.

| Specifying *ALLREAD:
| v Allows record blocking under commitment control level *CHG in addition to
| the blocking allowed for *READ.
| v Can improve the performance of almost all read-only cursors in programs,
| but limits queries in the following ways:
| – The Rollback (ROLLBACK) command, a ROLLBACK statement in host
| languages, or the ROLLBACK HOLD SQL statement does not reposition a
| read-only cursor when *ALLREAD is specified.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 773


CVTSQLCPP
| – Dynamic running of a positioned UPDATE or DELETE statement (for
| example, using EXECUTE IMMEDIATE), cannot be used to update a row
| in a cursor unless the DECLARE statement for the cursor includes the
| FOR UPDATE clause.

| *NONE: Rows are not blocked for retrieval of data for cursors.

| Specifying *NONE:
| v Guarantees that the data retrieved is current.
| v May reduce the amount of time required to retrieve the first row of data for a
| query.
| v Stops the database manager from retrieving a block of data rows that is not
| used by the program when only the first few rows of a query are retrieved
| before the query is closed.
| v Can degrade the overall performance of a query that retrieves a large
| number of rows.

| *READ: Records are blocked for read-only retrieval of data for cursors when:
| v *NONE is specified on the COMMIT parameter, which indicates that
| commitment control is not used.
| v The cursor is declared with a FOR READ ONLY clause or there are no
| dynamic statements that could run a positioned UPDATE or DELETE
| statement for the cursor.

| Specifying *READ can improve the overall performance of queries that meet the
| above conditions and retrieve a large number of records.
| DLYPRP
| Specifies whether the dynamic statement validation for a PREPARE statement
| is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
| validation improves performance by eliminating redundant validation.

| *NO: Dynamic statement validation is not delayed. When the dynamic


| statement is prepared, the access plan is validated. When the dynamic
| statement is used in an OPEN or EXECUTE statement, the access plan is
| revalidated. Because the authority or the existence of objects referred to by the
| dynamic statement may change, you must still check the SQLCODE or
| SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
| dynamic statement is still valid.

| *YES: Dynamic statement validation is delayed until the dynamic statement is


| used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
| dynamic statement is used, the validation is completed and an access plan is
| built. If you specify *YES on this parameter, you should check the SQLCODE
| and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
| ensure that the dynamic statement is valid.

| Note: If you specify *YES, performance is not improved if the INTO clause is
| used on the PREPARE statement or if a DESCRIBE statement uses the
| dynamic statement before an OPEN is issued for the statement.
| GENLVL
| Specifies the severity level at which the create operation fails. If errors occur
| that have a severity level greater than this value, the operation ends.

774 DB2 UDB for AS/400 SQL Programming V4R4


CVTSQLCPP
| 10: The default severity level is 10.

| severity-level: Specify a value ranging from 0 through 40.


| MARGINS
| Specifies the part of the precompiler input record that contains source text.

| *SRCFILE: The file member margin values specified by the user on the
| SRCMBR parameter are used. The margin default values are 1 and 80.

| Element 1: Left Margin

| left: Specify the beginning position for the statements. Valid values range from 1
| through 80.

| Element 2: Right Margin

| right: Specify the ending position for the statements. Valid values range from 1
| through 80.
| DATFMT
| Specifies the format used when accessing date result columns. All output date
| fields are returned in the specified format. For input date strings, the specified
| value is used to determine whether the date is specified in a valid format.

| Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
| always valid.

| If a relational database is specified on the RDB parameter and the


| database is on a system that is not an AS/400 system, then *USA, *ISO,
| *EUR, or *JIS must be specified.

| *JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
| command to determine the current date format for the job.

| *USA: The United States date format (mm/dd/yyyy) is used.

| *ISO: The International Organization for Standardization (ISO) date format


| (yyyy-mm-dd) is used.

| *EUR: The European date format (dd.mm.yyyy) is used.

| *JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

| *MDY: The date format (mm/dd/yy) is used.

| *DMY: The date format (dd/mm/yy) is used.

| *YMD: The date format (yy/mm/dd) is used.

| *JUL: The Julian date format (yy/ddd) is used.


| DATSEP
| Specifies the separator used when accessing date result columns.

| Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
| specified on the DATFMT parameter.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 775


CVTSQLCPP
| *JOB:The date separator specified for the job at precompile time is used. Use
| the Display Job (DSPJOB) command to determine the current value for the job.

| ’/’: A slash (/) is used.

| ’.’: A period (.) is used.

| ’,’: A comma (,) is used.

| ’-’: A dash (-) is used.

| ’ ’: A blank ( ) is used.

| *BLANK: A blank ( ) is used.


| TIMFMT
| Specifies the format used when accessing time result columns. For input time
| strings, the specified value is used to determine whether the time is specified in
| a valid format.

| Note: An input time string that uses the format *USA, *ISO, *EUR, or *JIS is
| always valid.

| If a relational database is specified on the RDB parameter and the


| database is on a system that is not another AS/400 system, the time
| format must be *USA, *ISO, *EUR, *JIS, or *HMS with a time separator
| of colon or period.

| *HMS: The hh:mm:ss format is used.

| *USA: The United States time format hh:mm xx is used, where xx is AM or


| PM.

| *ISO: The International Organization for Standardization (ISO) time format


| hh.mm.ss is used.

| *EUR: The European time format hh.mm.ss is used.

| *JIS: The Japanese Industrial Standard time format hh:mm:ss is used.


| TIMSEP
| Specifies the separator used when accessing time result columns.

| Note: This parameter applies only when *HMS is specified on the TIMFMT
| parameter.

| *JOB: The time separator specified for the job at precompile time is used. Use
| the Display Job (DSPJOB) command to determine the current value for the job.

| ’:’: A colon (:) is used.

| ’.’: A period (.) is used.

| ’,’: A comma (,) is used.

| ’ ’: A blank ( ) is used.

776 DB2 UDB for AS/400 SQL Programming V4R4


CVTSQLCPP
| *BLANK: A blank ( ) is used.
| RDB
| Specifies the name of the relational database where the SQL package object is
| created.

| *LOCAL: The program is created as a distributed SQL program. The SQL


| statements will access the local database. An SQL package object is not
| created as part of the precompile process. The Create Structured Query
| Language Package (CRTSQLPKG) command can be used.

| relational-database-name: Specify the name of the relational database where


| the new SQL package object is to be created. When the name of the local
| relational database is specified, the program created is still a distributed SQL
| program. The SQL statements will access the local database.

| *NONE: An SQL package object is not created. The program object is not a
| distributed program and the Create Structured Query Language Package
| (CRTSQLPKG) command cannot be used.
| USER
| Specifies the user name sent to the remote system when starting the
| conversation. This parameter is valid only when RDB is specified.

| *CURRENT: The user profile under which the current job is running is used.

| user-name: Specify the user name being used for the application server job.
| PASSWORD
| Specifies the password to be used on the remote system. This parameter is
| valid only if RDB is specified.

| *NONE: No password is sent. If this value is specified, USER(*CURRENT)


| must also be specified.

| password: Specify the password of the user name specified on the USER
| parameter.
| RDBCNNMTH
| Specifies the semantics used for CONNECT statements. Refer to the SQL
| Reference, SC41-3612 book for more information.

| *DUW: CONNECT (Type 2) semantics are used to support distributed unit of


| work. Consecutive CONNECT statements to additional relational databases do
| not result in disconnection of previous connections.

| *RUW: CONNECT (Type 1) semantics are used to support remote unit of work.
| Consecutive CONNECT statements result in the previous connection being
| disconnected before a new connection is established.
| DFTRDBCOL
| Specifies the collection name used for the unqualified names of tables, views,
| indexes, and SQL packages. This parameter applies only to static SQL
| statements.

| *NONE: The naming convention defined on the OPTION parameter is used.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 777


CVTSQLCPP
| collection-name: Specify the name of the collection identifier. This value is used
| instead of the naming convention specified on the OPTION parameter.
| DYNDFTCOL
| Specifies whether the default collection name specified for the DFTRDBCOL
| parameter is also used for dynamic statements.

| *NO: Do not use the value specified on the DFTRDBCOL parameter for
| unqualified names of tables, views, indexes, and SQL packages for dynamic
| SQL statements. The naming convention specified on the OPTION parameter is
| used.

| *YES: The collection name specified on the DFTRDBCOL parameter will be


| used for the unqualified names of the tables, views, indexes, and SQL
| packages in dynamic SQL statements.
| SQLPKG
| Specifies the qualified name of the SQL package created on the relational
| database specified on the RDB parameter of this command.

| The possible library values are:


| *OBJLIB: The package is created in the library with the same name as the
| library specified on the OBJ parameter.
| library-name: Specify the name of the library where the package is created.

| *OBJ: The name of the SQL package is the same as the object name specified
| on the OBJ parameter.

| package-name: Specify the name of the SQL package. If the remote system is
| not an AS/400 system, no more than 8 characters can be specified.
| SQLPATH
| Specifies the path to be used to find procedures, functions, and user defined
| types in static SQL statements.

| *NAMING: The path used depends on the naming convention specified on the
| OPTION parameter.

| For *SYS naming, the path used is *LIBL, the current library list at runtime.

| For *SQL naming, the path used is ″QSYS″, ″QSYS2″, ″userid″, where ″userid″
| is the value of the USER special register. If a collection-name is specified on
| the DFTRDBCOL parameter, the collection-name takes the place of userid.

| *LIBL: The path used is the library list at runtime.

| collection-name: Specify a list of one or more collection names. A maximum of


| 43 individual collections may be specified.
| SAAFLAG
| Specifies the IBM SQL flagging function. This parameter flags SQL statements
| to verify whether they conform to IBM SQL syntax More information about
| which IBM database products IBM SQL syntax is in the DRDA IBM SQL
| Reference, SC26-3255-00.

| *NOFLAG: The precompiler does not check to see whether SQL statements
| conform to IBM SQL syntax.

778 DB2 UDB for AS/400 SQL Programming V4R4


CVTSQLCPP
| *FLAG: The precompiler checks to see whether SQL statements conform to
| IBM SQL syntax
| FLAGSTD
| Specifies the American National Standards Institute (ANSI) flagging function.
| This parameter flags SQL statements to verify whether they conform to the
| following standards.
| ANSI X3.135-1992 entry
| ISO 9075-1992 entry
| FIPS 127.2 entry

| *NONE: The precompiler does not check to see whether SQL statements
| conform to ANSI standards.

| *ANS: The precompiler checks to see whether SQL statements conform to


| ANSI standards.
| DBGVIEW
| This parameter specifies the type of source debug information to be provided by
| the SQL precompiler.

| *NONE: The source view will not be generated.

| *SOURCE: The SQL precompiler provides the source views for the root and if
| necessary, SQL INCLUDE statements. A view is provided that contains the
| statements generated by the precompiler.
| USRPRF
| Specifies the user profile that is used when the compiled program object is run,
| including the authority that the program object has for each object in static SQL
| statements. The profile of either the program owner or the program user is used
| to control which objects can be used by the program object.

| *NAMING: The user profile is determined by the naming convention. If the


| naming convention is *SQL, USRPRF(*OWNER) is used. If the naming
| convention is *SYS, USRPRF(*USER) is used.

| *USER: The profile of the user running the program object is used.

| *OWNER: The user profiles of both the program owner and the program user
| are used when the program is run.
| DYNUSRPRF
| Specifies the user profile to be used for dynamic SQL statements.

| *USER: Local dynamic SQL statements are run under the profile of the
| program’s user. Distributed dynamic SQL statements are run under the profile
| of the SQL package’s user.

| *OWNER: Local dynamic SQL statements are run under the profile of the
| program’s owner. Distributed dynamic SQL statements are run under the profile
| of the SQL package’s owner.
| SRTSEQ
| Specifies the sort sequence table to be used for string comparisons in SQL
| statements.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 779


CVTSQLCPP
| Note: *HEX must be specified for this parameter on distributed applications
| where the application server is not on an AS/400 system or the release
| level is prior to V2R3M0.

| *JOB: The SRTSEQ value for the job is retrieved during the precompile.

| *JOBRUN: The SRTSEQ value for the job is retrieved when the program is run.
| For distributed applications, SRTSEQ(*JOBRUN) is valid only when
| LANGID(*JOBRUN) is also specified.

| *HEX: A sort sequence table is not used. The hexadecimal values of the
| characters are used to determine the sort sequence.

| *LANGIDSHR: The sort sequence table uses the same weight for multiple
| characters, and is the shared-weight sort sequence table associated with the
| language specified on the LANGID parameter.

| *LANGIDUNQ: The unique-weight sort table for the language specified on the
| LANGID parameter is used.

| The name of the table name can be qualified by one of the following library
| values:
| *LIBL: All libraries in the job’s library list are searched until the first match is
| found.
| *CURLIB: The current library for the job is searched. If no library is specified
| as the current library for the job, the QGPL library is used.
| library-name: Specify the name of hte library to be searched.

| table-name: Specify the name of the sort sequence table to be used.


| LANGID
| Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
| SRTSEQ(*LANGIDSHR) is specified.

| *JOB: The LANGID value for the job is retrieved during the precompile.

| *JOBRUN: The LANGID value for the job is retrieved when the program is run.
| For distributed applications, LANGID(*JOBRUN) is valid only when
| SRTSEQ(*JOBRUN) is also specified.

| language-identifier: Specify a language identifier.


| OUTPUT
| Specifies whether the precompiler listing is generated.

| *NONE: The precompiler listing is not generated.

| *PRINT: The precompiler listing is generated.


| PRTFILE
| Specifies the qualified name of the printer device file to which the precompiler
| printout is directed. The file must have a minimum length of 132 bytes. If a file
| with a record length of less than 132 bytes is specified, information is lost.

| The name of the printer file can be qualified by one of the following library
| values:

780 DB2 UDB for AS/400 SQL Programming V4R4


CVTSQLCPP
| *LIBL: All libraries in the job’s library list are searched until the first match is
| found.
| *CURLIB: The current library for the job is searched. If no library is specified
| as the current library for the job, the QGPL library is used.
| library-name: Specify the name of the library to be searched.

| QSYSPRT: If a file name is not specified, the precompiler printout is directed to


| the IBM-supplied printer file QSYSPRT.

| printer-file-name: Specify the name of the printer device file to which the
| precompiler printout is directed.
| TEXT
| Specifies the text that briefly describes the program and the function. More
| information on this parameter is in Appendix A, ″Expanded Parameter
| Descriptions″ in the CL Reference book.

| *SRCMBRTXT: The text is taken from the source file member being used as
| the text for the output source member. Text can be added or changed for a
| database source member by using the Start Source Entry Utility (STRSEU)
| command, or by using either the Add Physical File Member (ADDPFM)
| command or the Change Physical File Member (CHGPFM) command. If the
| source file is an inline file or a device file, the text is blank.

| *BLANK: Text is not specified.

| ’description’: Specify no more than 50 characters of text, enclosed in


| apostrophes.

| Example
| CVTSQLCPP SRCFILE(PAYROLL) SRCMBR(PAYROLL)
| TOSRCFILE(MYLIB/MYSRCFILE) TEXT('Payroll Program')

| This command runs the SQL precompiler which precompiles the source and stores
| the changed source in member PAYROLL in file MYSRCFILE in library MYLIB. No
| module or program object is created.

DLTSQLPKG (Delete Structured Query Language Package) Command


Job: B,I Pgm: B,I REXX: B,I Exec

ÊÊ DLTSQLPKG Ê

*LIBL/ (1)
Ê SQLPKG( SQL-package-name ) ÊÍ
*CURLIB/ generic*-SQL-package name
*USRLIBL/
*ALL/
*ALLUSR/
library-name/

Notes:
1. All parameters preceding this point can be specified in positional form.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 781


DLTSQLPKG
Purpose
The Delete Structured Query Language Package (DLTSQLPKG) command is used
to delete one or more SQL packages.

DLTSQLPKG is a local command and must be used on the AS/400 system where
the SQL package being deleted is located.

To delete an SQL package on a remote system that is also an AS/400 system, use
the Submit Remote Command (SBMRMTCMD) command to run the DLTSQLPKG
command on the remote system.

The user can do the following to delete an SQL package from a remote system that
is not an AS/400 system:
v Use interactive SQL to run the CONNECT and DROP PACKAGE operations.
v Sign on the remote system and use a command local to that system.
v Create and run an SQL program that contains a DROP PACKAGE SQL
statement.

Parameters
SQLPKG
Specifies the qualified name of the SQL package being deleted. A specific or
generic SQL package name can be specified.

The name of the SQL Package can be qualified by one of the following library
values:

*LIBL: All libraries in the job’s library list are searched until the first match is
found.

*CURLIB: The current library for the job is searched. If no library is specified as
the current library for the job, the QGPL library is used.

*USRLIBL: Only the libraries in the user portion of the job’s library list are
searched.

*ALL: All libraries in the system, including QSYS, are searched.

*ALLUSR: All user libraries are searched. All libraries with names that do not
begin with the letter Q are searched except for the following:
#CGULIB #DFULIB #RPGLIB #SEULIB
#COBLIB #DSULIB #SDALIB

Although the following Qxxx libraries are provided by IBM, they typically contain
user data that changes frequently. Therefore, these libraries are considered
user libraries and are also searched:
QDSNX QRCL QUSRBRM QUSRSYS
QGPL QS36F QUSRIJS QUSRVxRxMx
QGPL38 QUSER38 QUSRINFSKR
QPFRDATA QUSRADSM QUSRRDARS

Note: A different library name, of the form QUSRVxRxMx, can be created by


the user for each release that IBM supports. VxRxMx is the version, release,
and modification level of the library.

782 DB2 UDB for AS/400 SQL Programming V4R4


DLTSQLPKG
library-name: Specify the name of the library to be searched.

SQL-package-name: Specify the name of the SQL package being deleted.

generic*-SQL-package-name: Specify the generic name of the SQL package to


be deleted. A generic name is a character string of one or more characters
followed by an asterisk (*); for example, ABC*. If a generic name is specified, all
SQL packages with names that begin with the generic name, and for which the
user has authority, are deleted. If an asterisk is not included with the generic
(prefix) name, the system assumes it to be the complete SQL package name.

Example
DLTSQLPKG SQLPKG(JONES)

This command deletes the SQL package JONES.

PRTSQLINF (Print Structured Query Language Information) Command


Job: B,I Pgm: B,I REXX: B,I Exec

*LIBL/
ÊÊ PRTSQLINF OBJ( object-name ) Ê
*CURLIB/
library-name/

(1)
Ê ÊÍ
*PGM
OBJTYPE( *SQLPKG )
*SRVPGM

Notes:
1. All parameters preceding this point can be specified in positional form.

Purpose
The Print Structured Query Language Information (PRTSQLINF) command prints
information about the embedded SQL statements in a program, SQL package, or
service program. The information includes the SQL statements, the access plans
used during the running of the statement, and a list of the command parameters
used to precompile the source member for the object.

Parameters
OBJ
Specifies the name of the program or SQL package for which you want SQL
information printed.

The name of the object can be qualified by one of the following library values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 783


PRTSQLINF
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the program or SQL package for which
you want information printed.

object-name: Specify the name of the program or SQL package for which you
want information printed.
OBJTYPE
Specifies the type of object.

*PGM: The object is a program.

*SQLPKG: The object is an SQL package.

*SRVPGM: The object is a service program.

Example
Example 1: Printing SQL Information
PRTSQLINF PAYROLL

This command will print information about the SQL statements contained in program
PAYROLL.

RUNSQLSTM (Run Structured Query Language Statement) Command


Job: B,I Pgm: B,I REXX: B,I Exec

*LIBL/
ÊÊ RUNSQLSTM SRCFILE ( source-file-name ) Ê
*CURLIB/
library-name/

(1)
Ê SRCMBR ( source-file-member-name ) Ê
*UR
*CHG
COMMIT ( *ALL )
*RS
*CS
*NONE
*NC
*RR

Ê Ê
*SYS *RUN
NAMING ( *SQL ) PROCESS( *SYN )

Ê Ê
*OPTIMIZE *ALLREAD
ALWCPYDTA ( *YES ) ALWBLK ( *NONE )
*NO *READ

784 DB2 UDB for AS/400 SQL Programming V4R4


RUNSQLSTM
Ê Ê
10 *JOB
ERRLVL ( severity-level ) DATFMT ( *USA )
*ISO
*EUR
*JIS
*MDY
*DMY
*YMD
*JUL

Ê Ê
*JOB *HMS
DATSEP ( '/' ) TIMFMT ( *USA )
'.' *ISO
',' *EUR
'-' *JIS
' '
*BLANK

Ê Ê
*JOB *SYSVAL
TIMSEP ( ':' ) *JOB
'.' DECMPT ( *PERIOD )
',' *COMMA
' '
*BLANK

Ê Ê
*JOB
SRTSEQ ( *LANGIDUNQ )
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

Ê Ê
*JOB
LANGID ( language-identifier )

Ê Ê
*NONE *NONE
DFTRDBCOL ( collection-name ) FLAGSTD ( *ANS )

Ê Ê
*NOFLAG
SAAFLAG ( *FLAG )

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 785


RUNSQLSTM
Ê ÊÍ
*LIBL/ QSYSPRT
PRTFILE ( printer-file-name )
*CURLIB/
library-name/

SQL-procedure-parameters:

Ê
*CURRENT *ENDACTGRP
TGTRLS ( VxRxMx ) CLOSQLCSR ( *ENDMOD )

Ê Ê
*NONE *NONE
OUTPUT ( *PRINT ) DBGVIEW ( *STMT )
*LIST

Ê Ê
*NAMING *USER
USRPRF ( *OWNER ) DYNUSRPRF ( *OWNER )
*USER

Ê
*NO
DLYPRP ( *YES )

Notes:
1. All parameters preceding this point can be specified in positional form.

Purpose
The Run Structured Query Language Statement (RUNSQLSTM) command
processes a source file of SQL statements.

Parameters
SRCFILE
Specifies the qualified name of the source file that contains the SQL statements
to be run.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

source-file-name: Specify the name of the source file that contains the SQL
statements to be run. The source file can be a database file or an inline data
file.

786 DB2 UDB for AS/400 SQL Programming V4R4


RUNSQLSTM
SRCMBR
Specifies the name of the source file member that contains the SQL statements
to be run.
COMMIT
Specifies whether SQL statements in the source file are run under commitment
control.

*CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows updated, deleted, and inserted are locked
until the end of the unit of work (transaction). Uncommitted changes in other
jobs can be seen.

*ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows selected, updated, deleted, and inserted are
locked until the end of the unit of work (transaction). Uncommitted changes in
other jobs cannot be seen.

*CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows updated, deleted, and inserted are locked until the end of the unit of
work (transaction). A row that is selected, but not updated, is locked until the
next row is selected. Uncommitted changes in other jobs cannot be seen.

*NONE or *NC: Specifies that commitment control is not used. Uncommitted


changes in other jobs can be seen. If the SQL DROP COLLECTION statement
is included in the program, *NONE or *NC must be used. If a relational
database is specified on the RDB parameter and the relational database is on a
system that is not on an AS/400, *NONE or *NC cannot be specified.

*RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows selected, updated, deleted, and inserted are locked until the end of the
unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
are locked exclusively until the end of the unit of work (transaction).
NAMING
Specifies the naming convention used for naming objects in SQL statements.

*SYS: The system naming convention (library-name/file-name) is used.

*SQL: The SQL naming convention (collection-name.table-name) is used.


PROCESS
Specifies whether SQL statements in the source file member are executed or
syntax-checked only.

*RUN: Statement are syntax-checked and run.

*SYN: Statements are syntax-checked only.


ALWCPYDTA
Specifies whether a copy of the data can be used in a SELECT statement.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 787


RUNSQLSTM
*OPTIMIZE: The system determines whether to use the data retrieved directly
from the database or to use a copy of the data. The decision is based on which
method provides the best performance. If COMMIT is *CHG or *CS and
ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
data is used only when it is necessary to run a query.

*YES: A copy of the data is used only when necessary.

*NO: A copy of the data is not used. If temporary copy of the data is required to
perform the query, an error message is returned.
ALWBLK
Specifies whether the database manager can use record blocking, and the
extent to which blocking can be used for read-only cursors.

*ALLREAD: Rows are blocked for read-only cursors if *NONE or *CHG is


specified on the COMMIT parameter. All cursors in a program that are not
explicitly able to be updated are opened for read-only processing even though
EXECUTE or EXECUTE IMMEDIATE statements may be in the program.

Specifying *ALLREAD:
v Allows record blocking under commitment control level *CHG in addition to
the blocking allowed for *READ.
v Can improve the performance of almost all read-only cursors in programs,
but limits queries in the following ways:
– The Rollback (ROLLBACK) command, a ROLLBACK statement in host
languages, or the ROLLBACK HOLD SQL statement does not reposition a
read-only cursor when *ALLREAD is specified.
– Dynamic running of a positioned UPDATE or DELETE statement (for
example, using EXECUTE IMMEDIATE), cannot be used to update a row
in a cursor unless the DECLARE statement for the cursor includes the
FOR UPDATE clause.

*NONE: Rows are not blocked for retrieval of data for cursors.

Specifying *NONE:
v Guarantees that the data retrieved is current.
v May reduce the amount of time required to retrieve the first row of data for a
query.
v Stops the database manager from retrieving a block of data rows that is not
used by the program when only the first few rows of a query are retrieved
before the query is closed.
v Can degrade the overall performance of a query that retrieves a large
number of rows.

*READ: Records are blocked for read-only retrieval of data for cursors when:
v *NONE is specified on the COMMIT parameter, which indicates that
commitment control is not used.
v The cursor is declared with a FOR FETCH ONLY clause or there are no
dynamic statements that could run a positioned UPDATE or DELETE
statement for the cursor.

Specifying *READ can improve the overall performance of queries that meet the
above conditions and retrieve a large number of records.

788 DB2 UDB for AS/400 SQL Programming V4R4


RUNSQLSTM
ERRLVL
Specifies whether the processing is successful, based on the severity of the
messages generated by the processing of the SQL statements. If errors that are
greater than the value specified on this parameter occur during processing, no
more statements are processed and the statements are rolled back if they are
running under commitment control.

10: Statement processing is stopped when error messages with a severity level
greater than 10 are received.

severity-level: Specify the severity level to be used.


DATFMT
Specifies the format used when accessing date result columns. For input date
strings, the specified value is used to determine whether the date is specified in
a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

*JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
command to determine the current date format for the job.

*USA: The United States date format (mm/dd/yyyy) is used.

*ISO: The International Organization for Standardization (ISO) date format


(yyyy-mm-dd) is used.

*EUR: The European date format (dd.mm.yyyy) is used.

*JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

*MDY: The date format (mm/dd/yy) is used.

*DMY: The date format (dd/mm/yy) is used.

*YMD: The date format (yy/mm/dd) is used.

*JUL: The Julian date format (yy/ddd) is used.


DATSEP
Specifies the separator used when accessing date result columns.

Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
specified on the DATFMT parameter.

*JOB: The date separator specified for the job is used. Use the Display Job
(DSPJOB) command to determine the current value for the job.

’/’: A slash (/) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’-’: A dash (-) is used.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 789


RUNSQLSTM
’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


TIMFMT
Specifies the format used when accessing time result columns. For input time
strings, the specified value is used to determine whether the time is specified in
a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

*HMS: The hh:mm:ss format is used.

*USA: The United States time format hh:mm xx is used, where xx is AM or PM.

*ISO: The International Organization for Standardization (ISO) time format


hh.mm.ss is used.

*EUR: The European time format hh.mm.ss is used.

*JIS: The Japanese Industrial Standard time format hh:mm:ss is used.


TIMSEP
Specifies the separator used when accessing time result columns.

Note: This parameter applies only when *HMS is specified on the TIMFMT
parameter.

*JOB: The time separator specified for the job is used. Use the Display Job
(DSPJOB) command to determine the current value for the job.

’:’: A colon (:) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


DECMPT
Specifies the decimal point value used for numeric constants in SQL
statements.

*JOB: The value used as the decimal point for numeric constants in SQL is the
representation of decimal point specified by the job running the statement.

*SYSVAL: The QDECFMT system value is used as the decimal point.

*PERIOD: A period represents the decimal point.

*COMMA: A comma represents the decimal point.


SRTSEQ
Specifies the sort sequence table to be used for string comparisons in SQL
statements.

790 DB2 UDB for AS/400 SQL Programming V4R4


RUNSQLSTM
*JOB: The LANGID value for the job is retrieved.

*LANGIDSHR: The sort sequence table uses the same weight for multiple
characters, and is the shared-weight sort sequence table associated with the
language specified on the LANGID parameter.

*LANGIDUNQ: The unique-weight sort table for the language specified on the
LANGID parameter is used.

*HEX: A sort sequence table is not used. The hexadecimal values of the
characters are used to determine the sort sequence.

The name of the table name can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

table-name: Specify the name of the sort sequence table to be used.


LANGID
Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
SRTSEQ(*LANGIDSHR) is specified.

*JOB: The LANGID value for the job is retrieved during the precompile.

language-identifier: Specify a language identifier.


DFTRDBCOL
Specifies the collection name used for the unqualified names of tables, views,
indexes, and SQL packages. This parameter applies only to static SQL
statements.

*NONE: The naming convention defined on the OPTION parameter is used.

collection-name: Specify the name of the collection identifier. This value is used
instead of the naming convention specified on the OPTION parameter.
FLAGSTD
Specifies the American National Standards Institute (ANSI) flagging function.
This parameter flags SQL statements to verify whether they conform to the
following standards.
ANSI X3.135-1992 entry
ISO 9075-1992 entry
FIPS 127.2 entry

*NONE: The SQL statements are not checked to determine whether they
conform to ANSI standards.

*ANS: The SQL statements are checked to determine whether they conform to
ANSI standards.
SAAFLAG
Specifies the IBM SQL flagging function. This parameter flags SQL statements

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 791


RUNSQLSTM
to verify whether they conform to IBM SQL syntax More information about
which IBM database products IBM SQL syntax is in the DRDA IBM SQL
Reference, SC26-3255-00.

*NOFLAG: The SQL statements are not checked to determine whether they
conform to IBM SQL syntax.

*FLAG: The SQL statements are checked to determine whether they conform to
IBM SQL syntax.
PRTFILE
Specifies the qualified name of the printer device file to which the RUNSQLSTM
printout is directed. The file must have a minimum length of 132 bytes. If a file
with a record length of less than 132 bytes is specified, information is lost.

The name of the printer file can be qualified by one of hte following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QSYSPRT: If a file name is not specified, the RUNSQLSTM printout is directed


to the IBM-supplied printer file QSYSPRT.

printer-file-name: Specify the name of the printer device file to which the
RUNSQLSTM printout is directed.

Parameters for SQL procedures


The parameters listed below only apply to statements within the source file that
create SQL procedures. The parameters are used during the creation of the
program object associated with the SQL procedure.
TGTRLS
Specifies the release of the operating system on which the user intends to use
the object being created.

In the examples given for the *CURRENT value, and when specifying the
release-level value, the format VxRxMx is used to specify the release, where Vx
is the version, Rx is the release, and Mx is the modification level. For example,
V2R3M0 is version 2, release 3, modification level 0.

*CURRENT The object is to be used on the release of the operating system


currently running on the user’s system. For example, if V2R3M5 is running on
the system, *CURRENT means the user intends to use the object on a system
with V2R3M5 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

Note: If V2R3M5 is running on the system, and the object is to be used on a


system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
TGRRLS(*CURRENT).

792 DB2 UDB for AS/400 SQL Programming V4R4


RUNSQLSTM
release-level: Specify the release in the format VxRxMx. The object can be
used on a system with the specified release or with any subsequent release of
the operating system installed.

Valid values depend on the current version, release, and modification level, and
they change with each new release. If you specify a release-level which is
earlier than the earliest release level supported by this command, an error
message is sent indicating the earliest supported release.
CLOSQLCSR
Specifies when SQL cursors are implicitly closed, SQL prepared statements are
implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
HOLD) SQL statements.

*ENDACTGRP: SQL cursors are closed and SQL prepared statements are
implicitly discarded.

ENDMOD: SQL cursors are closed and SQL prepared statements are implicitly
discarded when the module is exited. LOCK TABLE locks are released when
the first SQL program on the call stack ends.
OUTPUT
Specifies whether the precompiler listing is generated.

*NONE: The precompiler listing is not generated.

*PRINT: The precompiler listing is generated.


DBGVIEW
Specifies the type of source debug information to be provided by the SQL
precompiler.

*NONE: The source view will not be generated.

*STMT: Allows the compiled module to be debugged using program statement


numbers and symbolic identifiers.

*LIST: Generates the listing view for debugging the compiled module object.
USRPRF
Specifies the user profile that is used when the compiled program object is run,
including the authority that the program object has for each object in static SQL
statements. The profile of either the program owner or the program user is used
to control which objects can be used by the program object.

*NAMING: The user profile is determined by the naming convention. If the


naming convention is *SQL, USRPRF(*OWNER) is used. If the naming
convention is *SYS, USRPRF(*USER) is used.

*USER: The profile of the user running the program object is used.

*OWNER: The user profiles of both the program owner and the program user
are used when the program is run.
DYNUSRPRF
Specifies the user profile to be used for dynamic SQL statements.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 793


RUNSQLSTM
*USER: For local, dynamic SQL statements run under the user of the program’s
user. For distributed, dynamic SQL statements run under the profile of the SQL
package’s user.

*OWNER: For local, dynamic SQL statements run under the profile of the
program’s owner. For distributed, dynamic SQL statements run under the profile
of the SQL package’s owner.
DLYPRP
Specifies whether the dynamic statement validation for a PREPARE statement
is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
validation improves performance by eliminating redundant validation.

*NO: Dynamic statement validation is not delayed. When the dynamic


statement is prepared, the access plan is validated. When the dynamic
statement is used in an OPEN or EXECUTE statement, the access plan is
revalidated. Because the authority or the existence of objects referred to by the
dynamic statement may change, you must still check the SQLCODE or
SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
dynamic statement is still valid.

*YES: Dynamic statement validation is delayed until the dynamic statement is


used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
dynamic statement is used, the validation is completed and an access plan is
built. If you specify *YES on this parameter, you should check the SQLCODE
and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
ensure that the dynamic statement is valid.

Note: If you specify *YES, performance is not improved if the INTO clause is
used on the PREPARE statement or if a DESCRIBE statement uses the
dynamic statement before an OPEN is issued for the statement.

Example
RUNSQLSTM SRCFILE(MYLIB/MYFILE) SRCMBR(MYMBR)

This command processes the SQL statements in member MYMBR found in file
MYFILE in library MYLIB.

STRSQL (Start Structured Query Language) Command


Job: I Pgm: I REXX: I Exec

ÊÊ STRSQL Ê
*NC *SYS
*NONE NAMING( *SQL )
COMMIT( *CHG )
*UR
*CS
*RS
*ALL
*RR

794 DB2 UDB for AS/400 SQL Programming V4R4


STRSQL
Ê Ê
*RUN *LIBL
PROCESS( *VLD ) LIBOPT( *CURLIB )
*SYN *USRLIBL
*ALL
*ALLUSR
library-name

(1)
Ê Ê
*ALL *ALWAYS
LISTTYPE( *SQL ) REFRESH( *FORWARD )

Ê Ê
*YES *JOB
ALWCPYDTA( *OPTIMIZE ) DATFMT( *USA )
*NO *ISO
*EUR
*JIS
*MDY
*DMY
*YMD
*JUL

Ê Ê
(2) *JOB *HMS
DATSEP( *BLANK ) TIMFMT( *USA )
’/’ *ISO
’.’ *EUR
’,’ *JIS
’-’
’ ’

Ê Ê
(3) *JOB *SYSVAL
TIMSEP( *BLANK ) DECPNT( *PERIOD )
’:’ *COMMA
’.’ *JOB
’,’
’ ’

Ê Ê
(4) *NONE
PGMLNG( *C )
*CBL
*PLI
*RPG
*FTN

Ê Ê
(5) (6) *QUOTESQL
SQLSTRDLM( *APOSTSQL )

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 795


STRSQL
Ê Ê
*JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

Ê ÊÍ
*JOB
LANGID( *JOBRUN )
language-ID

Notes:
1. All parameters preceding this point can be specified in positional form.
2. DATSEP is only valid when *MDY, *DMY, *YMD, or *JUL is specified on the
DATFMT parameter.
3. TIMSEP is only valid when TIMFMT(*HMS) is specified.
4. PGMLNG and SQLSTRDLM are valid only when PROCESS(*SYN) is specified.
5. PGMLNG and SQLSTRDLM are valid only when PROCESS(*SYN) is specified.
6. SQLSTRDLM is valid only when PGMLNG(*CBL) is specified.

Purpose
The Start Structured Query Language (STRSQL) command starts the interactive
Structured Query Language (SQL) program. The program starts the statement entry
of the interactive SQL program which immediately shows the Enter SQL Statements
display. This display allows the user to build, edit, enter, and run an SQL statement
in an interactive environment. Messages received during the running of the program
are shown on this display.

Parameters
COMMIT
Specifies whether the SQL statements are run under commitment control.

*NONE or *NC: Specifies that commitment control is not used. Uncommitted


changes in other jobs can be seen. If the SQL DROP COLLECTION statement
is included in the program, *NONE or *NC must be used. If a relational
database is specified on the RDB parameter and the relational database is on a
system that is not on an AS/400, *NONE or *NC cannot be specified.

*CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows updated, deleted, and inserted are locked
until the end of the unit of work (transaction). Uncommitted changes in other
jobs can be seen.

*CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and

796 DB2 UDB for AS/400 SQL Programming V4R4


STRSQL
the rows updated, deleted, and inserted are locked until the end of the unit of
work (transaction). A row that is selected, but not updated, is locked until the
next row is selected. Uncommitted changes in other jobs cannot be seen.

*ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows selected, updated, deleted, and inserted are
locked until the end of the unit of work (transaction). Uncommitted changes in
other jobs cannot be seen.

*RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows selected, updated, deleted, and inserted are locked until the end of the
unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
are locked exclusively until the end of the unit of work (transaction).

Note: The default for this parameter for the CRTSQLXXX commands (when
XXX=CI, CPPI, CBL, FTN, PLI, CBLI, RPG or RPGI) is *CHG.
NAMING
Specifies the naming convention used for naming objects in SQL statements.

*SYS: The system naming convention (library-name/file-name) is used.

*SQL: The SQL naming convention (collection-name.table-name) is used.


PROCESS
Specifies the values used to process the SQL statements.

*RUN: The statements are syntax checked, data checked, and then run.

*VLD: The statements are syntax checked and data checked, but not run.

*SYN: The statements are syntax checked only.


LIBOPT
Specifies which collections and libraries are used as a basis for building a
collection list when the F4, F16, F17, or F18 function key is pressed.

The name of the collection list can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
*USRLIBL: Only the libraries in the user portion of the job’s library list are
searched.
*ALL: All libraries in the system, including QSYS, are searched.
*ALLUSR: All user libraries are searched. All libraries with names that do
not begin with the letter Q are searched except for the following:
#CGULIB #DFULIB #RPGLIB #SEULIB
#COBLIB #DSULIB #SDALIB

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 797


STRSQL
Although the following Qxxx libraries are provided by IBM, they typically
contain user data that changes frequently. Therefore, these libraries are
considered user libraries and are also searched:
QDSNX QRCL QUSRBRM QUSRSYS
QGPL QS36F QUSRIJS QUSRVxRxMx
QGPL38 QUSER38 QUSRINFSKR
QPFRDATA QUSRADSM QUSRRDARS

Note: A different library name, of the form QUSRVxRxMx, can be created


by the user for each release that IBM supports. VxRxMx is the
version, release, and modification level of the library.

library-name: Specify the name of the library to be searched.


LISTTYPE
Specifies the types of objects that are displayed with list support by pressing
the F4, F16, F17, or F18 function key.

*ALL: All objects are displayed.

*SQL: Only SQL-created objects are displayed.


REFRESH
Specifies when the display select output data is refreshed.

*ALWAYS: Data is normally refreshed during forward and backward scrolling.

*FORWARD: Data is refreshed only during forward scrolling to the end of the
data for the first time. When scrolling backward, a copy of the data already
viewed is shown.
ALWCPYDTA
Specifies whether a copy of the data can be used in a SELECT statement. If
COMMIT(*ALL) is specified, SQL run time ignores the ALWCPYDTA value and
uses current data.

*YES: A copy of the data is used when necessary.

*OPTIMIZE: The system determines whether to use the data retrieved from the
database or to use a copy of the data. The determination is based on which will
provide the best performance.

*NO: A copy of the data is not allowed. If a temporary copy of the data is
required to perform the query, an error message is returned.
DATFMT
Specifies the date format used in SQL statements.

*JOB: The format specified on the job attribute DATFMT is used.

*USA: The United States date format (mm/dd/yyyy) is used.

*ISO: The International Standards Organization date format (yyyy-mm-dd) is


used.

*EUR: The European date format (dd.mm.yyyy) is used.

798 DB2 UDB for AS/400 SQL Programming V4R4


STRSQL
*JIS: The Japanese Industry Standard Christian Era date format (yyyy-mm-dd)
is used.

*MDY: The month, day, and year date format (mm/dd/yy) is used.

*DMY: The day, month, and year date format (dd/mm/yy) is used.

*YMD: The year, month, and day date format (yy/mm/dd) is used.

*JUL: The Julian date format (yy/ddd) is used.


DATSEP
Specifies the date separator used in SQL statements.

*JOB: The date separator specified on the job attribute is used. If the user
specifies *JOB on a new interactive SQL session, the current value is stored
and used. Later changes to the job’s date separator are not detected by
interactive SQL.

*BLANK: A blank ( ) is used.

’/’: A slash (/) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’-’: A dash (-) is used.

’ ’: A blank ( ) is used.
TIMFMT
Specifies the time format used in SQL statements.

*HMS: The Hour-Minute-Second time format (hh:mm:ss) is used.

*USA: The United States time format (hh:mm xx, where xx is AM or PM) is
used.

*ISO: The International Standards Organization time format (hh.mm.ss) is used.

*EUR: The European time format (hh.mm.ss) is used.

*JIS: The Japanese Industry Standard Christian Era time format (hh:mm:ss) is
used.
TIMSEP
Specifies the time separator used in SQL statements.

*JOB: The time separator specified on the job attribute is used. If the user
specifies *JOB on a new interactive SQL session, the current value is stored
and used. Later changes to the job’s time separator are not detected by
interactive SQL.

*BLANK: A blank ( ) is used.

’:’: A colon (:) is used.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 799


STRSQL
’.’: A period (.) is used.

’,’: A comma (,) is used.

’ ’: A blank ( ) is used.
DECPNT
Specifies the kind of decimal point to use.

*JOB: The value used as the decimal point for numeric constants in SQL is the
representation of decimal point specified for the job running the statement.

*SYSVAL: The decimal point is extracted from the system value. If the user
specifies *SYSVAL on a new interactive SQL session, the current value is
stored and used. Later changes to the system’s time separator are not detected
by interactive SQL.

*PERIOD: A period represents the decimal point.

*COMMA: A comma represents the decimal point.


PGMLNG
Specifies which program language syntax rules to use. To use this parameter,
*SYN must be selected at the PROCESS parameter.

*NONE: No specific language’s syntax check rules are used.

The supported languages are:

*C: Syntax checking is done according to the C language syntax rules.

*CBL: Syntax checking is done according to the COBOL language syntax rules.

*PLI: Syntax checking is done according to the PL/I language syntax rules.

*RPG: Syntax checking is done according to the RPG language syntax rules.

*FTN: Syntax checking is done according to the FORTRAN language syntax


rules.
SQLSTRDLM
Specifies the SQL string delimiter. Use of this parameter requires using the
COBOL (*CBL) character set.

*QUOTESQL: A quotation mark represents the SQL string delimiter.

*APOSTSQL: An apostrophe represents the SQL string delimiter.


SRTSEQ
Specifies the sort sequence table to be used for string comparisons in SQL
statements on the Enter SQL Statements display.

*JOB: The SRTSEQ value for the job is retrieved.

*JOBRUN: The SRTSEQ value for the job is retrieved each time the user starts
interactive SQL.

800 DB2 UDB for AS/400 SQL Programming V4R4


STRSQL
*LANGIDUNQ: The unique-weight sort table for the language specified on the
LANGID parameter is used.

*LANGIDSHR: The shared-weight sort table for the language specified on the
LANGID parameter is used.

*HEX: A sort sequence table is not used. The hexadecimal values of the
characters are used to determine the sort sequence.

The name of the table name can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

table-name: Specify the name of the sort sequence table to be used with the
interactive SQL session.
LANGID
Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
SRTSEQ(*LANGIDSHR) is specified.

*JOB: The LANGID value for the job is retrieved.

*JOBRUN: The LANGID value for the job is retrieved each time interactive SQL
is started.

language-ID: Specify the language identifier to be used.

Example
STRSQL PROCESS(*SYN) NAMING(*SQL)
DECPNT(*COMMA) PGMLNG(*CBL)
SQLSTRDLM(*APOSTSQL)

This command starts an interactive SQL session that checks only the syntax of SQL
statements. The character set used by the syntax checker uses the COBOL
language syntax rules. The SQL naming convention is used for this session. The
decimal point is represented by a comma, and the SQL string delimiter is
represented by an apostrophe.

Appendix D. DB2 UDB for AS/400 CL Command Descriptions 801


STRSQL

802 DB2 UDB for AS/400 SQL Programming V4R4


Appendix E. Using the C for AS/400 and FORTRAN for AS/400
Precompilers
This appendix contains the syntax diagrams for the C for AS/400 and FORTRAN for
AS/400 precompilers, although these are no longer supported on the AS/400.
Another appendix, “Appendix F. Coding SQL Statements in FORTRAN Applications”
on page 837, describes the unique application and coding requirements for
embedding SQL statements in a FORTRAN/400 program.

Using the C for AS/400 Precompiler


C for AS/400 is no longer a supported compiler for the AS/400 system. This
appendix is intended to help those customers who are using the SQL C for AS/400
precompiler with other non-IBM C compilers. The SQL C for AS/400 precompiler
support is the same as the ILE C for AS/400 precompiler support with the exception
of the information included in this appendix.

Access plans
The SQL C for AS/400 precompiler generates access plan structures that are for
use with non-ILE programs.

Host variable data types


The SQL C for AS/400 precompiler does not support the decimal data type.

Using external file descriptions


You can use the C #pragma mapinc directive with the #include directive to include
external file descriptions in your program. When used with SQL, only a particular
format of the #pragma mapinc directive is recognized by the SQL precompiler. If all
of the required elements are not specified, the precompiler ignores the directive and
does not generate host variable structures. The required elements are:
v Include name
v Externally described file name
v Format name or a list of format names
v Options
v ″p z″ parameter
The library name, union name, and prefix name are optional. Although typedef
statements coded by the user are not recognized by the precompiler, those created
by the #pragma mapinc and #include directives are recognized. Unions declared
using the typedef union created by the #pragma mapinc and #include directive
cannot be used as host variables in SQL statements; the members of the unions
can be used. Structures that contain the typedef structure cannot be used in SQL
statements; the structure declared using the typedef can be used.

To retrieve the definition of the sample table DEPARTMENT described in


Appendix A. DB2 UDB for AS/400 Sample Tables, you can code the following:

© Copyright IBM Corp. 1997, 1999 803


#pragma mapinc ("dept","CORPDATA/DEPARTMENT(*ALL)","both","p z")
#include "dept"
CORPDATA_DEPARTMENT_DEPARTMENT_both_t Dept_Structure;

A host structure named Dept_Structure is defined with the following elements:


DEPTNO, DEPTNAME, MGRNO, and ADMRDEPT. These field names can be used
as host variables in SQL statements.

Note: DATE, TIME, and TIMESTAMP columns generate character host variable
definitions. They are treated by SQL with the same comparison and
assignment rules as a DATE, TIME, and TIMESTAMP column. For example,
a date host variable can only compared against a DATE column or a
character string which is a valid representation of a date.

Although packed, zoned, and binary (with non-zero scale fields) are mapped to
character fields in C, SQL will treat these fields as numeric. By using the extended
program model (EPM) routines, you can manipulate these fields to convert zoned
and packed decimal data. For more information, see the ILE C for AS/400
Language Reference book.

CRTSQLC (Create Structured Query Language C) Command


Job: B,I Pgm: B,I REXX: B,I Exec

*CURLIB/
ÊÊ CRTSQLC PGM( program-name ) Ê
library-name/

Ê Ê
*LIBL/ QCSRC
SRCFILE( source-file-name )
*CURLIB/
library-name/

(1)
Ê Ê
*PGM
SRCMBR( source-file-member-name )

Ê Ê
OPTION( OPTION Details ) *CURRENT
TGTRLS( *PRV )
VxRxMx

Ê Ê
*LIBL/ *SRCFILE
INCFILE( source-file-name )
*CURLIB/
library-name/

804 DB2 UDB for AS/400 SQL Programming V4R4


Ê Ê
*CHG *ENDPGM
COMMIT( *ALL ) CLOSQLCSR( *ENDSQL )
*CS *ENDJOB
*NONE

Ê Ê
*YES *READ
ALWCPYDTA( *OPTIMIZE ) ALWBLK( *NONE )
*NO *ALLREAD

Ê Ê
*NO 10
DLYPRP( *YES ) GENLVL( severity-level )

Ê Ê
*SRCFILE *JOB
MARGINS( left-right ) DATFMT( *USA )
*ISO
*EUR
*JIS
*MDY
*DMY
*YMD
*JUL

Ê Ê
*JOB *HMS
DATSEP( '/' ) TIMFMT( *USA )
'.' *ISO
',' *EUR
'-' *JIS
' '
*BLANK

Ê Ê
*JOB
TIMSEP( ':' )
'.'
','
' '
*BLANK

Ê Ê
*YES *NONE
REPLACE( *NO ) RDB( relational-database-name )

Ê Ê
*CURRENT *NONE
USER( user-name ) PASSWORD( password )

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 805
Ê Ê
*DUW *NONE
RDBCNNMTH( *RUW ) DFTRDBCOL( collection-name )

Ê Ê
*PGMLIB/ *PGM
SQLPKG( package-name )
library-name/

Ê Ê
*NOFLAG *NONE
SAAFLAG( *FLAG ) FLAGSTD( *ANS )

Ê Ê
*LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

Ê Ê
*JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

Ê Ê
*JOB *USER
LANGID( *JOBRUN ) DYNUSRPRF( *OWNER )
language-ID

Ê Ê
QTEMP/ QSQLTEMP
TOSRCFILE source-file-name )
*LIBL/
*CURLIB/
library-name/

Ê ÊÍ
*SRCMBRTXT
TEXT( *BLANK )
'description'

OPTION Details:

806 DB2 UDB for AS/400 SQL Programming V4R4


*NOSRC
*NOSOURCE *NOXREF *NOGEN *JOB *SYS
Ê
*SOURCE *XREF *PERIOD *SQL
*SRC *SYSVAL
*COMMA

*NOSECLVL *NODEBUG *NOCNULRQD *NOLSTDBG


Ê
*SECLVL *DEBUG *CNULRQD *LSTDBG

Notes:
1. All parameters preceding this point can be specified in positional form.

Purpose
The Create Structured Query Language C (CRTSQLC) command calls the
Structured Query Language (SQL) precompiler which precompiles C source
containing SQL statements, produces a temporary source member.

Note: The C for AS/400 Compiler is no longer supported. This CRTSQLC


command is provided for use by other non-IBM C compilers. The supported
IBM compiler is ILE C for AS/400 and the SQL precompiler command is
CRTSQLCI.

Parameters
PGM
Specifies the qualified name of the compiled program.

The name of the compiled C program can be qualified by one of the following
library values:
*CURLIB: The compiled C program is created in the current library for the
job. If no library is specified as the current library for the job, the QGPL
library is used.
library-name: Specify the name of the library where the compiled C program
is created.

program-name: Specify the name of the compiled C program.


SRCFILE
Specifies the qualified name of the source file that contains the C source with
SQL statements.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QCSRC: If the source file name is not specified, the IBM-supplied source file
QCSRC contains the C source.

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 807
source-file-name: Specify the name of the source file that contains the C
source.
SRCMBR
Specifies the name of the source file member that contains the C source. This
parameter is specified only if the source file name in the SRCFILE parameter is
a database file. If this parameter is not specified, the PGM name specified on
the PGM parameter is used.

*PGM: Specifies that the C source is in the member of the source file that has
the same name as that specified on the PGM parameter.

source-file-member-name: Specify the name of the member that contains the C


source.
OPTION
Specifies whether one or more of the following options are used when the C
source is precompiled. If an option is specified more than once, or if two options
conflict, the last option specified is used.

Element 1: Source Listing Options

*NOSOURCE or *NOSRC: A source printout is not produced by the precompiler


unless errors are detected by the precompile or create package.

*SOURCE or *SRC: The precompiler produces a source listing consisting of C


source input.

Element 2: Cross-Reference Options

*NOXREF: The precompiler does not cross-reference names.

*XREF: The precompiler cross-references items in the program to the statement


numbers in the program that refer to those items.

Element 3: Program Creation Option

*NOGEN: The precompiler does not call the C compiler, and a program and
SQL package are not created.

Element 4: Decimal Point Options

*JOB: The value used as the decimal point for numeric constants in SQL is the
representation of decimal point specified for the job at precompile time.

*PERIOD: The value used as the decimal point for numeric constants in SQL
statements is a period.

*SYSVAL: The value used as the decimal point for numeric constants in SQL
statements is the QDECFMT system value.

Note: If QDECFMT specifies that the value used as the decimal point is a
comma, any numeric constants in lists (such as in the SELECT clause or
the VALUES clause) must be separated by a comma followed by a
blank. For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) in which the decimal point is a period.

808 DB2 UDB for AS/400 SQL Programming V4R4


*COMMA: The value used as the decimal point for numeric constants in SQL
statements is a comma.

Note: Any numeric constants in lists (such as in the SELECT clause or the
VALUES clause) must be separated by a comma followed by a blank.
For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) where the decimal point is a period.

Element 5: Naming Convention Options

*SYS: The system naming convention (library-name/file-name) is used.

*SQL: The SQL naming convention is used (collection-name.table-name). When


creating a program on a remote database other than an AS/400 system, *SQL
must be specified as the naming convention.

Element 6: Second-Level Message Text Option

*NOSECLVL: Second-level text descriptions are not added to the listing.

*SECLVL: Second-level text with replacement data is added for all messages
on the listing.

Element 7: Debug Options

*NODEBUG: Symbolic extended program model (EPM) debug information is


not stored with the program. This option is passed to the compiler and does not
affect the SQL precompiler.

*DEBUG: Symbolic EPM debug information is stored with the program. This
option is passed to the compiler and does not affect the SQL precompiler.

Element 8: NUL Required Options

*NOCNULRQD: For output character and graphic host variables, the


NUL-terminator is not returned when the host variable is exactly the same
length as the data. Input character and graphic host variables do not require a
NUL-terminator.

*CNULRQD: Output character and graphic host variables always contain the
NUL-terminator. If there is not enough space for the NUL-terminator, the data is
truncated and the NUL-terminator is added. Input character and graphic host
variables require a NUL-terminator.

Element 9: Event File Creation

*NOEVENTF: The compiler will not produce an event file for use by
CoOperative Development Environment/400 (CODE/400).

*EVENTF: The compiler produces an event file for use by CoOperative


Development Environment/400 (CODE/400). The event file will be created as a
member in the file EVFEVENT in your source library. CODE/400 uses this file to
offer error feedback integrated with the CODE/400 editor. This option is
normally specified by CODE/400 on your behalf.

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 809
TGTRLS
Specifies the release of the operating system on which the user intends to use
the object being created.

In the examples given for the *CURRENT and *PRV values, and when
specifying the release-level value, the format VxRxMx is used to specify the
release, where Vx is the version, Rx is the release, and Mx is the modification
level. For example, V2R3M0 is version 2, release 3, modification level 0.

*CURRENT: The object is to be used on the release of the operating system


currently running on the user’s system. For example, if V2R3M5 is running on
the system, *CURRENT means the user intends to use the object on a system
with V2R3M5 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

Note: If V2R3M5 is running on the system, and the object is to be used on a


system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
TGTRLS(*CURRENT).

*PRV: The object is to be used on the previous release with modification level 0
of the operating system. For example, if V2R3M5 is running on the user’s
system, *PRV means the user intends to use the object on a system with
V2R2M0 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

release-level: Specify the release in the format VxRxMx. The object can be
used on a system with the specified release or with any subsequent release of
the operating system installed.

Valid values depend on the current version, release, and modification level, and
they change with each new release. If you specify a release-level which is
earlier than the earliest release level supported by this command, an error
message is sent indicating the earliest supported release.
INCFILE
Specifies the qualified name of the source file that contains members included
in the program with any SQL INCLUDE statement.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

*SRCFILE: The qualified source file specified in the SRCFILE parameter


contains the source file members specified on any SQL INCLUDE statement.

source-file-name: Specify the name of the source file that contains the source
file members specified on any SQL INCLUDE statement. The record length of
the source file specified here must be no less than the record length of the
source file specified on the SRCFILE parameter.
COMMIT
Specifies whether SQL statements in the compiled program are run under

810 DB2 UDB for AS/400 SQL Programming V4R4


commitment control. Files referred to in the host language source are not
affected by this option. Only SQL tables, SQL views, and SQL packages
referred to in SQL statements are affected.

*CHG: Specifies the objects referred to in SQL ALTER, COMMENT ON,


CREATE, DROP, GRANT, LABEL ON, and REVOKE statements and the rows
updated, deleted, and inserted are locked until the end of the unit of work
(transaction). Uncommitted changes in other jobs can be seen.

*ALL: Specifies the objects referred to in SQL ALTER, COMMENT ON,


CREATE, DROP, GRANT, LABEL ON, and REVOKE statements and the rows
selected, updated, deleted, and inserted are locked until the end of the unit of
work (transaction). Uncommitted changes in other jobs cannot be seen.

*CS: Specifies the objects referred to in SQL ALTER, COMMENT ON,


CREATE, DROP, GRANT, LABEL ON, and REVOKE statements and the rows
updated, deleted, and inserted are locked until the end of the unit of work
(transaction). A row that is selected, but not updated, is locked until the next
row is selected. Uncommitted changes in other jobs cannot be seen.

*NONE: Specifies that commitment control is not used. Uncommitted changes


in other jobs can be seen. If the SQL DROP COLLECTION statement is
included in the program, *NONE must be used. If a relational database is
specified on the RDB parameter and the relational database is on a system that
is not on an AS/400, *NONE cannot be specified.
CLOSQLCSR
Specifies when SQL cursors are implicitly closed, SQL prepared statements are
implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
HOLD) SQL statements.

*ENDPGM: SQL cursors are closed and SQL prepared statements are
discarded when the program ends. LOCK TABLE locks are released when the
first SQL program on the call stack ends.

*ENDSQL: SQL cursors remain open between calls and can be fetched without
running another SQL OPEN. One of the programs higher on the call stack must
have run at least one SQL statement. SQL cursors are closed, SQL prepared
statements are discarded, and LOCK TABLE locks are released when the first
SQL program on the call stack ends. If *ENDSQL is specified for a program that
is the first SQL program called (the first SQL program on the call stack), the
program is treated as if *ENDPGM was specified.

*ENDJOB: SQL cursors remain open between calls and can be fetched without
running another SQL OPEN. The programs higher on the call stack do not need
to have run SQL statements. SQL cursors are left open, SQL prepared
statements are preserved, and LOCK TABLE locks are held when the first SQL
program on the call stack ends. SQL cursors are closed, SQL prepared
statements are discarded, and LOCK TABLE locks are released when the job
ends.
ALWCPYDTA
Specifies whether a copy of the data can be used in a SELECT statement.

*OPTIMIZE: The system determines whether to use the data retrieved directly
from the database or to use a copy of the data. The decision is based on which

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 811
method provides the best performance. If COMMIT is *CHG or *CS and
ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
data is used only when it is necessary to run a query.

*YES: A copy of the data is used only when necessary.

*NO: A copy of the data is not used. If a temporary copy of the data is required
to perform the query, an error message is returned.
ALWBLK
Specifies whether the database manager can use record blocking, and the
extent to which blocking can be used for read-only cursors.

*ALLREAD: Rows are not blocked for retrieval of data for cursors.

Specifying *NONE:
v Guarantees that the data retrieved is current.
v May reduce the amount of time required to retrieve the first row of data for a
query.
v Stops the database manager from retrieving a block of data rows that is not
used by the program when only the first few rows of a query are retrieved
before the query is closed.
v Can degrade the overall performance of a query that retrieves a large
number of rows.

*NONE: Rows are not blocked for retrieval of data for cursors.

Specifying *NONE:
v Guarantees that the data retrieved is current.
v May reduce the amount of time required to retrieve the first row of data for a
query.
v Stops the database manager from retrieving a block of data rows that is not
used by the program when only the first few rows of a query are retrieved
before the query is closed.
v Can degrade the overall performance of a query that retrieves a large
number of rows.

*READ: Records are blocked for read-only retrieval of data for cursors when:
v *NONE is specified on the COMMIT parameter, which indicates that
commitment control is not used.
v The cursor is declared with a FOR FETCH ONLY clause or there are no
dynamic statements that could run a positioned UPDATE or DELETE
statement for the cursor.

Specifying *READ can improve the overall performance of queries that meet the
above conditions and retrieve a large number of records.
DLYPRP
Specifies whether the dynamic statement validation for a PREPARE statement
is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
validation improves performance by eliminating redundant validation.

*NO: Dynamic statement validation is not delayed. When the dynamic


statement is prepared, the access plan is validated. When the dynamic

812 DB2 UDB for AS/400 SQL Programming V4R4


statement is used in an OPEN or EXECUTE statement, the access plan is
revalidated. Because the authority or the existence of objects referred to by the
dynamic statement may change, you must still check the SQLCODE or
SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
dynamic statement is still valid.

*YES: Dynamic statement validation is delayed until the dynamic statement is


used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
dynamic statement is used, the validation is completed and an access plan is
built. If you specify *YES on this parameter, you should check the SQLCODE
and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
ensure that the dynamic statement is valid.

Note: If you specify *YES, performance is not improved if the INTO clause is
used on the PREPARE statement or if a DESCRIBE statement uses the
dynamic statement before an OPEN is issued for the statement.
GENLVL
Specifies the severity level at which the create operation fails. If errors occur
that have a severity level greater than or equal to this value, the operation
ends.

10: The default severity level is 10.

severity-level: Specify a value ranging from 0 through 40.


MARGINS
Specifies the part of the precompiler input record that contains source text.

*SRCFILE:The file member margin values that you specified on the SRCMBR
parameter are used. If the member is an SQLC, SQLCLE, C, or CLE source
type, the margin values are the values specified on the source entry utility
(SEU) services display. If the member is a different source type, the margin
values are the default values of 1 and 80.

Element 1: Left Margin

left: Specify the beginning position for the statements. Valid values range from 1
through 80.

Element 2: Right Margin

right: Specify the ending position for the statements. Valid values range from 1
through 80.
DATFMT
Specifies the format used when accessing date result columns. All output date
fields are returned in the specified format. For input date strings, the specified
value is used to determine whether the date is specified in a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not an AS/400 system, then *USA, *ISO,
*EUR, or *JIS must be specified.

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 813
*JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
command to determine the current date format for the job.

*USA: The United States date format (mm/dd/yyyy) is used.

*ISO: The International Organization for Standardization (ISO) date format


(yyyy-mm-dd) is used.

*EUR: The European date format (dd.mm.yyyy) is used.

*JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

*MDY: The date format (mm/dd/yy) is used.

*DMY: The date format (dd/mm/yy) is used.

*YMD: The date format (yy/mm/dd) is used.

*JUL: The Julian date format (yy/ddd) is used.


DATSEP
Specifies the separator used when accessing date result columns.

Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
specified on the DATFMT parameter.

*JOB: The date separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’/’: A slash (/) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’-’: A dash (-) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


TIMFMT
Specifies the format used when accessing time result columns. For input time
strings, the specified value is used to determine whether the time is specified in
a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not another AS/400 system, the time
format must be *USA, *ISO, *EUR, *JIS, or *HMS with a time separator
of a colon or period.

*HMS: The hh:mm:ss format is used.

814 DB2 UDB for AS/400 SQL Programming V4R4


*USA: The United States time format hh:mm xx is used, where xx is AM or
PM.

*ISO: The International Organization for Standardization (ISO) time format


hh.mm.ss is used.

*EUR: The European time format hh.mm.ss is used.

*JIS: The Japanese Industrial Standard time format hh:mm:ss is used.


TIMSEP
Specifies the separator used when accessing time result columns.

Note: This parameter applies only when *HMS is specified on the TIMFMT
parameter.

*JOB: The time separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’:’: A colon (:) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


REPLACE
Specifies whether a new program or SQL package is created when a program
or SQL package of the same name exists in the same library. The value of this
parameter is passed to the C command.More information on this parameter is
in Appendix A, ″Expanded Parameter Descriptions″ in the CL Reference
(Abridged) book.

*YES: A new program or SQL package is created, and any existing program or
SQL package of the same name and type in the specified library is moved to
QRPLOBJ.

*NO: A new program or SQL package is not created if an object of the same
name and type already exists in the specified library.
RDB
Specifies the name of the relational database where the SQL package object is
created.

*NONE: An SQL package object is not created. The program object is not a
distributed program and the Create Structured Query Language Package
(CRTSQLPKG) command cannot be used.

relational-database-name: Specify the name of the relational database where


the new SQL package object is to be created. When the name of the local
relational database is specified, the program created is still a distributed SQL
program. The SQL statements will access the local database.

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 815
USER
Specifies the user name sent to the remote system when starting the
conversation. This parameter is valid only when RDB is specified.

*CURRENT: The user profile under which the current job is running is used.

user-name: Specify the user name to be used for the application server job.
PASSWORD
Specifies the password to be used on the remote system. This parameter is
valid only if RDB is specified.

*NONE: No password is sent. If this value is specified, USER(*CURRENT)


must also be specified.

password: Specify the password of the user name specified on the USER
parameter.
RDBCNNMTH
Specifies the semantics used for CONNECT statements. Refer to the SQL
Reference, SC41-3612 book for more information.

*DUW: CONNECT (Type 2) semantics are used to support distributed unit of


work. Consecutive CONNECT statements to additional relational databases do
not result in disconnection of previous connections.

*RUW: CONNECT (Type 1) semantics are used to support remote unit of work.
Consecutive CONNECT statements result in the previous connection being
disconnected before a new connection is established.
DFTRDBCOL
Specifies the collection name used for the unqualified names of tables, views,
indexes, and SQL packages. This parameter applies only to static SQL
statements.

*NONE: The naming convention defined on the OPTION parameter is used.

collection-name: Specify the name of the collection identifier. This value is used
instead of the naming convention specified on the OPTION parameter.
SQLPKG
Specifies the qualified name of the SQL package created on the relational
database specified on the RDB parameter of this command.

The possible library values are:


*PGMLIB: The package is created in the library with the same name as the
library containing the program.
library-name: Specify the name of the library where the package is created.

*PGM: The name of the SQL package is the same as the program name.

package-name: Specify the name of the SQL package. If the remote system is
not an AS/400 system, no more than 8 characters can be specified.
SAAFLAG
Specifies the IBM SQL flagging function. This parameter flags SQL statements

816 DB2 UDB for AS/400 SQL Programming V4R4


to verify whether they conform to IBM SQL syntax More information about
which IBM database products IBM SQL syntax is in the DRDA IBM SQL
Reference, SC26-3255-00.

*NOFLAG: The precompiler does not check to see whether SQL statements
conform to IBM SQL standards.

*FLAG: The precompiler checks to see whether SQL statements conform to


IBM SQL standards.
FLAGSTD
Specifies the American National Standards Institute (ANSI) flagging function.
This parameter flags SQL statements to verify whether they conform to the
following standards.
ANSI X3.135-1992 entry
ISO 9075-1992 entry
FIPS 127.2 entry

*NONE: The precompiler does not check to see whether SQL statements
conform to ANSI standards.

*ANS: The precompiler checks to see whether SQL statements conform to


ANSI standards.
PRTFILE
Specifies the qualified name of the printer device file to which the listing is
directed. The file must have a minimum record length of 132 bytes or
information is lost.

The name of the printer file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QSYSPRT: If a file name is not specified, the precompiler printout is directed to


the IBM-supplied printer file QSYSPRT.

printer-file-name: Specify the name of the printer device file to which the
precompiler printout is directed.
SRTSEQ
Specifies the sort sequence table to be used for string comparisons in SQL
statements.

Note: *HEX must be specified for this parameter on distributed applications


where the application server is not on an AS/400 system or the release
level is prior to V2R3M0.

*JOB: The SRTSEQ value for hte job is retrieved during the precompile.

*JOBRUN: The SRTSEQ value for the job is retrieved when the program is run.
For distributed applications, SRTSEQ(*JOBRUN) is valid only when
LANGID(*JOBRUN) is also specified.

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 817
*LANGIDUNQ: The unique-weight sort table for the language specified on the
LANGID parameter is used.

*LANGIDSHR: The shared-weight sort table for the language specified on the
LANGID parameter is used.

*HEX: A sort sequence table is not used. The hexadecimal values of the
characters are used to determine the sort sequence.

The name of the sort sequence table can be qualified by one of the following
library values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

table-name: Specify the name of the sort sequence table to be used.


LANGID
Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
SRTSEQ(*LANGIDSHR) is specified.

*JOB: The LANGID value for the job is received during the precompile.

*JOBRUN: The LANGID value for the job is retrieved when the program is run.
For distributed applications, LANGID(*JOBRUN) is valid only when
SRTSEQ(*JOBRUN) is also specified.

language-id: Specify a language identifier to be used by the program.


DYNUSRPRF
Specifies the user profile used for dynamic SQL statements.

*USER: Local dynamic SQL statements are run under the user profile of the
job. Distributed dynamic SQL statements are run under the user profile of the
application server job.

*OWNER: Local dynamic SQL statements are run under the user profile of the
program’s owner. Distributed dynamic SQL statements are run under the user
profile of the SQL package’s owner.
| TOSRCFILE
| Specifies the qualified name of the source file that is to contain the output
| source member that has been processed by the SQL precompiler. If the
| specified source file is not found, it will be created. The output member will
| have the same name as the name that is specified for the SRCMBR parameter.

| The possible library values are:


| QTEMP: The library QTEMP will be used.
| *LIBL: The job’s library list is searched for the specified file. If the file is not
| found in any library in the library list, the file will be created in the current
| library.
| *CURLIB: The current library for the job will be used. If no library is
| specified as the current library for the job, the QGPL library will be used.

818 DB2 UDB for AS/400 SQL Programming V4R4


| library-name: Specify the name of the library that is to contain the output
| source file.

| QSQLTEMP: The source file QSQLTEMP will be used.

| source-file-name: Specify the name of the source file to contain the output
| source member.
TEXT
Specifies the text that briefly describes the function. More information on this
parameter is in Appendix A, ″Expanded Parameter Descriptions″ in the CL
Reference book.

*SRCMBRTXT: The text is taken from the source file member being used to
create the FORTRAN program. Text can be added or changed for a database
source member by using the Start Source Entry Utility (STRSEU) command, or
by using either the Add Physical File Member (ADDPFM) or Change Physical
File Member (CHGPFM) command. If the source file is an inline file or a device
file, the text is blank.

*BLANK: Text is not specified.

’description’: Specify no more than 50 characters of text, enclosed in


apostrophes.

Example
CRTSQLC PAYROLL TEXT('Payroll Program')

This command runs the SQL precompiler which precompiles the source and stores
the changed source in member PAYROLL in file QSQLTEMP in library QTEMP.

Using the FORTRAN/400 Precompiler


FORTRAN/400 is no longer a supported compiler for the AS/400 system. This
appendix is intended to help those customers who are using the SQL FORTRAN
precompiler with other non-IBM FORTRAN compilers. For a description of using the
FORTRAN precompiler, see Appendix F. Coding SQL Statements in FORTRAN
Applications.

CRTSQLFTN (Create Structured Query Language FORTRAN) Command


Job: B,I Pgm: B,I REXX: B,I Exec

*CURLIB/
ÊÊ CRTSQLFTN PGM( program-name ) Ê
library-name/

Ê Ê
*LIBL/ QFTNSRC
SRCFILE( source-file-name )
*CURLIB/
library-name/

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 819
(1)
Ê Ê
*PGM
SRCMBR( source-file-member-name )

Ê Ê
OPTION( OPTION Details ) *CURRENT
TGTRLS( *PRV )
VxRxMx

Ê Ê
*LIBL/ *SRCFILE
INCFILE( source-file-name )
*CURLIB/
library-name/

Ê Ê
*UR *ENDPGM
*CHG CLOSQLCSR( *ENDSQL )
COMMIT( *ALL ) *ENDJOB
*RS
*CS
*NONE
*NC
*RR

Ê Ê
*YES *READ
ALWCPYDTA( *OPTIMIZE ) ALWBLK( *NONE )
*NO *ALLREAD

Ê Ê
*NO 10
DLYPRP( *YES ) GENLVL( severity-level )

Ê Ê
*JOB *JOB
DATFMT( *USA ) DATSEP( '/' )
*ISO '.'
*EUR ','
*JIS '-'
*MDY ' '
*DMY *BLANK
*YMD
*JUL

820 DB2 UDB for AS/400 SQL Programming V4R4


Ê Ê
*HMS *JOB
TIMFMT( *USA ) TIMSEP( ':' )
*ISO '.'
*EUR ','
*JIS ' '
*BLANK

Ê Ê
*YES
REPLACE( *NO )

Ê Ê
*LOCAL *CURRENT
RDB( relational-database-name ) USER( user-name )
*NONE

Ê Ê
*NONE *DUW
PASSWORD( password ) RDBCNNMTH( *RUW )

Ê Ê
*NONE
DFTRDBCOL( collection-name )

Ê Ê
*PGMLIB/ *PGM
SQLPKG( package-name )
library-name/

Ê Ê
*NOFLAG *NONE
SAAFLAG( *FLAG ) FLAGSTD( *ANS )

Ê Ê
*LIBL/ QSYSPRT
PRTFILE( printer-file-name )
*CURLIB/
library-name/

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 821
Ê Ê
*JOB
SRTSEQ( *JOBRUN )
*LANGIDUNQ
*LANGIDSHR
*HEX
*LIBL/
table-name
*CURLIB/
library-name/

Ê Ê
*JOB *NAMING
LANGID( *JOBRUN ) USRPRF( *OWNER )
language-ID *USER

Ê Ê
*USER
DYNUSRPRF( *OWNER )

Ê Ê
QTEMP/ QSQLTEMP
TOSRCFILE( source-file-name )
*LIBL/
*CURLIB/
library-name/

Ê ÊÍ
*SRCMBRTXT
TEXT( *BLANK )
'description'

OPTION Details:

*NOSRC
*NOSOURCE *NOXREF *GEN *PERIOD *SYS
Ê
*SOURCE *XREF *NOGEN *JOB *SQL
*SRC *SYSVAL
*COMMA

*NOSECLVL *NODEBUG
Ê
*SECLVL *DEBUG

Notes:
1. All parameters preceding this point can be specified in positional form.

Purpose
The Create Structured Query Language FORTRAN (CRTSQLFTN) command calls
the Structured Query Language (SQL) precompiler which precompiles FORTRAN

822 DB2 UDB for AS/400 SQL Programming V4R4


source containing SQL statements, produces a temporary source member, and then
optionally calls the FORTRAN compiler to compile the program.

Parameters
PGM
Specifies the qualified name of the compiled program.

The name of the compiled FORTRAN program can be qualified by one of the
following library values:

*CURLIB: The compiled FORTRAN program is created in the current library for
the job. If no library is specified as the current library for the job, the QGPL
library is used.

library-name: Specify the name of hte library where the compiled FORTRAN
program is created.

program-name: Specify the name of the compiled FORTRAN program.


SRCFILE
Specifies the qualified name of the source file that contains the FORTRAN
source with SQL statements.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QFTNSRC: If the source file name is not specified, the IBM-supplied source file
QFTNSRC contains the FORTRAN source.

source-file-name: Specify the name of the source file that contains the
FORTRAN source.
SRCMBR
Specifies the name of the source file member that contains the C source. This
parameter is specified only if the source file name in the SRCFILE parameter is
a database file. If this parameter is not specified, the PGM name specified on
the PGM parameter is used.

*PGM: Specifies that the FORTRAN source is in the member of the source file
that has the same name as that specified on the PGM parameter.

source-file-member-name: Specify the name of the member that contains the


FORTRAN source.
OPTION
Specifies whether one or more of the following options are used when the
FORTRAN source is precompiled. If an option is specified more than once, or if
two options conflict, the last option specified is used.

Element 1: Source Listing Options

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 823
*NOSOURCE: or *NOSRC: A source printout is not produced by the
precompiler unless errors are detected during precompile or create package.

*SOURCE or *SRC: The precompiler produces a source printout consisting of


FORTRAN source input.

Element 2: Cross-Reference Options

*NOXREF: The precompiler does not cross-reference names.

*XREF:The precompiler cross-references items in the program to the statement


numbers in the program that refer to those items.

Element 3: Program Creation Options

*GEN:

*NOGEN: The precompiler does not call the FORTRAN compiler, and a
program and SQL package are not created.

Element 4: Decimal Point Options

*PERIOD: The value used as the decimal point for numeric constants used in
SQL statements is a period.

*JOB The value used as the decimal point for numeric constants in SQL is the
representation of decimal point specified for the job at precompile time.

*SYSVAL: The value used as the decimal point for numeric constants in SQL
statements is the QDECFMT system value.

Note: If QDECFMT specifies that the value used as the decimal point is a
comma, any numeric constants in lists (such as in the SELECT clause or
the VALUES clause) must be separated by a comma followed by a
blank. For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) in which the decimal point is a period.

*COMMA: The value used as the decimal point for numeric constants in SQL
statements is a comma.

Note: Any numeric constants in lists (such as in the SELECT clause or the
VALUES clause) must be separated by a comma followed by a blank.
For example, VALUES(1,1, 2,23, 4,1) is equivalent to
VALUES(1.1,2.23,4.1) where the decimal point is a period.

Element 5: Naming Convention Options

*SYS:The system naming convention (library-name/file-name) is used.

*SQL: The SQL naming convention is used (collection-name.table-name). When


creating a program on a remote database other than an AS/400 system, *SQL
must be specified as the naming convention.

Element 6: Second-Level Message Text Option

*NOSECLVL: Second-level text descriptions are not added to the listing.

824 DB2 UDB for AS/400 SQL Programming V4R4


*SECLVL: Second-level text with replacement data is added for all messages
on the listing.

Element 7: Debug Options

*NODEBUG: Symbolic extended program model (EPM) debug information is


not stored with the program. This option is passed to the compiler and does not
affect the SQL precompiler.

*DEBUG: Symbolic EPM debug information is stored with the program. This
option is passed to the compiler and does not affect the SQL precompiler.
TGTRLS
Specifies the release of the operating system on which the user intends to use
the object being created.

In the examples given for the *CURRENT and *PRV values, and when
specifying the release-level value, the format VxRxMx is used to specify the
release, where Vx is the version, Rx is the release, and Mx is the modification
level. For example, V2R3M0 is version 2, release 3, modification level 0.

*CURRENT: The object is to be used on the release of the operating system


currently running on the user’s system. For example, if V2R3M5 is running on
the system, *CURRENT means the user intends to use the object on a system
with V2R3M5 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

Note: If V2R3M5 is running on the system, and the object is to be used on a


system with V2R3M0 installed, specify TGTRLS(V2R3M0) not
TGTRLS(*CURRENT).

*PRV: The object is to be used on the previous release with modification level 0
of the operating system. For example, if V2R3M5 is running on the user’s
system, *PRV means the user intends to use the object on a system with
V2R2M0 installed. The user can also use the object on a system with any
subsequent release of the operating system installed.

release-level: Specify the release in the format VxRxMx. The object can be
used on a system with the specified release or with any subsequent release of
the operating system installed.

Valid values depend on the current version, release, and modification level, and
they change with each new release. If you specify a release-level which is
earlier than the earliest release level supported by this command, an error
message is sent indicating the earliest supported release.
INCFILE
Specifies the qualified name of the source file that contains members included
in the program with any SQL INCLUDE statement.

The name of the source file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 825
library-name: Specify the name of the library to be searched.

*SRCFILE: The qualified source file specified in the SRCFILE parameter


contains the source file members specified on any SQL INCLUDE statement.

source-file-name: Specify the name of the source file that contains the source
file members specified on any SQL INCLUDE statement. The record length of
the source file the user specifies here must be no less than the record length of
the source file specified on the SRCFILE parameter.
COMMIT
Specifies whether SQL statements in the compiled program are run under
commitment control. Files referred to in the host language source are not
affected by this option. Only SQL tables, SQL views, and SQL packages
referred to in SQL statements are affected.

*CHG or *UR: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows updated, deleted, and inserted are locked
until the end of the unit of work (transaction). Uncommitted changes in other
jobs can be seen.

*ALL or *RS: Specifies the objects referred to in SQL ALTER, CALL,


COMMENT ON, CREATE, DROP, GRANT, LABEL ON, RENAME, and
REVOKE statements and the rows selected, updated, deleted, and inserted are
locked until the end of the unit of work (transaction). Uncommitted changes in
other jobs cannot be seen.

*CS: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows updated, deleted, and inserted are locked until the end of the unit of
work (transaction). A row that is selected, but not updated, is locked until the
next row is selected. Uncommitted changes in other jobs cannot be seen.

*NONE or *NC: Specifies that commitment control is not used. Uncommitted


changes in other jobs can be seen. If the SQL DROP COLLECTION statement
is included in the program, *NONE or *NC must be used. If a relational
database is specified on the RDB parameter and the relational database is on a
system that is not on an AS/400, *NONE or *NC cannot be specified.

*RR: Specifies the objects referred to in SQL ALTER, CALL, COMMENT ON,
CREATE, DROP, GRANT, LABEL ON, RENAME, and REVOKE statements and
the rows selected, updated, deleted, and inserted are locked until the end of the
unit of work (transaction). Uncommitted changes in other jobs cannot be seen.
All tables referred to in SELECT, UPDATE, DELETE, and INSERT statements
are locked exclusively until the end of the unit of work (transaction).
CLOSQLCSR
Specifies when SQL cursors are implicitly closed, SQL prepared statements are
implicitly discarded, and LOCK TABLE locks are released. SQL cursors are
explicitly closed when you issue the CLOSE, COMMIT, or ROLLBACK (without
HOLD) SQL statements.

*ENDPGM: SQL cursors are closed and SQL prepared statements are
discarded when the program ends. LOCK TABLE locks are released when the
first SQL program on the call stack ends.

826 DB2 UDB for AS/400 SQL Programming V4R4


*ENDSQL: SQL cursors remain open between calls and can be fetched without
running another SQL OPEN. One of the programs higher on the call stack must
have run at least one SQL statement. SQL cursors are closed, SQL prepared
statements are discarded, and LOCK TABLE locks are released when the first
SQL program on the call stack ends. If *ENDSQL is specified for a program that
is the first SQL program called (the first SQL program on the call stack), the
program is treated as if *ENDPGM was specified.

*ENDJOB: SQL cursors remain open between calls and can be fetched without
running another SQL OPEN. The programs higher on the call stack do not need
to have run SQL statements. SQL cursors are left open, SQL prepared
statements are preserved, and LOCK TABLE locks are held when the first SQL
program on the call stack ends. SQL cursors are closed, SQL prepared
statements are discarded, and LOCK TABLE locks are released when the job
ends.
ALWCPYDTA
Specifies whether a copy of the data can be used in a SELECT statement.

*OPTIMIZE: The system determines whether to use the data retrieved directly
from the database or to use a copy of the data. The decision is based on which
method provides the best performance. If COMMIT is *CHG or *CS and
ALWBLK is not *ALLREAD, or if COMMIT is *ALL or *RR, then a copy of the
data is used only when it is necessary to run a query.

*YES: A copy of the data is used only when necessary.

*NO: A copy of the data is not allowed. If a temporary copy of the data is
required to perform the query, an error message is returned.
ALWBLK
Specifies whether the database manager can use record blocking, and the
extent to which blocking can be used for read-only cursors.

*ALLREAD: Rows are blocked for read-only cursors if *NONE or *CHG is


specified on the COMMIT parameter. All cursors in a program that are not
explicitly able to be updated are opened for read-only processing even though
EXECUTE or EXECUTE IMMEDIATE statements may be in the program.

Specifying *ALLREAD:
v Allows record blocking under commitment control level *CHG in addition to
the blocking allowed for *READ.
v Can improve the performance of almost all read-only cursors in programs,
but limits queries in the following ways:
– The Rollback (ROLLBACK) command, a ROLLBACK statement in host
languages, or the ROLLBACK HOLD SQL statement does not reposition a
read-only cursor when *ALLREAD is specified.
– Dynamic running of a positioned UPDATE or DELETE statement (for
example, using EXECUTE IMMEDIATE), cannot be used to update a row
in a cursor unless the DECLARE statement for the cursor includes the
FOR UPDATE clause.

*NONE: Rows are not blocked for retrieval of data for cursors.

Specifying *NONE:
v Guarantees that the data retrieved is current.

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 827
v May reduce the amount of time required to retrieve the first row of data for a
query.
v Stops the database manager from retrieving a block of data rows that is not
used by the program when only the first few rows of a query are retrieved
before the query is closed.
v Can degrade the overall performance of a query that retrieves a large
number of rows.

*READ: Records are blocked for read-only retrieval of data for cursors when:
v *NONE is specified on the COMMIT parameter, which indicates that
commitment control is not used.
v The cursor is declared with a FOR FETCH ONLY clause or there are no
dynamic statements that could run a positioned UPDATE or DELETE
statement for the cursor.

Specifying *READ can improve the overall performance of queries that meet the
above conditions and retrieve a large number of records.
DLYPRP
Specifies whether the dynamic statement validation for a PREPARE statement
is delayed until an OPEN, EXECUTE, or DESCRIBE statement is run. Delaying
validation improves performance by eliminating redundant validation.

*NO: Dynamic statement validation is not delayed. When the dynamic


statement is prepared, the access plan is validated. When the dynamic
statement is used in an OPEN or EXECUTE statement, the access plan is
revalidated. Because the authority or the existence of objects referred to by the
dynamic statement may change, you must still check the SQLCODE or
SQLSTATE after issuing the OPEN or EXECUTE statement to ensure that the
dynamic statement is still valid.

*YES: Dynamic statement validation is delayed until the dynamic statement is


used in an OPEN, EXECUTE, or DESCRIBE SQL statement. When the
dynamic statement is used, the validation is completed and an access plan is
built. If you specify *YES on this parameter, you should check the SQLCODE
and SQLSTATE after running an OPEN, EXECUTE, or DESCRIBE statement to
ensure that the dynamic statement is valid.

Note: If you specify *YES, performance is not improved if the INTO clause is
used on the PREPARE statement or if a DESCRIBE statement uses the
dynamic statement before an OPEN is issued for the statement.
GENLVL
Specifies the severity level at which the create operation fails. If errors occur
that have a severity level greater than or equal to this value, the operation
ends.

10: The default severity level is 10.

severity-level: Specify a value ranging from 0 through 40.


DATFMT
Specifies the format used when accessing date result columns. All output date
fields are returned in the specified format. For input date strings, the specified
value is used to determine whether the date is specified in a valid format.

828 DB2 UDB for AS/400 SQL Programming V4R4


Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

If a relational database is specified on the RDB parameter and the


database is on a system that is not an AS/400 system, then *USA, *ISO,
*EUR, or *JIS must be specified.

*JOB: The format specified for the job is used. Use the Display Job (DSPJOB)
command to determine the current date format for the job.

*USA: The United States date format (mm/dd/yyyy) is used.

*ISO: The International Organization for Standardization (ISO) date format


(yyyy-mm-dd) is used.

*EUR: The European date format (dd.mm.yyyy) is used.

*JIS: The Japanese Industrial Standard date format (yyyy-mm-dd) is used.

*MDY: The date format (mm/dd/yy) is used.

*DMY: The date format (dd/mm/yy) is used.

*YMD: The date format (yy/mm/dd) is used.

*JUL: The Julian date format (yy/ddd) is used.


DATSEP
Specifies the separator used when accessing date result columns.

Note: This parameter applies only when *JOB, *MDY, *DMY, *YMD, or *JUL is
specified on the DATFMT parameter.

*JOB: The date separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’/’: A slash (/) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’-’: A dash (-) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


TIMFMT
Specifies the format used when accessing time result columns. For input time
strings, the specified value is used to determine whether the time is specified in
a valid format.

Note: An input date string that uses the format *USA, *ISO, *EUR, or *JIS is
always valid.

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 829
If a relational database is specified on the RDB parameter and the
database is on a system that is not another AS/400 system, the time
format must be *USA, *ISO, *EUR, *JIS, or *HMS with a time separator
of colon or period.

*HMS: The (hh:mm:ss) format is used.

*USA: The United States time format (hh:mm xx) is used, where xx is AM or
PM.

*ISO: The International Organization for Standardization (ISO) time format


(hh.mm.ss) is used.

*EUR: The European time format (hh.mm.ss) is used.

*JIS: The Japanese Industrial Standard time format (hh:mm:ss) is used.


TIMSEP
Specifies the separator used when accessing time result columns.

Note: This parameter applies only when *HMS is specified on the TIMFMT
parameter.

*JOB: The time separator specified for the job at precompile time is used. Use
the Display Job (DSPJOB) command to determine the current value for the job.

’:’: A colon (:) is used.

’.’: A period (.) is used.

’,’: A comma (,) is used.

’ ’: A blank ( ) is used.

*BLANK: A blank ( ) is used.


REPLACE
Specifies whether a new program or SQL package is created when a program
or SQL package of the same name exists in the same library. The value of this
parameter is passed to the CRTFTNPGM command. More information on this
parameter is in Appendix A, ″Expanded Parameter Descriptions″ in the CL
Reference (Abridged) book.

*YES: A new program or SQL package is created, and any existing program or
SQL package of the same name and type in the specified library is moved to
QRPLOBJ.

*NO: A new program or SQL package is not created if an object of the same
name and type already exists in the specified library.
RDB
Specifies the name of the relational database where the SQL package object is
created.

*LOCAL: The program is created as a distributed SQL program. The SQL


statements will access the local database. An SQL package object is not

830 DB2 UDB for AS/400 SQL Programming V4R4


created as part of the precompile process. The Create Structured Query
Language Package (CRTSQLPKG) command can be used.

relational-database-name: Specify the name of the relational database where


the new SQL package object is to be created. When the name of the local
relational database is specified, the program created is still a distributed SQL
program. The SQL statements will access the local database.

*NONE: An SQL package object is not created. The program object is not a
distributed program and the Create Structured Query Language Package
(CRTSQLPKG) command cannot be used.
USER
Specifies the user name sent to the remote system when starting the
conversation. This parameter is valid only when RDB is specified.

*CURRENT: The user profile under which the current job is running is used.

user-name: Specify the user name being used for the application server job.
PASSWORD
Specifies the password to be used on the remote system. This parameter is
valid only if RDB is specified.

*NONE: No password is sent. If this value is specified, USER(*CURRENT)


must also be specified.

password: Specify the password of the user name specified on the USER
parameter.
RDBCNNMTH
Specifies the semantics used for CONNECT statements. Refer to the SQL
Reference book for more information.

*DUW: CONNECT (Type 2) semantics are used to support distributed unit of


work. Consecutive CONNECT statements to additional relational databases do
not result in disconnection of previous connections.

*RUW: CONNECT (Type 1) semantics are used to support remote unit of work.
Consecutive CONNECT statements result in the previous connection being
disconnected before a new connection is established.
DFTRDBCOL
Specifies the collection name used for the unqualified names of tables, views,
indexes, and SQL packages. This parameter applies only to static SQL
statements.

*NONE: The naming convention defined on the OPTION parameter is used.

collection-name: Specify the name of the collection identifier. This value is used
instead of the naming convention specified on the OPTION parameter.
SQLPKG
Specifies the qualified name of the SQL package created on the relational
database specified on the RDB parameter of this command.

The possible library values are:

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 831
*PGMLIB: The package is created in the library with the same name as the
library containing the program.
library-name: Specify the name of the library where the package is created.

*PGM: The package name is the same as the program name.

package-name: Specify the name of the package created on the remote


database specified on the RDB parameter.
SAAFLAG
Specifies the IBM SQL flagging function. This parameter flags SQL statements
to verify whether they conform to IBM SQL syntax More information about
which IBM database products IBM SQL syntax is in the DRDA IBM SQL
Reference, SC26-3255-00.

*NOFLAG: The precompiler does not check to see whether SQL statements
conform to IBM SQL syntax.

*FLAG: The precompiler checks to see whether SQL statements conform to


IBM SQL syntax.
FLAGSTD
Specifies the American National Standards Institute (ANSI) flagging function.
This parameter flags SQL statements to verify whether they conform to the
following standards.
ANSI X3.135-1992 entry
ISO 9075-1992 entry
FIPS 127.2 entry

*NONE: The precompiler does not check to see whether SQL statements
conform to ANSI standards.

*ANS: The precompiler checks to see whether SQL statements conform to


ANSI standards.
PRTFILE
Specifies the qualified name of the printer device file to which the listing is
directed. The file must have a minimum record length of 132 bytes or
information is lost.

The name of the printer file can be qualified by one of the following library
values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

QSYSPRT: If a file name is not specified, the precompiler printout is directed to


the IBM-supplied printer file QSYSPRT.

printer-file-name: Specify the name of the printer device file to which the
precompiler printout is directed.
SRTSEQ
Specifies the sort sequence table to be used for string comparisons in SQL
statements.

832 DB2 UDB for AS/400 SQL Programming V4R4


Note: *HEX must be specified for this parameter on distributed applications
where the application server is not on an AS/400 system or the release
level is prior to V2R3M0.

Specifies the sort sequence table to be used for string comparisons in SQL
statements.

Note: *HEX must be specified for this parameter on distributed applications


where the application server is not on an AS/400 system or the release
level is prior to V2R3M0.

*JOB: The SRTSEQ value for the job is retrieved during the precompile.

*JOBRUN: The SRTSEQ value for the job is retrieved when the program is run.
For distributed applications, SRTSEQ(*JOBRUN) is valid only when
LANGID(*JOBRUN) is also specified.

*LANGIDUNQ: The unique-weight sort table for the language specified on the
LANGID parameter is used.

*LANGIDSHR: The shared-weight sort table for the language specified on the
LANGID parameter is used.

*HEX: A sort sequence table is not used. The hexadecimal values of the
characters are used to determine the sort sequence.

The name of the sort sequence table can be qualified by one of the following
library values:
*LIBL: All libraries in the job’s library list are searched until the first match is
found.
*CURLIB: The current library for the job is searched. If no library is specified
as the current library for the job, the QGPL library is used.
library-name: Specify the name of the library to be searched.

table-name: Specify the name of the sort sequence table to be used.


LANGID
Specifies the language identifier to be used when SRTSEQ(*LANGIDUNQ) or
SRTSEQ(*LANGIDSHR) is specified.

*JOB: The LANGID value for the job is retrieved during the precompile.

*JOBRUN: The LANGID value for the job is retrieved when the program is run.
For distributed applications, LANGID(*JOBRUN) is valid only when
SRTSEQ(*JOBRUN) is also specified.

language-id: Specify a language identifier to be used by the program.


USRPRF
Specifies the user profile that is used when the compiled program object is run,
including the authority that the program object has for each object in static SQL
statements. The profile of either the program owner or the program user is used
to control which objects can be used by the program object.

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 833
*NAMING: The user profile is determined by the naming convention. If the
naming convention is *SQL, USRPRF(*OWNER) is used. If the naming
convention is *SYS, USRPRF(*USER) is used.

*USER: The profile of the user running the program object is used.

*OWNER: The user profiles of both the program owner and the program user
are used when the program is run.
DYNUSRPRF
Specifies the user profile used for dynamic SQL statements.

*USER: Local dynamic SQL statements are run under the user profile of the
job. Distributed dynamic SQL statements are run under the user profile of the
application server job.

*OWNER: Local dynamic SQL statements are run under the user profile of the
program’s owner. Distributed dynamic SQL statements are run under the user
profile of the SQL package’s owner.
| TOSRCFILE
| Specifies the qualified name of the source file that is to contain the output
| source member that has been processed by the SQL precompiler. If the
| specified source file is not found, it will be created. The output member will
| have the same name as the name that is specified for the SRCMBR parameter.

| The possible library values are:


| QTEMP: The library QTEMP will be used.
| *LIBL: The job’s library list is searched for the specified file. If the file is not
| found in any library in the library list, the file will be created in the current
| library.
| *CURLIB: The current library for the job will be used. If no library is
| specified as the current library for the job, the QGPL library will be used.
| library-name: Specify the name of the library that is to contain the output
| source file.

| QSQLTEMP: The source file QSQLTEMP will be used.

| source-file-name: Specify the name of the source file to contain the output
| source member.
TEXT
Specifies the text that briefly describes the LANGID. More information on this
parameter is in Appendix A, ″Expanded Parameter Descriptions″ in the CL
Reference (Abridged) book.

*SRCMBRTXT: The text is taken from the source file member being used to
create the FORTRAN program. Text can be added or changed for a database
source member by using the Start Source Entry Utility (STRSEU) command, or
by using either the Add Physical File Member (ADDPFM) or Change Physical
File Member (CHGPFM) command. If the source file is an inline file or a device
file, the text is blank.

*BLANK: Text is not specified.

834 DB2 UDB for AS/400 SQL Programming V4R4


’description’: Specify no more than 50 characters of text, enclosed in
apostrophes.

Example
CRTSQLFTN PAYROLL TEXT('Payroll Program')

This command runs the SQL precompiler, which precompiles the source and stores
the changed source in member PAYROLL in file QSQLTEMP in library QTEMP. The
FORTRAN compiler is called to create program PAYROLL in the current library by
using the source member created by the SQL precompiler.

Appendix E. Using the C for AS/400 and FORTRAN for AS/400 Precompilers 835
836 DB2 UDB for AS/400 SQL Programming V4R4
Appendix F. Coding SQL Statements in FORTRAN
Applications
This appendix describes the unique application and coding requirements for
embedding SQL statements in a FORTRAN/400 program. Requirements for host
variables are defined.

Defining the SQL Communications Area


A FORTRAN program that contains SQL statements must include one or both of the
following:
v An SQLCOD variable declared as INTEGER
v An SQLSTA (or SQLSTATE) variable declared as CHARACTER*5

Or,
v An SQLCA (which contains an SQLCOD and SQLSTA variable).

The SQLCOD and SQLSTA (or SQLSTATE) values are set by the database
manager after each SQL statement is executed. An application can check the
SQLCOD or SQLSTA (or SQLSTATE) value to determine whether the last SQL
statement was successful.

The SQLCA can be coded in a FORTRAN program either directly or by using the
SQL INCLUDE statement. Using the SQL INCLUDE statement requests the
inclusion of a standard declaration:
EXEC SQL INCLUDE SQLCA

The included FORTRAN source statements for the SQLCA are:


*
* The SQL communications area
*
CHARACTER SQLCA(136)
CHARACTER SQLCAID*8
INTEGER*4 SQLCABC
INTEGER*4 SQLCODE
INTEGER*2 SQLERRML
CHARACTER SQLERRMC*70
CHARACTER SQLERRP*8
INTEGER*4 SQLERRD(6)
CHARACTER SQLWARN*11
CHARACTER SQLSTATE*5
EQUIVALENCE (SQLCA( 1), SQLCAID)
EQUIVALENCE (SQLCA( 9), SQLCABC)
EQUIVALENCE (SQLCA( 13), SQLCODE)
EQUIVALENCE (SQLCA( 17), SQLERRML)
EQUIVALENCE (SQLCA( 19), SQLERRMC)
EQUIVALENCE (SQLCA( 89), SQLERRP)
EQUIVALENCE (SQLCA( 97), SQLERRD)
EQUIVALENCE (SQLCA(121), SQLWARN)
EQUIVALENCE (SQLCA(132), SQLSTATE)

*
INTEGER*4 SQLCOD
C SQLERR(6)
INTEGER*2 SQLTXL
CHARACTER SQLERP*8,
C SQLWRN(0:7)*1,
C SQLWRX(1:3)*1,

© Copyright IBM Corp. 1997, 1999 837


C SQLTXT*70,
C SQLSTT*5,
C SQLWRNWK*8,
C SQLWRXWK*3,
C SQLERRWK*24,
C SQLERRDWK*24
EQUIVALENCE (SQLWRN(1), SQLWRNWK)
EQUIVALENCE (SQLWRX(1), SQLWRXWK)
EQUIVALENCE (SQLCA(97), SQLERRDWK)
EQUIVALENCE (SQLERR(1), SQLERRWK)
COMMON /SQLCA1/SQLCOD,SQLERR,SQLTXTL
COMMON /SQLCA2/SQLERP,SQLWRN,SQLTXT,SQLWRX,SQLSTT

SQLSTATE is replaced with SQLSTOTE when a declare for SQLSTATE is found in


the program and the SQLCA is provided by the compiler. If compatibility with other
IBM SQL implementations is not a primary consideration, it is recommended that
the SQLCA be included by coding the FORTRAN variable SQLCOD, SQLSTA, or
SQLSTATE in the program. This improves performance, but does not generate a
compatible SQLCA.

For more information on SQLCA, see Appendix B, “SQL Communication Area” in


the DB2 UDB for AS/400 SQL Reference book.

The SQLCOD, SQLSTA, SQLSTATE, and SQLCA variables must be placed before
the first executable SQL statement. All executable SQL statements in a program
must be within the scope of the declaration of the SQLCOD, SQLSTA, SQLSTATE,
and SQLCA variables.

All SQL statements that can be run in a program must be within the scope of the
declaration of the SQLCOD variable or SQLCA variables.

Defining SQL Descriptor Areas


The following statements require an SQLDA:
EXECUTE...USING DESCRIPTOR descriptor-name
FETCH...USING DESCRIPTOR descriptor-name
OPEN...USING DESCRIPTOR descriptor-name
CALL...USING DESCRIPTOR descriptor-name
DESCRIBE statement-name INTO descriptor-name
DESCRIBE TABLE host-variable INTO descriptor-name
PREPARE statement-name INTO descriptor-name

Unlike the SQLCA, there can be more than one SQLDA in a program, and an
SQLDA can have any valid name.

Dynamic SQL is an advanced programming technique described in Chapter 10.


Dynamic SQL Applications. With dynamic SQL, your program can develop and then
run SQL statements while the program is running. A SELECT statement with a
variable SELECT list (that is, a list of the data to be returned as part of the query)
that runs dynamically requires an SQL descriptor area (SQLDA). This is because
you cannot know in advance how many or what type of variables to allocate in
order to receive the results of the SELECT. Because the SQLDA uses pointer
variables, which are not supported by FORTRAN, an INCLUDE SQLDA statement

838 DB2 UDB for AS/400 SQL Programming V4R4


cannot be specified in a FORTRAN program. Unless an SQLDA is set up by a C,
COBOL, PL/I, or ILE RPG program and passed to the FORTRAN program, you
cannot use the SQLDA.

Coding an SQLDA on the multiple-row FETCH statement using a row storage area
provides a technique to retrieve multiple rows on each FETCH statement. This
technique can improve an application’s performance if a large number of rows are
read by the application. For more information on using the FETCH statement, see
the DB2 UDB for AS/400 SQL Reference book.

Embedding SQL Statements


SQL statements can be coded in a FORTRAN program wherever a statement that
can be run appears. If the SQL statement is within an IF statement, any necessary
THEN and END IF statements will be generated.

Each SQL statement in a FORTRAN program must begin with EXEC SQL. The
EXEC SQL keywords must appear all on one line, but the remainder of the
statement can appear on the same line and on subsequent lines.

Example:

An UPDATE statement coded in a FORTRAN program might be coded as follows:


EXEC SQL
C UPDATE DEPARTMENT
C SET MGRNO = :MGRNUM
C WHERE DEPTNO = :INTDEPT

An SQL statement cannot be followed on the same line by another SQL statement
or by a FORTRAN statement.

FORTRAN does not require the use of blanks to delimit words within a statement,
but the SQL language does. The rules for embedded SQL follow the rules for SQL
syntax, which requires the use of one or more blanks as delimiters.

Comments
In addition to SQL comments (--), FORTRAN comments can be included within the
embedded SQL statements wherever a blank is allowed, except between the
keywords EXEC and SQL.

The comment extends to the end of the line. Comment lines can appear between
the lines of a continued SQL statement. The character (!) indicates a comment,
except when it appears in a character context or in column 6.

Debug Lines
Lines contain debug statements (’D’ or ’d’ in column 1) are treated as comments
lines by the precompiler.

Continuation for SQL statements


The line continuation rules for SQL statements are the same as those for other
FORTRAN statements, except that EXEC SQL must be specified within one line.

Appendix F. Coding SQL Statements in FORTRAN Applications 839


Constants containing DBCS data can be continued across multiple lines by placing
the shift-in character in column 73 of the continued line and placing the shift-out
character in column 6 of the continuation line.

This SQL statement has a valid graphic constant of


G’<AABBCCDDEEFFGGHHIIJJKK>’.
*...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
EXEC SQL SELECT * FROM GRAPHTAB WHERE GRAPHCOL = G'<AABBCC>
<DDEEFFGGHHIIJJKK>'

Including Code
SQL statements or FORTRAN statements can be included by embedding the
following SQL statement at the point in the source code where the statements are
to be embedded:
EXEC SQL INCLUDE member-name

The FORTRAN INCLUDE compiler directive cannot be used to include SQL


statements or FORTRAN host variable declarations that are to be used in an SQL
statement.

Margins
Code the SQL statements (starting with EXEC SQL) in coding columns 7 to 72.

Names
Any valid FORTRAN variable name can be used for a host variable and is subject
to the following restrictions:

Do not use host variable names or external entry names that begin with 'SQ', 'SQL',
'RDI', or 'DSN'. These names are reserved for the database manager.

Do not use the following keywords to identify host variables:


FUNCTION
IMPLICIT
PROGRAM
SUBROUTINE

Statement Labels
Executable SQL statements can have statement numbers associated with them,
specified in columns 1 to 5. However, during program preparation, a labelled SQL
statement causes a CONTINUE statement with that label to be generated before
the code runs the statement. A labelled SQL statement should not be the last
statement in a DO loop. Because CONTINUE statements can be run, SQL
statements that occur before the first statement that can be run in a FORTRAN
program (for example, INCLUDE and BEGIN DECLARE SECTION) should not be
labelled.

840 DB2 UDB for AS/400 SQL Programming V4R4


WHENEVER Statement
The target for the GOTO clause in the SQL WHENEVER statement must be a label
in the FORTRAN source and must reference a statement in the same subprogram.
A WHENEVER statement only applies to SQL statements in the same subprogram.

FORTRAN Compile-Time Options


The FORTRAN PROCESS statement can be used to specify the compile-time
options for the FORTRAN compiler. Although the PROCESS statement will be
recognized by the FORTRAN compiler when it is called by the precompiler to create
the program, the SQL precompiler itself does not recognize the PROCESS
statement.

Using Host Variables


All host variables used in SQL statements must be explicitly declared. Implicit
declarations of host variables via default typing or by the IMPLICIT statement are
not supported. A host variable used in an SQL statement must be declared prior to
the first use of the host variable in an SQL statement.

The FORTRAN statements that are used to define the host variables should be
preceded by a BEGIN DECLARE SECTION statement and followed by an END
DECLARE SECTION statement. If a BEGIN DECLARE SECTION and END
DECLARE SECTION are specified, all host variable declarations used in SQL
statements must be between the BEGIN DECLARE SECTION and the END
DECLARE SECTION statements. Note: LOB host variables are not supported in
FORTRAN.

All host variables within an SQL statement must be preceded with a colon (:).

The names of host variables should be unique within the program, even if the host
variables are in different blocks or procedures.

The declaration for a character host variable must not use an expression to define
the length of the character variable. The declaration for a character host variable
must not have an undefined length (for example, CHARACTER(*)).

An SQL statement that uses a host variable must be within the scope of the
statement in which the variable was declared.

Host variables must be scalar variables; they cannot be elements of arrays


(subscripted variables).

Declaring Host Variables


The FORTRAN precompiler only recognizes a subset of valid FORTRAN
declarations as valid host variable declarations.

Numeric Host Variables


The following figure shows the syntax for valid numeric host variable declarations.

Appendix F. Coding SQL Statements in FORTRAN Applications 841


Numeric

ÊÊ INTEGER*2 Ê
INTEGER
*4
REAL
*4
REAL*8
DOUBLE PRECISION

Ê · variable-name ÊÍ
/ numeric-constant /

Character Host Variables


The following figure shows the syntax for valid character host variable declarations.

Character

ÊÊ CHARACTER Ê
*n

Ê · variable-name ÊÍ
*n / character-constant /

Note: n must be a constant no greater than 32766.

Determining Equivalent SQL and FORTRAN Data Types


The precompiler determines the base SQLTYPE and SQLLEN of host variables
based on the following table. If a host variable appears with an indicator variable,
the SQLTYPE is the base SQLTYPE plus one.
Table 78. FORTRAN Declarations Mapped to Typical SQL Data Types
FORTRAN Data Type SQLTYPE of SQLLEN of Host SQL Data Type
Host Variable Variable
INTEGER*2 500 2 SMALLINT
INTEGER*4 496 4 INTEGER
REAL*4 480 4 FLOAT (single
precision)

842 DB2 UDB for AS/400 SQL Programming V4R4


Table 78. FORTRAN Declarations Mapped to Typical SQL Data Types (continued)
FORTRAN Data Type SQLTYPE of SQLLEN of Host SQL Data Type
Host Variable Variable
REAL*8 480 8 FLOAT (double
precision)
CHARACTER*n 452 n CHAR(n)

The following table can be used to determine the FORTRAN data type that is
equivalent to a given SQL data type.
Table 79. SQL Data Types Mapped to Typical FORTRAN Declarations
SQL Data Type FORTRAN Equivalent Explanatory Notes
SMALLINT INTEGER*2
INTEGER INTEGER*4
DECIMAL(p,s) or No exact equivalent Use REAL*8
NUMERIC(p,s)
FLOAT (single precision) REAL*4
FLOAT (double precision) REAL*8
CHAR(n) CHARACTER*n n is a positive integer from 1
to 32766.
VARCHAR(n) No exact equivalent Use a character host variable
large enough to contain the
largest expected VARCHAR
value.
GRAPHIC(n) Not supported Not supported
VARGRAPHIC(n) Not supported Not supported
DATE CHARACTER*n If the format is *USA, *JIS,
*EUR, or *ISO, n must be at
least 10 characters. If the
format is *YMD, *DMY, or
*MDY, n must be at least 8
characters. If the format is
*JUL, n must be at least 6
characters.
TIME CHARACTER*n n must be at least 6; to
include seconds, n must be at
least 8.
TIMESTAMP CHARACTER*n n must be at least 19. To
include microseconds at full
precision, n must be 26. If n
is less than 26, truncation
occurs on the microseconds
part.

Notes on FORTRAN Variable Declaration and Usage


In FORTRAN, a string of digits with a decimal point is interpreted as a real
constant. In an SQL statement, such a string is interpreted as a decimal constant.
Therefore, use exponent notation when specifying a real (floating-point) constant in
an SQL statement.

Appendix F. Coding SQL Statements in FORTRAN Applications 843


In FORTRAN, a real (floating-point) constant having a length of eight bytes uses a
D as the exponent indicator (for example, 3.14159D+04). An 8-byte floating-point
constant in an SQL statement must use an E (for example, 3.14159E+04).

Using Indicator Variables


An indicator variable is a two-byte integer (INTEGER*2). On retrieval, an indicator
variable is used to show if its associated host variable has been assigned a null
value. On assignment to a column, a negative indicator variable is used to indicate
that a null value should be assigned.

See DB2 UDB for AS/400 SQL Reference book for more information on the use of
indicator variables.

Indicator variables are declared in the same way as host variables. The
declarations of the two can be mixed in any way that seems appropriate to the
programmer.

Example:

Given the statement:


EXEC SQL FETCH CLS_CURSOR INTO :CLS_CD,
C :DAY :DAY_IND,
C :BGN :BGN_IND,
C :ENDCLS :ENDCLS_IND

The variables can be declared as follows:


EXEC SQL BEGIN DECLARE SECTION
CHARACTER*7 CLS_CD
INTEGER*2 DAY
CHARACTER*8 BGN, ENDCLS
INTEGER*2 DAY_IND, BGN_IND, ENDCLS_IND
EXEC SQL END DECLARE SECTION

844 DB2 UDB for AS/400 SQL Programming V4R4


Bibliography
This guide lists publications that provide additional information about protecting the system and
information about topics described or referred to in data from being used by people who do not
this guide. The manuals in this section are listed have the proper authorization, protecting the
with their full title and order number, but when data from intentional or unintentional damage or
referred to in text, a shortened version of the title destruction, keeping security up-to-date, and
is used. setting up security on the system.
v Backup and Recovery, SC41-5304-03 v DB2 UDB for AS/400 SQL Reference
This guide contains a subset of the information This guide provides information about DB2 UDB
found in the Backup and Recovery book The for AS/400 statements and their parameters. It
manual contains information about planning a also includes an appendix describing the SQL
backup and recovery strategy, the different communications area (SQLCA) and SQL
types of media available to save and restore description area (SQLDA).
procedures, and disk recovery procedures. It v IDDU Use, SC41-5704-00
also describes how to install the system again
This guide describes how to use DB2 UDB for
from backup.
AS/400 interactive data definition utility (IDDU)
v Data Management to describe data dictionaries, files, and records
This guide provides information about using to the system.
files in application programs. v DATABASE 2/400 Advanced Database
v DB2 UDB for AS/400 Database Programming Functions, GG24-4249
This guide provides a detailed description of the This guide provides suggestions, guidelines,
DB2 UDB for AS/400 database organization, and practical examples of when and how
including information on how to create, functions offered by DB2 UDB for AS/400 such
describe, and update database files on the as triggers, referential integrity, DRDA-2,
system. 2-phase commit, and stored procedures, can be
v CL Programming, SC41-5721-02 effectively used. The book reports examples
developed in several programming languages
This guide provides a wide-ranging discussion
(RPG, COBOL, C), using native and SQL data
of the AS/400 programming topics, including a
access interface, both in the Integrated
general discussion of objects and libraries, CL
Language Environment and with the Original
programming, controlling flow and
Program Model.
communicating between programs, working with
objects in CL programs, and creating CL v ILE COBOL for AS/400 Programmer’s Guide,
programs. Other topics include predefined and SC09-2540-01
impromptu messages and handling, defining This guide provides information you need to
and creating user-defined commands and design, write, test, and maintain COBOL for
menus, application testing, including debug AS/400 programs on the AS/400 system.
mode, breakpoints, traces, and display v ILE RPG for AS/400 Programmer’s Guide,
functions. SC09-2507-02
v CL Reference (Abridged), SC41-5722-03 This guide provides information you need to
This guide provides a description of the AS/400 design, write, test, and maintain ILE RPG for
control language (CL) and its OS/400 AS/400 programs on the AS/400 system.
commands. (Non-OS/400 commands are v ILE C for AS/400 Language Reference,
described in the respective licensed program SC09-2711-01
publications.) It also provides an overview of all
This guide provides information you need to
the CL commands for the AS/400 system, and it
design, write, test, and maintain ILE C for
describes the syntax rules needed to code
AS/400 programs on the AS/400 system.
them.
v ILE C for AS/400 Programmer’s Guide,
v Security - Reference, SC41-5302-03
SC09-2712-01
This guide provides information about system
security concepts, planning for security, and
setting up security on the system. It also gives

© Copyright IBM Corp. 1997, 1999 845


This guide provides information you need to
design, write, test, and maintain ILE C for
AS/400 programs on the AS/400 system.
v ILE COBOL for AS/400 Reference,
SC09-2539-01
This guide provides information you need to
design, write, test, and maintain COBOL for
AS/400 programs on the AS/400 system.
v REXX/400 Programmer’s Guide, SC41-5728-00
This guide provides information you need to
design, write, test, and maintain REXX/400
programs on the AS/400 system.
v PL/I User’s Guide and Reference, SC09-1825
This guide provides information about using
AS/400 PL/I in the System/38 environment.
Differences between the System/38
environment and the AS/400 environment are
identified as well as the enhancements
available in the AS/400 environment.
v DB2 Multisystem for AS/400
This guide describes the fundamental concepts
of distributed relational database files,
nodegroups, and partitioning. The book
provides the information you need to create and
use database files that are partitioned across
multiple AS/400 systems. Information is
provided on how to configure the systems, how
to create the files, and how the files can be
used in applications.
v Performance Tools for AS/400, SC41-5340-00
This guide provides the programmer with the
information needed to collect data about the
system, job, or program performance. This book
also has tips for printing and analyzing
performance data to identify and correct
inefficiencies that might exist. Information about
the manager and agent feature is included.
v DB2 UDB for AS/400 SQL Call Level Interface
This guide provides the information necessary
for application programmers to write
applications using the DB2 call level interface.

846 DB2 UDB for AS/400 SQL Programming V4R4


Index
Special Characters access path (continued)
keyed sequence 396
% (percent sign)
sequential 396
use with LIKE 73
temporary keyed
: (colon)
from keyed access path 436
C++ host variable 230
from the table 435
C host variable 230
access plan 344
COBOL 255
definition 11
FORTRAN 841
in a package 12
ILE RPG for AS/400 313
in a program 11
PL/I 282
validation 425
REXX 330
access plan rebuilt
RPG for AS/400 300
summary record 513
- (dash)
accessing remote databases
in COBOL host variable 255
interactive SQL 359
- (minus)
activation groups
COBOL 255
connection management
%INCLUDE directive 291
example 561
PL/I 281
add row to table 32
*APOST 254
adding data to end of table 552
*CNULRQD 232
address variable, in dynamic SQL 197
/COPY
advanced coding technique
ILE RPG for AS/400 312, 316
complex search condition 72
RPG for AS/400 299, 302
inserting multiple rows into a table 69
#include directive
joining data from multiple tables 75
C 228
advisor
C++ 228
query optimizer index 482
*NOCNULRQD 232
aggregating functions 159
*NOCVTDT 317
ALIAS statement 48
*NOSEQSRC
ALL 86
ILE RPG for AS/400 312 ALLOCATE clause
RPG for AS/400 299 performance implications 457
#pragma mapinc directive allocating storage for SQLDA 208
C 245 allow copy data (ALWCPYDTA) parameter 464
C++ 245 ALTER TABLE 93
*QUOTE 254 ALWCPYDTA (allow copy data) parameter 464
*SEQSRC ALWCPYDTA parameter
ILE RPG for AS/400 312 effect on query optimimizer 423
RPG for AS/400 299 AND keyword
description 74
multiple search condition 74
A ANY 86
access method API
dataspace scan 399 QSQCHKS 2
hashing access 415 QSQPRCED 2
index-from-index 414 apostrophe
index only access 412 C 249
key positioning 406 C++ 249
key selection 404 application
parallel data space scan 403 binding 344
parallel key positioning 411 dynamic SQL
parallel key selection access method 405 designing and running 199
parallel pre-fetch 401 overview 197
parallel pre-load 413 application design
row selection method 397 user-defined function (UDF) 185
summary table 420 application domain and object-orientation 145
access path application forms using CREATE TABLE example 171
definition 396 application plans 344

© Copyright IBM Corp. 1997, 1999 847


application procedure assignments involving different UDTs example 176
coding SQL statements assignments involving UDTs example 175
REXX 325 asterisk (select all columns) 38
application program atomic operation
coding SQL statements data definition statements (DDL) 373
C 225, 251 data integrity 373
C++ 225 definition 373
COBOL 251, 279 Auditing
FORTRAN 837, 845 C2 security 366
ILE RPG for AS/400 309, 325 authority, public 365
PL/I 279, 295 authorization
RPG for AS/400 297, 307 Create SQL Package (CRTSQLPKG)
compiling, ILE 341 command 558
compiling, non-ILE 340 for creating package 557
creating 9 for running using a package 557
SQLCA (SQL communication area) ID 366
C 225 testing 379, 380
C++ 225 auxiliary storage pools 368, 378
COBOL 251 AVG over a UDT example 164
FORTRAN 837
ILE RPG for AS/400 309 B
PL/I 279 basic SQL statements and clauses 31
RPG for AS/400 297 BEGIN DECLARE SECTION statement
SQLDA C 230
C 226 C++ 230
C++ 226 COBOL 255
COBOL 252 FORTRAN 841
FORTRAN 838 ILE RPG for AS/400 312
ILE RPG for AS/400 310 PL/I 282
PL/I 280 RPG for AS/400 300
RPG for AS/400 298 BETWEEN clause, multiple search condition 72
testing SQL statements in 379 BETWEEN keyword 72
application requester 555 bibliography 845
application requester driver (ARD) programs Binary Large OBjects 146
package creation 577 binding 344
running statements 577 BLOBs (Binary Large OBjects)
application server 555 uses and definition 146
ARD (application requester driver) programs 577 blocked insert statement 70
arithmetic error blocking, SQL
in UDFs 188, 192 improving performance 462
arithmetic expression error 37, 38 blocking consideration
arranging rows 41 using, affect on performance 461
arrays of host structures
using arrays
C 241 C
C++ 241 C++ program
COBOL 268 #include directive 228
ILE RPG for AS/400 314 #pragma mapinc directive 245
PL/I 289 apostrophes 249
RPG for AS/400 301 BEGIN/END DECLARE SECTION 230
arrival sequence coding SQL statements 225
summary record 498 comment 228
assignment rule compiler parameters 341
date 218 continuation 228
host variable dynamic SQL coding 226
using 216 error and warning message during a compile 343
numeric assignment 218 external file description 245
string 217 host structure
time 218 array indicator structure, declaring 244
timestamp 218 arrays, declaring 241
assignments in dynamic SQL example 175 declaring 239

848 DB2 UDB for AS/400 SQL Programming V4R4


C++ program (continued) C program (continued)
indicator array 228 SQLCODE, declaring 228
host variable 230 SQLDA, declaring 226
character 231 SQLSTATE, declaring 225
declaring 230 statement label 229
externally described 245 trigraph 229
graphic 233 union elements 230
numeric 230 WHENEVER statement 230
using pointers 244 C2 security
INCLUDE statement 228 auditing 366
including code 228 call level interface 2
margin 229 call-type
naming convention 229 contents with table functions 190
null 229 call-type, passing to UDF 190
preprocessor sequence 229 calls, number
quotation marks 249 using
SQL data types FETCH statement 462
determining equivalent C++ 246 cancelling a query 392
SQLCA, declaring 225 CAST FROM clause 188, 190, 192
SQLCODE, declaring 225 castability 157
SQLDA, declaring 226 casting, UDFs 169
SQLSTATE, declaring 225 catalog
statement label 229 database design, use in 97
trigraph 229 definition 6
WHENEVER statement 230 getting information about 97
C program column 98
integrity 377
#include directive 228
LABEL ON information 48
#pragma mapinc directive 245
QSYS2 views 6
apostrophes 249
table 97
BEGIN/END DECLARE SECTION 230
CCSID
coding SQL statements 225, 251
connection to non-DB2 UDB for AS/400 561
comment 228
delimited identifier effect 561
compiler parameters 341
dynamic SQL statement 200
continuation 228
include file 334
dynamic SQL coding 226
package considerations 561
error and warning message during a compile 343
printer file 335
external file description 245
rule for using 217
host structure
source file 334
array indicator structure, declaring 244
temporary source file 335
arrays, declaring 241
Change Class (CHGCLS) command 367
declaring 239
change information
indicator array 241
in table
host variable 230
host variables 33, 34
character 231
Change Job (CHGJOB) command 367
declaring 230, 236
Change Logical File (CHGLF) command 367
externally described 245
Change Physical File (CHGPF) command 367
graphic 233
numeric 230 Change Query Attribute (CHGQRYA) command 402
using pointers 244 Change query attributes 543
INCLUDE statement 228 Change Query Attributes (CHGQRYA) command 381
including code 228 change session attributes
indicator structure 249 interactive SQL 357
indicator variable 249 changing
margin 229 data 33
naming convention 229 information in a table 25
null 229 query options file 546
preprocessor sequence 229 table definition 93, 554
quotation marks 249 character host variable
SQL data types C 231
determining equivalent C 246 C++ 231
SQLCA, declaring 225 COBOL 258

Index 849
character host variable (continued) COBOL program 262 (continued)
FORTRAN 231 file reference variable
ILE RPG for AS/400 314, 318 LOB 262, 316
PL/I 283 host structure
RPG for AS/400 300, 303 array indicator structure, declaring 272
Character Large OBjects 146 arrays, declaring 268
check constraints 99 declaring 264
check pending 107, 375 indicator array 268
checking syntax in interactive SQL 353 host variable 255
CHGPF command 33 character 258
CHGQRYA (Change Query Attributes) command 381 declaring 255, 261
CL_SCHED table 585 externally described 272
class schedule table 585 floating point 257
clause 47 graphic 259
AND 74 LOB 261, 315
DISTINCT 72 numeric 255
FROM 36 including code 254
GROUP BY indicator structure 276
example 40 indicator variable 276
HAVING 42 locator
INTO LOB 262, 316
example 32 margin 254
PREPARE statement, use with 202 multiple source programs 255
restriction 208 naming convention 254
NOT 74 REDEFINES 276
null value 45 sample program with SQL statements 613
OR 74 sequence numbers 254
ORDER BY 43 SQL 613
SELECT 38 SQL data types
SET 33 determining equivalent COBOL 274
USING DESCRIPTOR 213 SQLCA, declaring 251
VALUES 31 SQLCODE, declaring 251
WHENEVER NOT FOUND 60 SQLDA, declaring 252
WHERE SQLSTATE, declaring 251
character string 31 statement label 255
example 38, 213 WHENEVER statement 255
expression 39 coded character set conversion error 38
joining tables 76 coded character set identifier (CCSID) 217
multiple search condition within 74
coding examples, SQL statements in
NOT keyword 40
WHERE CURRENT OF 61 COBOL 613
CLI 2 ILE C 606
CLOBs (Character Large OBjects) ILE COBOL 613
uses and definition 146 ILE RPG for AS/400 program 634
PL/I 621
CLOSQLCSR parameter
REXX 640
effect on implicit disconnect 565
REXX applications 327
using 469
RPG for AS/400 628
COBOL program 272
BEGIN/END DECLARE SECTION 255 coding requirement
COBOL COPY statement 254, 272 C++ program
COBOL PROCESS statement 254 comment 228
coding SQL statements 251, 279 continuation 228
comment 253 host variable 230
compile-time option 254 including code 228
compiler parameters 340 margin 229
continuation 253 naming convention 229
Datetime host variable 263 null 229
debug lines 253 preprocessor sequence 229
dynamic SQL coding 252 statement label 229
error and warning message during a compile 344 trigraph 229
external file description 272 WHENEVER statement 230

850 DB2 UDB for AS/400 SQL Programming V4R4


coding requirement (continued) coding requirement (continued)
C program RPG for AS/400 program (continued)
comment 228 indicator variable 299
continuation 228 naming convention 299
host variable 230 statement label 300
including code 228 WHENEVER statement 300
indicator variable 249 coding SQL statements
margin 229 in REXX applications 325
naming convention 229 coding techniques 31, 55, 69
null 229 collating rows 41
preprocessor sequence 229 collection
statement label 229 changing
trigraph 229 table definition 554
WHENEVER statement 230 creating 13
COBOL program definition 3, 6
COBOL PROCESS statement 254 solving problem
comment 253 paging through retrieved data 551
compile-time option 254 retrieving data a second time 553
continuation 253 colon
debug lines 253 in C++ host variable 230
host variable 255 in C host variable 230
indicator variable 276 in COBOL host variable 255
margin 254 in FORTRAN host variable 841
multiple source programs 255 in ILE RPG for AS/400 host variable 313
naming convention 254 in PL/I host variable 282
statement label 255 in RPG for AS/400 host variable 300
WHENEVER statement 255 column
FORTRAN program defining heading 16, 48
comment 839 definition 3, 6
continuation 839 FOR UPDATE OF clause 58
debug lines 839 getting catalog information about 98
host variable 841 name
including code 840 definition 39
indicator variable 844 SET clause, value 33
margin 840 updating view 29
naming convention 840 column functions 159
statement label 840 combining
WHENEVER statement 841 information from multiple tables 23
ILE RPG for AS/400 program SELECT statement 80
comment 311 subselect with UNION
continuation 311 example 80
host variable 312 command
including code 312 CHGQRYA 543
indicator variable 322 CHGQRYA command 543
naming convention 312 QAQQINI 543
statement label 312 QAQQINI command 543
WHENEVER statement 312 RUNSQLSTM
PL/I program errors 362
comment 281
command, CL
continuation 281
Create Structured Query Language Package
host variable 282
(CRTSQLPKG) 763
including code 281
CRTSQLPKG (Create Structured Query Language
indicator variable 294
Package) 763
margin 281
Delete Structured Query Language Package
naming convention 282
(DLTSQLPKG) 782
WHENEVER statement 282
DLTSQLPKG (Delete Structured Query Language
RPG for AS/400 program
Package) 782
comment 299
command (CL) 819, 835
continuation 299
Change Class (CHGCLS) 367
host variable 300
Change Job (CHGJOB) 367
including code 299
Change Logical File (CHGLF) 367

Index 851
command (CL) 367, 835 (continued) command (CL) 1, 835 (continued)
Change Physical File (CHGPF) 367 RUNSQLSTM (Run SQL statements) 367
Change Query Attribute (CHGQRYA) command 402 RUNSQLSTM (Run SQL Statements) 361, 794
Change Query Attributes (CHGQRYA) 381 RVKOBJAUT (Revoke Object Authority) 365
CHGCLS (Change Class) 367 Send Program Message (SNDPGMMSG) 587
CHGJOB (Change Job) 367 Send User Message (SNDUSRMSG) 587
CHGLF (Change Logical File) 367 SNDPGMMSG (Send Program Message) 587
CHGPF (Change Physical File) 367 SNDUSRMSG (Send User Message) 587
CHGQRYA (Change Query Attribute) command 402 Start Commitment Control (STRCMTCTL) 370
CHGQRYA (Change Query Attributes) 381 Start Journal Access Path (STRJRNAP) 376
Convert SQL C++ (CVTSQLCPP) 781 STRCMTCTL (Start Commitment Control) 370
Create Duplicate Object (CRTDUPOBJ) 380 STRJRNAP (Start Journal Access Path) 376
Create Source Physical File (CRTSRCPF) STRSQL (Start SQL) 801
command 335 Trace Job (TRCJOB) 382, 461
Create SQL C++ (CRTSQLCPPI) 712 TRCJOB (Trace Job) 382, 461
Create SQL COBOL (CRTSQLCBL) 661 commands
Create SQL ILE C for AS/400 (CRTSQLCI) 695 End Database Monitor (ENDDBMON) 480
Create SQL ILE COBOL (CRTSQLCBLI) 678 Start Database Monitor (STRDBMON) 479
Create SQL ILE/RPG (CRTSQLRPGI) 761 comment
Create SQL Package (CRTSQLPKG) 557, 765 C 228
Create SQL PL/I (CRTSQLPLI) 728 C++ 228
Create SQL RPG (CRTSQLRPG) 744 COBOL 253
Create User Profile (CRTUSRPRF) 366 for RUNSQLSTM 361
CRTDUPOBJ (Create Duplicate Object) FORTRAN 839
command 380 getting 50
CRTUSRPRF (Create User Profile) 366 ILE RPG for AS/400 311
Delete Library (DLTLIB) 374 PL/I 281
Delete Override (DLTOVR) 459 REXX 328
Delete SQL Package (DLTSQLPKG) 557, 783 RPG for AS/400 299
Display Job (DSPJOB) 381 COMMENT ON statement
Display Journal (DSPJRN) 461 using, example 49
Display Message Description (DSPMSGD) 587 COMMIT
Display Module (DSPMOD) 345 keyword 370
Display Program (DSPPGM) 345 prepared statements 201
Display Program References (DSPPGMREF) 345 statement 559
Display Service Program (DSPSRVPGM) 345 statement description 6
DLTLIB (Delete Library) 374 commitment control
DLTOVR (Delete Override) 459 activation group
DSPJOB (Display Job) 381 example 561
DSPJRN (Display Journal) 461 committable updates 567
DSPMSGD (Display Message Description) 587 description 369
Edit Check Pending Constraints (EDTCPCST) 375 displaying 381
Edit Rebuild of Access Paths (EDTRBDAP) 375 distributed connection restrictions 570
Edit Recovery for Access Paths (EDTRCYAP) 376 DRDA resource 567
EDTCPCST (Edit Check Pending Constraints) 375 INSERT statement 32
EDTRBDAP (Edit Rebuild of Access Paths) 375 job-level commitment definition 565, 570
EDTRCYAP (Edit Recovery for Access Paths) 376 protected resource 567
Grant Object Authority (GRTOBJAUT) 365 rollback required 572
GRTOBJAUT (Grant Object Authority) 365, 367 RUNSQLSTM command 362
Override Database File (OVRDBF) 62, 302, 346, SQL statement processor 362
367, 459, 461, 462 sync point manager 567
OVRDBF (Override Database File) 62, 302, 346, two-phase commit 567
367, 459, 461, 462 unprotected resource 567
Print SQL Information (PRTSQLINF) 345, 382, 393, common database problem
784 solving 551
QAQQINI 546 comparison operators 40
Reclaim DDM connections (RCLDDMCNV) 573 comparisons involving UDTs example 173, 174
Retrieve Message (RTVMSG) 587
compile step
Revoke Object Authority (RVKOBJAUT) 365
warning 343
RTVMSG (Retrieve Message) 587
compile-time option
Run SQL Statements (RUNSQLSTM) 1
COBOL 254

852 DB2 UDB for AS/400 SQL Programming V4R4


compiled application program object connection management (continued)
managing object 9 multiple connections to same relational
output source file member 11 database 577
program 9 connection status
user source file member 11 determining 570
compiling example 576
application program consistency token 560
ILE 341 consistent behavior and UDTs 169
non-ILE 340 constant
application program object definition 39
output source file member 11 SET clause, value 33
program 11 constraint 375
user source file member 11 definition 8
error message 343 referential 8
warning message 343 unique 8
compiling a UDF 160 constraint mechanisms on large objects 145
completing a unit of work 68 constraints
complex search condition check 99
keyword for use in 72 referential
multiple search condition 72 check pending 107
performing 72 creating tables 100
WHERE clause 31 delete rules 105
concept deleting from tables 105
assignment rule, using SQL with host language 216 inserting into tables 102
host language, using SQL with removing 102
handling return code 221 update rules 103
host structure 220 updating tables 103
host variable 215 continuation
SQLCODEs 221 C 228
SQLSTATEs 221 C++ 228
SQLSTATEs 221 COBOL 253
concurrency FORTRAN 839
data 367 ILE RPG for AS/400 311
definition 367 PL/I 281
condition RPG for AS/400 299
keyword for use in search 72 control, commitment 369
multiple search within a WHERE clause 74 control information to access large object data 147
performing complex search 72 control structures 12
CONNECT statement 555, 559 controlling parallel processing 473
interactive SQL 360 convention
SQL naming 4
connection
system naming 3
DDM 573
conversion error 37
determining type 567
Convert SQL C++ (CVTSQLCPP) command 781
ending DDM 573
copy of the data
protected 567
using to improve performance 465
unprotected 567
COPY statement
connection management
COBOL 254
ARD programs 577
externally described 272
commitment control restrictions 570
CORPDATA.DEPARTMENT (department) 579
distributed unit of work considerations 572
ending connections CORPDATA.EMP_ACT (employee to project
DDMCNV effect on 573 activity) 581
DISCONNECT statement 573 CORPDATA.EMP_ACT table 581
RELEASE statement 573 CORPDATA.EMPLOYEE table 580
example 561 CORPDATA.PROJECT (project) 584
implicit connection CORPDATA.PROJECT table 584
default activation group 565 correlated
nondefault activation group 566 names 91
implicit disconnection references 91
default activation group 565 correlated subquery
nondefault activation group 566 definition 88

Index 853
correlated subquery (continued) creating (continued)
DELETE statement, use in 88 view 13
examples description 28
HAVING clause 90 on a table 29
UPDATE statement 91 over multiple tables 30
WHERE clause 89 cross join 78
note on using 92 CRTDUPOBJ (Create Duplicate Object) command 380
correlation CRTSQLC (Create SQL C) command 819
definition 85 CRTSQLCBL (Create SQL COBOL) command 661
name 23, 79 CRTSQLCBLI (Create SQL ILE/COBOL)
using subquery 85 command 678
cost estimation CRTSQLCI (Create SQL ILE C for AS/400)
query optimizer 423 command 695
cost of a UDT example 163 CRTSQLCPPI (Create SQL C++) command 712
counter for UDFs example 194 CRTSQLFTN (Create SQL FORTRAN) command 835
counting and defining UDFs example 164 CRTSQLPKG (Create SQL Package) command 765
CREATE COLLECTION statement 13 CRTSQLPKG (Create Structured Query Language
CREATE DISTINCT TYPE statement Package) command 763
and castability 157 CRTSQLPLI (Create SQL PL/I) command 728
examples of using 171 CRTSQLRPG (Create SQL RPG) command 744
to define a UDT 170 CRTSQLRPGI (Create SQL ILE/RPG) command 761
Create Duplicate Object (CRTDUPOBJ) command 380 CRTSQLxxx commands 3
CREATE FUNCTION statement 190 CRTUSRPRF command
to register a UDF 161 create user profile 366
CREATE INDEX ctr() UDF C program listing 194
sort sequence 53 CURDATE scalar function 46
CREATE SCHEMA CURRENT DATE special register 45
statement 362 current row 60
Create Source Physical File (CRTSRCPF) command CURRENT SERVER special register 45
precompile use 335 current session
Create SQL C++ (CRTSQLCPPI) command 712 printing 357
Create SQL C (CRTSQLC) command 819 removing all entries from 357
Create SQL COBOL (CRTSQLCBL) command 661 CURRENT TIME special register 45
Create SQL FORTRAN (CRTSQLFTN) command 835 CURRENT TIMESTAMP special register 45
Create SQL ILE C for AS/400 (CRTSQLCI) CURRENT TIMEZONE special register 45
command 695 cursor
Create SQL ILE COBOL (CRTSQLCBLI) distributed unit of work 576
command 678 example overview 56
Create SQL ILE/RPG (CRTSQLRPGI) command 761 example steps 58, 62
Create SQL Package (CRTSQLPKG) command 340, open 59
557, 765 open, effect of recovery on 68
authority required 558 positions
Create SQL PL/I (CRTSQLPLI) command 728 retaining across program call 467, 468
Create SQL RPG (CRTSQLRPG) command 744 rules for retaining 467
Create Structured Query Language Package using to improve performance 467, 468
(CRTSQLPKG) command 763 retrieving SELECT statement result 212
CREATE TABLE scrollable
prompting 353 positioning within a table 55
CREATE TABLE statement 14 serial
examples of using 171 positioning within a table 55
using 55
Create User Profile (CRTUSRPRF) command 366
WITH HOLD clause 68
CREATE VIEW statement 29
CURTIME scalar function 46
creating
CVTSQLCPP (Convert SQL C++) command 781
collection
example 13
index D
example 96 damage tolerance 376
structured query language package 763 dash
table in COBOL host variable 255
description 14 data
example 14 adding to the end of table 552

854 DB2 UDB for AS/400 SQL Programming V4R4


data (continued) database monitor performance records 481
paging database query performance
interactively displayed to improve monitoring 478
performance 463 dataspace
retrieved 551 definition 397
retrieving dataspace scan
in reverse order 551 access method 399
selecting from multiple tables date assignment rule
affect on performance 442 host variable, using 218
updating date format 47
as it is retrieved 552 specifying current value 47
previously retrieved 553 date/time arithmetic 47
view, processing 36 date/time host variable
data definition statement (DDL) 4 ILE RPG for AS/400 313
data dictionary Datetime host variable
WITH DATA DICTIONARY clause COBOL 263
CREATE COLLECTION statement 6 DATFMT
CREATE SCHEMA statement 6 ILE RPG for AS/400 313, 317
data independence 32, 38 DATSEP
data integrity 99 ILE RPG for AS/400 313, 317
atomic operation 373 DB2 Multisystem 2
commitment control 369 DB2 Query Manager for AS/400 2
concurrency 367 DB2 UDB for AS/400 1
constraint 375 C program 605
damage tolerance 376 distributed relational database support 555
data definition statements (DDL) 373 DB2 UDB for AS/400 sample table 579
function 366 DB2 UDB Query Manager and SQL Development Kit 1
index recovery 376 distributed relational database support 555
journaling 368 DB2 UDB Symmetric Multiprocessing 2
save/restore 375 DB2 Universal Database
data items considerations for packages 558
ILE RPG for AS/400 314 DBCLOBs (Double-Byte Character Large OBjects)
RPG for AS/400 300 uses and definition 146
data manipulation statement (DML) 4 DBCS (double-byte character set)
data mapping error 37 considerations in interactive SQL 353
data path, open 388 DBCS constants
data protection 365 continuation
data type C 228
determining equivalent C++ 228
C 246 COBOL 254
C++ 246 FORTRAN 839
COBOL 274 ILE RPG for AS/400 311
FORTRAN 842 PL/I 281
ILE RPG for AS/400 318 RPG for AS/400 299
PL/I 292 in SQL source 334
REXX 330 DBGVIEW(*SOURCE) parameter 380
RPG for AS/400 303 dbinfo, passing to UDF 190
data types DBINFO keyword 190
BLOBs 146 dbminfo argument, elements of 190
CLOBs 146 DDM (distributed data management)
DBCLOBs 146 considerations 346
object-oriented 145 running a program with embedded SQL 346
database DDS
design, using the catalog in 97 database monitor logical file 493
relational 3 database monitor physical file 489
database monitor deadlock detection 367
end 480 debug lines
examples 482, 485 COBOL 253
logical file DDS 493 FORTRAN 839
physical file DDS 489 debugging 379
start 479 common database problem 551

Index 855
debugging 551 (continued) definitions 406 (continued)
program 551 key positioning access method 396
DECLARE CURSOR statement key selection access method 404
using 36 keyed sequence 396
DECLARE statement 198 library 3
default collection name (DFTRDBCOL) parameter 3 logical file 3
default filter factors 424 miniplan 425
DEFAULT keyword NULL value 40
SET clause, value 34 null value 45
default value 14, 18, 32 open data path 388
inserting in a view 96 outer-level SELECT 84
define output source file member 11
cursor 58 package 3, 9, 12, 557
defining parallel data space scan method 403
parallel key positioning access method 411
column heading 16, 48
parallel key selection access method 405
table name 48
parallel pre-fetch access method 401
defining the UDT and UDFs example 178
physical file 3
definitions 555
predicate 38
access path 396
primary table 426
access plan 11, 344
program 11
authorization ID 3
record 3
authorization name 3
referential integrity 8
binding 344
remote unit of work 555
catalog 6
row 3, 6
collection 3, 6
search condition 38
column 3, 6
secondary tables 426
column name 39
sequential access path 396
concurrency 367
special register 40
constant 39
SQL package 3
constraint 8
SQLCODE 587
correlated subquery 88
SQLSTATE 587
correlation 85
stored procedure 8
CURRENT DATE special register 45
subquery 84
current row 60
symmetrical multiprocessing 397
CURRENT SERVER special register 45
table 3, 6
CURRENT TIME special register 45
trigger 8
CURRENT TIMESTAMP special register 45
user profile 3
CURRENT TIMEZONE special register 45
user source file member 11
data definition statement (DDL) 4
USER special register 45
data dictionary 6
view 3, 7
data manipulation statement (DML) 4
delete current row 61
dataspace 397
Delete Library (DLTLIB) command 374
default filter factors 424
Delete Override (DLTOVR) command 459
dial 426
Delete SQL Package (DLTSQLPKG) command 557,
distributed unit of work 555
783
expression 39
DELETE statement
field 3
correlated subquery, use in 92
hashing access method 415
description 28, 34
host structure 215
Delete Structured Query Language Package
host variable 39, 215
(DLTSQLPKG) command 782
implementation cost 423
index 8 deleted rows
index-from-index access method 414 getting rid of using REUSEDLT(*YES) 399
index only access method 412 getting rid of using RGZPFM 399
indicator structure 220 deleting
indicator variable 219 structured query language package 782
isolatable 437 deleting information in a table 28
join 30 department table
join operation 23 CORPDATA.DEPARTMENT 579
journal 6 DESCRIBE statement
journal receiver 6 use with dynamic SQL 201

856 DB2 UDB for AS/400 SQL Programming V4R4


DESCRIBE TABLE statement 559 distributed relational database (continued)
description packages 359
SQLCODEs and SQLSTATEs 589 statement in 558
descriptions, C for AS/400 external file 803 precompiler diagnostic messages 558
descriptor-name problem handling 578
in REXX 325 protected connection 567
designing protected resource 567
dynamic SQL application 199 remote unit of work 555, 566
detail record rollback required state 572
records retrieved 523 session attributes 360
DFT_SQLMATHWARN configuration parameter 188, SQL packages 557
192 sync point manager 567
DFTRDBCOL (default collection name) parameter 3 two-phase commit 567
diagnostic-message, passing to UDF 189 unprotected connection 567
DISCONNECT statement 555, 559 unprotected resource 567
ending connection 573 valid SQL statements 558
Display Job (DSPJOB) command 381 Distributed Relational Database Architecture (DRDA) 1
Display Journal (DSPJRN) command 461 distributed unit of work 555, 566, 573
Display Message Description (DSPMSGD) connection considerations 572
command 587 connection status 570
Display Module (DSPMOD) 345 connection type 567
Display Program (DSPPGM) command 345 cursors 576
Display Program References (DSPPGMREF) prepared statements 576
command 345 sample program 574
Display Service Program (DSPSRVPGM) 345 DLTSQLPKG (Delete SQL Package) command 783
displaying SQLCODE and SQLSTATE description 587 DLTSQLPKG (Delete Structured Query Language
DISTINCT 71 Package) command 782
clause 72 Double-Byte Character Large OBjects 146
keyword 553 DRDA (Distributed Relational Database
distinct type 157 Architecture) 555
distributed data management (DDM) 346 DRDA level 1 566
distributed relational database DRDA level 2 566
accessing remote databases 359 DRDA resource 567
application requester 555 DROP PACKAGE statement 555
application server 555 DSPJOB (Display Job) command 381
committable updates 567, 570 duplicate rows
connection management 561 eliminating 81
multiple connections 565 preventing 71
connection restrictions 570 DUW (distributed unit of work) 555
connection type dynamic SQL
determining 567 address variable 197
protected 567 allocating storage 203
unprotected 567 application 197, 199
consideration for creating packages 558 building and running statements 197
creating packages 558 CCSID 200
DB2 UDB for AS/400 support 555 coding in C 226
determining connection status 570 coding in C++ 226
distributed RUW example program 556 coding in COBOL 252
distributed unit of work 555, 566, 573 coding in FORTRAN 838
ending connections coding in ILE RPG for AS/400 310
DDMCNV effect on 573 coding in PL/I 280
DISCONNECT statement 573 coding in RPG for AS/400 298
RELEASE statement 573 cursor, use in 202
first failure data capture (FFDC) 578 DESCRIBE statement 201
implicit connection EXECUTE statement 199
default activation group 565 FETCH, multiple-row
nondefault activation group 566 ILE RPG for AS/400 323
implicit disconnection fixed-list SELECT statement, using 202
default activation group 565 parameter marker 213
nondefault activation group 566 PREPARE statement 199
interactive SQL 359 processing non-SELECT statements 199

Index 857
dynamic SQL (continued) examples 74, 50, 220 (continued)
replacing parameter markers with host AND 74, 75
variables 197 application forms using CREATE TABLE 171
run-time overhead 197 assignments in dynamic SQL 175
statements 4 assignments involving different UDTs 176
varying-list SELECT statement 201 assignments involving UDTs 175
AVG over a UDT 164
BETWEEN 72
E catalog
Edit Check Pending Constraints (EDTCPCST) getting column information 97
command 375 getting table information 97
Edit Rebuild of Access Paths (EDTRBDAP) changing information in a table 25
command 375 changing rows in table
Edit Recovery for Access Paths (EDTRCYAP) host variables 33, 34
command 376 COBOL, UPDATE statement 253
eliminating duplicate rows 81 COMMENT ON 49
embedded SQL comparisons involving UDTs 173, 174
C 227 correlated subquery
C++ 227 HAVING clause 90
COBOL 253 WHERE clause 89
FORTRAN 839 correlation name 23
ILE RPG for AS/400 311 cost of a UDT 163
PL/I 280 counter for UDFs 194
precompiling 333 counting and defining UDFs 164
RPG for AS/400 298 creating
running a program with 346 collection 13
employee-to-project activity table 581 index 96
encapsulation and UDTs 169 table 14
End Database Monitor (ENDDBMON) command 480 view on a table 29
END DECLARE SECTION statement views over multiple tables 30
C 230 ctr() UDF C program listing 194
C++ 230 CURRENT DATE 47
COBOL 255 CURRENT TIMEZONE 47
FORTRAN 841 cursor 56
ILE RPG for AS/400 312 cursor in DUW program 576
PL/I 282 database monitor 482, 485
RPG for AS/400 300 defining stored procedures
end-of-data with CREATE PROCEDURE 117
reached 59 defining the UDT and UDFs 178
ENDDBMON (end database monitor) command 480 deleting information in a table 28
entering DBCS data 353 determining connection status 576
ERRLVL 362 distributed RUW program 556
error distributed unit of work program 574
data mapping dynamic CALL 127
ORDER BY 37 embedded CALL 124, 125
error determination EXISTS 87
in distributed relational database exploiting LOB function to populate the
first failure data capture (FFDC) 578 database 179
error message during a compile 343 exploiting LOB locators to manipulate UDT
C++ program 343 instances 180
C program 343 exploiting UDFs to query instances of UDTs 179
COBOL program 343, 344 exponentiation and defining UDFs 161
PL/I program 343 extracting a document to a file (CLOB elements in a
RPG program 343, 344 table) 152
error message during precompile function invocations 165
displayed on listing 335 getting catalog information about
error return code, handling column 98
table 97
general 221
getting comment 50
establishing
getting information about
position at end of table 551
column using catalog 97
examples 49, 50, 220

858 DB2 UDB for AS/400 SQL Programming V4R4


examples 97, 50, 220 (continued) examples 83, 50, 220 (continued)
table using catalog 74 Union
getting information from simple 83
multiple tables 23 UNION
single table 20 using host variables 81
governor 394 UNION ALL
host variable in SQL statement 215 using host variables 83
IN 73 unqualified function reference 167
index 446 UPDATE statement 25
inserting use of UDTs in UNION 177
add row to table 32 user-defined sourced functions on UDTs 175
multiple rows into a table 69 using a locator to work with a CLOB value 148
inserting data into a CLOB column 154 using index 96
invoking stored procedures 127 using qualified function reference 166
where a CREATE PROCEDURE exists 124 variable declaration 276
where no CREATE PROCEDURE exists 125 view
join 76 sort sequence 53
LABEL ON statement 16, 48 WITH CASCADED CHECK OPTION 110
LIKE 73 WITH LOCAL CHECK OPTION 110
list function in interactive SQL 354 working with index 96
LOBFILE.SQB COBOL program listing 153 exception condition 222
LOBFILE.SQC C program listing 153 exception join 77
LOBLOC.SQB COBOL program listing 150 EXECSQL REXX command 325, 327
LOBLOC.SQC C program listing 149 EXECUTE IMMEDIATE statement 199
money using CREATE DISTINCT TYPE 171 EXECUTE privileges
multiple search condition (WHERE clause) 74 for packages 557
OR 75 EXECUTE statement 199, 200
ORDER BY EXISTS keyword, use in subquery 87
sort sequence 51 exiting interactive SQL 357
output from precompiler, COBOL 336 exploiting
parameter markers in functions 166 LOB function to populate the database
performance analysis 483, 484 example 179
preventing duplicate rows 71 LOB locators to manipulate UDT instances
QSYSPRT listing example 180
SQL statement processor 363 UDFs to query instances of UDTs example 179
reducing the number of open database exponentiation and defining UDFs example 161
operation 459 expression
removing information definition 39
from table 28, 34 SET clause, value 33
resume using CREATE DISTINCT TYPE 171 using in the WHERE clause 39
returning completion status extended dynamic
to calling program 135 QSQPRCED 2
RPG for AS/400 extensibility and UDTs 169
declare variable 306 external file description
sales using CREATE TABLE 171 C 245
sample table 579 C++ 245
search 72 C for AS/400 803
search string and BLOBs 162 COBOL 272
SELECT records host structure arrays
sort sequence 52 COBOL 273
SELECT statement allocating storage for ILE RPG for AS/400 317
SQLDA 208 RPG for AS/400 303
selecting data from multiple tables 442 ILE RPG for AS/400 316
selecting into table PL/I 291
host variables 36 RPG for AS/400 302
special register 47 extracting a document to a file (CLOB elements in a
stored procedures table) example 152
returning completion status 135
string search and defining UDFs 162
string search over UDT 163
subquery 84
F
failed session, recovering 358

Index 859
FETCH FORTRAN program (continued)
using host structure array margin 841
multiple-row 63 naming convention 840
FETCH statement 212 PROCESS statement 841
multiple-row SQL data types
ILE RPG for AS/400 314, 323 determining equivalent FORTRAN 842
RPG for AS/400 301 SQLCA, declaring 837
FFDC (first failure data capture) 578 SQLCOD, declaring 837
field 3 SQLCODE, declaring 837
file SQLSTA, declaring 837
query options 546 SQLSTATE, declaring 837
file description statement label 840
external WHENEVER statement 841
C 245 FROM clause 36
C++ 245 function
C for AS/400 803 interactive SQL 349
COBOL 272 function invocations example 165
ILE RPG for AS/400 316 function-name, passing to UDF 189
PL/I 291 function path and UDFs 158
RPG for AS/400 302 function references, summary for UDFs 167
host structure arrays function selection algorithm and UDFs 158
COBOL 273 functions
ILE RPG for AS/400 317 aggregating functions 159
RPG for AS/400 303 column functions 159
file reference variable scalar functions 159
LOB syntax for referring to 165
COBOL 262, 316 table functions 159
file reference variables
examples of using 152
for manipulating LOBs 146 G
input values 151 generic query information
LOB summary record 520
PL/I 286 getting
output values 152 catalog information about
filter factors, default column 98
in query optimization 424 table 97
first failure data capture (FFDC) 578 comment 50
fixed-list SELECT statement information
definition 201 from multiple table 23
using 201 from single table 20
flexibility and UDTs 169 governor 391
floating point host variable *DFT 393
COBOL 257 *RQD 393
FOR UPDATE OF clause *SYSRPYL 393
restrictions 58 CHGQRYA 391
format, SQLDA 204 JOB 392
FORTRAN program QRYTIMLMT 391
BEGIN/END DECLARE SECTION 841 time limit 392
coding SQL statements 837, 845 Grant Object Authority (GRTOBJAUT) command 365
comment 839 GRANT PACKAGE statement 555
compile-time options 841 graphic host variable
continuation 839 C 233
debug lines 839 C++ 233
dynamic SQL coding 838 COBOL 259
host variable 841 ILE RPG for AS/400 318
character 842 GROUP BY
declaring 841, 842 clause 40
numeric 841 keyword 553
IMPLICIT statement 841 using null value with 41
including code 840 grouping optimization 442
indicator variable 844 grouping the row you select 41

860 DB2 UDB for AS/400 SQL Programming V4R4


H host variable 245 (continued)
external file description
halfword binary integer (SMALLINT) 218 C 245
handling C++ 245
error return code COBOL 272
SQLCODEs and SQLSTATEs 221 ILE RPG for AS/400 316
exception condition (WHENEVER statement) 222 PL/I 291
hash join 427 RPG for AS/400 302
hashing access method 415 floating point
HAVING clause 42 COBOL 257
host language FORTRAN 841
concepts and rules 215 declaring 841
host structure general use in SQL statement 215
C 239 graphic
C++ 239 C 233
COBOL 264 C++ 233
definition 215 COBOL 259
ILE RPG for AS/400 314 ILE RPG for AS/400 318
indicator array ILE RPG for AS/400 312
C 241, 244 declaring 313
C++ 241, 244 LOB
COBOL 268, 272 COBOL 261, 315
PL/I 288, 290 PL/I 284
PL/I 286 numeric
RPG for AS/400 300 C 230
used to set null value 220 C++ 230
using arrays COBOL 255
C 241 FORTRAN 841
C++ 241 ILE RPG for AS/400 318
COBOL 268, 273 PL/I 283
ILE RPG for AS/400 314 RPG for AS/400 303
PL/I 289 PL/I 282
RPG for AS/400 301 declaring 282
using indicator variable with, example 220 requirement for COBOL program 255
host structure array requirement for ILE RPG for AS/400 312
multiple-row FETCH 63 requirement for PL/I program 282
host structure indicator array REXX 330
C 241 RPG for AS/400 300
C++ 241 declaring 300
COBOL 268 SET clause, value 33
PL/I 288 SQL statement, use in
rule for date, time, and timestamp
host variable 230
assignment 218
assignment rule 216
rule for numeric assignment 218
C 230
string assignment, rule 217
using pointers 244
host variable and ODP implementation
C++ 230
summary record 518
using pointers 244
character
C 231
C++ 231
I
COBOL 258 ID, authorization 366
FORTRAN 842 IDDU (interactive data definition utility) 6
ILE RPG for AS/400 314, 318 ILE (Integrated Language Environment)
PL/I 283 compiling application 341
RPG for AS/400 300, 303 ILE C program
COBOL 255 SQL statements in, sample 606
date/time ILE COBOL program
ILE RPG for AS/400 313, 318 sample program with SQL statements 613
Datetime SQL 613
COBOL 263 ILE programs
definition 39, 215 package 559

Index 861
ILE RPG for AS/400 program improving performance 467, 465 (continued)
/COPY statement 312, 316 using
character host variables 314 close SQL cursor (CLOSQLCSR) 467, 468
coding SQL statements 309, 325 FETCH FOR n ROWS 462
comment 311 INSERT n ROWS 463
compiler parameters 341 parameter passing techniques 472
continuation 311 precompile options 471
dynamic SQL coding 310 IN keyword
error and warning message during a compile 344 description 73
external file description 316 subquery, use in 87
host structure in tray
declaring 314 table 585
host structure array IN_TRAY table 585
declaring 314 include file
host variable 312 C 228
character 318 C++ 228
date/time 313, 318 CCSID 334
declaring 313 COBOL 254
externally described 316 ILE RPG for AS/400 312
graphic 318 input to precompiler 334
numeric 318 PL/I 281
including code 312 RPG for AS/400 299
indicator structure 322 INCLUDE statement 334
indicator variable 322 C 228
naming convention 312 C++ 228
notes and usage 322 COBOL 254
occurrence data structure 314 ILE RPG for AS/400 312
sequence numbers 312 PL/I 281
SQL data types RPG for AS/400 299
determining equivalent RPG 318 including code
SQL statements in C 228
sample 634 C++ 228
SQLCA 309 COBOL 254
SQLCA placement 309 COBOL COPY statement 254
SQLDA FORTRAN 840
example 323 ILE RPG for AS/400 312
SQLDA, declaring 310 PL/I 281
statement label 312 RPG for AS/400 299
variable declaration 322 index
WHENEVER statement 312 columns used for keys 396
ILE RPG program creating
SQLCA placement 605 from another index 414
ILE service programs definition 8
package 559 recovery 376
using 96
immediate sensitivity 63, 67
using effectively, example 446
implementing a UDF 160 working with 96
implicit connect 565 index advisor
implicit disconnect 565 query optimizer 482
IMPLICIT statement index created
FORTRAN 841 summary record 505
improving performance 464, 465 index-from-index
blocking, using 461 access method 414
join queries 439 index only access method 412
paging interactively displayed data 463 indexes
PREPARE statement 470 using with sort sequence 449
retaining cursor positions across program call 467, indicator array
468 C 241, 244
SELECT statements, using effectively 464 C++ 241, 244
selecting data from multiple tables 442 COBOL 268, 272
SQL blocking 462 PL/I 288, 290

862 DB2 UDB for AS/400 SQL Programming V4R4


indicator structure 220 interactive SQL (continued)
indicator variable function 357
C 249 general use 349
C++ 249 getting started 350
COBOL 276 overview 349
definition 219 package 360
FORTRAN 844 Interactive SQL
ILE RPG for AS/400 322 prompting 354
PL/I 294 interactive SQL
REXX 332 prompting
RPG for AS/400 306 DBCS consideration 353
used to set null value 220 overview 349
used with host structure, example 220 session services 349, 356, 357
with host structure 220 statement entry 349, 351
indicator variables statement processing mode 353
stored procedures 132 Interactive SQL
indicator variables and LOB locators 151 syntax checking 353
infix notation and UDFs 168 interactive SQL
information, inserting into terminology 3
table 18 testing your SQL statements with 349, 358
information messages interactively displayed data, paging
open data path 388, 390 affect on performance 463
performance 382, 388 INTO clause
inner join 75 description 32
INSERT n ROWS PREPARE statements 202
improving performance 463 restriction 208
INSERT statement invoking UDFs 164
blocked 31
ILE RPG for AS/400 314 J
RPG for AS/400 301 JOB 392
column value 216 job attribute
default value 18, 32 DDMCNV 573
description 31 job-level commitment definition 565, 570
VALUES clause 31 join
inserting cross 78
information into table 18 definitions 30
multiple rows exception 77
into tables 69 hash 427
note 70 inner 75
inserting data into a CLOB column example 154 left outer 76
instances of object-oriented data types, storing 145 optimization 426
Integrated Language Environment (ILE) join operation
module 12 definition 23
program 11 in a view 30
service program 12 join optimization
integrity performance tips 439
catalog 377 join order
data 99, 366 optimization 432
referential 99 join position 385
interactive data definition utility 6 join secondary dials
interactive interface costing 432
joining
concepts 1
data from multiple tables 75
Interactive SQL 1
table with WHERE clause 76
interactive SQL
technique 79
accessing remote databases 359
journal 6
Interactive SQL journal receiver 6
adding DBCS data 353 journaling 368
interactive SQL
change session attributes 357 K
description 349 key positioning
exiting 357 access method 406

Index 863
key range estimate 424 LOBs (Large Objects)
key selection and DB2 object extensions 145
access method 404 file reference variables 146
keyed sequence examples of using 152
access path 396 input values 151
keyword output values 152
AND 74 SQL_FILE_APPEND, output value option 152
BETWEEN 72 SQL_FILE_CREATE, output value option 152
COMMIT 370 SQL_FILE_OVERWRITE, output value
DISTINCT 553 option 152
EXISTS 87 SQL_FILE_READ, input value option 152
GROUP BY 553 large object descriptor 146
IN 73, 87 large object value 146
LIKE 73 locators 146, 147
NOT 40 example of using 148
OR 74 indicator variables 151
search condition, use in 72 manipulating 145
UNION 80, 553 programming options for values 147
UNION ALL, specifying 83 storing 145
synergy with UDTs and UDFs
examples of complex applications 177
L locator
LABEL ON statement 16, 48 LOB
information in catalog 48 COBOL 262, 316
package 560 locators
language, host LOB
concepts and rules 215 PL/I 285
large object descriptor 146 locators for manipulating LOBs 146
large object value 146 locks
learn how to analyzing 381
prompt logical file 3, 7
using interactive SQL 354 logical file DDS
leaving interactive SQL 357 database monitor 493
left outer join 76 long object names
library performance 470
definition 3
LONG VARCHAR
LIKE keyword 73
storage limits 146
limit, time 392
LONG VARGRAPHIC
linking a UDF 160
storage limits 146
list function 356
list function in interactive SQL Loosely Coupled Parallelism 2
description 354 LR indicator
listing ending RPG for AS/400 programs 307
output from precompiler 335
live data
using to improve performance 464 M
LOB file reference variable manipulating large objects 145
COBOL 262, 316 mapping error
LOB file reference variables data 37
PL/I 286 margins
LOB host variable C 229
COBOL 261, 315 C++ 229
PL/I 284 COBOL 254
LOB locator FORTRAN 840
COBOL 262, 316 PL/I 281
LOB locators REXX 329
PL/I 285 MARGINS parameter
LOBEVAL.SQB COBOL program listing 153 C 229
LOBEVAL.SQC C program listing 153 C++ 229
LOBLOC.SQB COBOL program listing 150 marker, parameter 213
LOBLOC.SQC C program listing 149 maximum size for large object columns, defining 147

864 DB2 UDB for AS/400 SQL Programming V4R4


member NOW scalar function 46
output source file 11 NUL-terminator
user source file 11 C 232
message C++ 232
analyzing error and warning messages 343 character host variables
cause and user response 382 C 231
error and warning during a compile 343 C++ 231
open data path information 388, 390 null
performance information 382, 388 usage in C 229
running in debug mode 382 usage in C++ 229
minus null string in REXX 329
COBOL 255 NULL value 14
mode null value 45
interactive SQL 353 NULL value
modelling entities as independent objects 145 definition 40
module null value
Integrated Language Environment (ILE) INSERT statement 32
object 12 inserting in a view 96
money using CREATE DISTINCT TYPE example 171 set by indicator variable 220
monitor (ENDDBMON) command, end database 480 SET clause, value 33
monitoring UPDATE statement 33
database query performance 478 used with GROUP BY clause 41
moving large objects using a file reference used with ORDER BY clause 44
variable 146 null value, SQL
multiple contrasted with null value in REXX 329
row number of calls
inserting into a table 69 using a FETCH statement 462
notes on inserting 70 number of open database operations
search condition within a WHERE clause 74 improving performance by reducing 459
table numbers
improving performance when selecting data sequence
from 442 COBOL 254
joining data from 75 ILE RPG for AS/400 312
multiple-row FETCH statement RPG for AS/400 299
using numeric assignment rule
descriptor area 64 host variable, using 218
host structure arrays 63 numeric conversion error 38
row storage area 64 numeric host variable
with languages 63 C 230
C++ 230
COBOL 255
N FORTRAN 841
naming convention ILE RPG for AS/400 318
*SQL 3 PL/I 283
*SYS 3 RPG for AS/400 303
C 229
C++ 229
COBOL 254 O
FORTRAN 840 object
ILE RPG for AS/400 312 application program 9
PL/I 282 collection 3
REXX 329 module 9
RPG for AS/400 299 Integrated Language Environment (ILE) 12
SQL 4 package 9
system 3 program
negative SQLCODEs 591 Integrated Language Environment (ILE) 11
nested loop join 426 service program 9
new release Integrated Language Environment (ILE) 12
considerations 346 SQL 5
non-SELECT statements, processing 199 object-orientation and UDFs 156
NOT keyword 40, 74 object-oriented extensions and UDTs 169

Index 865
object-relational override consideration
application domain and object-orientation 145 running a program with embedded SQL 346
constraint mechanisms 145 Override Database File (OVRDBF) command 62, 346,
data types 145 367, 459, 462
definition 145 used with RPG for AS/400 /COPY 302
LOBs 145 overview, interactive SQL 349
support for 146
triggers 145
UDTs and UDFs 145
P
package
why use the DB2 object extensions 145
authority to create 557
occurrence data structure
authority to run 557
ILE RPG for AS/400 314
bind to an application 9
RPG for AS/400 301
CCSID considerations for 561
ODBC 199
consistency token 560
ODP (open data path) 459
Create SQL Package (CRTSQLPKG)
ODP implementation and host variable
command 557
summary record 518 authority required 558
open creating
closing 459 authority required 557
determing number 461 effect of ARD programs 577
effect on performance 459 errors during 558
reducing number 459 on local system 560
open cursor RDB parameter 557
during a unit of work 68 RDBCNNMTH parameter 560
open data path 459 TGTRLS parameter 559
definition 388 type of connection 560
information messages 388 unit of work boundary 560
open database connectivity (ODBC) 199 creating on a non-DB2 UDB for AS/400
OPEN statement 213 errors during 558
operation, atomic 373 required precompiler options for DB2 Common
operators, comparison 40 Server 558
OPNQRYF (Open Query File) command 477 unsupported precompiler options 558
optimization 395 DB2 UDB for AS/400 support 557
grouping 442 definition 9, 12, 557
join 426 Delete SQL Package (DLTSQLPKG) command 557
join order 432 deleting 557
nested loop join 426 interactive SQL 360
OPTIMIZE FOR n ROWS clause labeling 560
effect on query optimizer 423 restore 560
optimizer save 560
SQL statement size 559
operation 422
statements that do not require package 559
query index advisor 482
page fault 397
optimizer timed out
paging
summary record 515
interactively displayed data 463
options, precompile
retrieved data 551
improving performance by using 471 parallel data space scan
ORDER BY access method 403
clause 43 parallel key positioning access method 411
using null values with 44 parallel key selection access method 405
data mapping errors 37 parallel pre-fetch
sort sequence, using 50 access method 401
using 51 parallel pre-load
outer join 76 index-based 413
outer-level SELECT 84 table-based 413
output parallel processing
all queries that performed table scans 484 controlling
SQL queries that performed table scans 483 in jobs (CHGQRYA command) 474
output source file member system wide (QQRYDEGREE) value 474
definition 11 parameter markers
overloaded function names and UDFs 158 in functions example 166

866 DB2 UDB for AS/400 SQL Programming V4R4


parameter passing physical file 3, 6
differences 473 physical file DDS
PL/I 294 database monitor 489
RPG for AS/400 307 PL/I
stored procedures 128, 132 SQL statements in, sample 621
table 128
PL/I program
parameters
%INCLUDE directive 281, 291
marker 213
BEGIN/END DECLARE SECTION 282
parameters, command
coding SQL statements 279, 295
ALWCPYDTA (allow copy data) 464, 465
comment 281
CLOSQLCSR (close SQL cursor) 467, 468
compiler parameters 340
passing argument to UDF
continuation 281
call-type 190
dynamic SQL coding 280
dbinfo 190
error and warning message during a compile 343
diagnostic-message 189
external file description 291
function-name 189
file reference variables
scratchpad 190
LOB 286
specific-name 189
host structure
SQL-argument 190, 191
array indicator structure, declaring 290
SQL-argument-ind 188
arrays, declaring 289
SQL-argument-ind-array 191
declaring 286
SQL-result 190, 192
indicator array 288
SQL-result-ind 188, 192
host variable 282
SQL-state 188
character 283
path, open data 388
declaring 282, 284
pending
externally described 291
check 107
LOB 284
performance 395
numeric 283
information messages 382, 388
INCLUDE statement 281
monitoring 477
including code 281
monitoring query 478
indicator structure 294
open data path messages 388, 390
indicator variable 294
OPNQRYF 477
locators
optimizing 477
LOB 285
tools 477
margin 281
UDFs 156
naming convention 282
using long object names 470
SQL data types
performance analysis determining equivalent PL/I 292
example 1 483 SQLCA, declaring 279
example 2 484 SQLCODE, declaring 279
example 3 484 SQLDA, declaring 280
performance and UDTs 169 SQLSTATE, declaring 279
performance considerations 393, 459 structure parameter passing 294
performance improvement WHENEVER statement 282
blocking, using 461 pointer
paging interactively displayed data 463 C 244
PREPARE statement 470 C++ 244
reducing number of open database operation 459
positive SQLCODEs 589
retaining cursor positions across program call 467,
468 pre-fetching 399
SELECT statements, using effectively 464 precompile options
selecting data from multiple tables 442 improving performance, using 471
SQL blocking 462 precompiler
using copy of the data 465 basic process 333
using INSERT n ROWS 463 complete diagnostics 334
using live data 464 concepts 1
using precompile options 471 diagnostic messages 558
performance records diagnostics 335
database monitor 481 displaying
performance verification 381 options 345
performing complex search condition 72 errors 343

Index 867
precompiler (continued) precompiler parameter (continued)
include file OPTION(*NOGEN) 316, 341
CCSID 334 OPTION(*NOSEQSRC) 312
input to 334 OPTION(*SEQSRC) 299
other preprocessors 334 OPTION(*QUOTE) 254
output from OPTION(*SEQSRC) 312
listing 335 OPTION(*SOURCE) 334
sample 336 OPTION(*XREF) 334, 335
temporary source file member 335 OUTPUT 334
parameters passed to compiler 340 parameters passed to compiler 340
passing PGM 335
host variables 472 PRTFILE 335
record number 337 RDB
reference column 339 Effect on precompile 333
secondary input 334 TIMFMT 313, 317
sequence number 337 TIMSEP 313, 317
source file predicate
CCSID 334 definition 38
containing DBCS constants 334 transitive closure 436
margins 334 Predictive Query Governor 391
source record 337 PREPARE statement
VisualAge C++ for OS/400 342 improving performance 470
warning 343 non-SELECT statement 200
precompiler command restrictions 199
CRTSQLC 819 using 213
CRTSQLCBL 340 prepared statement
CRTSQLCBLI 341 distributed unit of work 576
CRTSQLCI 229, 232, 234, 341 preparing program with SQL statements 333
CRTSQLCPPI 229, 232, 234, 341 preprocessor
CRTSQLFTN 835 usage with SQL C++ program 229
CRTSQLPLI 281, 340 usage with SQL C program 229
CRTSQLRPG 340 with SQL 334
CRTSQLRPGI 341 preventing duplicate rows 71
CRTSQLxxx 51, 558 Print SQL Information (PRTSQLINF) 345, 382, 393
CVTSQLCPP 229, 232, 234, 341 printer file 335
default 468 CCSID 335
description 340 printing current session 357
precompiler file problem handling 221
QSQLTEMP 335 problems
QSQLTEMP1 335 join query performance 438
precompiler parameter problems, solving database 551
*CVTDT 316 process, basic
*NOCVTDT 316, 317 precompiler 333
ALWCPYDTA 464 PROCESS statement
CLOSQLCSR 469 COBOL 254
DATFMT 313, 317 FORTRAN 841
DATSEP 313, 317 processing
DBGVIEW(*SOURCE) 380 data in a view 36
displayed on listing 335 non-SELECT statements 199
INCFILE 334 SELECT statement with SQLDA 201
MARGINS 281, 334, 343 producing reports from sample programs 643
C 229 program
C++ 229 application 379
OBJ 335 compiling application
OBJTYPE(*MODULE) 341 ILE 341
OBJTYPE(*PGM) 341 non-ILE 340
OBJTYPE(*SRVPGM) 341 debugging 380
OPTION(*APOST) 254 definition 11
OPTION(*CNULRQD) 232, 234 Integrated Language Environment (ILE) object 11
OPTION(*CVTDT) 316 non-ILE object 11
OPTION(*NOCNULRQD) 232, 234 performance verification 381

868 DB2 UDB for AS/400 SQL Programming V4R4


program (continued) Query options file 543
preparing and running with SQL statements 379 query options file
reference 345 changing 546
report produced by sample 643 query performance
running with embedded SQL monitoring 478
DDM consideration 346 query sort
instruction 346 summary record 508
override consideration 346 query time limit 392
return code 347 quotation mark
sample 605 C 249
SQL statements in C++ 249
COBOL 613
ILE C 606
ILE COBOL 613 R
ILE RPG for AS/400 program 634 re-use and UDFs 156
PL/I 621 read-only
REXX 640 table 59
RPG for AS/400 628 view 96
program calls read-only connection 567
rules for retaining cursor positions 469 receiver, journal 6
project table 584 Reclaim DDM connections (RCLDDMCNV)
prompt command 573
using interactive SQL 349, 354 record, definition 3
prompting record selection 52
CREATE TABLE 353 sort sequence, using 50
function 349, 351 records
overview 349 database monitor performance 481
subqueries 353 records retrieved
protected connections detail record 523
dropping 570 recovering
protected resource 567 effect on open cursor 68
protection, data 365 index 376
PRTSQLINF (Print SQL Information) command 784 interactive SQL
public authority 365 saved or failed session 358
Q reducing number of open database operations
QAQQINI 546 improving performance, example 459
QDT 425 reference, program 345
QRYTIMLMT parameter referential constraints
CHGQRYA (Change Query Attributes) check pending 107
command 381 creating tables 100
QSQCHKS 2 definition 8
QSQLTEMP 335 delete rules 105
QSQLTEMP1 335 deleting from tables 105
QSQPRCED 2 inserting into tables 102
package 9 removing 102
QSYS2 update rules 103
catalog views 6 updating tables 103
QSYSPRT listing referential integrity 99
SQL statement processor definition 8
example 363 registering
query UDFs 160
cancelling 392 related information 845
Query Definition Template (QDT) 425 relational database 3
query optimizer 395 RELEASE statement 555, 559
cost estimation 423 ending connection 573
decision-making rules 425 remote databases
default filter factors 424 accessing from interactive SQL 359
optimization goals 423 remote unit of work 555, 566
query optimizer index advisor 482 connection status 570
query options connection type 567
file 546 example program 556

Index 869
removing all entries from current session 357 RPG for AS/400 program 299 (continued)
Reorganize Physical File Member (RGZPFM) command continuation 299
effect on variable-length columns 458 dynamic SQL coding 298
getting rid of deleted rows 399 ending
report produced by sample programs 643 using LR indicator 307
resource using RETRN statement 307
optimization 395 error and warning message during a compile 344
restriction external file description 302
FOR UPDATE OF 553 host structure
result table 80 array, declaring 301
resume using CREATE DISTINCT TYPE example 171 declaring 300
retaining cursor positions host variable 300
across program call character 303
improving performance 467, 468 declaring 300
all program calls externally described 302
rules 469 numeric 303
Retrieve Message (RTVMSG) command 587 including code 299
retrieving indicator structure 306
data indicator variable 306
from a table. 20 naming convention 299
in reverse order 551 occurrence data structure 301
row sequence numbers 299
using a cursor 60 SQL data types
SELECT statement result determining equivalent RPG 303
cursor, using 212 SQL statements in
RETRN statement sample 628
ending RPG for AS/400 programs 307 SQLCA
return code 38 placement 297
handling in statement label 300
general 221 structure parameter passing 307
running a program with embedded SQL 347 using the SQLDA 298
RETURNS TABLE clause 188, 190, 192 WHENEVER statement 300
reuse deleted records RRN scalar function 77
INSERT 33 rule
Revoke Object Authority (RVKOBJAUT) command 365 host variable, using 218
REVOKE PACKAGE statement 555 retaining cursor positions
REXX 2 program calls 469
coding SQL statements 325, 332 rule 216, 218
SQL statements in SQL with host language, using 215
sample 640 rules that govern operations on large objects 145
ROLLBACK run mode
prepared statements 201 interactive SQL 353
rollback Run SQL Statements (RUNSQLSTM) command 1
rollback required state 572 run-time support
ROLLBACK statement 559 concepts 1
row running
definition 3, 6 dynamic SQL application 199
delete current 61 program with embedded SQL
inserting multiple DDM consideration 346
into a table 69 instruction 346
note 70 override consideration 346
preventing duplicate 71 return code 347
ROWS, INSERT n programs 346
RUNSQLSTM (Run SQL Statements) 357, 358
improving performance 463
command 1, 361
RPG 297, 309
command errors 362
RPG for AS/400 program 309
commitment control 362
/COPY statement 299, 302
RUNSQLSTM (Run SQL Statements) command 794
character host variables 300
RUW (remote unit of work) 555
coding SQL statements 297, 307
comment 299 S
compiler parameters 340 sales using CREATE TABLE example 171

870 DB2 UDB for AS/400 SQL Programming V4R4


sample programs sensitivity
DB2 UDB for AS/400 statements, using 605 immediate 63, 67
distributed RUW program 556 sequence numbers
report 643 COBOL 254
SQL statements in ILE RPG for AS/400 program 312
COBOL 613 RPG for AS/400 program 299
ILE C 606 sequential access path 396
ILE COBOL 613 serial cursor 55
ILE RPG for AS/400 program 634 service program
PL/I 621 Integrated Language Environment (ILE)
REXX 640 object 12
RPG for AS/400 628 services, session 356
sample tables DB2 UDB for AS/400 579 session 358
save/restore 375 printing current 357
packages 560 removing all entries from current 357
saved session saving in a source file 357, 358
in a source file 357, 358 session services
recovering 358 in interactive SQL 349, 356, 357
scalar functions 159 SET clause
schedule table description 33
class 585 value
schema-name and UDFs 158 column name 33
schemas constant 33
SQL statement processor 362 expression 33
scratchpad, passing to UDF 190 host variable 33
scrollable cursor 55 null 33
search condition scalar subselect 34
definition 38 special register 33
performing complex 72 SET CONNECTION statement 555, 559
subqueries 85 SET CURRENT FUNCTION PATH statement 160
using keyword in 72 SET TRANSACTION statement
security 365 effect on implicit disconnect 565
authorization 380 not allowed in package 558
authorization ID 366 setting query time limit 394
commitment control 369 SEU (source entry utility) 358
data integrity 366 SIGNAL ON ERROR in REXX 329
concurrency 367 SIGNAL ON FAILURE in REXX 329
public authority 365 signature, two functions and the same 158
view 366 SMALLINT 188, 192
SELECT clause 38 solving 551
select information common database problem 551
into host variables 36 solving common problems 551
SELECT INTO statement SOME 86
column value 216 sort sequence
restriction 199 CREATE INDEX 53
retrieving row 35 used with ORDER BY 50
SELECT statement used with record selection 50
definition 20 using 50
example of allocating storage for SQLDA 208 using indexes 449
processing and using SQLDA 201 views 53
using effectively to improve performance 464 source entry utility (SEU) 358
using fixed-list 201 source file
using varying-list 202
CCSID 334
selecting containing DBCS constants 334
column 70 for RUNSQLSTM 361
data from multiple tables 442 include files 334
semantic behavior of stored objects 145 input to precompiler 334
Send Program Message (SNDPGMMSG) margins 334
command 587 member, output
Send User Message (SNDUSRMSG) command 587 definition 11

Index 871
source file (continued) SQL statement processor
member, temporary commitment control 362
output from precompiler 335 example
member, user 11 QSYSPRT listing 363
multiple source in COBOL 255 schemas 362
saving a session in 357, 358 using 361
temporary for precompile 335 SQLCA (SQL communication area)
sourced UDF 174 C 225
special register C++ 225
CURRENT DATE 45 COBOL 251
CURRENT SERVER 45 FORTRAN 837
CURRENT TIME 45 ILE RPG for AS/400 309
CURRENT TIMESTAMP 45 PL/I 279
CURRENT TIMEZONE 45 REXX 325
definition 40 RPG for AS/400 297
SET clause, value 33 SQLCOD
USER 45 FORTRAN 837
specific-name, passing to UDF 189 SQLCODE
specifying C 225
column, SELECT INTO statement 38 C++ 225
UNION ALL 83 COBOL 251
SQL 1 FORTRAN 837
call level interface 2 in REXX 325
introduction 1 PL/I 279
object 5 SQLCODEs
statements definition 221, 587
COBOL 613 description 589
ILE COBOL 613 negative 591
ILE RPG for AS/400 program 634 positive 589
PL/I 606, 621 testing application program 380
REXX 640 SQLD 204
RPG for AS/400 628 SQLD field of SQLDA
types 4 in REXX 326
using host variable 215
SQLDA (SQL descriptor area)
using with host language, concepts and rules 215
allocating storage for 208
SQL-argument, passing to UDF 190, 191
C 226
SQL-argument 188
C++ 226
SQL-argument-ind, passing to UDF 188 COBOL 252
SQL-argument-ind-array, passing to UDF 191 format 204
SQL blocking FORTRAN 838
improving performance 462 ILE RPG for AS/400 310
SQL data types PL/I 280
determining equivalent processing SELECT statement 201
C 246 programming language, use in 203
C++ 246 REXX 325
COBOL 274 RPG for AS/400 298
FORTRAN 842 SELECT statement for allocating storage for
ILE RPG for AS/400 318 SQLDA 208
PL/I 292 SQLDABC 204
REXX 330 SQLDAID 204
RPG for AS/400 303
SQLDATA 206
SQL_FILE_READ, input value option 152
SQLDATA field of SQLDA
SQL information
in REXX 327
summary record 494, 526
SQLERRD field of SQLCA 325
SQL naming convention 4
SQLERRD(3) field of SQLCA
SQL package 3 determining connection status 570
SQL-result, passing to UDF 190, 192 determining number of rows fetched 63
SQL-result 188 SQLERRD(4) field of SQLCA 570
SQL-result-ind, passing to UDF 188, 192 determining connection type 567
SQL-state, passing to UDF 188 determining length of each row retrieved 63

872 DB2 UDB for AS/400 SQL Programming V4R4


SQLERRD field of SQLCA 570 (continued) statements 48, 221, 606, 613, 621, 628, 634, 640
SQLERRD(5) field of SQLCA (continued)
determining end-of-file 63 ALIAS statement
SQLERRMC field of SQLCA 325 example 48
SQLERROR statement basic, using 31
WHENEVER 221 COMMENT ON statement 49
SQLERRP field of SQLCA 325 COMMIT 6
SQLIND 206 CONNECT 555
SQLIND field of SQLDA CREATE COLLECTION 13
in REXX 327 CREATE INDEX
SQLLEN 204 sort sequence 53
SQLLEN field of SQLDA CREATE PROCEDURE
in REXX 326 external procedure 117
SQLN 204 SQL procedure 117
SQLNAME 206 CREATE SCHEMA 362
SQLNAME field of SQLDA CREATE TABLE 14
in REXX 326 CREATE VIEW 29
SQLPRECISION field of SQLDA 326 data definition (DDL) 4
SQLRES 206 data manipulation (DML) 4
date value 47
SQLSCALE field of SQLDA 327
DECLARE CURSOR 36
SQLSTA
DELETE
FORTRAN 837
example 34
SQLSTATE
WHERE clause 28
C 225 DISCONNECT 555
C++ 225 DROP PACKAGE 555
COBOL 251 dynamic 4
FORTRAN 837 EXECUTE 199, 200
in REXX 325 FETCH 212
PL/I 279 FOR n ROWS 462
SQLSTATEs multiple-row 62
code definition 587 number of calls 462
definition 221, 587 GRANT PACKAGE 555
description 589 host variable in SQL, using 215
testing application program 380 INSERT
SQLTYPE 204 assignment operation 216
SQLTYPE field of SQLDA n ROWS 463
in REXX 326 using 31
sqludf.h include file for UDFs 190 LABEL ON statement
SQLVAR 204 example 48
SQLWARN field of SQLCA 325 examples 16
Start Commitment Control (STRCMTCTL) multiple-row FETCH 64
command 370 OPEN 213
Start Database Monitor (STRDBMON) command 479 package not required 559
Start Journal Access Path (STRJRNAP) command 376 packages 558
Start SQL (STRSQL) command 801 PREPARE
starting interactive SQL 350 cursor 213
statement entry 349, 351 improving performance 470
statement label non-SELECT statement 200
COBOL 255 using 199
in C 229 preparing and running a program with 333
in C++ 229 processing non select 199
requirements for FORTRAN program 840 RELEASE 555
requirements for ILE RPG for AS/400 312 REVOKE PACKAGE 555
RPG for AS/400 300 ROLLBACK 6
statement-name sample programs 605
select 20
in DESCRIBE
SELECT INTO
in REXX 325
column value 216
statement processing mode
example 35
interactive SQL 353
processing data (view) 36
statements 45, 221, 606, 613, 621, 628, 634, 640

Index 873
statements 216, 221, 606, 613, 621, 628, 634, 640 subquery processing
(continued) summary record 517
restriction 48 subselect
specifying column 38 combining with the UNION keyword, example 80
SET CONNECTION 555 SET clause, value 34
SQL packages 558 summary records
testing access plan rebuilt 513
in application program 379 arrival sequence 498
using interactive SQL 349, 358 generic query information 520
time value 47 host variable and ODP implementation 518
timestamp value 47 index created 505
UPDATE optimizer timed out 515
assignment operation 216 query sort 508
changing data value 25 SQL information 494, 526
example 33 STRDBMON/ENDDBMON commands 522
WHENEVER 230, 255, 282, 841 subquery processing 517
handling exception condition 222 table locked 511
ILE RPG for AS/400 312 temporary file 509
RPG for AS/400 300 using existing index 502, 530, 531, 533, 535, 536,
WHENEVER SQLERROR 221 537, 538, 539
stopping interactive SQL 357 Symmetric Multiprocessing 2
storage, allocating for SQLDA 208 symmetrical multiprocessing 397
stored procedures 117, 144 sync point manager 567
definition 8 syntax check
parameter passing 128 QSQCHKS 2
indicator variables 132 syntax check mode
table 128 interactive SQL 353
storing large objects 145 syntax for referring to functions 165
STRDBMON (Start Database Monitor) command 479 system naming convention 3
STRDBMON/ENDDBMON commands system table name 17
summary record 522
string assignment
rule using host variable 217
T
table
string search and defining UDFs example 162
adding data to the end 552
string search on BLOBs 162
changing definition 93, 554
string search over UDT example 163
changing information in 25
strong typing and UDTs 172
CL_SCHED (class schedule) 585
STRSQL (Start SQL) command 350, 801
CORPDATA.DEPARTMENT (department) 579
structure parameter passing 473 CORPDATA.EMP_ACT (employee to project
PL/I 294 activity) 581
RPG for AS/400 307 CORPDATA.EMPLOYEE 580
Structured Query Language 1 CORPDATA.PROJECT (project) 584
structured query language package creating
creating 763 CREATE TABLE statement 14
deleting 782 view 29
subfields data management methods 420
ILE RPG for AS/400 314 DB2 UDB for AS/400 sample 579
RPG for AS/400 300 defining name 48
subquery 88 definition 3, 6
basic comparison 86 deleting information in 28
correlated 85, 88 establishing position at the end 551
correlated names and references 91 getting catalog information
definition 84 about column 97
examples 84 getting information
EXISTS keyword 87 from multiple 23
IN keyword 87 from one 20
notes on using IN_TRAY 585
with UPDATE and DELETE 88 inserting
prompting 353 information into 18
quantified comparison 86 multiple rows into 69
search condition 85 joining 75

874 DB2 UDB for AS/400 SQL Programming V4R4


table (continued) tools
the WHERE clause 552 performance 477
multiple Trace Job (TRCJOB) command 382, 461
creating view over 30 transitive closure 436
improving performance when selecting data TRCJOB (Trace Job) command 382
from 442 trigger
sample 579 definition 8
used in examples event 8
CORPDATA.DEPARTMENT (department) 579 trigger support 111
CORPDATA.EMP_ACT (employee to project triggers
activity) 581 and DB2 object extensions 145
CORPDATA.EMPLOYEE 580
trigraph
CORPDATA.PROJECT (project) 584
C 229
using 14
C++ 229
table functions 159
contents of call-type argument 190 truncation error 36
table locked two-phase commit 567
summary record 511 typing
table name interactive SQL 351
system 17
table scans
output for all queries 484 U
output for SQL queries 483 UDFs (User-defined functions)
TAG statement and DB2 object extensions 145
ILE RPG for AS/400 312 casting 169
RPG for AS/400 300 concepts 158
technique definition 156
coding 31, 55, 69 function path 158
solving database problem 551 function selection algorithm 158
temporary file general considerations 168
summary record 509 implementing UDFs 156
temporary keyed access path 435, 436 infix notation 168
temporary source file member invoking
output from precompiler 335 examples of invocations 164
terminology parameter markers in functions 166
interactive SQL 3 qualified function reference 166
relational database 3 unqualified function reference 167
relationship table LOB types 168
*SQL 3 overloaded function names 158
*SYS 3 process of implementation 160
testing referring to functions 165
authorization 379, 380 registering UDFs 161
debugging your program 380 examples of registering 161
input data 379 schema-name and UDFs 158
performance verification 381 sourced 174
SQL statements using interactive SQL 349, 358 summary of function references 167
statements in application program 379 synergy with UDTs and LOBs
view 379 examples of complex applications 177
time assignment rule type of functions 159
host variable, using 218 unqualified reference 158
time format 47 why use UDFs 156
specifying current value 47 writing your own UDF 185
timestamp assignment rule UDFs and LOB types 168
host variable, using 218 UDTs (User-defined types)
timestamp format 47 and DB2 object extensions 145
specifying current value 47 defining a UDT 170
TIMFMT defining tables 171
ILE RPG for AS/400 313, 317 manipulating
TIMSEP examples of 172
ILE RPG for AS/400 313, 317 resolving unqualified UDTs 171
tolerance, damage 376 strong typing 172

Index 875
UDTs (User-defined types) (continued) using (continued)
synergy with UDFs and LOBs parameter markers 462
examples of complex applications 177 parameter passing techniques
why use UDTs 169 performance improvement 472
union record selection 52
C 230 sort sequence 50
C++ 230 time value 47
UNION ALL, specifying 83 timestamp value 47
UNION keyword Using
restriction 553 views 95
using to combine subselects 80 using a locator to work with a CLOB value
unique constraint example 148
definition 8 using existing index
unit of work summary record 502, 530, 531, 533, 535, 536, 537,
distributed 555 538, 539
effect on open cursor 68 using interactive SQL 349
package creation 560 after first time 356
remote 555 list selection function 354
rollback required 572 prompting 351
unit of work boundary statement entry 351
package creation 560 using JOB parameter 394
unprotected resource 567 using qualified function reference example 166
unqualified function reference example 167 using SQL
unqualified reference 158 application programs 395
UPDATE statement
assignment operation 216
correlated subquery, using in 91 V
description 33 validate mode
WHERE clause 25 interactive SQL 353
updating data value
as it is retrieved, restrictions 552 default 14, 18
committable updates 567 inserting
previously retrieved 553 into table or view 31
use of UDTs in UNION example 177 VALUES clause 31
user auxiliary storage pool (ASP) 378 variable 230, 249
user-defined sourced functions on UDTs example 175 host
user profile REXX 330
authorization ID 3 indicator 219
authorization name 3 use of indicator with host structure, example 220
user source file member used to set null value 220
definition 11 variable-length data
USER special register 45 tips 456
using varying-list SELECT statement
a copy of the data 464, 465 definition 202
allow copy data (ALWCPYDTA) 464, 465 using 202
blocked insert statement 70 verification
USING performance 381
clause 210 view
using creating 95
close SQL cursor (CLOSQLCSR) 464, 469 CREATE VIEW statement 28
cursor on a table 29
example 56 over multiple tables 30
retrieve row 60 definition 3, 7
date value 47 limiting access 28
USING processing data in 36
DESCRIPTOR clause 213 read-only 96
using security 366
FETCH statement 462 sort sequence 53
index 96 testing 379
null value 45 using 95
ORDER BY 51 WITH CASCADED CHECK 108

876 DB2 UDB for AS/400 SQL Programming V4R4


view (continued)
WITH CHECK 95
WITH LOCAL CHECK 109

W
warning
test for negative SQLCODEs 221
warning message during a compile 343
C++ program 343
C program 343
COBOL program 343, 344
PL/I program 343
RPG program 343, 344
WHENEVER NOT FOUND clause 60
WHENEVER SQLERROR 221
WHENEVER statement
C 230
C++ 230
COBOL 255
FORTRAN 841
handling exception condition with 222
ILE RPG for AS/400 312
PL/I 282
REXX, substitute for 329
RPG for AS/400 300
WHERE clause
character string 31
constant 39
description 38
example 213
expression in, using 39
joining tables 76
multiple search condition within a 74
NOT keyword 40
WHERE CURRENT OF clause 61
WITH CASCADED CHECK OPTION 108
WITH CHECK OPTION 108
WITH DATA DICTIONARY clause
CREATE COLLECTION statement 6
CREATE SCHEMA statement 6
creating data dictionary 6
WITH LOCAL CHECK OPTION 109
working with
index 96

X
X/Open call level interface 2

Index 877
878 DB2 UDB for AS/400 SQL Programming V4R4
Readers’ Comments — We’d Like to Hear from You

AS/400e
DB2 UDB for AS/400 SQL Programming
Version 4

Publication No. RBAF-Y000-00

Overall, how satisfied are you with the information in this book?

Very Satisfied Satisfied Neutral Dissatisfied Very Dissatisfied


Overall satisfaction h h h h h

How satisfied are you that the information in this book is:

Very Satisfied Satisfied Neutral Dissatisfied Very Dissatisfied


Accurate h h h h h
Complete h h h h h
Easy to find h h h h h
Easy to understand h h h h h
Well organized h h h h h
Applicable to your tasks h h h h h

Please tell us how we can improve this book:

Thank you for your responses. May we contact you? h Yes h No

When you send comments to IBM, you grant IBM a nonexclusive right to use or distribute your comments in any way
it believes appropriate without incurring any obligation to you.

Name Address

Company or Organization

Phone No.
___________________________________________________________________________________________________
Readers’ Comments — We’d Like to Hear from You Cut or Fold
RBAF-Y000-00 IBMR Along Line

_ _ _ _ _ _ _Fold
_ _ _ and
_ _ _Tape
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _Please
_ _ _ _ do
_ _ not
_ _ _staple
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _Fold
_ _ _and
_ _ Tape
______

NO POSTAGE
NECESSARY
IF MAILED IN THE
UNITED STATES

BUSINESS REPLY MAIL


FIRST-CLASS MAIL PERMIT NO. 40 ARMONK, NEW YORK

POSTAGE WILL BE PAID BY ADDRESSEE

IBM CORPORATION
ATTN DEPT 542 IDCLERK
3605 HWY 52 N
ROCHESTER MN 55901-7829

________________________________________________________________________________________
Fold and Tape Please do not staple Fold and Tape

Cut or Fold
RBAF-Y000-00 Along Line
IBMR

Printed in U.S.A.

RBAF-Y000-00

Anda mungkin juga menyukai