DB2 UDB For AS400 SQL Programming1
DB2 UDB For AS400 SQL Programming1
DB2 UDB For AS400 SQL Programming1
AS/400e
Copyright International Business Machines Corporation 2000. All rights reserved. US Government Users Restricted Rights Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
Contents
About DB2 UDB for AS/400 SQL Programming Concepts . . . . . . . vii
Who should read this book . . . . . . . . . vii Assumptions relating to examples of SQL statements. . . . . . . . . . . . . . vii How to interpret syntax diagrams in this guide viii Whats new in the V4R5 version of the SQL programming concepts information . . . . . . ix Example: Creating a view combining data from more than one table . . . . . . . . . . 30
. 13 . 13 . 14 . 14 14 . 16 . 16 . 18 . . . . . . 18 20 23 25 25 28
. 28 . 28 . 29
iii
Using the multiple-row FETCH statement . . . . Multiple-row FETCH using a host structure array Multiple-row FETCH using a row storage area Unit of work and open cursors . . . . . . . .
62 63 64 67
WITH CHECK OPTION on a View . . WITH CASCADED CHECK OPTION WITH LOCAL CHECK OPTION . . DB2 UDB for AS/400 trigger support . Trigger sample . . . . . . . .
. 124 . 125 . 125 . 127 . 128 . 132 . 135 . 136 . 137 . 145 . 145 . 146 . 147
| |
iv
Defining a UDT . . . . . . . . . . Resolving unqualified UDTs . . . . . . Examples: Using CREATE DISTINCT TYPE . Defining tables with UDTs . . . . . . . Manipulating UDTs . . . . . . . . . Examples of manipulating UDTs . . . . . Synergy between UDTs, UDFs, and LOBs . . . Combining UDTs, UDFs, and LOBs . . . . Examples of complex applications . . . . Using DataLinks . . . . . . . . . . . NO LINK CONTROL . . . . . . . . FILE LINK CONTROL (with File System Permissions). . . . . . . . . . . . FILE LINK CONTROL (with Database Permissions). . . . . . . . . . . . Commands used for working with DataLinks
. . . . . . . . . . .
174 174 175 175 176 176 181 181 181 184 185
Using the list selection function . . . . Session services description . . . . . Exiting interactive SQL . . . . . . . Using an existing SQL session . . . . . Recovering an SQL session . . . . . . Accessing remote databases with interactive SQL . . . . . . . . . . . . .
. . . . . .
. . . . .
. 229
| | | | | |
Contents
DB2 UDB for AS/400 distributed relational database example program . . . . . . . . . SQL package support. . . . . . . . . . . Valid SQL statements in an SQL package . . . Considerations for creating an SQL package . . CCSID considerations for SQL. . . . . . . . Connection management and activation groups Connections and conversations . . . . . . Source code for PGM1: . . . . . . . . . Source code for PGM2: . . . . . . . . . Source code for PGM3: . . . . . . . . . Multiple connections to the same relational database . . . . . . . . . . . . . . Implicit connection management for the default activation group . . . . . . . . . . . Implicit connection management for nondefault activation groups . . . . . . . . . . . Distributed support . . . . . . . . . . . Determining connection type . . . . . . . Connect and commitment control restrictions Determining connection status. . . . . . . Distributed unit of work connection considerations . . . . . . . . . . . . Ending connections . . . . . . . . . . Distributed unit of work. . . . . . . . . . Managing distributed unit of work connections Cursors and prepared statements . . . . . . Application requester driver programs . . . . . Problem handling . . . . . . . . . . . .
258 259 260 260 263 263 263 264 265 265 267 267 268 268 269 272 273 274 275 276 276 278 279 279
Department Table (CORPDATA.DEPARTMENT) DEPARTMENT . . . . . . . . . . . Employee Table (CORPDATA.EMPLOYEE) . . Employee to Project Activity Table (CORPDATA.EMP_ACT) . . . . . . . . EMP_ACT . . . . . . . . . . . . Project Table (CORPDATA.PROJECT) . . . . PROJECT. . . . . . . . . . . . . Class Schedule Table (CL_SCHED) . . . . . In Tray Table (IN_TRAY) . . . . . . . .
Bibliography . . . . . . . . . . . . 331 Appendix A. DB2 UDB for AS/400 Sample Tables . . . . . . . . . . . 281 Index . . . . . . . . . . . . . . . 333
vi
vii
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. 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 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.
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.
viii
required_item
required_choice1 required_choice2
If choosing one of the items is optional, the entire stack appears below the main path.
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.
Whats new in the V4R5 version of the SQL programming concepts information
The two major changes to this information for this release were: v Providing information on the big integer (BIGINT) data type v Providing information on using Java stored procedures.
ix
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 the topic Preparing and Running a Program with SQL Statements in the SQL Programming with Host
Copyright IBM Corp. 2000
Languages information. The precompiler support is part of the DB2 UDB Query Manager and SQL Development Kit licensed program. SQL interactive interface SQL interactive interface allows you to create and run SQL statements. For more information on interactive SQL, see Chapter 12. Using Interactive SQL. Interactive SQL is part of the DB2 UDB Query Manager and SQL Development Kit licensed program. Run SQL Statements CL command 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 13. Using the SQL Statement Processor for more information on the Run SQL Statements command. 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 Query Manager Use book. 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 the topic Coding SQL Statements in REXX Applications in the SQL Programming with Host Languages information. 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 SQL Call Level Interface (ODBC) 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 OS/400 API 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 OS/400 API 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 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 the topic Controlling Parallel Processing in the Database Performance and Query Optimization information for details on how to control parallel processing.
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. 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.
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.
SQL DDL Statements ALTER TABLE COMMENT ON CREATE ALIAS CREATE COLLECTION CREATE DISTINCT TYPE CREATE FUNCTION CREATE INDEX CREATE PROCEDURE CREATE SCHEMA CREATE TABLE CREATE VIEW DROP ALIAS DROP COLLECTION 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 DESCRIBE EXECUTE EXECUTE IMMEDIATE PREPARE
SQL DML Statements CLOSE COMMIT DECLARE CURSOR DELETE FETCH INSERT LOCK TABLE OPEN ROLLBACK SELECT INTO SET variable UPDATE VALUES INTO
Miscellaneous Statements BEGIN DECLARE SECTION CALL CONNECT 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
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.
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 SQL Reference book.
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 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 book. The following is a sample SQL table:
Columns
PROJNAME MFG AUTOMATION MFG PROGRAMMING ROBOT DESIGN PROD CONTROL PROG ...
PRSTAFF 12 3 3 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 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
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 Database Programming book.
2. Although CREATE INDEX can create a unique index that also guarantees uniqueness, such an index is not a constraint.
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 189.
User-defined type
A user-defined type is a distinct data type that users can define independently of those supplied by the database management system. Distinct data types map on a one-to-one basis to existing database types. For more information on user-defined types, see User-defined distinct types (UDT) on page 173.
SQL 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 17. Distributed Relational Database Function SQL packages can also be created using the QSQPRCED API. For more information on QSQPRCED, see the OS/400 API book.
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 involved and steps that happen during the precompile and compile processes for a nondistributed non-ILE DB2 UDB for AS/400 program:
User Source File Member
Precompile
Compile
Program
Access Plan
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:
Compile
Module
Bind
Program
Access Plan
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 Compile Program SQL Package Access Plan SQL Package
Precompile
Access 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
10
steps that occur during the precompile and compile processes for a distributed ILE DB2 UDB for AS/400 program:
Create SQL Package
Precompile
Compile
Module
Bind
Program
SQL Package
Access Plan
Access Plan
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.
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
Chapter 1. Introduction to DB2 UDB for AS/400 Structured Query Language
11
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.
SQL 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
v Changing information in a table on page 25 v Deleting information from a table on page 28 v Creating and using a view on page 28
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 12. 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).
13
For an example of creating a collection using interactive SQL, see Example: Creating the SQL Collection (SAMPLECOLL).
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.
14
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):
Specify CREATE TABLE Statement Type information, press Enter. Table . . . . . . . . . Collection . . . . . . Nulls: INVENTORY_LIST______ SAMPLECOLL__ Name Name, F4 for list
1=NULL, 2=NOT NULL, 3=NOT NULL WITH DEFAULT FOR Column ____________ ____________ ____________ ____________ ____________ ____________ ____________ Type CHAR___________ VARCHAR________ DECIMAL________ SMALLINT_______ DATE___________ SMALLINT_______ _______________ N N Length 6____ 20___ 8____ _____ _____ _____ _____ Scale Nulls __ 2 __ 3 2_ 3 __ 1 __ 1 __ 1 __ 3 Bottom Y=Yes, N=No Y=Yes, N=No F10=Copy line F24=More keys
Table CONSTRAINT . . . . . . . . . . . . . Distributed Table . . . . . . . . . . . . F3=Exit F4=Prompt F11=Display more attributes F5=Refresh F12=Cancel
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 . . . . . . . . . Collection . . . . . . Data: INVENTORY_LIST______ SAMPLECOLL__ Name Name, F4 for list
1=BIT, 2=SBCS, 3=MIXED, 4=CCSID Data _ _ _ _ _ _ _ Allocate _____ _____ _____ _____ _____ _____ _____
Column ITEM NUMBER_______ ITEM NAME_________ UNIT_COST_________ QUANTITY_ON_HAND__ LAST_ORDER_DATE___ ORDER_QUANTITY____ __________________
CCSID CONSTRAINT Default _____ N __________________ _____ N '***UNKNOWN***'___ _____ N __________________ _____ N NULL______________ _____ N __________________ _____ N 20________________ _____ _ __________________ Bottom Table CONSTRAINT . . . . . . . . . . . . . N Y=Yes, N=No Distributed Table . . . . . . . . . . . . N Y=Yes, N=No F5=Refresh F12=Cancel F6=Insert line F14=Delete line F10=Copy 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.
Chapter 2. Getting Started with SQL
15
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. 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)
16
Specify LABEL ON Statement Type choices, press Enter. Label on . . . . 2 1=Table or view 2=Column 3=Package 4=Alias Name, F4 for list Name, F4 for list 1=Column heading 2=Text
INVENTORY_LIST______ SAMPLECOLL__ 1
F12=Cancel
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 ITEM_NUMBER ITEM_NAME UNIT_COST QUANTITY_ON_HAND LAST_ORDER_DATE ORDER_QUANTITY Column Heading ....+....1....+....2....+....3....+....4....+....5.... 'ITEM NUMBER'___________________________ 'ITEM NAME'_____________________________ 'UNIT COST'_____________________________ 'QUANTITY ON HAND'_________ 'LAST ORDER DATE'_________ 'NUMBER ORDERED'__________________________
Bottom F5=Refresh F6=Insert line F10=Copy line F12=Cancel 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 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 ITEM_NAME IS 'ITEM UNIT_COST IS 'UNIT QUANTITY_ON_HAND IS 'QUANTITY LAST_ORDER_DATE IS 'LAST ORDER_QUANTITY IS 'NUMBER NUMBER', NAME', COST', ON ORDER ORDERED')
HAND', DATE',
F12=Cancel
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
Specify INSERT Statement Type sequence numbers (1-999) to make selections, press Enter. Seq 1__ 2__ 3__ 4__ ___ ___ Column ITEM_NUMBER ITEM_NAME UNIT_COST QUANTITY_ON_HAND LAST_ORDER_DATE ORDER_QUANTITY Type CHARACTER VARCHAR DECIMAL SMALLINT DATE SMALLINT Length 6 20 8 4 4 Bottom Scale 2
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 ITEM_NUMBER ITEM_NAME UNIT_COST QUANTITY_ON_HAND Value '153047'_____________________________________________ 'Pencils, red'_______________________________________ 10.00________________________________________________ 25___________________________________________________
F3=Exit F12=Cancel
Bottom F5=Refresh F6=Insert line F10=Copy line F11=Display type 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)
19
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 153047 229740 544931 303476 559343 291124 775298 073956 Paper clips Envelopes, legal Envelopes, standard Chairs, secretary Pens, black 225.00 20.00 6 25 ITEM_NAME Pencils, red Lined tablets UNIT_COST 10.00 1.50 5.00 2.00 3.00 100 500 QUANTITY_ON_HAND 25 120
The sample collection now contains two tables with several rows of data in each.
20
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 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. FROM tables . . . . . SELECT columns . . . . WHERE conditions . . . GROUP BY columns . . . HAVING conditions . . ORDER BY columns . . . FOR UPDATE OF columns . . . . . . . . . . . . . . . . . . . . . Press F4 for a list.
SAMPLECOLL.INVENTORY_LIST____________________ *____________________________________________ _____________________________________________ _____________________________________________ _____________________________________________ _____________________________________________ _____________________________________________ Bottom N N N Y=Yes, N=No Y=Yes, N=No Y=Yes, N=No
Type choices, press Enter. DISTINCT rows in result table . . . . . . . . . UNION with another SELECT . . . . . . . . . . . Specify additional options . . . . . . . . . . .
F4=Prompt F5=Refresh F6=Insert line F9=Specify subquery 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:
Data width . . . . . . : 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 Display Data 71
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 the rows where no value was inserted. The LAST_ORDER_DATE column contains all null values since that column is not in
Chapter 2. Getting Started with SQL
21
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. FROM tables . . . . . SELECT columns . . . . WHERE conditions . . . GROUP BY columns . . . HAVING conditions . . ORDER BY columns . . . FOR UPDATE OF columns . . . . . . . . . . . . . . . . . . . . . Press F4 for a list.
SAMPLECOLL.INVENTORY_LIST____________________ ITEM_NUMBER, UNIT_COST, ITEM_NAME____________ UNIT_COST > 10.00____________________________ _____________________________________________ _____________________________________________ _____________________________________________ _____________________________________________ Bottom N N N Y=Yes, N=No Y=Yes, N=No Y=Yes, N=No
Type choices, press Enter. DISTINCT rows in result table . . . . . . . . . UNION with another SELECT . . . . . . . . . . . Specify additional options . . . . . . . . . . .
F4=Prompt F5=Refresh F6=Insert line F9=Specify subquery 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:
Data width . . . . . . : 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 Display Data 41
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 from the columns you explicitly specified in the SELECT clause. Data values of columns other than those explicitly identified are not returned.
22
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
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 SQL Reference book. Running this example returns the following output:
23
Data width . . . . . . : 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
Display Data
45
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
24
Data width . . . . . . : 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
Display Data
45
25
Specify UPDATE Statement Type choices, press Enter. Table . . . . . . . . Collection . . . . . Correlation . . . . . INVENTORY_LIST______ SAMPLECOLL__ ____________________ Name, F4 for list Name, F4 for list Name
F12=Cancel
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 . . . . . . . . Collection . . . . . Correlation . . . . . INVENTORY_LIST______ SAMPLECOLL__ ____________________ Name, F4 for list Name, F4 for list Name
Type information, press Enter. Column ITEM_NUMBER ITEM_NAME UNIT_COST QUANTITY_ON_HAND LAST_ORDER_DATE ORDER_QUANTITY F3=Exit F4=Prompt F11=Display type Value _____________________________________________________ _____________________________________________________ _____________________________________________________ _____________________________________________________ CURRENT DATE_________________________________________ 50___________________________________________________ F5=Refresh F12=Cancel F6=Insert line F14=Delete line F10=Copy line F24=More keys Bottom
Specifying CURRENT DATE for a value will change the date in all the selected rows to be todays 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
Specify UPDATE Statement Type WHERE conditions, press Enter. Press F4 for a list. ITEM_NUMBER = '303476'________________________________________________ ______________________________________________________________________
Bottom 1=Current level, 2=NC (NONE) 3=UR (CHG), 4=CS, 5=RS (ALL) 6=RR
F4=Prompt F5=Refresh F6=Insert line F9=Specify subquery 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:
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 Display Data
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.
27
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:
Data width . . . . . . : 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 ******** F3=Exit F12=Cancel F19=Left F20=Right F21=Split Display Data 71
Bottom
28
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. For examples of creating a view using interactive SQL, see the following: v Example: Creating a view on a single table v 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.
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
29
Display Data Position to line . . . . . ....+....1....+....2....+. ITEM LAST QUANTITY NUMBER ORDER ON DATE HAND 303476 05/30/94 100 ******** End of data ******** F3=Exit F12=Cancel F19=Left
26
F20=Right
F21=Split
Bottom
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
Bottom
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
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.
31
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. 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 statements 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.
32
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 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).
For example, suppose an employee was relocated. To update several items of the employees 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 columns current value with the contents of another column in the same row. A constant. Replace the columns current value with the value provided in the SET clause. A null value. Replace the columns 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.
Chapter 3. Basic Concepts and Techniques
33
A host variable. Replace the columns current value with the contents of a host variable. A special register. Replace the columns current value with a special register value; for example, USER. An expression. Replace the columns current value with the value that results from an expression. The expression can contain any of the values in this list. A scalar subselect. Replace the columns current value with the value that the subquery returns. The DEFAULT keyword. Replace the columns 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).
34
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 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 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).
35
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. 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
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.
36
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.
37
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 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.
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).
38
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'
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 Sort sequences in SQL on page 50 for more information on sort sequence and selection.
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
Chapter 3. Basic Concepts and Techniques
39
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
v A special register identifies a special value generated by the database manager. For example:
... WHERE LASTNAME = USER
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 SQL Reference book.
Comparison operators
SQL supports the following comparison operators:
= <> or = or != < > <= or > or !> > = or < or !< Equal to Not equal to Less than Greater than Less than or equal to (or not greater than) Greater than or equal to (or not less than)
NOT Keyword
You can precede a predicate with the NOT keyword to specify that you want the opposite of the predicates 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'
40
Results in: fetch WORK-DEPT AVG-SALARY 1 2 ... A00 B01 ... 42833 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. ( 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 Sort sequences 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:
41
Results in: fetch SUM-PR 1 2 3 ... 6 5 10 ... MAJ-PROJ AD3100 AD3110 MA2100 ...
RV2W552-3
The result is a list of the companys 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:
Results in: fetch DEPT 1 2 3 4 ... A00 A00 B01 C01 ... SEX F M M F ... AVG-WAGES 52750 37875 41250 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.
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'.
42
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:
Results in: fetch DEPT 1 2 3 A00 C01 D11 AVG-WAGES 52750 30156 24476 MIN-EDUC 18 16 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 Sort sequences in SQL on page 50 for more information on sort sequence and selection.
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 columns 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:
43
Results in: fetch PGM-NAME3 1 2 3 4 5 6 7 8 9 10 11 12 13 HAAS KWAN QUINTANA NICHOLLS PIANKA SCOUTTEN LUTZ PULASKI JOHNSON PEREZ HENDERSON SCHNEIDER SETRIGHT DEPT A00 C01 C01 C01 D11 D11 D11 D21 D21 D21 E11 E11 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
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
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 Sort sequences in SQL on page 50 for more information on sort sequence and its affect on ordering.
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 SQL Reference book.
45
Special Registers CURRENT TIME CURRENT_TIME CURRENT TIMESTAMP CURRENT_TIMESTAMP CURRENT TIMEZONE CURRENT_TIMEZONE
Contents The current time. The current date and time in timestamp format. A duration of time that links local time to Universal Coordinated Time (UTC) using the formula: local time - CURRENT TIMEZONE = UTC It is taken from the system value QUTCOFFSET.
CURRENT SERVER CURRENT_SERVER USER CURRENT PATH CURRENT_PATH CURRENT FUNCTION PATH
The name of the relational database as contained in the relational database directory table in the relational database directory. The run-time authorization identifier (user profile) of the job. The SQL path used to resolve unqualified data type names, procedure names, and 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 CURRENT DATE CURRENT_DATE CURRENT TIME CURRENT_TIME CURRENT TIMESTAMP CURRENT_TIMESTAMP CURRENT TIMEZONE CURRENT_TIMEZONE CURRENT SERVER CURRENT_SERVER USER CURRENT PATH CURRENT_PATH CURRENT FUNCTION PATH Contents The current date and time at the remote system, not the local system.
A duration of time that links the remote system time to UTC. The name of the relational database as contained in the relational database directory table in the relational database directory. The run-time authorization identifier of the server job on the remote system. The current path value at the remote system.
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 Multisystembook.
46
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 SQL Reference book .
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 SQL Reference book.
47
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
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, and
48
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 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 SQL Reference book.
49
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'
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 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.
50
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 100 90 80 10 50 30 20 40 70 60 NAME Plotz Koonitz James Sanders Hanes Merenghi Pernal OBrien Rothman Quigley DEPT 42 42 20 20 15 38 20 38 15 38 JOB mgr sales Clerk Mgr Mgr MGR Sales Sales Sales SALES YEARS 6 6 0 7 10 5 8 6 7 0 SALARY 18352.80 18001.75 13504.60 18357.50 20659.80 17506.75 18171.25 18006.00 16502.83 16808.30 COMM 0 1386.70 128.20 0 0 0 612.45 846.55 1152.00 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 80 100 10 50 30 90 20 40 70 60 NAME James Plotz Sanders Hanes Merenghi Koonitz Pernal OBrien Rothman Quigley DEPT 20 42 20 15 38 42 20 38 15 38 JOB Clerk mgr Mgr Mgr MGR sales Sales Sales Sales SALES YEARS 0 6 7 10 5 6 8 6 7 0 SALARY 13504.60 18352.80 18357.50 20659.80 17506.75 18001.75 18171.25 18006.00 16502.83 16808.30 COMM 128.20 0 0 0 0 1386.70 612.45 846.55 1152.00 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 sort comparison, each lowercase letter is treated the same as the corresponding uppercase letter. In Table 5 on page 52, notice that all the values 'MGR', 'mgr' and 'Mgr' are mixed together.
51
Table 5. SELECT * FROM STAFF ORDER BY JOB Using the Shared-Weight Sort Sequence for the ENU Language Identifier. ID 80 10 30 50 100 20 40 60 70 90 NAME James Sanders Merenghi Hanes Plotz Pernal OBrien Quigley Rothman Koonitz DEPT 20 20 38 15 42 20 38 38 15 42 JOB Clerk Mgr MGR Mgr mgr Sales Sales SALES Sales sales YEARS 0 7 5 10 6 8 6 0 7 6 SALARY 13504.60 18357.50 17506.75 20659.80 18352.80 18171.25 18006.00 16808.30 16502.83 18001.75 COMM 128.20 0 0 0 0 612.45 846.55 650.25 1152.00 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 30 NAME Merenghi DEPT 38 JOB MGR YEARS 5 SALARY 17506.75 COMM 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 30 NAME Merenghi DEPT 38 JOB MGR YEARS 5 SALARY 17506.75 COMM 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 10 30 50 NAME Sanders Merenghi Hanes DEPT 20 38 15 JOB Mgr MGR Mgr YEARS 7 5 10 SALARY 18357.50 17506.75 20659.80 COMM 0 0 0
52
Table 8. SELECT * FROM STAFF WHERE JOB = MGR Using the Shared-Weight Sort Sequence for the ENU Language Identifier. (continued) ID 100 NAME Plotz DEPT 42 JOB mgr YEARS 6 SALARY 18352.80 COMM 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 30 NAME Merenghi DEPT 38 JOB MGR YEARS 5 SALARY 17506.75 COMM 0
53
54
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 rows contents into your programs 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. 2000
55
statement), SQL moves the current rows contents into your programs 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 PRIOR FIRST LAST BEFORE AFTER CURRENT RELATIVE n Positions the cursor on the next row. This is the default if no position is specified. Positions the cursor on the previous row. Positions the cursor on the first row. Positions the cursor on the last row. Positions the cursor before the first row. Positions the cursor after the last row. Does not change the cursor position. Evaluates a host variable or integer n in relationship to the cursors 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.
56
Table 11. A Serial Cursor Example (continued) Serial Cursor SQL Statement EXEC SQL FETCH THISEMP INTO :EMP-NUM, :NAME2, :DEPT, :JOB-CODE END-EXEC. ... for all employees in department D11, update 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, delete the row: EXEC SQL DELETE FROM CORPDATA.EMPLOYEE WHERE CURRENT OF THISEMP END-EXEC. Branch back to fetch and process the next row. CLOSE-THISEMP. EXEC SQL CLOSE THISEMP END-EXEC. Step 6: Close the cursor on page 62. Step 5b: Delete the current row on page 61. Described in Section Step 4: Retrieve a row using a cursor on page 60.
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
Step 1: Define the cursor on page 58. EXEC SQL DECLARE THISEMP DYNAMIC SCROLL CURSOR FOR SELECT EMPNO, LASTNAME, SALARY FROM CORPDATA.EMPLOYEE WHERE WORKDEPT = D11 END-EXEC. EXEC SQL OPEN THISEMP END-EXEC. EXEC SQL WHENEVER NOT FOUND GO TO CLOSE-THISEMP END-EXEC. Step 2: Open the cursor on page 59.
57
Table 12. Scrollable Cursor Example (continued) Scrollable Cursor SQL Statement ...initialize program summation salary variable 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. EXEC SQL CLOSE THISEMP END-EXEC. Step 6: Close the cursor on page 62. Described in Section Step 4: Retrieve a row using a cursor on page 60.
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
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.
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.
60
When used with a cursor, the UPDATE statement: v Updates only one rowthe 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 cursors 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.
When used with a cursor, the DELETE statement: v Deletes only one rowthe 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. Removing rows from a table using 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.
61
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.
62
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.
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 SQL Reference book for a description of the SQLCA.
64
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 SQL Reference book for a description of the SQLDA. Consider the following PL/I example:
*....+....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';
65
... 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 */ ... 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:
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
66
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 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.
67
68
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. 2000
69
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.
70
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.
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 into the result table). For example, suppose you want a list of employee job
Chapter 5. Advanced Coding Techniques
71
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 1 JOB 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 columns 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.
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'
72
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 theSQL 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 columns 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.
73
'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'
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. 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:
4. You could also use IN to specify this request: WHERE WORKDEPT IN ('C01', 'D11').
74
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
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. 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
75
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.
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 000020 000060 000100 000250 LASTNAME THOMPSON STERN SPENSER SMITH PROJNO PL2100 MA2110 OP2010 AD3112
76
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 000020 000060 000100 000170 000180 000190 000250 000280 000300 000310 LASTNAME THOMPSON STERN SPENSER YOSHIMURA SCOUTTEN WALKER SMITH SCHNEIDER SMITH SETRIGHT PROJNO PL2100 MA2110 OP2010 AD3112 -
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'
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:
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 A1 A2 A3 Table 14. Table B T2COL1 B1 B2 T2COL2 BB1 BB2 T1COL2 AA1 AA2 AA3
The result table for either of these select statements looks like this:
T1COL1 A1 A1 A2 A2 A3 A3 T1COL2 AA1 AA1 AA2 AA2 AA3 AA3 T2COL1 B1 B2 B1 B2 B1 B2 T2COL2 BB1 BB2 BB1 BB2 BB1 BB2
78
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 000020 000060 000100 000170 000180 000190 000250 000280 000300 000310 LASTNAME THOMPSON STERN SPENSER YOSHIMURA SCOUTTEN WALKER SMITH SCHNEIDER SMITH SETRIGHT DEPTNAME PLANNING MANUFACTURING SYSTEMS SOFTWARE SUPPORT MANUFACTURING SYSTEMS MANUFACTURING SYSTEMS MANUFACTURING SYSTEMS ADMINISTRATION SYSTEMS OPERATIONS OPERATIONS OPERATIONS PROJNO PL2100 MA2110 OP2010 AD3112 -
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.
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
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%'
80
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:
81
Which results in an interim result table: (from CORPDATA.EMPLOYEE) 000060 000150 000160 000170 ...
Which results in another interim result table: (from CORPDATA.EMP ACT) 000230 000230 000230 ...
Which results in a combined result table with values in ascending sequence: fetch EMP-NUMBER 1 2 3 4 5 ... 000060 000150 000160 000170 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
82
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 rows 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 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.
Resulting in a result table that includes duplicates: fetch EMP-NUMBER 1 2 3 4 5 6 7 8 ... 000060 000150 000150 000150 000160 000160 000170 000170 ...
RV3W187-0
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
Chapter 5. Advanced Coding Techniques
83
evaluation. 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.
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
Which results in an interim results table: (from CORPDATA.EMP ACT) 000010 000110
Step 2: The interim results table then serves as a list in the search condition of the outer-level SELECT. Essentially, this is what is executed.
fetch 1 2
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.
85
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.
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.
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. 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)
86
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 SQL Reference.
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 ...)
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 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
87
The result table produced by a subquery can have zero or more rows. For some usages, no more than one row is allowed.
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 new row (WHERE clause) or group of rows (HAVING clause) in the outer-level SELECT. This is called a correlated subquery.
88
this information, SQL must search the CORPDATA.EMPLOYEE table. For each employee in the table, SQL needs to compare the employees education level to the average education level for the employees 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 subselects 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 Christines department. This is then compared in the outer statement to Christines 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:
(from CORPDATA.EMPLOYEE)
EDLEVEL 18 20 16 16
RV2W560-3
89
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:
(from CORPDATA.EMPLOYEE) fetch WORKDEPT 1 2 D21 E01 AVG SALARY 25153.33 40175.00
RV2W561-3
90
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 querys 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.
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.
91
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.
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. v You can nest correlated subqueries.
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.
92
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 definition 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 Decimal TO data type Numeric Bigint, Integer, Smallint Float Decimal Bigint, Integer, Smallint Float Decimal Numeric Float Numeric Bigint, Integer, Smallint DBCS-open UCS-2 graphic Character UCS-2 graphic Character DBCS-open UCS-2 graphic DBCS-open
| | | | |
Numeric Numeric Bigint, Integer, Smallint Bigint, Integer, Smallint Bigint, Integer, Smallint Float Float Character Character DBCS-open DBCS-open DBCS-either DBCS-either DBCS-either DBCS-only
93
Table 15. Allowable Conversions (continued) FROM data type DBCS-only DBCS-only DBCS graphic UCS-2 graphic UCS-2 graphic UCS-2 graphic distinct type source type TO data type DBCS graphic UCS-2 graphic UCS-2 graphic Character DBCS-open DBCS graphic 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)
COL2 would still have an allocated length of 10 and CCSID 937, and COL3 would still have an allocated length of 10.
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.
94
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
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.
Chapter 5. Advanced Coding Techniques
95
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 Sort sequences 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)
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 in the Database Performance and Query Optimization information. One 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 INDX 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 Sort sequences in SQL on page 50 for more information on sort sequences.
96
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
Chapter 5. Advanced Coding Techniques
97
v If the column allows default values The result looks like this:
NAME DEPTNO DEPTNAME MGRNO ADMRDEPT TBNAME DEPARTMENT DEPARTMENT DEPARTMENT DEPARTMENT COLTYPE CHAR VARCHAR CHAR CHAR LENGTH 3 29 6 3 DEFAULT N N Y N
98
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)
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. 2000
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 SQL Reference book.
100
v A primary or unique key 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.
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.
101
WORKDEPT_EXISTS establishes the EMPLOYEE table as a dependent table, and the column of 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.
102
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')
103
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 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 239 and Commitment control on page 239.
104
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';
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.
105
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. 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.
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 A00 B01 C01 D01 D11 DEPTNAME SPIFFY COMPUTER SERVICE DIV. PLANNING INFORMATION CENTER DEVELOPMENT CENTER MANUFACTURING SYSTEMS MGRNO 000010 000020 000030 ? 000060 ADMRDEPT A00 A00 A00 A00 D01
106
Table 16. DEPARTMENT Table (continued). Contents of the table after the DELETE statement is complete. DEPTNO D21 E01 E21 DEPTNAME ADMINISTRATION SYSTEMS SUPPORT SERVICES SOFTWARE SUPPORT MGRNO 000070 000050 000100 ADMRDEPT D01 A00 E01
Note that there were no cascaded deletes in the DEPARTMENT table because no department reported to department E11. 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 000230 000240 000250 000260 000270 000280 000290 000300 000310 000320 000330 000340 FIRSTNME MI JAMES J LASTNAME WORKDEPTPHONENO HIREDATE JEFFERSON MARINO SMITH JOHNSON PEREZ D21 D21 D21 D21 D21 2094 3780 0961 8953 9001 0997 4502 2095 3332 9990 2103 5696 1966-11-21 1979-12-05 1960-10-30 1975-09-11 1980-09-30 1967-03-24 1980-05-30 1972-06-19 1964-09-12 1965-07-07 1976-02-23 1947-05-05
SALVATORE M DANIEL SYBIL MARIA ETHEL JOHN PHILIP MAUDE RAMLAL WING JASON R S P L R R X F V
SCHNEIDER E11 PARKER SMITH SETRIGHT MEHTA LEE GOUNOT E11 E11 E11 E21 E21 E21
Table 18. Partial EMPLOYEE Table. Partial contents after the DELETE statement. EMPNO 000230 000240 000250 000260 000270 000280 000290 000300 000310 000320 000330 000340 FIRSTNME MI JAMES J LASTNAME WORKDEPTPHONENO HIREDATE JEFFERSON MARINO SMITH JOHNSON PEREZ D21 D21 D21 D21 D21 2094 3780 0961 8953 9001 0997 4502 2095 3332 9990 2103 5696 1966-11-21 1979-12-05 1960-10-30 1975-09-11 1980-09-30 1967-03-24 1980-05-30 1972-06-19 1964-09-12 1965-07-07 1976-02-23 1947-05-05
SALVATORE M DANIEL SYBIL MARIA ETHEL JOHN PHILIP MAUDE RAMLAL WING JASON R S P L R R X F V
SCHNEIDER ? PARKER SMITH SETRIGHT MEHTA LEE GOUNOT ? ? ? E21 E21 E21
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
Chapter 6. Data Integrity
107
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. 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 Database Programming book.
108
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)
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)
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)
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)
Chapter 6. Data Integrity
109
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. 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.
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 doesnt 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,
110
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.
111
Trigger sample
A sample trigger program follows. It is written in ILE C, with embedded SQL. See the Database Programming book for a full discussion and more examples of trigger usage in DB2 UDB for AS/400.
#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 2. Sample Trigger Program (Part 1 of 5)
112
main(int argc, char **argv) { int i; int obufoff; /* int nuloff; /* int nbufoff; /* int nul2off; /* short work_days = 253; /* decimal(9,2) commission = 2000.00; /* decimal(9,2) percentage = 1.04; /* char raise_date[12] = "1982-06-01";/* struct { char empno[6]; char name[30]; decimal(9,2) salary; decimal(9,2) new_salary; } rpt1;
old buffer offset old null byte map offset new buffer offset new null byte map offset work days during in one year cutoff to qualify for raised salary as percentage effective raise date
*/ */ */ */ */ */ */ */
/*******************************************************/ /* 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 2. Sample Trigger Program (Part 2 of 5) */ */
113
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);
*/
114
/******************************************************************/ /* 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 *, void *, void *, int, char *, char *, int, void *, void *, ...); Message identifier */ Qualified message file name */ Message data or text */ Length of message data or text */ Message type */ Call message queue */ Call stack counter */ Message key */ 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 2. Sample Trigger Program (Part 4 of 5) /* /* /* /* /* /* /* /* /* /*
115
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 2. Sample Trigger Program (Part 5 of 5)
116
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.
117
v Gives other information about the procedure which will the system uses when it calls the procedure. Consider the following example:
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.
118
Consider the following simple example that takes as input an employee number and a rate and updates the employees salary:
EXEC SQL CREATE PROCEDURE UPDATE_SALARY_1 (IN EMPLOYEE_NUMBER CHAR(10), IN RATE DECIMAL(6,2)) 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 v v v v a CASE statement a compound statement a FOR statement an IF statement 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;
119
This CREATE PROCEDURE statement: v Names the procedure UPDATE_SALARY_2. 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)DEFAULT 0 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.
120
Declares SQL variables BONUS_CNT and END_TABLE which are integers and are initialized to 0. 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 employees 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 SQLSTATE '42710' SELECT COUNT(*) INTO CNT FROM DATALIB.EMPLOYEE_BONUS; DECLARE CONTINUE HANDLER FOR SQLSTATE '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
Chapter 7. Stored Procedures
| |
| |
121
| |
WHERE WORKDEPT = CREATE_BONUS_TABLE.DEPT_NUMBER; DO IF BONUS > 0 THEN SET NAME = FIRSTNME CONCAT ' ' CONCAT MIDINIT CONCAT ' 'CONCAT 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.
122
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.
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 = 'CORPDATA.DEPT_' CONCAT P_DEPT CONCAT '_T'; SET STMT = 'DROP TABLE ' CONCAT TABLE_NAME; PREPARE S1 FROM STMT; EXECUTE S1; SET STMT = 'CREATE TABLE ' CONCAT TABLE_NAME CONCAT '( EMPNO CHAR(6) NOT NULL, FIRSTNME VARCHAR(12) 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 ' CONCAT TABLE_NAME CONCAT 'SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, SALARY FROM CORPDATA.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.
123
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
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.
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.
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
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.
| | |
BIGINT
DECIMAL(p,s)
decimal(p,s)
TYPE(*DEC) LEN(p s)
NUMERIC(p,s)
REAL or FLOAT(p)
float
double
TYPE(*CHAR) LEN(n) -
128
Table 19. Data Types of Parameters (continued) SQL Data Type VARCHAR(n) FOR BIT DATA C and C++ CL COBOL for AS/400 and ILE COBOL for AS/400 Varying-Length Character String (see COBOL chapter) Note: Only supported for ILE COBOL for AS/400. PIC G(n) DISPLAY-1 or PIC N(n) Note: Only supported for ILE COBOL for AS/400. Varying-Length Graphic String (see COBOL chapter) Note: Only supported for ILE COBOL for AS/400. PIC X(10) For ILE COBOL for AS/400 only, FORMAT DATE. PIC X(8) For ILE COBOL for AS/400 only, FORMAT TIME. PIC X(26) For ILE COBOL for AS/400 only, FORMAT TIMESTAMP. PIC S9(4) BINARY CLOB structured form (see COBOL chapter in SQL Programming with Host Languages). Note: only supported for ILE COBOL for AS/400. BLOB structured form (see COBOL chapter in SQL Programming with Host Languages). Note: only supported for ILE COBOL for AS/400. DBCLOB structured form (see COBOL chapter in SQL Programming with Host Languages). Note: only supported for ILE COBOL for AS/400. -
GRAPHIC(n)
VARGRAPHIC(n)
DATE
TYPE(*CHAR) LEN(10)
TIME
TYPE(*CHAR) LEN(8)
TIMESTAMP
TYPE(*CHAR) LEN(26)
short CLOB structured form (see C chapter in SQL Programming with Host Languages)
BLOB
BLOB structured form (see C chapter in SQL Programming with Host Languages)
DBCLOB
DBCLOB structured form (see C chapter in SQL Programming with Host Languages)
DataLink
Table 20. Data Types of Parameters SQL Data Type SMALLINT INTEGER FORTRAN INTEGER*2 INTEGER*4 Java Parameter Style JAVA short int long BigDecimal Java Parameter Style DB2GENERAL short int long BigDecimal PL/I FIXED BIN(15) FIXED BIN(31) FIXED DEC(p,s)
BIGINT DECIMAL(p,s)
129
Table 20. Data Types of Parameters (continued) SQL Data Type NUMERIC(p,s) REAL or FLOAT(p) FORTRAN REAL*4 Java Parameter Style JAVA BigDecimal float double Java Parameter Style DB2GENERAL BigDecimal float double PL/I FLOAT BIN(p) FLOAT BIN(p)
DOUBLE PRECISION REAL*8 or FLOAT or FLOAT(p) CHARACTER(n) VARCHAR(n) VARCHAR(n) FOR BIT DATA GRAPHIC(n) VARGRAPHIC(n) DATE TIME TIMESTAMP Indicator Variable CLOB CHARACTER*n CHARACTER*10 CHARACTER*8 CHARACTER*26 INTEGER*2 -
String String
com.ibm.db2.app.Blob CHAR(n) VAR String String String String String CHAR(10) CHAR(8) CHAR(26) FIXED BIN(15)
com.ibm.db2.app.Clob CLOB structured form (see PL/I chapter in SQL Programming with Host Languages) com.ibm.db2.app.Blob BLOB structured form (see PL/I chapter in SQL Programming with Host Languages) com.ibm.db2.app.Clob DBCLOB structured form (see PL/I chapter in SQL Programming with Host Languages) -
BLOB
DBCLOB
DataLink
Table 21. Data Types of Parameters SQL Data Type REXX RPG Data structure that contains a single sub-field. B in position 43, length must be 2, and 0 in position 52 of the sub-field specification. ILE RPG Data specification. B in position 40, length must be <= 4, and 00 in positions 41-42 of the sub-field specification. or Data specification. I in position 40, length must be 5, and 00 in positions 41-42 of the sub-field specification.
| | | | | | | | |
SMALLINT
130
Table 21. Data Types of Parameters (continued) SQL Data Type REXX RPG ILE RPG Data specification. B in position 40, length must be <=09 and >=05, and 00 in positions 41-42 of the sub-field specification. or Data specification. I in position 40, length must be 10, and 00 in positions 41-42 of the sub-field specification. Data specification. I in position 40, length must be 20, and 00 in positions 41-42 of the sub-field specification. Data specification. P in position 40 and 00 through 31 in positions 41-42 of the sub-field specification.
| | | | | | | | | | | | |
INTEGER
numeric string with Data structure that contains a no decimal (and an single sub-field. B in position 43, optional leading sign) length must be 4, and 0 in position 52 of the sub-field specification.
BIGINT
DECIMAL(p,s)
numeric string with a Data structure that contains a decimal (and an single sub-field. P in position 43 optional leading sign) and 0 through 9 in position 52 of the sub-field specification. or A numeric input field or calculation result field. Data structure that contains a single sub-field. Blank in position 43 and 0 through 9 in position 52 of the sub-field specification. -
NUMERIC(p,s)
Data specification. S in position 40, or Blank in position 40 and 00 through 31 in position 41-42 of the sub-field specification. Data specification. F in position 40, length must be 4.
REAL or FLOAT(p)
DOUBLE PRECISION string with digits, then an E, (then an or FLOAT or optional sign), then FLOAT(p) digits CHARACTER(n) string with n characters within two apostrophes
Data structure field without sub-fields or data structure that contains a single sub-field. Blank in position 43 and 52 of the sub-field specification. or A character input field or calculation result field. -
Data specification. A in position 40, or Blank in position 40 and 41-42 of the sub-field specification.
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. 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. Data specification. G in position 40 of the sub-field specification.
GRAPHIC(n)
131
Table 21. Data Types of Parameters (continued) SQL Data Type VARGRAPHIC(n) REXX RPG ILE RPG Data specification. G in position 40 of the sub-field specification and the keyword VARYING in positions 44-80.
string starting with G, then n double byte characters, then string with 10 characters within two apostrophes
DATE
Data structure field without Data specification. D in position sub-fields or data structure that 40 of the sub-field specification. contains a single sub-field. Blank DATFMT(*ISO) in position 44-80. in position 43 and 52 of the sub-field specification. Length is 10. or A character input field or calculation result field. Data specification. T in position Data structure field without 40 of the sub-field specification. sub-fields or data structure that contains a single sub-field. Blank TIMFMT(*ISO) in position 44-80. in position 43 and 52 of the sub-field specification. Length is 8. or A character input field or calculation result field. Data specification. Z in position Data structure field without 40 of the sub-field specification. sub-fields or data structure that contains a single 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. Data specification. B in position 40, length must be <=4, and 00 in positions 41-42 of the sub-field specification. CLOB structured form (see RPG chapter in SQL Programming with Host Languages) BLOB structured form (see RPG chapter in SQL Programming with Host Languages) DBCLOB structured form (see RPG chapter in SQL Programming with Host Languages) -
TIME
TIMESTAMP
Indicator Variable
Data structure that contains a numeric string with single sub-field. B in position 43, no decimal (and an optional leading sign). length must be 2, and 0 in position 52 of the sub-field specification. -
CLOB
BLOB
DBCLOB
DataLink
132
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)
133
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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 3. Handling of Indicator Variables in CALL Statements (Part 1 of 2)
134
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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 3. Handling of Indicator Variables in CALL Statements (Part 2 of 2)
135
136
137
/*******************************************************/ /* 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 4. Sample of CREATE PROCEDURE and CALL (Part 2 of 2)
138
/******** 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 5. Sample Procedure P1 (Part 1 of 2) */ */ */ */ */ */
139
/**********************************************************/ /* 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 5. Sample Procedure P1 (Part 2 of 2)
140
/******** 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; */ */
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
141
142
/* *************************************************************/ /* 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 7. Sample REXX Procedure Called From C Application (Part 2 of 4)
143
/**********************************************************************/ /****** 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 7. Sample REXX Procedure Called From C Application (Part 3 of 4)
144
/************************************************************/ /* 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 **********************************/
| | |
145
A connection to the embedding application context is accessed using the following Java Database Connectivity (JDBC) call: connection=DriverManager.getConnection(jdbc:default:connection); This connection then runsSQL statements with JDBC APIs. The following is a small stored procedure with one input and two outputs. It executes the given SQL query, and returns the number of rows in the result, and the SQLSTATE.
package mystuff; import java.sql.*; public class sample2 { public static void donut(String query, int[] rowCount, String[] sqlstate) throws Exception { try { Connection c=DriverManager.getConnection("jdbc:default:connection"); Statement s=c.createStatement(); ResultSet r=s.executeQuery(query); int counter=0; while(r.next()){ counter++; } r.close(); s.close(); rowCount[0] = counter; }catch(SQLException x){ sqlstate[0]= x.getSQLState(); } } }
All Java class files that are used by a Java stored procedure must reside in the /QIBM/UserData/OS400/SQLLib/Function directory. This directory is the AS/400 equivalent of sqllib/function, the directory where DB2 UDB stores Java stored procedures on other platforms.
146
Within the classes, the stored procedures are identified by their method name and signature. When you call a stored procedure, its signature is generated dynamically, based on the variable types defined by the CREATE PROCEDURE statement. The com.ibm.db2.app.StoredProc class provides the isNull( ) method which permits a Java method to determine if an input parameter is an SQL NULL. The com.ibm.db2.app.StoredProc class also provides set...( ) methods that set output parameters. You must use these methods to set output parameters. If you do not set an output parameter, then the output parameter will return the SQL NULL value. The com.ibm.db2.app.StoredProc class provides the following routine to fetch a JDBC connection to the embedding application context. A connection to the embedding application context is accessed using the following JDBC call:
public Java.sql.Connection getConnection( )
This connection then runs SQL statements with JDBC APIs. The following is a small stored procedure with one input and two outputs. It executes the given SQL query, and returns the number of rows in the result, and the SQLSTATE.
package mystuff; import com.ibm.db2.app.*; import java.sql.*; public class sample2 extends StoredProc { public void donut(String query, int rowCount, String sqlstate) throws Exception { try { Statement s=getConnection().createStatement(); ResultSet r=s.executeQuery(query); int counter=0; while(r.next()){ counter++; } r.close(); s.close(); set(2, counter); }catch(SQLException x){ set(3, x.getSQLState()); } } }
All Java class files that are used by a Java stored procedure must reside in the /QIBM/UserData/OS400/SQLLib/Function directory. This directory is the AS/400 equivalent of sqllib/function, the directory where DB2 UDB stores Java stored procedures on other platforms. When compiling a Java stored procedure that uses the DB2GENERAL parameter style, the user must add /QIBM/ProdData/Java400/ext/db2routines_classes.jar to the CLASSPATH.
147
v v
v v v
is no guaranteed that a job that calls an SQL stored procedure is multithread capable, a Java stored procedure should not create additional threads. Like stored procedures that are written in other programming languages, Java stored procedures may not execute the following SQL statements: COMMIT, ROLLBACK, SET TRANSACTION, CONNECT, DISCONNECT, RELEASE, or SET CONNECTION. Java stored procedures do no have the ability to return RESULT SETS. Since there is not a program object associated with a Java class file, the CREATE PROCEDURE information associated with the database is not stored with the program object. Therefore, it is not restored when a Java class is restored. You cannot use adopted authority to access Java class files. A Java stored procedure always uses the latest version of the Java Development Kit that is installed on the system. Since Blob and Clob classes reside in both the java.sql and com.ibm.db2.app packages, the programmer must use the entire name of these classes if both classes are used in the same program. The program must ensure that the Blob and Clob classes from the com.ibm.db2.app are used as the parameters passed to the stored procedure. Java stored procedures are stored in Java class files instead of *PGM objects or *SRVPGM objects. Therefore, the REVOKE and GRANT SQL commands cannot be used to revoke or grant authority to the Java class files.
148
149
LOBs are general-purpose mechanisms that can be used to model any database 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.
150
151
v Select the LOB value into a LOB locator. The LOB value remains on the server; it is not copied to the host variable. 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.
152
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
153
CHECKERR ("FREE LOCATOR"); EXEC SQL CLOSE c1; CHECKERR ("CLOSE CURSOR"); EXEC SQL CONNECT RESET; CHECKERR ("CONNECT RESET"); return 0;
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 * format with the length inspect passwd-name before initial " statement must be entered in a VARCHAR of the input string. tallying passwd-length for characters ".
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. 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. 3
154
go to End-Prog. Fetch-Loop Section. EXEC SQL FETCH c1 INTO :empnum, :resume :lobind 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. 2
155
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.
156
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 users 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 COBOL
#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;
check_error is redefined as CHECKERR and is located in the util.c file. CHECKERR is an external program named checkerr.cbl
C Sample: LOBFILE.SQC
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 WHERE resume_format='ascii' AND empno='000130'; 3
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;
157
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 * format with the length inspect passwd-name before initial " statement must be entered in a VARCHAR of the input string. tallying passwd-length for characters ".
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. 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. 2
158
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 v v v Copy File (CPYF) when the value *PRINT is specified for the TOFILE keyword Display Journal (DSPJRN) Retrieve Journal Entry (RTVJRNE) Receive Journal Entry (RCVJRNE) when the values *TYPE1, *TYPE2, *TYPE3 and *TYPE4 are specified for the ENTFMT keyword.
159
160
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 155 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 173. For additional details on UDTs and the important concept of castability discussed herein, see the CREATE DISTINCT TYPE statement in the 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(1M)
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
Chapter 8. Using the Object-Relational Capabilities
161
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, ... )
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. The full name of a function using *SQL naming is <schema-name>.<functionname>.
162
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 DB2s 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 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 166. See the 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.
163
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 SQLan 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 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 189 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 189. 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
164
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 189. 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. The statement allows you to specify the language and name of the program, along with options such as DETERMINISTIC, ALLOW PARALLEL, and RETURNS NULL 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 189.
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 DETERMINISTIC NO EXTERNAL ACTION RETURNS NULL ON NULL INPUT ALLOW PARALLEL
165
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.
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 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 167). 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.
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
166
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.
Note that this FINDSTRING function has a different signature from the FINDSTRING functions in Example: BLOB string search on page 166, 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 166. 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.
Observe that CAST FROM and SPECIFIC are not specified, but that NOT DETERMINISTIC is specified.
167
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). The 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 162 for a summary of the use and importance of the path and the function resolution algorithm. You can find the details for both of
168
these concepts in the 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.
169
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))
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 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 SQL Reference. The INTEGER function is a built-in function in the QSYS2 schema.
170
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 170, 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 Kathys 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.
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.
Chapter 8. Using the Object-Relational Capabilities
171
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 ...
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)...
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 ; SQL TYPE IS CLOB_LOCATOR clob_locator1; char string[40]; EXEC SQL END DECLARE SECTION; /* LOB host var */ /* LOB locator host var */ /* string host var */
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 166, 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
172
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. DB2s 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 167, 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.
173
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 160) 6. 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 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 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.
174
For information on how unqualified function references are resolved, see Using qualified function reference on page 170.
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)
Example: Sales
Suppose you want to define tables to keep your companys 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) 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)
Chapter 8. Using the Object-Relational Capabilities
175
The UDTs in the above examples are created using the same CREATE DISTINCT TYPE statements in Example: Money on page 175. Note that the above examples use check constraints. For information on check constraints see the SQL Reference.
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.
176
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
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:
177
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())
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.
178
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.
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.
You made use of DB2s 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.
179
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
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.
180
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.
181
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 NO SQL DETERMINISTIC NO EXTERNAL ACTION CREATE TABLE ELECTRONIC_MAIL (ARRIVAL_TIMESTAMP TIMESTAMP, MESSAGE E_MAIL)
182
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 of the distinct type.
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.
183
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 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.
184
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.
185
186
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 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.
187
188
189
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 in the Programming category of the Information Center. 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 statements thread. Primarily, these are the table resources discussed above. v UDFs do not inherit 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 in the Programming category of the Information Center.
190
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 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.
SQL-argument
SQL-argument-ind
191
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 -1 The argument is present and not null. 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.
192
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-result-ind SQL-state
SQL-argument
SQL-argument-ind
scratchpad This argument is set by DB2 before calling the UDF. It is only present if the
Chapter 9. Writing User-Defined Functions (UDFs)
193
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 0s 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 0 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. This is a normal call. (All the normal input argument values are passed). 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. 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
194
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. 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 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 -1 The argument is present and not null. 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
Chapter 9. Writing User-Defined Functions (UDFs)
195
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. 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. Note: v The external name specified on the CREATE FUNCTION statement can be specified either with quotes or without quotes. If the name is not quoted, it is uppercased before it is stored; if it is quoted, it is stored as specified. This becomes important when naming the actual program, as the database searches for the program that has a name that exactly matches the name stored with the function definition. For example, if a function was created as:
CREATE FUNCTION X(INT) RETURNS INT LANGUAGE C EXTERNAL NAME 'MYLIB/MYPGM(MYENTRY)'
the database would not find the entry because it is in lower case myentry and the database was instructed to look for uppercase MYENTRY. v For service programs with C++ modules, make sure in the C++ source code to precede the program function definition with extern C. Otherwise, the C++ compiler will perform name mangling of the functions name and the database will not find it.
The following examples show how to define the UDF several different ways. v Using an SQL function
196
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; }
v Using an external function, parameter style GENERAL: 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 GENERAL ALLOW PARALLEL
The code:
double SQUARE(int *inval) { double outval; outval=*inval; outval=outval*outval; return(outval); }
197
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, short *outnull, char *sqlstate, char *funcname, char *specname, char *mesgtext, struct scr *scratchptr) { *out = ++scratchptr->countr; *outnull = 0; return; /* /* /* /* /* /* /* output answer (counter) */ output NULL indicator */ SQL STATE */ function name */ specific function name */ message text insert */ scratch pad */
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. 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.
198
199
Table 22. List of SQL Statements Allowed in Dynamic Applications (continued) SQL Statement CONNECT CREATE ALIAS CREATE COLLECTION CREATE DISTINCT TYPE CREATE FUNCTION CREATE INDEX CREATE PROCEDURE CREATE SCHEMA CREATE TABLE CREATE VIEW DECLARE CURSOR DECLARE PROCEDURE DECLARE STATEMENT DECLARE VARIABLE DELETE DESCRIBE DESCRIBE TABLE DISCONNECT DROP END DECLARE SECTION EXECUTE EXECUTE IMMEDIATE FETCH FREE LOCATOR GRANT INCLUDE INSERT LABEL ON LOCK TABLE OPEN PREPARE RELEASE RENAME REVOKE ROLLBACK SELECT INTO SELECT statement SET CONNECTION SET OPTION SET PATH Static SQL Y Y Y Y Y Y Y N Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Dynamic SQL N Y Y Y Y Y Y See Note 8. Y Y See Note 4. N N N Y See Note 7. N N Y N See Note 1. See Note 2. N Y Y N Y Y Y N See Note 3. N Y Y Y See Note 5. See Note 6. N See Note 9. Y
200
Table 22. List of SQL Statements Allowed in Dynamic Applications (continued) SQL Statement SET RESULT SETS SET TRANSACTION SET variable UPDATE VALUES INTO WHENEVER Static SQL Y Y Y Y Y Y Dynamic SQL N Y N Y N 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 202. 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 on page 202. 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 on page 202. 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.
201
202
EXEC SQL PREPARE S1 FROM :DSTRING; /*DSTRING is the delete statement that the PREPARE statement is naming S1.*/ 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.
203
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). 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 5b on page 205, 6 on page 205, and 7 on page 205 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.
204
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. 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.
205
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 the topic Coding SQL Statements in REXX Applications in the SQL Programming with Host Languages information. 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.
206
SQLLEN SQLLEN is a 2-byte integer variable that specifies the length attributes of the host variables shown in Figure 10-2.
Table 23. SQLTYPE and SQLLEN Values for PREPARE, DESCRIBE, FETCH, OPEN, CALL, or EXECUTE For PREPARE and DESCRIBE SQLTYPE 384/385 COLUMN DATA TYPE Date SQLLEN 10 For FETCH, OPEN, CALL, and EXECUTE HOST VARIABLE DATA TYPE Fixed-length character string representation of a date Fixed-length character string representation of a time Fixed-length character string representation of a timestamp N/A NUL-terminated graphic string Fixed-length character string representation of a timestamp BLOB CLOB DBCLOB Fixed-length character string Long varying-length character string NUL-terminated character string Varying-length graphic string SQLLEN Length attribute of the host variable Length attribute of the host variable Length attribute of the host variable N/A Length attribute of the host variable Length attribute of the host variable Not used.7 Not used.7 Not used.7 Length attribute of the host variable Length attribute of the host variable Length attribute of the host variable Length attribute of the host variable
388/389
Time
392/393
Timestamp
26
396/397 400/401
DataLink6 N/A
392/393
Timestamp
26
BLOB CLOB DBCLOB Fixed-length character string Long varying-length character string N/A
456/457
460/461
464/465
468/469
Fixed-length graphic string Length attribute of the column Long varying-length graphic string N/A Length attribute of the column N/A
Fixed-length graphic string Length attribute of the host variable Long graphic string Length attribute of the host variable Length attribute of the host variable 4 for single precision, 8 for double precision
472/473
476/477
PASCAL L-string
480/481
Floating point
Floating point
207
Table 23. SQLTYPE and SQLLEN Values for PREPARE, DESCRIBE, FETCH, OPEN, CALL, or EXECUTE (continued) For PREPARE and DESCRIBE SQLTYPE 484/485 488/489 COLUMN DATA TYPE Packed decimal Zoned decimal Big integer Large integer Small integer N/A N/A N/A N/A N/A N/A N/A SQLLEN Precision in byte 1; scale in byte 2 Precision in byte 1; scale in byte 2 8 4 2
5 5
For FETCH, OPEN, CALL, and EXECUTE HOST VARIABLE DATA TYPE Packed decimal Zoned decimal Big integer Large integer Small integer DISPLAY SIGN LEADING SEPARATE BLOB file reference variable CLOB file reference variable DBCLOB file reference variable BLOB locator CLOB locator DBCLOB locator SQLLEN Precision in byte 1; scale in byte 2 Precision in byte 1; scale in byte 2 8 4 2 Precision in byte 1; scale in byte 2 267 267 267 4 4 4
492/493 496/497 500/501 504/505 916/917 920/921 924/925 960/961 964/965 968/969
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.
5. Large and small binary numbers can be represented in the SQL descriptor area (SQLDA) as either lengths 2 or 4. They can also be represented with the precision in byte 1 and the scale in byte 2. If the first byte is greater than X00, it indicates precision and scale. Big integer numbers do not allow a precision and scale. The SQLDA defines them as length 8. 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.
208
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:
Data Type Character Character Character GRAPHIC Any other data type Sub-type SBCS MIXED BIT not applicable not applicable Length of SQLNAME 8 8 8 8 not applicable SQLNAME Bytes 1 & 2 X0000 X0000 X0000 X0000 not applicable SQLNAME Bytes 3 & 4 CCSID CCSID XFFFF CCSID not applicable
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.
209
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. 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.
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;
210
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. 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 8 shows the contents of the SQLDA after the DESCRIBE is run:
SQLDA Size SQLDA (8 bytes) 453 37 SQLVAR Element 1 (80 bytes) 8 0 WORKDEPT 3 1616 SQLDA (4 bytes) (reserved) 20 SQLN (2 bytes) 2 SQLD (2 bytes)
(reserved)
P H O N E N O
RV3W188-0
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
Chapter 10. Dynamic SQL Applications
211
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;
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 8 on page 211). 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 8 on page 211). 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+BC), 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;
212
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. 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 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 453 Q 3 L D A (reserved) 1616 20 2 FLDA: (CHAR(3))
Address of FLDA SQLVAR Element 1 (80 bytes) Address of FLDAI 8 WORKDEPT FLDB: (CHAR(4))
(reserved)
RV3W189-0
213
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.*/
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.
214
Address of FLDA SQLVAR Element 1 (80 bytes) Address of FLDAI 8 WORKDEPT FLDB: (CHAR(4)) 4502
(reserved)
RV3W190-0
The meaning of the SMALLINT pointed to by SQLIND is the same as any other indicator variable:
0 <0 >0 Denotes that the returned value is not null. Denotes that the returned value is null. 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.
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 202) 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
Chapter 10. Dynamic SQL Applications
215
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? 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. Allocate storage to hold the input values (the ? values). Set these values. Set SQLDATA and SQLIND (if applicable) for each ? parameter marker. 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. c. d. e. f. | The statement can then be processed normally.
216
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
217
218
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.
Copyright IBM Corp. 2000
219
Remove all entries from the current session. Save the session in a source file.
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 .
220
v SQL statements you entered in the session along with corresponding messages that follow each SQL statement 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.
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:
221
Specify SELECT Statement Type SELECT statement information. FROM tables . . . . . SELECT columns . . . WHERE conditions . . GROUP BY columns . . HAVING conditions . . ORDER BY columns . . FOR UPDATE OF columns . . . . . . . . . . . . . . . . . . . . . Press F4 for a list.
_____________________________________________ _____________________________________________ _____________________________________________ _____________________________________________ _____________________________________________ _____________________________________________ _____________________________________________ Bottom Y=Yes, N=No Y=Yes, N=No Y=Yes, N=No
Type choices, press Enter. DISTINCT rows in result table . . . . . . . . . N UNION with another SELECT . . . . . . . . . . . N Specify additional options . . . . . . . . . . . N
F4=Prompt F5=Refresh F6=Insert line F9=Specify subquery 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. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. ALTER TABLE CALL COMMENT ON COMMIT CONNECT CREATE ALIAS CREATE COLLECTION CREATE INDEX CREATE PROCEDURE CREATE TABLE CREATE VIEW DELETE DISCONNECT DROP ALIAS
More...
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.
222
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.
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 Subqueries in SELECT statements on page 84.
223
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>'
224
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 1 Collection YOURCOLL1 YOURCOLL2 YOURCOLL3 YOURCOLL4 Type SYS SYS SYS SYS Text Company benefits Employee personal data Job classifications/requirements 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 1 Table EMPLCO PEOPLE EMPLEXP EMPLEVL EMPLBEN EMPLMED EMPLINVST Collection YOURCOLL2 YOURCOLL2 YOURCOLL2 YOURCOLL2 YOURCOLL2 YOURCOLL2 YOURCOLL2 Type TAB TAB TAB TAB TAB TAB TAB Text Employee Employee Employee Employee Employee Employee Employee company data personal data experience evaluation reports benefits record medical record investments record
8. Press Enter.
225
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 2 1 Column NAME EMPLNO SOCSEC STRADDR CITY ZIP PHONE Table PEOPLE PEOPLE PEOPLE PEOPLE PEOPLE PEOPLE PEOPLE Type CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER Digits Length 6 30 11 30 20 9 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.
226
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.
227
228
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 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.
Commitment Control
229
Table 24. Values Table (continued) Session Attribute Decimal Point Sort Sequence Original Value *SYSVAL Any value other than *HEX New Value *PERIOD *HEX
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.
230
v CREATE PROCEDURE
v GRANT (Function or Procedure Privileges) v GRANT (Package Privileges) v v v v GRANT (Table Privileges) GRANT (User-Defined Type Privileges) INSERT LABEL ON
v LOCK TABLE v RENAME v v v v v REVOKE (Function or Procedure Privileges) REVOKE (Package Privileges) REVOKE (Table Privileges) REVOKE (User-Defined Type Privileges) 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 ()
Copyright IBM Corp. 2000
231
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. To perform syntax checking only on all statements in the source member, specify the PROCESS(*SYN) parameter on the RUNSQLSTM command.
232
The second section of the CREATE SCHEMA statement can contain from zero to any number of the following statements: v COMMENT ON v CREATE ALIAS v CREATE DISTINCT TYPE v CREATE INDEX v CREATE TABLE v CREATE VIEW v GRANT (Table Privileges) v GRANT (User-Defined Type 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.
233
5769ST1 V4R45M0 000225 Run SQL Statements SCHEMA Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 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 * * * * *
SEQNBR
Page
5769ST1 V4R5M0 000225 Run SQL Statements SCHEMA Record *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 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 * * * * *
SEQNBR
Page
234
235
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 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.
236
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: v Concurrency v Journaling v Commitment control v Atomic operations v Constraints v Save/restore v Damage tolerance v Index recovery The 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 239. 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
Chapter 14. DB2 UDB for AS/400 Data Protection
237
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. 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 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 details see the Database Performance and Query Optimization information). 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.
238
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. 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)
239
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: 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. 8 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 cursors 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.
8. 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.
240
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 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 25. Record Lock Duration SQL Statement SELECT INTO SET variable VALUES INTO FETCH (read-only cursor) COMMIT Parameter (See note 6) *NONE *CHG *CS (See note 8) *ALL (See note 2) *NONE *CHG *CS (See note 8) *ALL (See note 2) Duration of Record Locks No locks No locks Row locked when read and released From read until ROLLBACK or COMMIT No locks No locks From read until the next FETCH From read until ROLLBACK or COMMIT Lock Type
READ READ
READ READ
241
Table 25. Record Lock Duration (continued) SQL Statement FETCH (update or delete capable cursor) (See note 1) COMMIT Parameter (See note 6) *NONE Duration of Record Locks When record not updated or deleted from read until next FETCH When record is updated or deleted from read until UPDATE or DELETE When record not updated or deleted from read until next FETCH When record is updated or deleted from read until COMMIT or ROLLBACK When record not updated or deleted from read until next FETCH When record is updated or deleted from read until COMMIT or ROLLBACK From read until ROLLBACK or COMMIT No locks From insert until ROLLBACK or COMMIT From insert until ROLLBACK or COMMIT From insert until ROLLBACK or COMMIT No locks No locks Each record locked while being read From read until ROLLBACK or COMMIT Each record locked while being From read until ROLLBACK or From read until ROLLBACK or From read until ROLLBACK or Each record locked while being From read until ROLLBACK or From read until ROLLBACK or From read until ROLLBACK or updated COMMIT COMMIT COMMIT deleted COMMIT COMMIT COMMIT Lock Type UPDATE
*CHG
UPDATE
*CS
UPDATE
*ALL INSERT (target table) *NONE *CHG *CS *ALL *NONE *CHG *CS *ALL *NONE *CHG *CS *ALL *NONE *CHG *CS *ALL *NONE *CHG *CS *ALL *NONE *CHG *CS *ALL *NONE *CHG *CS *ALL (see note 2) *NONE *CHG *CS *ALL
READ READ UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE READ READ READ READ
UPDATE (non-cursor)
DELETE (non-cursor)
Lock released when record updated From read until ROLLBACK or COMMIT From read until ROLLBACK or COMMIT From read until ROLLBACK or COMMIT Lock released when record deleted From read until ROLLBACK or COMMIT From read until ROLLBACK or COMMIT From read until ROLLBACK or COMMIT From From From From read read read read until until until until next FETCH next FETCH next FETCH ROLLBACK or COMMIT
Subqueries (update or delete capable cursor or UPDATE or DELETE non-cursor) Subqueries (read-only cursor or SELECT INTO)
No locks No locks Each record locked while being read From read until ROLLBACK or COMMIT
READ READ
242
Table 25. Record Lock Duration (continued) SQL Statement 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 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 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. COMMIT Parameter (See note 6) Duration of Record Locks Lock Type
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
243
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.
244
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 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 application server. This also allows a single distributed SQL program to
Chapter 14. DB2 UDB for AS/400 Data Protection
245
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 (this means that these indexes are rebuilt before the OS/400 has been
246
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 26. Effect of Various Functions on Catalogs Function Add constraint to table Remove of constraint from table Create object into collection Delete of object from collection Restore of object into collection Change of object long comment Change of object label (text) Change of object owner Move of object from a collection Move of object into collection Rename of object Effect on the Catalog Information added to catalog Related information removed from catalog Information added to catalog Related information removed from catalog Information added to catalog Comment updated in catalog Label updated in catalog Owner updated in catalog Related information removed from catalog Information added to catalog Name of object updated in catalog
247
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.
248
249
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. 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 SQL Reference book.
250
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.
251
252
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.
253
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.
254
Table 27. Updating a Table (continued) Scrollable Cursor SQL Statement EXEC SQL FETCH RELATIVE :NUMBACK FROM THISEMP END-EXEC. EXEC SQL UPDATE CORPDATA.EMPLOYEE SET BONUS = 500 WHERE CURRENT OF THISEMP END-EXEC. EXEC SQL FETCH RELATIVE :NUMBACK FROM THISEMP FOR 5 ROWS INTO :DEPTINFO :IND-ARRAY END-EXEC. ... 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. Comments ... positions to the record in the block to update by fetching in the reverse order. ... updates the bonus for the employee in department D11 that is under the new $500.00 minimum. ... positions to the beginning of the same block that was already fetched and fetches the block again. (NUMBACK -(5 - NUMBACK - 1))
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 v v v The outer subselect contains a GROUP BY clause. The outer subselect contains a HAVING clause. The first SELECT clause contains a column function. 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.
255
256
For detailed descriptions of these statements, see the SQL Reference book.
257
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 Preparing and Running a Program with SQL Statements in the SQL Programming with Host Languages information. 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 C. DB2 UDB for AS/400 CL Command Descriptions.
Wait for the batch job to complete. To use the sample program, specify the following command on the command line:
========> ADDLIBLE QSQSAMP
258
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...........: D (DISPLAY) OBJECT...........: DS (DEPT STRUCTURE) _ __ A (ADD) U (UPDATE) DE (DEPARTMENT) E (ERASE) EM (EMPLOYEE) MN (MANAGER NAME)
SEARCH CRITERIA..: __ DI (DEPARTMENT ID) DN (DEPARTMENT NAME) EI (EMPLOYEE ID) MI (MANAGER ID) EN (EMPLOYEE NAME) LOCATION.........: DATA.............: ________________
_______________________________
259
CRTSQLPKG Authorization
When creating an SQL package on an AS/400 system the authorization ID used must have *USE authority to the CRTSQLPKG command.
v SRTSEQ(*JOBRUN) v SRTSEQ(*LANGIDUNQ)
260
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.
261
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.
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.)
262
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.
263
APPC conversation may or may not have been kept up, depending on the jobs 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.
264
....
265
Job:
Default Activation Group: SQL Package for PGM1
PGM1 Call
Connect
SYSC (Remote)
System-Named Activation Group:
Job:
Default Activation Group:
Connect
PGM2
Call
Return Call
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
266
is then committed. The pending changes in the system-named 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.
SYSA Job:
SYSB Job:
Default ActivationGroup:
Connect
Job:
System-Named Activation Group:
Connect
RV2W578-2
267
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.
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
268
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. 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.
269
1. Committable updates can be performed on the connection. The connection is unprotected. This will occur when: 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.
270
There are no one-phase API commitment control resources for the commitment definition. There are protected connections registered for the commitment definition. 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.
271
Table 28. Summary of Connection Type Application Server Supports Two-phase Commit No No No No Yes Yes Yes Yes No No No No Yes Yes Yes Yes Application Server Supports Distributed Unit of Work No No Yes Yes No No Yes Yes No No Yes Yes No No Yes Yes Other Updateable One-phase Resource Registered No Yes No Yes No Yes No Yes No Yes No Yes No Yes No Yes
Connect under Commitment Control No No No No No No No No Yes Yes Yes Yes Yes Yes Yes Yes
*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.
272
273
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.
Table 29. Summary of Determining SQLERRD(3) Values Connection Exists to Updateable Remote Unit of Work Application Server --Yes No No No No Yes No No No No Yes No No No No Where First Committable Update Occurred * ---no updates one-phase this connection two-phase -no updates one-phase this connection two-phase -no updates one-phase this connection two-phase
SQLERRD(4) 1 2 3 3 3 3 3 4 4 4 4 4 5 5 5 5 5
SQLERRD(3) 1 2 2 1 2 1 1 2 1 2 1 2 2 1 2 1 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.
274
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. 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 267 and Implicit connection management for nondefault activation groups on page 268. 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.
275
276
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 13. Example of Distributed Unit of Work Program (Part 2 of 4)
} done:
/* 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;
EXEC SQL WHENEVER SQLERROR /* Release the connections EXEC SQL RELEASE SYSB; EXEC SQL RELEASE SYSC; /* Close the cursor */ EXEC SQL CLOSE C1; /* Do another commit which The local connection is released. */ EXEC SQL COMMIT; ...
will end the released connections. still active because it was not
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 17. Distributed Relational Database Function
277
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.
278
..... 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 15. Example of Cursors in a DUW program
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 9 can be created.
279
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.
280
281
DEPARTMENT
DEPTNO A00 B01 C01 D01 D11 D21 E01 E11 E21 DEPTNAME SPIFFY COMPUTER SERVICE DIV. PLANNING INFORMATION CENTER DEVELOPMENT CENTER MANUFACTURING SYSTEMS ADMINISTRATION SYSTEMS SUPPORT SERVICES OPERATIONS SOFTWARE SUPPORT MGRNO 000010 000020 000030 ? 000060 000070 000050 000090 000100 ADMRDEPT A00 A00 A00 A00 D01 D01 A00 E01 E01
282
EMP NO 000010 000020 000030 000050 000060 000070 000090 000100 000110 000120 000130 000140 000150 000160 000170 000180 000190 000200 000210 000220 000230 000240 000250 000260 000270 000280 000290 000300 000310 000320 000330 000340
FIRST NAME CHRISTINE MICHAEL SALLY JOHN IRVING EVA EILEEN THEODORE VINCENZO SEAN DOLORES HEATHER BRUCE ELIZABETH MASATOSHI MARILYN JAMES DAVID WILLIAM JENNIFER JAMES SALVATORE DANIEL SYBIL MARIA ETHEL JOHN PHILIP MAUDE RAMLAL WING JASON
MID INIT I L A B F D W Q G M A R J S H T K J M S P L R R X F V R
LASTNAME HAAS THOMPSON KWAN GEYER STERN PULASKI HENDERSON SPENSER LUCCHESSI O'CONNELL QUINTANA NICHOLLS ADAMSON PIANKA YOSHIMURA SCOUTTEN WALKER BROWN JONES LUTZ JEFFERSON MARINO SMITH JOHNSON PEREZ SCHNEIDER PARKER SMITH SETRIGHT MEHTA LEE GOUNOT
WORK DEPT A00 B01 C01 E01 D11 D21 E11 E21 A00 A00 C01 C01 D11 D11 D11 D11 D11 D11 D11 D11 D21 D21 D21 D21 D21 E11 E11 E11 E11 E21 E21 E21
PHONE NO 3978 3476 4738 6789 6423 7831 5498 0972 3490 2167 4578 1793 4510 3782 2890 1682 2986 4501 0942 0672 2094 3780 0961 8953 9001 8997 4502 2095 3332 9990 2103 5698
HIRE DATE 1965-01-01 1973-10-10 1975-04-05 1949-08-17 1973-09-14 1980-09-30 1970-08-15 1980-06-19 1958-05-16 1963-12-05 1971-07-28 1976-12-15 1972-02-12 1977-10-11 1978-09-15 1973-07-07 1974-07-26 1966-03-03 1979-04-11 1968-08-29 1966-11-21 1979-12-05 1969-10-30 1975-09-11 1980-09-30 1967-03-24 1980-05-30 1972-06-19 1964-09-12 1965-07-07 1976-02-23 1947-05-05
JOB PRES MANAGER MANAGER MANAGER MANAGER MANAGER MANAGER MANAGER SALESREP CLERK ANALYST ANALYST DESIGNER DESIGNER DESIGNER DESIGNER DESIGNER DESIGNER DESIGNER DESIGNER CLERK CLERK CLERK CLERK CLERK OPERATOR OPERATOR OPERATOR OPERATOR FILEREP FILEREP FILEREP
ED LEVEL 18 18 20 16 16 16 16 14 19 14 16 18 16 17 16 17 16 16 17 18 14 17 15 16 15 17 12 14 12 16 14 16
SEX F M F M M F F M M M F F M F M F M M M F M M M F F F M M F M M M
BIRTH DATE 1933-08-24 1948-02-02 1941-05-11 1925-09-15 1945-07-07 1953-05-26 1941-05-15 1956-12-18 1929-11-05 1942-10-18 1925-09-15 1946-01-19 1947-05-17 1955-04-12 1951-01-05 1949-02-21 1952-06-25 1941-05-29 1953-02-23 1948-03-19 1935-05-30 1954-03-31 1939-11-12 1936-10-05 1953-05-26 1936-03-28 1946-07-09 1936-10-27 1931-04-21 1932-08-11 1941-07-18 1926-05-17
SALARY 52750 41250 38250 40175 32250 36170 29750 26150 46500 29250 23800 28420 25280 22250 24680 21340 20450 27740 18270 29840 22180 28760 19180 17250 27380 26250 15340 17750 15900 19950 25370 23840
BONUS 1000 800 800 800 500 700 600 500 900 600 500 600 500 400 500 500 400 600 400 600 400 600 400 300 500 500 300 400 300 400 500 500
COMM 4220 3300 3060 3214 2580 2893 2380 2092 3720 2340 1904 2274 2022 1780 1974 1707 1636 2217 1462 2387 1774 2301 1534 1380 2190 2100 1227 1420 1272 1596 2030 1907
EMSTDATE
283
Table 31. Columns of the Employee to Project Activity Table (continued) Column Name EMENDATE Description Completion date of the activity
EMP_ACT
EMPNO 000010 000070 000230 000230 000230 000230 000230 000240 000240 000250 000250 000250 000250 000250 000250 000250 000250 000250 000250 000260 000260 000260 000260 000260 000260 000260 000270 000270 000270 000270 000270 000270 000270 000030 000130 000130 PROJNO AD3100 AD3110 AD3111 AD3111 AD3111 AD3111 AD3111 AD3111 AD3111 AD3112 AD3112 AD3112 AD3112 AD3112 AD3112 AD3112 AD3112 AD3112 AD3112 AD3113 AD3113 AD3113 AD3113 AD3113 AD3113 AD3113 AD3113 AD3113 AD3113 AD3113 AD3113 AD3113 AD3113 IF1000 IF1000 IF1000 ACTNO 10 10 60 60 70 80 180 70 80 60 60 60 60 70 70 70 80 80 180 70 70 80 80 180 180 180 60 60 60 70 70 80 80 10 90 100 EMPTIME .50 1.00 1.00 .50 .50 .50 1.00 1.00 1.00 1.00 .50 .50 1.00 .50 1.00 .25 .25 .50 .50 .50 1.00 1.00 .50 .50 1.00 .50 .50 1.00 .25 .75 1.00 1.00 .50 .50 1.00 .50 EMSTDATE 1982-01-01 1982-01-01 1982-01-01 1982-03-15 1982-03-15 1982-04-15 1982-10-15 1982-02-15 1982-09-15 1982-01-01 1982-02-01 1982-12-01 1983-01-01 1982-02-01 1982-03-15 1982-08-15 1982-08-15 1982-10-15 1982-08-15 1982-06-15 1982-07-01 1982-01-01 1982-03-01 1982-03-01 1982-04-15 1982-06-01 1982-03-01 1982-04-01 1982-09-01 1982-09-01 1982-10-15 1982-01-01 1982-03-01 1982-06-01 1982-01-01 1982-10-01 EMENDATE 1982-07-01 1983-02-01 1982-03-15 1982-04-15 1982-10-15 1982-10-15 1983-01-01 1982-09-15 1983-01-01 1982-02-01 1982-03-15 1983-01-01 1983-02-01 1982-03-15 1982-08-15 1982-10-15 1982-10-15 1982-12-01 1983-01-01 1982-07-01 1983-02-01 1982-03-01 1982-04-15 1982-04-15 1982-06-01 1982-07-01 1982-04-01 1982-09-01 1982-10-15 1982-10-15 1983-02-01 1982-03-01 1982-04-01 1983-01-01 1982-10-01 1983-01-01
284
EMPNO 000140 000030 000140 000140 000140 000140 000010 000110 000010 000200 000200 000220 000150 000150 000170 000170 000190 000190 000160 000170 000180 000210 000210 000050 000090 000280 000290 000300 000310 000050 000100 000320 000320 000330 000330 000340 000340 000020
PROJNO IF1000 IF2000 IF2000 IF2000 IF2000 IF2000 MA2100 MA2100 MA2110 MA2111 MA2111 MA2111 MA2112 MA2112 MA2112 MA2112 MA2112 MA2112 MA2113 MA2113 MA2113 MA2113 MA2113 OP1000 OP1010 OP1010 OP1010 OP1010 OP1010 OP2010 OP2010 OP2011 OP2011 OP2012 OP2012 OP2013 OP2013 PL2100
ACTNO 90 10 100 100 110 110 10 20 10 50 60 40 60 180 60 70 70 80 60 80 70 80 180 10 10 130 130 130 130 10 10 140 150 140 160 140 170 30
EMPTIME .50 .50 1.00 .50 .50 .50 .50 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 .50 .50 .25 1.00 1.00 1.00 1.00 1.00 .75 1.00 .75 .25 .25 .75 .50 .50 1.00
EMSTDATE 1982-10-01 1982-01-01 1982-01-01 1982-03-01 1982-03-01 1982-10-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-06-15 1982-01-01 1982-01-01 1982-07-15 1982-01-01 1982-06-01 1982-02-01 1982-10-01 1982-07-15 1982-01-01 1982-04-01 1982-10-01 1982-10-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01
EMENDATE 1983-01-01 1983-01-01 1982-03-01 1982-07-01 1982-07-01 1983-01-01 1982-11-01 1982-03-01 1983-02-01 1982-06-15 1983-02-01 1983-02-01 1982-07-15 1983-02-01 1983-06-01 1983-02-01 1982-10-01 1983-10-01 1983-02-01 1983-02-01 1982-06-15 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1982-09-15
285
PROJECT
PROJNO AD3100 AD3110 AD3111 AD3112 AD3113 IF1000 IF2000 MA2100 MA2110 MA2111 PROJNAME DEPTNO RESPEMP 000010 000070 000230 000250 000270 000030 000030 000010 000060 000220 PRSTAFF 6.5 6 2 1 2 2 1 12 9 2 PRSTDATE 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 PRENDATE MAJPROJ 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1982-12-01 ? AD3100 AD3110 AD3110 AD3110 ? ? ? MA2100 MA2110 ADMIN SERVICES D01 GENERAL ADMIN SYSTEMS PAYROLL PROGRAMMING PERSONNEL PROGRAMMING ACCOUNT PROGRAMMING D21 D21 D21 D21
QUERY SERVICES C01 USER EDUCATION WELD LINE AUTOMATION WL PROGRAMMING W L PROGRAM DESIGN C01 D01 D11 D11
286
PROJNO MA2112 MA2113 OP1000 OP1010 OP2000 OP2010 OP2011 OP2012 OP2013 PL2100
PROJNAME W L ROBOT DESIGN W L PROD CONT PROGS OPERATION SUPPORT OPERATION GEN SYSTEMS SERVICES SYSTEMS SUPPORT SCP SYSTEMS SUPPORT APPLICATIONS SUPPORT DB/DC SUPPORT WELD LINE PLANNING
DEPTNO D11 D11 E01 E11 E01 E21 E21 E21 E21 B01
RESPEMP 000150 000160 000050 000090 000050 000100 000320 000330 000340 000020
PRSTAFF 3 3 6 5 5 4 1 1 1 1
PRSTDATE 1982-01-01 1982-02-15 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01 1982-01-01
PRENDATE MAJPROJ 1982-12-01 1982-12-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1983-02-01 1982-09-15 MA2110 MA2110 ? OP1000 ? OP2000 OP2010 OP2010 OP2010 MA2100
287
288
289
v v v v v v v v v v v v v v v v v v
0A Feature Not Supported 09 Invalid Token 20 Case Not Found for CASE Statement 21 Cardinality Violation 22 Data Exception 23 Constraint Violation 24 Invalid Cursor State 25 Invalid Transaction State 26 Invalid SQL Statement Identifier 27 Triggered Data Change Violation 28 Invalid Authorization Specification 2B Dependent Privilege Descriptors Still Exist 2C Invalid Character Set Name 2D Invalid Transaction Termination 2E Invalid Connection Name 2F SQL Function Exception 33 Invalid SQL Descriptor Name 34 Invalid Cursor Name
v 35 Invalid Condition Number v 38 External Function Exception v 39 External Function Call Exception v v v v v v v v v v v v 3C Ambiguous Cursor Name 3D Invalid Catalog Name 3F Invalid Collection (Schema) Name 40 Transaction Rollback 42 44 51 53 54 55 56 57 Syntax Error and Access Rule Violation WITH CHECK OPTION Violation Invalid Application State Invalid Operand or Inconsistent Specification SQL or Product Limit Exceeded Object Not in Prerequisite State Miscellaneous SQL or Product Error 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.
290
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.
Positive SQLCODEs
N/A SQLCODE 0 SQL0088 SQLCODE +88 SQLSTATE 01504
Explanation: The SQL statement has run successfully. If SQLWARN0 is blank, and SQLSTATE is '00000', the statement was run successfully. Otherwise, a warning condition exists. Check the other warning indicators or SQLSTATE to determine the particular warning condition. For example, if SQLWARN1 is not blank, a string has been truncated. The following warnings have an SQLCODE of zero: v SQLWARN1 SQLSTATE 01004 Explanation: The value of a string column was truncated when assigned to a host variable. v SQLWARN2 SQLSTATE 01003 Explanation: Null values were eliminated from the argument of a column function. v SQLWARN3 SQLSTATE 01503 Explanation: The number of result columns is larger than the number of host variables provided. v SQLWARN4 SQLSTATE 01504 Explanation: The UPDATE or DELETE statement does not include a WHERE clause. v SQLWARN6 SQLSTATE 01506 Explanation: An adjustment was made to a DATE or TIMESTAMP value to correct a date the was not valid. The date resulted from an arithmetic operation. SQL0012 SQLCODE +12 SQLSTATE 01545
Explanation: Row not found for &1. SQL0114 SQLCODE +114 SQLSTATE 01536
Explanation: Relational database &1 not the same as current server &2. SQL0138 SQLCODE +138 SQLSTATE 01544
Explanation: Argument &1 of SUBSTR function not valid. SQL0177 SQLCODE +177 SQLSTATE 01009
Explanation: CHECK condition text too long. SQL0178 SQLCODE +178 SQLSTATE 0100A
Explanation: Query expression text for view &1 in &2 too long. SQL0180 SQLCODE +180 SQLSTATE 01534
Explanation: Syntax of date, time, or timestamp value not valid. SQL0181 SQLCODE +181 SQLSTATE 01534
Explanation: Correlation without qualification occurred for column &1 to table &2. SQL0030 SQLCODE +30 SQLSTATE 01503
291
SQL0183
SQLCODE +183
SQLSTATE 01535
SQL0445
SQLCODE +445
SQLSTATE 01004
Explanation: The result of a date or timestamp expression not valid. SQL0191 SQLCODE +191 SQLSTATE 01547
Explanation: Value of parameter &4 in procedure &1 in &2 too long. SQL0460 SQLCODE +460 SQLSTATE 01593
Explanation: MIXED data not properly formed. SQL0204 SQLCODE +204 SQLSTATE 01532
Explanation: Truncation of data may have occurred for ALTER TABLE in &1 of &2. SQL0462 SQLCODE +462 SQLSTATE 01Hxx
Explanation: Object &1 in &2 type *&3 not found. SQL0237 SQLCODE +237 SQLSTATE 01005
Explanation: Procedure or user-defined function &1 in &2 returned a warning SQLSTATE. SQL0551 SQLCODE +551 SQLSTATE 01548
Explanation: Not enough SQLVAR entries were provided in the SQLDA. SQL0239 SQLCODE +239 SQLSTATE 01005
Explanation: Not authorized to object &1 in &2 type *&3. SQL0552 SQLCODE +552 SQLSTATE 01542
Explanation: Not enough SQLVAR entries were provided in the SQLDA. SQL0304 SQLCODE +304 01547, 01565 SQLSTATE 01515,
Explanation: Conversion error in assignment to host variable &2. SQL0326 SQLCODE +326 SQLSTATE 01557
Explanation: Not all requested privileges revoked from object &1 in &2 type &3. SQL0570 SQLCODE +570 SQLSTATE 01007
Explanation: Too many host variables specified. SQL0331 SQLCODE +331 SQLSTATE 01520
Explanation: Not all requested privileges to object &1 in &2 type &3 granted. SQL0595 SQLCODE +595 SQLSTATE 01526
Explanation: Characters conversion cannot be performed. SQL0335 SQLCODE +335 SQLSTATE 01517
Explanation: Commit level &1 escalated to &2 lock. SQL0596 SQLCODE +596 SQLSTATE 01002
Explanation: Characters conversion has resulted in substitution characters. SQL0360 SQLCODE +360 SQLSTATE 01627
Explanation: Error occurred during disconnect. SQL0645 SQLCODE +645 SQLSTATE 01528
Explanation: Datalink in table &1 in &2 may not be valid due to pending links. SQL0403 SQLCODE +403 SQLSTATE 01522
Explanation: WHERE NOT NULL clause ignored for index &1 in &2. SQL0802 SQLCODE +802 SQLSTATE 01519, 01547, 01564, 01565
Explanation: Alias &1 in &2 created but table or view not found. SQL0420 SQLCODE +420 SQLSTATE 01565
Explanation: Data conversion or data mapping error. SQL0863 SQLCODE +863 SQLSTATE 01539
292
SQL0990
SQLCODE +990
SQLSTATE 01587
Explanation: Outcome unknown for the unit of work. SQL7905 SQLCODE +7905 SQLSTATE 01567
Negative SQLCODEs
SQL0007 SQLCODE -07 SQLSTATE 42601 SQL0099 SQLCODE -99 SQLSTATE 42992 Explanation: Character &1 (HEX &2) not valid in SQL statement. SQL0010 SQLCODE -10 SQLSTATE 42603 Explanation: Operator in join condition not valid. SQL0101 Explanation: String constant beginning &1 not delimited. SQL0029 SQLCODE -29 SQLSTATE 42601 SQLCODE -101 54010, 54011 SQLSTATE 54001,
Explanation: SQL statement too long or complex. SQL0102 SQLCODE -102 SQLSTATE 54002
Explanation: INTO clause missing from embedded SELECT statement. SQL0051 SQLCODE -51 SQLSTATE 3C000
Explanation: String constant beginning with &1 too long. SQL0103 SQLCODE -103 SQLSTATE 42604
Explanation: Numeric constant &1 not valid. SQL0104 SQLCODE -104 SQLSTATE 42601
Explanation: Cursor or procedure &1 previously declared. SQL0060 SQLCODE -60 SQLSTATE 42815
Explanation: Token &1 was not valid. Valid tokens: &2. SQL0105 SQLCODE -105 SQLSTATE 42604
Explanation: Value &3 for argument &1 of &2 function not valid. SQL0078 SQLCODE -78 SQLSTATE 42629
Explanation: Mixed or graphic string constant not valid. SQL0106 SQLCODE -106 SQLSTATE 42611
Explanation: Parameter name required for routine &1 in &2. SQL0080 SQLCODE -80 SQLSTATE 42978
Explanation: Precision specified for FLOAT column not valid. SQL0107 SQLCODE -107 SQLSTATE 42622
Explanation: Indicator variable &1 not SMALLINT type. SQL0084 SQLCODE -84 SQLSTATE 42612
Explanation: &1 too long. Maximum &2 characters. SQL0109 SQLCODE -109 SQLSTATE 42601
Explanation: SQL statement not allowed. SQL0090 SQLCODE -90 SQLSTATE 42618
Explanation: &1 clause not allowed. SQL0110 SQLCODE -110 SQLSTATE 42606
Explanation: Host variable not permitted here. SQL0097 SQLCODE -97 SQLSTATE 42601
293
SQL0112
SQLCODE -112
SQLSTATE 42607
SQL0129
SQLCODE -129
SQLSTATE 54004
Explanation: Argument of function &1 is another function. SQL0113 SQLCODE -113 2E000, 42602 SQLSTATE 28000,
Explanation: Too many tables in SQL statement. SQL0130 SQLCODE -130 22025 SQLSTATE 22019,
Explanation: Name &1 not allowed. SQL0114 SQLCODE -114 SQLSTATE 42961
Explanation: Escape character &1 or LIKE pattern not valid. SQL0131 SQLCODE -131 SQLSTATE 42818
Explanation: Relational database &1 not the same as current server &2. SQL0115 SQLCODE -115 SQLSTATE 42601
Explanation: Operands of LIKE not compatible or not valid. SQL0132 SQLCODE -132 SQLSTATE 42824
Explanation: Comparison operator &1 not valid. SQL0117 SQLCODE -117 SQLSTATE 42802
Explanation: LIKE predicate not valid. SQL0133 SQLCODE -133 SQLSTATE 42906
Explanation: Statement inserts wrong number of values. SQL0118 SQLCODE -118 SQLSTATE 42902
Explanation: Operator on correlated column in SQL function not valid. SQL0134 SQLCODE -134 SQLSTATE 42907
Explanation: Table &1 in &2 also specified in a FROM clause. SQL0119 SQLCODE -119 SQLSTATE 42803
Explanation: Argument of function too long. SQL0136 SQLCODE -136 SQLSTATE 54005
Explanation: Column &1 in HAVING clause not in GROUP BY. SQL0120 SQLCODE -120 SQLSTATE 42903
Explanation: ORDER BY or GROUP BY columns too long. SQL0137 SQLCODE -137 SQLSTATE 54006
Explanation: Use of column function &2 not valid. SQL0121 SQLCODE -121 SQLSTATE 42701
Explanation: Duplicate column name &1 in INSERT or UPDATE. SQL0122 SQLCODE -122 SQLSTATE 42803
Explanation: Argument &1 of SUBSTR function not valid. SQL0144 SQLCODE -144 SQLSTATE 58003
Explanation: Section number not valid. SQL0145 SQLCODE -145 SQLSTATE 55005
Explanation: Column specified in SELECT list not valid. SQL0125 SQLCODE -125 SQLSTATE 42805
Explanation: Recursion not supported for an application server other than the AS/400 system. SQL0150 SQLCODE -150 SQLSTATE 42807
Explanation: ORDER BY column number &1 not valid. SQL0128 SQLCODE -128 SQLSTATE 42601
294
SQL0151
SQLCODE -151
SQLSTATE 42808
SQL0175
SQLCODE -175
SQLSTATE 58028
Explanation: Column &1 in table &2 in &3 read-only. SQL0152 SQLCODE -152 SQLSTATE 42809
Explanation: Constraint type not valid for constraint &1 in &2. SQL0153 SQLCODE -153 SQLSTATE 42908
Explanation: Syntax of date, time, or timestamp value not valid. SQL0181 SQLCODE -181 SQLSTATE 22007
Explanation: Column list required for CREATE VIEW. SQL0154 SQLCODE -154 SQLSTATE 42909
Explanation: Value in date, time, or timestamp string not valid. SQL0182 SQLCODE -182 SQLSTATE 42816
Explanation: UNION and UNION ALL for CREATE VIEW not valid. SQL0156 SQLCODE -156 SQLSTATE 42809
Explanation: A date, time, or timestamp expression not valid. SQL0183 SQLCODE -183 SQLSTATE 22008
Explanation: &1 in &2 not a table. SQL0157 SQLCODE -157 SQLSTATE 42810
Explanation: The result of a date or timestamp expression not valid. SQL0184 SQLCODE -184 SQLSTATE 42610
Explanation: View &1 in &2 not valid in FOREIGN KEY clause. SQL0158 SQLCODE -158 SQLSTATE 42811
Explanation: Parameter marker not valid in expression. SQL0187 SQLCODE -187 SQLSTATE 42816
Explanation: Number of columns specified not consistent. SQL0159 SQLCODE -159 SQLSTATE 42809
Explanation: Use of labeled duration is not valid. SQL0188 SQLCODE -188 28000, 2E000 SQLSTATE 22503,
Explanation: &1 in &2 not correct type. SQL0160 SQLCODE -160 SQLSTATE 42813
Explanation: &1 is not a valid string representation of an authorization name or a relational database name. SQL0189 SQLCODE -189 SQLSTATE 22522
Explanation: WITH CHECK OPTION not allowed for view &1 in &2. SQL0161 SQLCODE -161 SQLSTATE 44000
Explanation: Coded Character Set Identifier &1 is not valid. SQL0190 SQLCODE -190 SQLSTATE 42837
Explanation: INSERT/UPDATE not allowed due to WITH CHECK OPTION. SQL0170 SQLCODE -170 SQLSTATE 42605
Explanation: Attributes of column &3 in &1 in &2 not compatible. SQL0191 SQLCODE -191 SQLSTATE 22504
Explanation: Number of arguments for function &1 not valid. SQL0171 SQLCODE -171 SQLSTATE 42815
Explanation: MIXED data not properly formed. SQL0192 SQLCODE -192 SQLSTATE 42937
295
SQL0194
SQLCODE -194
SQLSTATE 42848
SQL0221
SQLCODE -221
SQLSTATE 42873
Explanation: KEEP LOCKS not allowed. SQL0195 SQLCODE -195 SQLSTATE 42814
Explanation: Number of rows &2 not valid. SQL0225 SQLCODE -225 SQLSTATE 42872
Explanation: Last column of &1 in &2 cannot be dropped. SQL0196 SQLCODE -196 SQLSTATE 42817
Explanation: FETCH not valid; cursor &1 not declared with SCROLL. SQL0226 SQLCODE -226 SQLSTATE 24507
Explanation: Column &3 in &1 in &2 cannot be dropped with RESTRICT. SQL0197 SQLCODE -197 SQLSTATE 42877
Explanation: Current row deleted or moved for cursor &1. SQL0227 SQLCODE -227 SQLSTATE 24513
Explanation: Column &1 cannot be qualified. SQL0198 SQLCODE -198 SQLSTATE 42617
Explanation: FETCH not valid, cursor &1 in unknown position. SQL0228 SQLCODE -228 SQLSTATE 42620
Explanation: SQL statement empty or blank. SQL0199 SQLCODE -199 SQLSTATE 42601
Explanation: FOR UPDATE OF clause not valid with SCROLL for cursor &1. SQL0231 SQLCODE -231 SQLSTATE 22006
Explanation: Keyword &1 not expected. Valid tokens: &2. SQL0203 SQLCODE -203 SQLSTATE 42702
Explanation: Position of cursor &1 not valid for FETCH of current row. SQL0250 SQLCODE -250 SQLSTATE 42718
Explanation: Local relational database not defined in the directory. SQL0251 SQLCODE -251 42602 SQLSTATE 2E000,
Explanation: &1 in &2 type *&3 not found. SQL0205 SQLCODE -205 SQLSTATE 42703
Explanation: Column &1 not in table &2. SQL0206 SQLCODE -206 SQLSTATE 42703
Explanation: Character in relational database name &1 is not valid. SQL0255 SQLCODE -255 SQLSTATE 42999
Explanation: Column &1 not in specified tables. SQL0208 SQLCODE -208 SQLSTATE 42707
Explanation: DB2 Multisystem query error. SQL0256 SQLCODE -256 SQLSTATE 42998
Explanation: ORDER BY column &1 not in results table. SQL0212 SQLCODE -212 SQLSTATE 42712
Explanation: Constraint &1 in &2 not allowed on distributed file. SQL0270 SQLCODE -270 SQLSTATE 42997
Explanation: Duplicate table designator &1 not valid. SQL0214 SQLCODE -214 SQLSTATE 42822
Explanation: Unique index not allowed. SQL0301 SQLCODE -301 07006,42895 SQLSTATE
296
SQL0302
SQL0331
SQLCODE -331
SQLSTATE 22021
Explanation: Conversion error on input host variable &2. SQL0303 SQLCODE -303 42806 SQLSTATE 22001,
Explanation: Character conversion cannot be performed. SQL0332 SQLCODE -332 SQLSTATE 57017
Explanation: Character conversion between CCSID &1 and CCSID &2 not valid. SQL0334 SQLCODE -334 SQLSTATE 22524
Explanation: Host variable &1 not compatible with SELECT item. SQL0304 SQLCODE -304 22023, 22504 SQLSTATE 22003,
Explanation: Character conversion has resulted in truncation. SQL0338 SQLCODE -338 SQLSTATE 42972
Explanation: Conversion error in assignment to host variable &2. SQL0305 SQLCODE -305 SQLSTATE 22002
Explanation: JOIN expression not valid. SQL0340 SQLCODE -340 SQLSTATE 42726
Explanation: Duplicate name &1 for common table expression. SQL0341 SQLCODE -341 SQLSTATE 42835
Explanation: Undefined host variable in REXX. SQL0311 SQLCODE -311 SQLSTATE 22501
Explanation: Cyclic references between common table expressions. SQL0346 SQLCODE -346 SQLSTATE 42836
Explanation: Length in a varying-length host variable not valid. SQL0312 SQLCODE -312 SQLSTATE 42618
Explanation: Recursion not allowed for common table expressions. SQL0350 SQLCODE -350 SQLSTATE 42962
Explanation: Host variable &1 not defined or not usable. SQL0313 SQLCODE -313 07004 SQLSTATE 07001,
Explanation: Column &1 is not valid as key field for index or constraint. SQL0351 SQLCODE -351 SQLSTATE 56084
Explanation: Number of host variables not valid. SQL0328 SQLCODE -328 SQLSTATE 42996
Explanation: Column &1 not allowed in partitioning key. SQL0329 SQLCODE -329 SQLSTATE 0E000
Explanation: The AR is not at the same level and DB2/400 cannot transform the data type to a compatible type. SQL0352 SQLCODE -352 SQLSTATE 56084
Explanation: The SET PATH name list is not valid. SQL0330 SQLCODE -330 SQLSTATE 22021
Explanation: The AS is not at the same level and DB2/400 cannot transform the data type to a compatible type. SQL0357 SQLCODE -357 SQLSTATE 57050
297
SQL0358
SQLCODE -358
SQLSTATE 428D1
SQL0414
SQLCODE -414
SQLSTATE 42824
Explanation: Error &1 occurred using DataLink data type. SQL0392 SQLCODE -392 SQLSTATE 42855
Explanation: Column &1 not valid in LIKE predicate. SQL0415 SQLCODE -415 SQLSTATE 42825
Explanation: UNION operands not compatible. SQL0417 SQLCODE -417 SQLSTATE 42609
Explanation: Assignment of LOB to specified host variable not allowed. SQL0398 SQLCODE -398 SQLSTATE 428D2
Explanation: Combination of parameter markers not valid. SQL0418 SQLCODE -418 SQLSTATE 42610
Explanation: AS LOCATOR cannot be specified for a non-LOB parameter. SQL0401 SQLCODE -401 SQLSTATE 42818
Explanation: Use of parameter marker is not valid. SQL0419 SQLCODE -419 SQLSTATE 42911
Explanation: Comparison operator &1 operands not compatible. SQL0402 SQLCODE -402 SQLSTATE 42819
Explanation: Negative scale not valid. SQL0420 SQLCODE -420 SQLSTATE 22018
Explanation: &1 use not valid. SQL0404 SQLCODE -404 SQLSTATE 22001
Explanation: Character in CAST argument not valid. SQL0421 SQLCODE -421 SQLSTATE 42826
Explanation: Value for column &1 too long. SQL0405 SQLCODE -405 SQLSTATE 42820
Explanation: Number of UNION operands not equal. SQL0423 SQLCODE -423 SQLSTATE 0F001
Explanation: Numeric constant &1 out of range. SQL0406 SQLCODE -406 22023, 22504 SQLSTATE 22003,
Explanation: LOB locator &1 not valid. SQL0428 SQLCODE -428 SQLSTATE 25501
Explanation: Conversion error on assignment to column &2. SQL0407 SQLCODE -407 SQLSTATE 23502
Explanation: SQL statement cannot be run. SQL0429 SQLCODE -429 SQLSTATE 54028
Explanation: Null values are not allowed in column &1. SQL0408 SQLCODE -408 SQLSTATE 42821
Explanation: The maximum number of concurrent LOB locators has been reached. SQL0432 SQLCODE -432 SQLSTATE 42841
Explanation: INSERT or UPDATE value for column &1 not compatible. SQL0410 SQLCODE -410 SQLSTATE 42820
Explanation: A parameter marker cannot have the user-defined type name &1. SQL0433 SQLCODE -433 SQLSTATE 22001
Explanation: Floating point literal &1 not valid. SQL0412 SQLCODE -412 SQLSTATE 42823
Explanation: Significant digits truncated during CAST from numeric to character. SQL0440 SQLCODE -440 SQLSTATE 42884
Explanation: Subquery with more than one result column not valid.
298
SQL0441
SQLCODE -441
SQLSTATE 42601
SQL0455
SQLCODE -455
SQLSTATE 42882
Explanation: Clause or keyword &1 not valid where specified. SQL0442 SQLCODE -442 SQLSTATE 54023
Explanation: Specific name not same as procedure name. SQL0456 SQLCODE -456 SQLSTATE 42710
Explanation: Maximum # of parameters on CALL exceeded. SQL0443 SQLCODE -443 38501 SQLSTATE 2Fxxx,
Explanation: Specific name &3 in &2 already exists. SQL0457 SQLCODE -457 SQLSTATE 42939
Explanation: Name &1 in &2 not allowed for function. SQL0458 SQLCODE -458 SQLSTATE 42883
Explanation: Trigger program or external procedure detected on error. SQL0444 SQLCODE -444 SQLSTATE 42724
Explanation: Function &1 in &2 not found with matching signature. SQL0461 SQLCODE -461 SQLSTATE 42846
Explanation: External program &4 in &1 not found. SQL0446 SQLCODE -446 SQLSTATE 22003
Explanation: Cast from &1 to &2 not supported. SQL0463 SQLCODE -463 SQLSTATE 39001
Explanation: Conversion error in assignment of argument &2. SQL0448 SQLCODE -448 SQLSTATE 54023
Explanation: SQLSTATE &4 returned from routine &1 in &2 not valid.. SQL0469 SQLCODE -469 SQLSTATE 42886
Explanation: Maximum parameters on DECLARE PROCEDURE exceeded. SQL0449 SQLCODE -449 SQLSTATE 42878
Explanation: IN, OUT, INOUT not valid for parameter &4 in procedure &1 in &2. SQL0470 SQLCODE -470 SQLSTATE 39002
Explanation: External program name for procedure &1 in &2 not valid. SQL0451 SQLCODE -451 SQLSTATE 42815
Explanation: NULL values not allowed for parameter &4 in procedure. SQL0473 SQLCODE -473 SQLSTATE 42918
Explanation: Attributes of parameter &1 not valid for procedure. SQL0452 SQLCODE -452 SQLSTATE 428A1
Explanation: User-defined type &1 cannot be created. SQL0475 SQLCODE -475 SQLSTATE 42866
Explanation: Unable to access a file that is referred to by a file reference variable. SQL0453 SQLCODE -453 SQLSTATE 42880
Explanation: RETURNS data type for function &3 in &4 not valid. SQL0476 SQLCODE -476 SQLSTATE 42725
Explanation: Return type for function &1 in &2 not compatible with CAST TO type. SQL0454 SQLCODE -454 SQLSTATE 42723
Explanation: Function &1 in &2 not unique. SQL0478 SQLCODE -478 SQLSTATE 42893
Explanation: Function &1 in &2 with the same signature already exists.
299
SQL0483
SQLCODE -483
SQLSTATE 42885
SQL0510
SQLCODE -510
SQLSTATE 42828
Explanation: Parameters for function &1 in &2 not same as sourced function. SQL0484 SQLCODE -484 SQLSTATE 42733
Explanation: Cursor &1 for file &2 is read-only. SQL0511 SQLCODE -511 SQLSTATE 42829
Explanation: FOR UPDATE OF clause not valid. SQL0513 SQLCODE -513 SQLSTATE 42924
Explanation: Routine &1 in &2 already exists. SQL0487 SQLCODE -487 SQLSTATE 38001
Explanation: SQL statements not allowed. SQL0490 SQLCODE -490 SQLSTATE 428B7
Explanation: Alias &1 in &2 cannot reference another alias. SQL0514 SQLCODE -514 SQLSTATE 26501
Explanation: Numeric value &1 not valid. SQL0491 SQLCODE -491 SQLSTATE 42601
Explanation: Prepared statement &2 not found. SQL0516 SQLCODE -516 SQLSTATE 26501
Explanation: RETURNS clause required on CREATE FUNCTION statement. SQL0492 SQLCODE -492 SQLSTATE 42879
Explanation: Prepared statement &2 not found. SQL0517 SQLCODE -517 SQLSTATE 07005
Explanation: Data type for function &1 in &2 not valid for source type. SQL0501 SQLCODE -501 SQLSTATE 24501
Explanation: Prepared statement &2 not SELECT statement. SQL0518 SQLCODE -518 SQLSTATE 07003
Explanation: Prepared statement &1 not found. SQL0519 SQLCODE -519 SQLSTATE 24506
Explanation: Cursor &1 not open. SQL0502 SQLCODE -502 SQLSTATE 24502
Explanation: Prepared statement &2 in use. SQL0520 SQLCODE -520 SQLSTATE 42828
Explanation: Cursor &1 already open. SQL0503 SQLCODE -503 SQLSTATE 42912
Explanation: Column &3 cannot be updated. SQL0504 SQLCODE -504 SQLSTATE 34000
Explanation: Cannot UPDATE or DELETE on cursor &1. SQL0525 SQLCODE -525 SQLSTATE 51015
Explanation: Cursor &1 not declared. SQL0507 SQLCODE -507 SQLSTATE 24501
Explanation: Statement not valid on application server. SQL0527 SQLCODE -527 SQLSTATE 42874
Explanation: Cursor &1 not open. SQL0508 SQLCODE -508 SQLSTATE 24504
Explanation: ALWCPYDTA(*NO) specified but temporary result required for &1. SQL0530 SQLCODE -530 SQLSTATE 23503
Explanation: Cursor &1 not positioned on locked row. SQL0509 SQLCODE -509 SQLSTATE 42827
Explanation: Insert or UPDATE value not allowed by referential constraint. SQL0531 SQLCODE -531 23504 SQLSTATE 23001,
300
SQL0532
SQLSTATE 23001,
SQL0557
SQLCODE -557
SQLSTATE 42852
Explanation: Delete prevented by referential constraint. SQL0536 SQLCODE -536 SQLSTATE 42914
Explanation: Privilege not valid for table or view &1 in &2. SQL0573 SQLCODE -573 SQLSTATE 42890
Explanation: Table does not have matching parent key. SQL0574 SQLCODE -574 SQLSTATE 42894
Explanation: Delete not allowed because table referenced in subquery can be affected. SQL0537 SQLCODE -537 SQLSTATE 42709
Explanation: Default value not valid. SQL0577 SQLCODE -577 2F002 SQLSTATE 38002,
Explanation: Duplicate column name in definition of key. SQL0538 SQLCODE -538 SQLSTATE 42830
Explanation: Modifying SQL data not permitted. SQL0578 SQLCODE -578 SQLSTATE 2F005
Explanation: Foreign key attributes do not match parent key. SQL0539 SQLCODE -539 SQLSTATE 42888
Explanation: RETURN statement not executed for SQL function &1 in &2. SQL0579 SQLCODE -579 2F004 SQLSTATE 38004,
Explanation: Table does not have primary key. SQL0541 SQLCODE -541 SQLSTATE 42891
Explanation: Reading SQL data not permitted. SQL0580 SQLCODE -580 SQLSTATE 42625
Explanation: Duplicate UNIQUE constraint already exists. SQL0543 SQLCODE -543 SQLSTATE 23511
Explanation: At least one result in CASE expression must be not NULL. SQL0581 SQLCODE -581 SQLSTATE 42804
Explanation: Constraint &1 conflicts with SET NULL or SET DEFAULT rule. SQL0544 SQLCODE -544 SQLSTATE 23512
Explanation: The results in a CASE expression are not compatible. SQL0583 SQLCODE -583 SQLSTATE 42845
Explanation: CHECK constraint &1 cannot be added. SQL0545 SQLCODE -545 SQLSTATE 23513
Explanation: Use of function &1 in &2 not valid. SQL0585 SQLCODE -585 SQLSTATE 42732
Explanation: INSERT or UPDATE not allowed by CHECK constraint. SQL0546 SQLCODE -546 SQLSTATE 42621
Explanation: Library &1 is used incorrectly on the SET PATH statement SQL0590 SQLCODE -590 SQLSTATE 42734
Explanation: CHECK condition of constraint &1 not valid. SQL0551 SQLCODE -551 SQLSTATE 42501
Explanation: Name &1 specified in &2 not unique. SQL0601 SQLCODE -601 SQLSTATE 42710
Explanation: Not authorized to object &1 in &2 type *&3. SQL0552 SQLCODE -552 SQLSTATE 42502
301
SQL0602
SQLCODE -602
SQLSTATE 54008
SQL0631
SQLCODE -631
SQLSTATE 54008
Explanation: More than 120 columns specified for CREATE INDEX. SQL0603 SQLCODE -603 SQLSTATE 23515
Explanation: Foreign key for referential constraint too long. SQL0637 SQLCODE -637 SQLSTATE 42614
Explanation: Unique index cannot be created because of duplicate keys. SQL0604 SQLCODE -604 SQLSTATE 42611
Explanation: Attributes of column not valid. SQL0607 SQLCODE -607 SQLSTATE 42832
Explanation: Maximum number of constraints exceeded. SQL0658 SQLCODE -658 SQLSTATE 42917
Explanation: Operation not allowed on system table &1 in &2. SQL0612 SQLCODE -612 SQLSTATE 42711
Explanation: &1 is a duplicate column name. SQL0613 SQLCODE -613 SQLSTATE 54008
Explanation: Estimated query processing time exceeds limit. SQL0667 SQLCODE -667 SQLSTATE 23520
Explanation: Primary or unique key constraint too long. SQL0614 SQLCODE -614 SQLSTATE 54008
Explanation: Foreign key does not match a value in the parent key. SQL0675 SQLCODE -675 SQLSTATE 42892
Explanation: Length of columns for CREATE INDEX too long. SQL0615 SQLCODE -615 SQLSTATE 55006
Explanation: Specified delete rule not allowed with existing trigger. SQL0679 SQLCODE -679 SQLSTATE 57006
Explanation: Object &1 in &2 type *&3 not dropped. It is in use. SQL0616 SQLCODE -616 SQLSTATE 42893
Explanation: Object &1 in &2 type *&3 not created due to pending operation. SQL0683 SQLCODE -683 SQLSTATE 42842
Explanation: &1 in &2 type &3 cannot be dropped with RESTRICT. SQL0624 SQLCODE -624 SQLSTATE 42889
Explanation: FOR DATA or CCSID clause not valid for specified type. SQL0707 SQLCODE -707 SQLSTATE 42939
Explanation: Table already has primary key. SQL0628 SQLCODE -628 SQLSTATE 42613
Explanation: Name &1 in &2 not allowed for distinct type. SQL0713 SQLCODE -713 SQLSTATE 42815
Explanation: Clauses are mutually exclusive. SQL0629 SQLCODE -629 SQLSTATE 42834
Explanation: Host variable for &2 is NULL. SQL0724 SQLCODE -724 SQLSTATE 54038
302
SQL0751
SQLCODE -751
SQLSTATE 42987
SQL0783
SQLCODE -783
SQLSTATE 42738
Explanation: SQL statement &1 not allowed in stored procedure or trigger. SQL0752 SQLCODE -752 SQLSTATE 0A001
Explanation: Select list for cursor &1 in FOR statement not valid. SQL0784 SQLCODE -784 SQLSTATE 42860
Explanation: Connection cannot be changed. Reason code is &1. SQL0773 SQLCODE -773 SQLSTATE 20000
Explanation: Check constraint &1 cannot be dropped. SQL0785 SQLCODE -785 SQLSTATE 428D8
Explanation: Case not found for CASE statement. SQL0774 SQLCODE -774 SQLSTATE 2D522
Explanation: Use of SQLCODE or SQLSTATE not valid. SQL0802 SQLCODE -802 SQLSTATE 22003, 22012, 22023, 22504
Explanation: Statement cannot be executed within a compound SQL statement. SQL0775 SQLCODE -775 SQLSTATE 42910
Explanation: Data conversion or data mapping error. SQL0803 SQLCODE -803 SQLSTATE 23505
Explanation: Statement not allowed in a compound SQL statement. SQL0776 SQLCODE -776 SQLSTATE 428D4
Explanation: Duplicate key value specified. SQL0804 SQLCODE -804 SQLSTATE 07002
Explanation: Cursor &1 specified in FOR statement not allowed. SQL0777 SQLCODE -777 SQLSTATE 42919
Explanation: SQL package &1 in &2 not found. SQL0811 SQLCODE -811 SQLSTATE 21000
Explanation: Nested compound statements not allowed. SQL0778 SQLCODE -778 SQLSTATE 428D5
Explanation: Result of SELECT INTO or subquery more than one row. SQL0818 SQLCODE -818 SQLSTATE 51003
Explanation: End label &1 not same as begin label. SQL0779 SQLCODE -779 SQLSTATE 42736
Explanation: Consistency tokens do not match. SQL0822 SQLCODE -822 SQLSTATE 51004
Explanation: Label &1 specified on LEAVE statement not valid. SQL0780 SQLCODE -780 SQLSTATE 428D6
Explanation: Address in SQLDA not valid. SQL0827 SQLCODE -827 SQLSTATE 42862
Explanation: UNDO specified for a handler and ATOMIC not specified. SQL0781 SQLCODE -781 SQLSTATE 42737
Explanation: &1 in &2 type *SQLPKG cannot be accessed. SQL0840 SQLCODE -840 SQLSTATE 54004
Explanation: Condition &1 specified in handler not defined. SQL0782 SQLCODE -782 SQLSTATE 428D7
Explanation: Number of selected items exceeds 8000. SQL0842 SQLCODE -842 SQLSTATE 08002
303
SQL0843
SQLCODE -843
SQLSTATE 08003
SQL0950
SQLCODE -950
SQLSTATE 42705
Explanation: Connection does not exist. SQL0858 SQLCODE -858 SQLSTATE 08501
Explanation: Relational database &1 not in relational database directory. SQL0951 SQLCODE -951 SQLSTATE 55007
Explanation: Cannot disconnect relational database due to LU 6.2 protected conversation. SQL0862 SQLCODE -862 SQLSTATE 55029
Explanation: Object &1 in &2 not altered. It is in use. SQL0952 SQLCODE -952 SQLSTATE 57014
Explanation: Local program attempted to connect to a remote relational database. SQL0871 SQLCODE -871 SQLSTATE 54019
Explanation: Processing of the SQL statement ended by ENDRDBRQS command. SQL0969 SQLCODE -969 SQLSTATE 58033
Explanation: Too many CCSID values specified. SQL0900 SQLCODE -900 SQLSTATE 08003
Explanation: Unexpected client driver error. SQL0971 SQLCODE -971 SQLSTATE 57011
Explanation: Application process not in a connected state. SQL0901 SQLCODE -901 SQLSTATE 58004
Explanation: Referential constraint &4 in check pending state. SQL5001 SQLCODE -5001 SQLSTATE 42703
Explanation: Column qualifier &2 undefined. SQL5002 SQLCODE -5002 SQLSTATE 42812
Explanation: Collection must be specified for table &1. SQL5003 SQLCODE -5003 SQLSTATE 42922
Explanation: Operation not performed because of previous error. SQL0907 SQLCODE -907 SQLSTATE 27000
Explanation: Cannot perform operation under commitment control. SQL5005 SQLCODE -5005 SQLSTATE 42815
Explanation: Attempt to change same row twice. SQL0910 SQLCODE -910 SQLSTATE 57007
Explanation: Operator &4 not consistent with operands. SQL5012 SQLCODE -5012 SQLSTATE 42618
Explanation: Object &1 in &2 type *&3 has a pending change. SQL0913 SQLCODE -913 SQLSTATE 57033
Explanation: Host variable not a numeric with zero scale. SQL5016 SQLCODE -5016 SQLSTATE 42833
Explanation: Row or object &1 in &2 type *&3 in use. SQL0917 SQLCODE -917 SQLSTATE 42969
Explanation: Object name &1 not valid for naming option. SQL5021 SQLCODE -5021 SQLSTATE 42930
304
SQL5023
SQLCODE -5023
SQLSTATE 26510
SQL7018
SQLCODE -7018
SQLSTATE 42970
Explanation: Duplicate statement name in DECLARE CURSOR. SQL5024 SQLCODE -5024 SQLSTATE 42618
Explanation: COMMIT HOLD or ROLLBACK HOLD not allowed. SQL7021 SQLCODE -7021 SQLSTATE 57043
Explanation: Host variable &1 not character. SQL5047 SQLCODE -5047 SQLSTATE 42616
Explanation: Local program attempting to run on application server. SQL7022 SQLCODE -7022 SQLSTATE 42977
Explanation: Error processing SRTSEQ or LANGID parameter. SQL5051 SQLCODE -5051 SQLSTATE 42875
Explanation: User &1 not the same as current user &2 for connect to local relational database. SQL7024 SQLCODE -7024 SQLSTATE 42876
Explanation: Index cannot be created because of CCSID incompatibility. SQL7026 SQLCODE -7026 SQLSTATE 42896
Explanation: File &1 in &2 not database file. SQL7002 SQLCODE -7002 SQLSTATE 42847
Explanation: Auxiliary storage pool not found. SQL7027 SQLCODE -7027 SQLSTATE 42984
Explanation: Override parameter not valid. SQL7003 SQLCODE -7003 SQLSTATE 42857
Explanation: File &1 in &2 has more than one format. SQL7006 SQLCODE -7006 SQLSTATE 55018
Explanation: Unable to CHGOBJOWN for primary group. SQL7029 SQLCODE -7029 SQLSTATE 428B8
Explanation: Cannot drop collection &1. SQL7007 SQLCODE -7007 SQLSTATE 51009
Explanation: New name &3 is not valid. SQL7031 SQLCODE -7031 SQLSTATE 54044
Explanation: COMMIT or ROLLBACK not valid. SQL7008 SQLCODE -7008 SQLSTATE 55019
Explanation: Sort sequence table &1 too long. SQL7032 SQLCODE -7032 SQLSTATE 42904
Explanation: &1 in &2 not valid for operation. SQL7010 SQLCODE -7010 SQLSTATE 42850
Explanation: SQL procedure &1 in &2 not created. SQL7033 SQLCODE -7033 SQLSTATE 42923
Explanation: Logical file &1 in &2 not valid for CREATE VIEW. SQL7011 SQLCODE -7011 SQLSTATE 42851
Explanation: Alias name &1 in &2 not allowed. SQL7034 SQLCODE -7034 SQLSTATE 42926
Explanation: &1 in &2 not table, view, or physical file. SQL7017 SQLCODE -7017 SQLSTATE 42971
Explanation: LOB locators are not allowed with COMMIT(*NONE). SQL7037 SQLCODE -7037 SQLSTATE 42835
305
SQL7038
SQLCODE -7038
SQLSTATE 429B7
SQ30053
SQLCODE -30053
SQLSTATE 42506
Explanation: Delete cascade not valid for &1 in &2. SQL7941 SQLCODE -7941 SQLSTATE 42981
Explanation: Not authorized to create package for owner &1. SQ30060 SQLCODE -30060 SQLSTATE 08004
Explanation: Application process not at commit boundary. SQL9012 SQLCODE -9012 SQLSTATE 42968
Explanation: User not authorized to relational database &1. SQ30061 SQLCODE -30061 SQLSTATE 08004
Explanation: DB2 UDB Query Manager and SQL Development Kit not available. SQ30000 SQLCODE -30000 SQLSTATE 58008
Explanation: Relational database &1 not found. SQ30070 SQLCODE -30070 SQLSTATE 58014
Explanation: Distributed Relational Database Architecture (DRDA) protocol error. SQ30001 SQLCODE -30001 SQLSTATE 57042
Explanation: Distributed Data Management (DDM) command &1 not supported. SQ30071 SQLCODE -30071 SQLSTATE 58015
Explanation: Call to distributed SQL program not allowed. SQ30020 SQLCODE -30020 SQLSTATE 58009
Explanation: Distributed Data Management (DDM) object &1 not supported. SQ30072 SQLCODE -30072 SQLSTATE 58016
Explanation: Distributed Relational Database Architecture (DRDA) protocol error. SQ30021 SQLCODE -30021 SQLSTATE 58010
Explanation: Distributed Data Management (DDM) parameter &1 not supported. SQ30073 SQLCODE -30073 SQLSTATE 58017
Explanation: Distributed relational database not supported by the remote system. SQ30040 SQLCODE -30040 SQLSTATE 57012
Explanation: Distributed Data Management (DDM) parameter value &1 not supported. SQ30074 SQLCODE -30074 SQLSTATE 58018
Explanation: DDM resource &2 at relational database &1 not available. SQ30041 SQLCODE -30041 SQLSTATE 57013
Explanation: Distributed Data Management (DDM) reply message &1 not supported. SQ30080 SQLCODE -30080 SQLSTATE 08001
Explanation: DDM resources at relational database &1 not available. SQ30050 SQLCODE -30050 SQLSTATE 58011
Explanation: Communication error occurred during distributed database processing. SQ30089 SQLCODE -30089 SQLSTATE 08001
Explanation: DDM command &1 is not valid while bind process is in progress. SQ30051 SQLCODE -30051 SQLSTATE 58012
Explanation: Communication error occurred during DB2 Multisystem processing. SQ30090 SQLCODE -30090 2D528, 2D529 SQLSTATE 25000,
Explanation: Bind process for specified package name and consistency token not active. SQ30052 SQLCODE -30052 SQLSTATE 42932
306
Exec
RDB(
USER(
*CURRENT user-name
PASSWORD(
*NONE password
GENLVL(
10 severity-level
REPLACE(
*YES *NO
DFTRDBCOL(
QSYSPRT printer-file-name
OBJTYPE(
*PGM *SRVPGM
307
CRTSQLPKG
*ALL (2) MODULE( module-name )
TEXT(
Notes: 1 2 All parameters preceding this point can be specified in positional form. 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 jobs 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.
308
CRTSQLPKG
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. 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.
Appendix C. DB2 UDB for AS/400 CL Command Descriptions
309
CRTSQLPKG
The name of the printer file can be qualified by one of the following library values: *LIBL: All libraries in the jobs 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. 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:
310
CRTSQLPKG
CRTSQLPKG PAYROLL RDB(SYSTEMA) TEXT('Payroll Program')
This command creates an SQL package from the distributed SQL program PAYROLL on relational database SYSTEMA.
DLTSQLPKG
*LIBL/ SQLPKG( *CURLIB/ *USRLIBL/ *ALL/ *ALLUSR/ library-name/ SQL-package-name generic*-SQL-package name )
(1)
Notes: 1 All parameters preceding this point can be specified in positional form.
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 jobs library list are searched until the first match is found.
Appendix C. DB2 UDB for AS/400 CL Command Descriptions
311
DLTSQLPKG
*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 jobs 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 #COBLIB #DFULIB #DSULIB #RPGLIB #SDALIB #SEULIB
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 QGPL QGPL38 QPFRDATA QRCL QS36F QUSER38 QUSRADSM QUSRBRM QUSRIJS QUSRINFSKR QUSRRDARS QUSRSYS QUSRVxRxMx
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. 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)
312
RUNSQLSTM
(1) SRCMBR ( source-file-member-name ) *UR *CHG *ALL *RS *CS *NONE *NC *RR
COMMIT (
NAMING (
*SYS *SQL
PROCESS(
*RUN *SYN
ALWCPYDTA (
ALWBLK (
ERRLVL (
10 severity-level
DATFMT (
DATSEP (
TIMFMT (
TIMSEP (
) DECMPT (
313
RUNSQLSTM
*JOB *LANGIDUNQ *LANGIDSHR *HEX *LIBL/ table-name *CURLIB/ library-name/
SRTSEQ (
LANGID (
*JOB language-identifier
DFTRDBCOL (
*NONE collection-name
FLAGSTD (
*NONE *ANS
SAAFLAG (
*NOFLAG *FLAG
QSYSPRT printer-file-name
SQL-procedure-parameters:
*CURRENT VxRxMx *ENDACTGRP *ENDMOD
TGTRLS (
CLOSQLCSR (
OUTPUT (
*NONE *PRINT
DBGVIEW (
USRPRF (
DYNUSRPRF (
*USER *OWNER
DLYPRP (
*NO *YES
314
RUNSQLSTM
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 jobs 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. 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
315
RUNSQLSTM
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. *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.
316
RUNSQLSTM
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. 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.
317
RUNSQLSTM
*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. : 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.
318
RUNSQLSTM
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. *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 jobs 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.
319
RUNSQLSTM
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 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 jobs 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.
320
RUNSQLSTM
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 users 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). 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.
Appendix C. DB2 UDB for AS/400 CL Command Descriptions
321
RUNSQLSTM
*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. *USER: For local, dynamic SQL statements run under the user of the programs user. For distributed, dynamic SQL statements run under the profile of the SQL packages user. *OWNER: For local, dynamic SQL statements run under the profile of the programs owner. For distributed, dynamic SQL statements run under the profile of the SQL packages 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.
322
RUNSQLSTM
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 *NC *NONE *CHG *UR *CS *RS *ALL *RR NAMING( ) )
COMMIT(
PROCESS(
LIBOPT(
LISTTYPE(
REFRESH(
ALWCPYDTA(
DATFMT(
323
STRSQL
(2) DATSEP( *JOB *BLANK / . , - *HMS *USA *ISO *EUR *JIS
TIMFMT(
(3) TIMSEP(
*JOB *BLANK : . ,
DECPNT(
(4) PGMLNG(
(5) SQLSTRDLM(
(6)
*QUOTESQL *APOSTSQL
SRTSEQ(
LANGID(
Notes: 1 2 3 4 All parameters preceding this point can be specified in positional form. DATSEP is only valid when *MDY, *DMY, *YMD, or *JUL is specified on the DATFMT parameter. TIMSEP is only valid when TIMFMT(*HMS) is specified. PGMLNG and SQLSTRDLM are valid only when PROCESS(*SYN) is specified.
324
STRSQL
5 6 PGMLNG and SQLSTRDLM are valid only when PROCESS(*SYN) is specified. 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 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.
325
STRSQL
*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 jobs 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 jobs 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 #COBLIB #DFULIB #DSULIB #RPGLIB #SDALIB #SEULIB
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 QGPL QGPL38 QPFRDATA QRCL QS36F QUSER38 QUSRADSM QUSRBRM QUSRIJS QUSRINFSKR QUSRRDARS QUSRSYS QUSRVxRxMx
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.
326
STRSQL
*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. *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 jobs date separator are not detected by interactive SQL. *BLANK: A blank ( ) is used. /: A slash (/) is used. .: A period (.) is used.
327
STRSQL
,: 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 jobs time separator are not detected by interactive SQL. *BLANK: A blank ( ) is used. :: A colon (:) is used. .: 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 systems 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.
328
STRSQL
*NONE: No specific languages 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. *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 jobs 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.
Appendix C. DB2 UDB for AS/400 CL Command Descriptions
329
STRSQL
*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.
330
Bibliography
This guide lists publications that provide additional information about topics described or referred to in this guide. The manuals in this section are listed with their full title and order number, but when referred to in text, a shortened version of the title is used. v Backup and Recovery, SC41-5304-04 This guide contains a subset of the information found in the Backup and Recovery book The manual contains information about planning a backup and recovery strategy, the different types of media available to save and restore procedures, and disk recovery procedures. It also describes how to install the system again from backup. v File Management This guide provides information about using files in application programs. v Database Programming This guide provides a detailed description of the DB2 UDB for AS/400 database organization, including information on how to create, describe, and update database files on the system. v CL Programming, SC41-5721-03 This guide provides a wide-ranging discussion of the AS/400 programming topics, including a general discussion of objects and libraries, CL programming, controlling flow and communicating between programs, working with objects in CL programs, and creating CL programs. Other topics include predefined and impromptu messages and handling, defining and creating user-defined commands and menus, application testing, including debug mode, breakpoints, traces, and display functions. v Control Language (CL) This guide provides a description of the AS/400 control language (CL) and its OS/400 commands. (Non-OS/400 commands are described in the respective licensed program publications.) It also provides an overview of all the CL commands for the AS/400 system, and it describes the syntax rules needed to code them. v Security - Reference, SC41-5302-04 This guide provides information about system security concepts, planning for security, and setting up security on the system. It also gives information about protecting the system and data from being used by people who do not have the proper authorization, protecting the data from intentional or unintentional damage or destruction, keeping security up-to-date, and setting up security on the system. v SQL Reference This guide provides information about DB2 UDB for AS/400 statements and their parameters. It also includes an appendix describing the SQL communications area (SQLCA) and SQL description area (SQLDA). v IDDU Use, SC41-5704-00 This guide describes how to use DB2 UDB for AS/400 interactive data definition utility (IDDU) to describe data dictionaries, files, and records to the system. v DATABASE 2/400 Advanced Database Functions, GG24-4249 This guide provides suggestions, guidelines, and practical examples of when and how functions offered by DB2 UDB for AS/400 such as triggers, referential integrity, DRDA-2, 2-phase commit, and stored procedures, can be effectively used. The book reports examples developed in several programming languages (RPG, COBOL, C), using native and SQL data access interface, both in the Integrated Language Environment and with the Original Program Model. v ILE COBOL for AS/400 Programmers Guide, SC09-2540-01 This guide provides information you need to design, write, test, and maintain COBOL for AS/400 programs on the AS/400 system. v ILE RPG for AS/400 Programmers Guide, SC09-2507-02 This guide provides information you need to design, write, test, and maintain ILE RPG for AS/400 programs on the AS/400 system. v ILE C for AS/400 Run-Time Library Reference, SC09-2711-01 This guide provides information you need to design, write, test, and maintain ILE C for AS/400 programs on the AS/400 system.
331
v ILE C for AS/400 Programmers Guide, SC09-2712-01 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 Programmers 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 Users 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. DB2 Multisystem 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. 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. SQL Call Level Interface (ODBC) This guide provides the information necessary for application programmers to write applications using the DB2 call level interface. AS/400 Developer Kit for Java This guide provides information you need to design, write, test, and maintain Java programs on the AS/400 system. It also contains a chapter, AS/400 Developer Kit for Java JDBC driver, which provides information about accessing AS/400 database files from Java programs by using JDBC or SQLj.
332
A
access plan definition 11 in a package 12 in a program 11 accessing remote databases interactive SQL 229 activation groups connection management example 263 add row to table 32 adding a column 92 adding data to end of table 254 adding indexes 96 address variable, in dynamic SQL 199 advanced coding technique complex search condition 72 inserting multiple rows into a table 69 joining data from multiple tables 75 aggregating functions 163 ALIAS names creating 48 ALIAS statement 48 ALL 86 allocating storage for SQLDA 210 ALTER TABLE 92 AND keyword description 74 multiple search condition 74 ANY 86 API QSQCHKS 2 QSQPRCED 2 application dynamic SQL designing and running 201 overview 199 application design user-defined function (UDF) 189 application domain and object-orientation 149 application forms using CREATE TABLE example 175 application program creating 9 testing SQL statements in 249 application requester 257 application requester driver (ARD) programs package creation 279 running statements 279 application server 257 ARD (application requester driver) programs 279 Copyright IBM Corp. 2000
B
basic SQL statements and clauses 31 BETWEEN clause, multiple search condition 72 BETWEEN keyword 72 bibliography 331 Binary Large OBjects 150 BLOBs (Binary Large OBjects) uses and definition 150 blocked insert statement 70
C
C2 security auditing 236 call level interface 2 call-type contents with table functions 194 call-type, passing to UDF 194 CAST FROM clause 192, 194, 195 castability 161 casting, UDFs 172 catalog database design, use in 97 definition 6 getting information about 97 column 97 integrity 247 LABEL ON information 48 QSYS2 views 6 table 97
333
CLOBs (Character Large OBjects) uses and definition 150 CLOSQLCSR parameter effect on implicit disconnect 267 coded character set conversion error 38 coding techniques 31, 55, 69 collating rows 41 collection changing table definition 256 creating 13 definition 3, 6 solving problem paging through retrieved data 253 retrieving data a second time 256 column adding 92 defining heading 16, 48 definition 3, 6 deleting 94 FOR UPDATE OF clause 58 getting catalog information about 97 name definition 39 SET clause, value 33 updating view 29 column definition changing 93 column functions 163 combining information from multiple tables 23 SELECT statement 80 subselect with UNION example 80 command RUNSQLSTM errors 232 command, CL Create Structured Query Language Package (CRTSQLPKG) 308 CRTSQLPKG (Create Structured Query Language Package) 308 Delete Structured Query Language Package (DLTSQLPKG) 311 DLTSQLPKG (Delete Structured Query Language Package) 311 command (CL) Change Class (CHGCLS) 237 Change Job (CHGJOB) 237 Change Logical File (CHGLF) 237 Change Physical File (CHGPF) 237 CHGCLS (Change Class) 237 CHGJOB (Change Job) 237 CHGLF (Change Logical File) 237 CHGPF (Change Physical File) 237 Create Duplicate Object (CRTDUPOBJ) 250 Create SQL Package (CRTSQLPKG) 259, 311 Create User Profile (CRTUSRPRF) 236 CRTDUPOBJ (Create Duplicate Object) command 250 CRTUSRPRF (Create User Profile) 236 Delete Library (DLTLIB) 244
command (CL) (continued) Delete SQL Package (DLTSQLPKG) 259, 312 Display Message Description (DSPMSGD) 289 DLTLIB (Delete Library) 244 DSPMSGD (Display Message Description) 289 Edit Check Pending Constraints (EDTCPCST) 245 Edit Rebuild of Access Paths (EDTRBDAP) 245 Edit Recovery for Access Paths (EDTRCYAP) 246 EDTCPCST (Edit Check Pending Constraints) 245 EDTRBDAP (Edit Rebuild of Access Paths) 245 EDTRCYAP (Edit Recovery for Access Paths) 246 Grant Object Authority (GRTOBJAUT) 235 GRTOBJAUT (Grant Object Authority) 235, 237 Override Database File (OVRDBF) 62, 237 OVRDBF (Override Database File) 62, 237 Reclaim DDM connections (RCLDDMCNV) 275 Retrieve Message (RTVMSG) 289 Revoke Object Authority (RVKOBJAUT) 235 RTVMSG (Retrieve Message) 289 Run SQL Statements (RUNSQLSTM) 2 RUNSQLSTM (Run SQL statements) 2 RUNSQLSTM (Run SQL Statements) 231, 323 RVKOBJAUT (Revoke Object Authority) 235 Send Program Message (SNDPGMMSG) 289 Send User Message (SNDUSRMSG) 289 SNDPGMMSG (Send Program Message) 289 SNDUSRMSG (Send User Message) 289 Start Commitment Control (STRCMTCTL) 240 Start Journal Access Path (STRJRNAP) 246 STRCMTCTL (Start Commitment Control) 240 STRJRNAP (Start Journal Access Path) 246 STRSQL (Start SQL) 330 comment for RUNSQLSTM 231 getting 49 COMMENT ON statement using, example 49 COMMIT keyword 240 prepared statements 203
COMMIT (continued) statement 261 statement description 6 commitment control activation group example 263 committable updates 269 description 239 distributed connection restrictions 272 DRDA resource 269 INSERT statement 33 job-level commitment definition 267, 272 protected resource 269 rollback required 274 RUNSQLSTM command 232 SQL statement processor 232 sync point manager 269 two-phase commit 269 unprotected resource 269 common database problem solving 253 comparison operators 40 comparisons involving UDTs example 177, 178 compiled application program object managing object 9 output source file member 11 program 9 user source file member 11 compiling application program object output source file member 11 program 11 user source file member 11 compiling a UDF 164 completing a unit of work 67 complex search condition keyword for use in 72 multiple search condition 72 performing 72 WHERE clause 31 concurrency data 237 definition 237 condition keyword for use in search 72 multiple search within a WHERE clause 74 performing complex search 72 CONNECT statement 257, 261 interactive SQL 230 connection DDM 275 determining type 269 ending DDM 275 protected 269 unprotected 269 connection management ARD programs 279 commitment control restrictions 272 distributed unit of work considerations 274 ending connections DDMCNV effect on 275 DISCONNECT statement 275
334
connection management (continued) RELEASE statement 275 example 263 implicit connection default activation group 267 nondefault activation group 268 implicit disconnection default activation group 267 nondefault activation group 268 multiple connections to same relational database 267 connection status determining 273 example 278 consistency token 262 consistent behavior and UDTs 173 constant definition 40 SET clause, value 33 constraint 245 definition 8 referential 8 unique 8 constraint mechanisms on large objects 149 constraints check 99 referential check pending 107 creating tables 100 delete rules 105 deleting from tables 105 inserting into tables 102 removing 102 update rules 104 updating tables 103 control, commitment 239 control information to access large object data 151 control structures 12 convention SQL naming 4 system naming 3 conversion error 37 CORPDATA.DEPARTMENT (department) 281 CORPDATA.EMP_ACT (employee to project activity) 283 CORPDATA.EMP_ACT table 283 CORPDATA.EMPLOYEE table 282 CORPDATA.PROJECT (project) 286 CORPDATA.PROJECT table 286 correlated names 90 references 90 correlated subquery definition 88 DELETE statement, use in 91 examples HAVING clause 90 UPDATE statement 91 WHERE clause 88 note on using 92 correlation definition 85 name 23, 79 using subquery 85
cost of a UDT example 167 counter for UDFs example 198 counting and defining UDFs example 168 CREATE COLLECTION statement 13 CREATE DISTINCT TYPE statement and castability 161 examples of using 175 to define a UDT 174 Create Duplicate Object (CRTDUPOBJ) command 250 CREATE FUNCTION statement 194 to register a UDF 165 CREATE INDEX sort sequence 53 CREATE SCHEMA statement 232 Create SQL Package (CRTSQLPKG) command 259, 311 authority required 260 Create Structured Query Language Package (CRTSQLPKG) command 308 CREATE TABLE prompting 223 CREATE TABLE statement 14 examples of using 175 Create User Profile (CRTUSRPRF) command 236 CREATE VIEW statement 29 creating index example 96 SQL collection example 13 structured query language package 308 table description 14 example 14 view 95 description 28 on a table 29 over multiple tables 30 creating ALIAS names 48 cross join 78 CRTDUPOBJ (Create Duplicate Object) command 250 CRTSQLPKG (Create SQL Package) command 311 CRTSQLPKG (Create Structured Query Language Package) command 308 CRTSQLxxx commands 3 CRTUSRPRF command create user profile 236 ctr() UDF C program listing 198 CURDATE scalar function 46 CURRENT DATE special register 45 current row 60 CURRENT SERVER special register 45 current session printing 227 removing all entries from 227 CURRENT TIME special register 45 CURRENT TIMESTAMP special register 45 CURRENT TIMEZONE special register 45
cursor distributed unit of work 278 example overview 56 example steps 58, 62 open 59 open, effect of recovery on 67 retrieving SELECT statement result 214 scrollable positioning within a table 55 serial positioning within a table 55 using 55 WITH HOLD clause 67 CURTIME scalar function 46
D
damage tolerance 246 data adding to the end of table 254 paging retrieved 253 retrieving in reverse order 253 updating as it is retrieved 254 previously retrieved 256 view, processing 36 data definition statement (DDL) 4 data dictionary WITH DATA DICTIONARY clause CREATE COLLECTION statement 6 CREATE SCHEMA statement 6 data independence 32, 38 data integrity 99 atomic operation 243 commitment control 239 concurrency 237 constraint 245 damage tolerance 246 data definition statements (DDL) 243 function 237 index recovery 246 journaling 239 save/restore 245 data manipulation statement (DML) 4 data mapping error 37 data protection 235 data types BLOBs 150 CLOBs 150 DBCLOBs 150 object-oriented 149 database design, using the catalog in 97 relational 3 date format 47 specifying current value 47 date/time arithmetic 47 DB2 Multisystem 2 DB2 Query Manager for AS/400 2 DB2 UDB for AS/400 1 distributed relational database support 257 DB2 UDB for AS/400 sample table 281 Index
335
DB2 UDB Query Manager and SQL Development Kit 1 distributed relational database support 257 DB2 UDB Symmetric Multiprocessing 2 DB2 Universal Database considerations for packages 260 DBCLOBs (Double-Byte Character Large OBjects) uses and definition 150 DBCS (double-byte character set) considerations in interactive SQL 223 DBGVIEW(*SOURCE) parameter 250 dbinfo, passing to UDF 194 DBINFO keyword 194 dbminfo argument, elements of 194 deadlock detection 238 debugging 249 common database problem 253 program 250 DECLARE CURSOR statement using 36 DECLARE statement 200 default collection name (DFTRDBCOL) parameter 3 DEFAULT keyword SET clause, value 34 default value 14, 18, 32 inserting in a view 95 define cursor 58 defining column heading 16, 48 table name 48 defining the UDT and UDFs example 181 definitions 257 access plan 11 authorization ID 3 authorization name 3 catalog 6 collection 3, 6 column 3, 6 column name 39 concurrency 237 constant 40 constraint 8 correlated subquery 88 correlation 85 CURRENT DATE special register 45 current row 60 CURRENT SERVER special register 45 CURRENT TIME special register 45 CURRENT TIMESTAMP special register 45 CURRENT TIMEZONE special register 45 data definition statement (DDL) 4 data dictionary 6 data manipulation statement (DML) 4 distributed unit of work 257 expression 39 field 3 host variable 40 index 8
definitions 257 (continued) join 30 join operation 23 journal 6 journal receiver 6 library 3 logical file 3 null value 45 NULL value 40 outer-level SELECT 84 output source file member 11 package 3, 9, 12, 259 physical file 3 predicate 38 program 11 record 3 referential integrity 8 remote unit of work 257 row 3, 6 search condition 38 special register 40 SQL package 3 SQLCODE 289 SQLSTATE 289 stored procedure 8 subquery 84 table 3, 6 trigger 8 user profile 3 user source file member 11 USER special register 45 view 3, 7 delete current row 61 Delete Library (DLTLIB) command 244 Delete SQL Package (DLTSQLPKG) command 259, 312 DELETE statement correlated subquery, use in 91 description 28, 34 Delete Structured Query Language Package (DLTSQLPKG) command 311 deleting structured query language package 311 deleting a column 94 deleting information in a table 28 department table CORPDATA.DEPARTMENT 281 DESCRIBE statement use with dynamic SQL 203 DESCRIBE TABLE statement 261 description SQLCODEs and SQLSTATEs 291 designing dynamic SQL application 201 DFT_SQLMATHWARN configuration parameter 192, 195 DFTRDBCOL (default collection name) parameter 3 diagnostic-message, passing to UDF 193 DISCONNECT statement 257, 261 ending connection 275 Display Message Description (DSPMSGD) command 289 displaying SQLCODE and SQLSTATE description 289 DISTINCT 71
DISTINCT 71 (continued) clause 72 keyword 255 distinct type 161 distributed relational database accessing remote databases 229 application requester 257 application server 257 committable updates 269, 273 connection management 263 multiple connections 267 connection restrictions 272 connection type determining 269 protected 269 unprotected 269 consideration for creating packages 260 creating packages 260 DB2 UDB for AS/400 support 257 determining connection status 273 distributed RUW example program 258 distributed unit of work 257, 268, 276 ending connections DDMCNV effect on 275 DISCONNECT statement 275 RELEASE statement 275 first failure data capture (FFDC) 279 implicit connection default activation group 267 nondefault activation group 268 implicit disconnection default activation group 267 nondefault activation group 268 interactive SQL 229 packages 259 statement in 260 precompiler diagnostic messages 260 problem handling 279 protected connection 269 protected resource 269 remote unit of work 257, 268 rollback required state 274 session attributes 230 SQL packages 259 sync point manager 269 two-phase commit 269 unprotected connection 269 unprotected resource 269 valid SQL statements 260 Distributed Relational Database Architecture (DRDA) 1 distributed unit of work 257, 268, 276 connection considerations 274 connection status 273 connection type 269 cursors 278 prepared statements 278 sample program 276 DLTSQLPKG (Delete SQL Package) command 312 DLTSQLPKG (Delete Structured Query Language Package) command 311 Double-Byte Character Large OBjects 150
336
DRDA (Distributed Relational Database Architecture) 257 DRDA level 1 268 DRDA level 2 268 DRDA resource 269 DROP PACKAGE statement 257 duplicate rows eliminating 81 preventing 71 DUW (distributed unit of work) 257 dynamic SQL address variable 199 allocating storage 205 application 199, 201 building and running statements 199 CCSID 202 cursor, use in 204 DESCRIBE statement 203 EXECUTE statement 201 fixed-list SELECT statement, using 204 parameter marker 215 PREPARE statement 201 processing non-SELECT statements 202 replacing parameter markers with host variables 216 run-time overhead 199 statements 4 varying-list SELECT statement 203
E
Edit Check Pending Constraints (EDTCPCST) command 245 Edit Rebuild of Access Paths (EDTRBDAP) command 245 Edit Recovery for Access Paths (EDTRCYAP) command 246 eliminating duplicate rows 81 employee-to-project activity table 283 encapsulation and UDTs 173 end-of-data reached 59 entering DBCS data 223 ERRLVL 232 error data mapping ORDER BY 37 error determination in distributed relational database first failure data capture (FFDC) 279 establishing position at end of table 253 examples 49 AND 74 application forms using CREATE TABLE 175 assignments in dynamic SQL 179 assignments involving different UDTs 180 assignments involving UDTs 179 AVG over a UDT 167 BETWEEN 72 catalog getting column information 97
examples 49 (continued) catalog (continued) getting table information 97 changing information in a table 25 changing rows in table host variables 33, 34 COMMENT ON 49 comparisons involving UDTs 177, 178 correlated subquery HAVING clause 90 WHERE clause 88 correlation name 23 cost of a UDT 167 counter for UDFs 198 counting and defining UDFs 168 creating index 96 SQL collection 13 table 14 view on a table 29 views over multiple tables 30 ctr() UDF C program listing 198 CURRENT DATE 47 CURRENT TIMEZONE 47 cursor 56 cursor in DUW program 278 defining stored procedures with CREATE PROCEDURE 118 defining the UDT and UDFs 181 deleting information in a table 28 determining connection status 278 distributed RUW program 258 distributed unit of work program 276 dynamic CALL 127 embedded CALL 124, 125 EXISTS 87 exploiting LOB function to populate the database 182 exploiting LOB locators to manipulate UDT instances 183 exploiting UDFs to query instances of UDTs 183 exponentiation and defining UDFs 165 extracting a document to a file (CLOB elements in a table) 156 function invocations 169 getting catalog information about column 97 table 97 getting comment 49 getting information about column using catalog 97 table using catalog 97 getting information from multiple tables 23 single table 20 IN 73 inserting add row to table 32 multiple rows into a table 69 inserting data into a CLOB column 158 invoking stored procedures 127
examples 49 (continued) where a CREATE PROCEDURE exists 124 where no CREATE PROCEDURE exists 125 join 76 LABEL ON statement 16, 48 LIKE 73 list function in interactive SQL 224 LOBFILE.SQB COBOL program listing 157 LOBFILE.SQC C program listing 157 LOBLOC.SQB COBOL program listing 154 LOBLOC.SQC C program listing 153 money using CREATE DISTINCT TYPE 175 multiple search condition (WHERE clause) 74 OR 74 ORDER BY sort sequence 51 parameter markers in functions 169 preventing duplicate rows 71 QSYSPRT listing SQL statement processor 233 removing information from table 28, 35 resume using CREATE DISTINCT TYPE 175 returning completion status to calling program 136 sales using CREATE TABLE 175 sample table 281 search 72 search string and BLOBs 166 SELECT records sort sequence 52 SELECT statement allocating storage for SQLDA 210 selecting into table host variables 36 special register 47 stored procedures returning completion status 136 string search and defining UDFs 166 string search over UDT 167 subquery 84 Union simple 83 UNION using host variables 81 UNION ALL using host variables 83 unqualified function reference 170 UPDATE statement 25 use of UDTs in UNION 180 user-defined sourced functions on UDTs 178 using a locator to work with a CLOB value 152 using index 96 using qualified function reference 170 view sort sequence 53
Index
337
examples 49 (continued) WITH CASCADED CHECK OPTION 110 WITH LOCAL CHECK OPTION 110 working with index 96 exception join 77 EXECUTE IMMEDIATE statement 201 EXECUTE privileges for packages 259 EXECUTE statement 201, 202 EXISTS keyword, use in subquery 87 exiting interactive SQL 228 exploiting LOB function to populate the database example 182 LOB locators to manipulate UDT instances example 183 UDFs to query instances of UDTs example 183 exponentiation and defining UDFs example 165 expression definition 39 SET clause, value 34 using in the WHERE clause 39 extended dynamic QSQPRCED 2 extensibility and UDTs 173 extracting a document to a file (CLOB elements in a table) example 156
G
getting catalog information about column 97 table 97 comment 49 information from multiple table 23 from single table 20 Grant Object Authority (GRTOBJAUT) command 235 GRANT PACKAGE statement 257 GROUP BY clause 41 keyword 255 using null value with 41 grouping the row you select 41
H
HAVING clause 42 host structure array multiple-row FETCH 63 host variable definition 40 SET clause, value 34
F
failed session, recovering 228 FETCH using host structure array multiple-row 63 FETCH statement 214 FFDC (first failure data capture) 279 field 3 file reference variables examples of using 156 for manipulating LOBs 150 input values 155 output values 156 first failure data capture (FFDC) 279 fixed-list SELECT statement definition 203 using 203 flexibility and UDTs 173 FOR UPDATE OF clause restrictions 58 format, SQLDA 206 FROM clause 36 function interactive SQL 219 function invocations example 169 function-name, passing to UDF 193 function path and UDFs 162 function references, summary for UDFs 171 function selection algorithm and UDFs 162 functions aggregating functions 163 column functions 163 scalar functions 163 syntax for referring to 169
I
ID, authorization 236 IDDU (interactive data definition utility) 6 ILE programs package 261 ILE service programs package 261 immediate sensitivity 63, 67 implementing a UDF 164 implicit connect 267 implicit disconnect 267 IN keyword description 73 subquery, use in 87 in tray table 287 IN_TRAY table 287 index add 96 definition 8 recovery 246 using 96 working with 96 indicator variables stored procedures 132 indicator variables and LOB locators infix notation and UDFs 172 information, inserting into table 18 inner join 75 INSERT statement blocked 31 default value 18, 32 description 31
INSERT statement (continued) VALUES clause 31 inserting information into table 18 multiple rows into tables 69 note 70 inserting data into a CLOB column example 158 instances of object-oriented data types, storing 149 Integrated Language Environment (ILE) module 12 program 11 service program 12 integrity catalog 247 data 99, 237 referential 99 interactive data definition utility 6 interactive interface concepts 2 interactive SQL accessing remote databases 229 change session attributes 227 description 219 exiting 228 function 219 general use 219 getting started 220 overview 219 package 230 prompting DBCS consideration 223 overview 219 session services 219, 226, 228 statement entry 219, 221 statement processing mode 223 terminology 3 testing your SQL statements with 219, 228 Interactive SQL 2 adding DBCS data 223 prompting 224 syntax checking 223 INTO clause description 32 PREPARE statements 205 restriction 210 invoking UDFs 168
J
job attribute DDMCNV 275 job-level commitment definition 267, 272 join cross 78 definitions 30 exception 77 inner 75 left outer 76 join operation definition 23 in a view 30 joining data from multiple tables 75 table with WHERE clause 76
155
338
K
keyword AND 74 BETWEEN 72 COMMIT 240 DISTINCT 255 EXISTS 87 GROUP BY 255 IN 73, 87 LIKE 73 NOT 40 OR 74 search condition, use in 72 UNION 80, 255 UNION ALL, specifying 83
LOBs (Large Objects) (continued) manipulating 149 programming options for values 151 storing 149 synergy with UDTs and UDFs examples of complex applications 181 locators for manipulating LOBs 150 logical file 3, 7 LONG VARCHAR storage limits 150 LONG VARGRAPHIC storage limits 150 Loosely Coupled Parallelism 2
null value 45 (continued) SET clause, value 33 UPDATE statement 33 used with GROUP BY clause 41 used with ORDER BY clause 44 NULL value 14 definition 40 numeric conversion error 38
O
object application program 9 collection 3 module 9 Integrated Language Environment (ILE) 12 package 9 program Integrated Language Environment (ILE) 11 service program 9 Integrated Language Environment (ILE) 12 SQL 5 object-orientation and UDFs 160 object-oriented extensions and UDTs 173 object-relational application domain and object-orientation 149 constraint mechanisms 149 data types 149 definition 149 LOBs 149 support for 150 triggers 149 UDTs and UDFs 149 why use the DB2 object extensions 149 ODBC 201 open cursor during a unit of work 67 open database connectivity (ODBC) 201 OPEN statement 215 operation, atomic 243 operators, comparison 40 ORDER BY clause 43 using null values with 44 data mapping errors 37 sort sequence, using 50 using 51 outer join 76 outer-level SELECT 84 output source file member definition 11 overloaded function names and UDFs 162 Override Database File (OVRDBF) command 62, 237 overview, interactive SQL 219
M
manipulating large objects 149 mapping error data 37 marker, parameter 215 maximum size for large object columns, defining 151 member output source file 11 user source file 11 mode interactive SQL 223 modelling entities as independent objects 149 module Integrated Language Environment (ILE) object 12 money using CREATE DISTINCT TYPE example 175 moving large objects using a file reference variable 150 multiple row inserting into a table 69 notes on inserting 70 search condition within a WHERE clause 74 table joining data from 75 multiple-row FETCH statement using descriptor area 64 host structure arrays 63 row storage area 64 with languages 63
L
LABEL ON statement 16, 48 information in catalog 48 package 262 large object descriptor 150 large object value 150 learn how to prompt using interactive SQL 224 leaving interactive SQL 228 left outer join 76 library definition 3 LIKE keyword 73 linking a UDF 164 list function 226 list function in interactive SQL description 224 LOBEVAL.SQB COBOL program listing 157 LOBEVAL.SQC C program listing 157 LOBLOC.SQB COBOL program listing 154 LOBLOC.SQC C program listing 153 LOBs (Large Objects) and DB2 object extensions 149 file reference variables 150 examples of using 156 input values 155 output values 156 SQL_FILE_APPEND, output value option 156 SQL_FILE_CREATE, output value option 156 SQL_FILE_OVERWRITE, output value option 156 SQL_FILE_READ, input value option 156 large object descriptor 150 large object value 150 locators 150, 151 example of using 152 indicator variables 155
N
naming convention *SQL 3 *SYS 3 SQL 4 system 3 negative SQLCODEs 293 non-SELECT statements, processing 202 NOT keyword 40, 74 NOW scalar function 46 null value 45 INSERT statement 32 inserting in a view 95
P
package authority to create 259 authority to run 259 Index
339
package (continued) bind to an application 9 CCSID considerations for 263 consistency token 262 Create SQL Package (CRTSQLPKG) command 259 authority required 260 creating authority required 259 effect of ARD programs 279 errors during 260 on local system 262 RDB parameter 259 RDBCNNMTH parameter 262 TGTRLS parameter 261 type of connection 262 unit of work boundary 262 creating on a non-DB2 UDB for AS/400 errors during 260 required precompiler options for DB2 Common Server 260 unsupported precompiler options 260 DB2 UDB for AS/400 support 259 definition 9, 12, 259 Delete SQL Package (DLTSQLPKG) command 259 deleting 259 interactive SQL 230 labeling 262 restore 262 save 262 SQL statement size 261 statements that do not require package 261 paging retrieved data 253 parameter markers in functions example 169 parameter passing stored procedures 128, 132 table 128 parameters marker 215 passing argument to UDF call-type 194 dbinfo 194 diagnostic-message 193 function-name 193 scratchpad 193 specific-name 193 SQL-argument 194, 195 SQL-argument-ind 192 SQL-argument-ind-array 195 SQL-result 194, 195 SQL-result-ind 192, 195 SQL-state 192 pending check 107 performance UDFs 160 performance and UDTs 173 performance verification 251 performing complex search condition 72 physical file 3, 6 positive SQLCODEs 291
precompiler concepts 1 diagnostic messages 260 precompiler command CRTSQLxxx 50, 260 precompiler parameter DBGVIEW(*SOURCE) 250 predicate definition 38 PREPARE statement non-SELECT statement 202 restrictions 201 using 215 prepared statement distributed unit of work 278 preventing duplicate rows 71 printing current session 227 problems, solving database 253 processing data in a view 36 non-SELECT statements 202 SELECT statement with SQLDA 203 program application 249 debugging 250 definition 11 Integrated Language Environment (ILE) object 11 non-ILE object 11 performance verification 251 project table 286 prompt using interactive SQL 219, 224 prompting CREATE TABLE 223 function 219, 221 overview 219 subqueries 223 protected connections dropping 272 protected resource 269 protection, data 235 public authority 235
Q
QSQCHKS 2 QSQPRCED 2 package 9 QSYS2 catalog views 6 QSYSPRT listing SQL statement processor example 233
R
re-use and UDFs 160 read-only table 59 view 95 read-only connection 269 receiver, journal 6 Reclaim DDM connections (RCLDDMCNV) command 275 record, definition 3 record selection 52
record selection 52 (continued) sort sequence, using 50 recovering effect on open cursor 67 index 246 interactive SQL saved or failed session 228 referential constraints check pending 107 creating tables 100 definition 8 delete rules 105 deleting from tables 105 inserting into tables 102 removing 102 update rules 104 updating tables 103 referential integrity 99 definition 8 registering UDFs 164 related information 331 relational database 3 RELEASE statement 257, 261 ending connection 275 remote databases accessing from interactive SQL 229 remote unit of work 257, 268 connection status 273 connection type 269 example program 258 removing all entries from current session 227 restriction FOR UPDATE OF 255 result table 80 resume using CREATE DISTINCT TYPE example 175 Retrieve Message (RTVMSG) command 289 retrieving data from a table. 20 in reverse order 253 row using a cursor 60 SELECT statement result cursor, using 214 return code 38 RETURNS TABLE clause 192, 194, 195 reuse deleted records INSERT 33 Revoke Object Authority (RVKOBJAUT) command 235 REVOKE PACKAGE statement 257 REXX 2 rollback rollback required state 274 ROLLBACK prepared statements 203 ROLLBACK statement 261 row definition 3, 6 delete current 61 inserting multiple into a table 69 note 70
340
row (continued) preventing duplicate 71 RRN scalar function 77 rules that govern operations on large objects 149 run mode interactive SQL 223 Run SQL Statements (RUNSQLSTM) command 2 run-time support concepts 1 running dynamic SQL application 201 RUNSQLSTM (Run SQL Statements) 227, 228 command 2, 231 command errors 232 commitment control 232 RUNSQLSTM (Run SQL Statements) command 323 RUW (remote unit of work) 257
S
sales using CREATE TABLE example 175 sample programs distributed RUW program 258 sample tables DB2 UDB for AS/400 281 save/restore 245 packages 262 saved session in a source file 227, 228 recovering 228 scalar functions 163 schedule table class 287 schema-name and UDFs 162 schemas SQL statement processor 232 scratchpad, passing to UDF 193 scrollable cursor 55 search condition definition 38 performing complex 72 subqueries 85 using keyword in 72 security 235 authorization 250 authorization ID 236 commitment control 239 data integrity 237 concurrency 237 public authority 235 view 236 SELECT clause 38 select information into host variables 36 SELECT INTO statement restriction 201 retrieving row 35 SELECT statement definition 20 example of allocating storage for SQLDA 210 processing and using SQLDA 203 using fixed-list 203 using varying-list 204
selecting column 70 semantic behavior of stored objects 149 Send Program Message (SNDPGMMSG) command 289 Send User Message (SNDUSRMSG) command 289 sensitivity immediate 63, 67 serial cursor 55 service program Integrated Language Environment (ILE) object 12 services, session 226 session 228 printing current 227 removing all entries from current 227 saving in a source file 227, 228 session services in interactive SQL 219, 226, 228 SET clause description 33 value column name 33 constant 33 expression 34 host variable 34 null 33 scalar subselect 34 special register 34 SET CONNECTION statement 257, 261 SET CURRENT FUNCTION PATH statement 164 SET TRANSACTION statement effect on implicit disconnect 267 not allowed in package 260 SEU (source entry utility) 228 signature, two functions and the same 162 SMALLINT 192, 195 solving 253 common database problem 253 solving common problems 253 SOME 86 sort sequence CREATE INDEX 53 used with ORDER BY 50 used with record selection 50 using 50 views 53 source entry utility (SEU) 228 source file for RUNSQLSTM 231 member, output definition 11 member, user 11 saving a session in 227, 228 sourced UDF 177 special register CURRENT DATE 45 CURRENT SERVER 45 CURRENT TIME 45 CURRENT TIMESTAMP 45 CURRENT TIMEZONE 45 definition 40
special register (continued) SET clause, value 34 USER 45 specific-name, passing to UDF 193 specifying column, SELECT INTO statement 38 UNION ALL 83 SQL 1 call level interface 2 introduction 1 object 5 statements types 4 SQL-argument, passing to UDF 194, 195 SQL-argument 192 SQL-argument-ind, passing to UDF 192 SQL-argument-ind-array, passing to UDF 195 SQL collection 13 SQL_FILE_READ, input value option 156 SQL naming convention 4 SQL package 3 SQL-result, passing to UDF 194, 195 SQL-result 192 SQL-result-ind, passing to UDF 192, 195 SQL-state, passing to UDF 192 SQL statement processor commitment control 232 example QSYSPRT listing 233 schemas 232 using 231 SQLCODEs definition 289 description 291 negative 293 positive 291 testing application program 250 SQLD 206 SQLDA (SQL descriptor area) allocating storage for 210 format 206 processing SELECT statement 203 programming language, use in 205 SELECT statement for allocating storage for SQLDA 210 SQLDABC 206 SQLDAID 206 SQLDATA 208 SQLERRD field of SQLCA SQLERRD(3) field of SQLCA determining connection status 273 determining number of rows fetched 63 SQLERRD(4) field of SQLCA 273 determining connection type 269 determining length of each row retrieved 63 SQLERRD(5) field of SQLCA determining end-of-file 63 SQLIND 208 SQLLEN 207 SQLN 206 SQLNAME 209 SQLRES 208 Index
341
SQLSTATEs code definition 289 definition 289 description 291 testing application program 250 SQLTYPE 206 sqludf.h include file for UDFs 194 SQLVAR 206 Start Commitment Control (STRCMTCTL) command 240 Start Journal Access Path (STRJRNAP) command 246 Start SQL (STRSQL) command 330 starting interactive SQL 220 statement entry 219, 221 statement processing mode interactive SQL 223 statements 45 ALIAS statement example 48 basic, using 31 COMMENT ON statement 49 COMMIT 6 CONNECT 257 CREATE COLLECTION 13 CREATE INDEX sort sequence 53 CREATE PROCEDURE external procedure 117 SQL procedure 117 CREATE SCHEMA 232 CREATE TABLE 14 CREATE VIEW 29 data definition (DDL) 4 data manipulation (DML) 4 date value 47 DECLARE CURSOR 36 DELETE example 34 WHERE clause 28 DISCONNECT 257 DROP PACKAGE 257 dynamic 4 EXECUTE 201, 202 FETCH 214 multiple-row 62 GRANT PACKAGE 257 INSERT using 31 LABEL ON statement example 48 examples 16 multiple-row FETCH 64 OPEN 215 package not required 261 packages 260 PREPARE cursor 215 non-SELECT statement 202 using 201 processing non select 202 RELEASE 257 REVOKE PACKAGE 257 ROLLBACK 6 select 20 SELECT INTO example 35
statements 45 (continued) SELECT INTO (continued) processing data (view) 36 restriction 201 specifying column 38 SET CONNECTION 257 SQL packages 260 testing in application program 249 using interactive SQL 219, 228 time value 47 timestamp value 47 UPDATE changing data value 25 example 33 stopping interactive SQL 228 storage, allocating for SQLDA 210 stored procedures 117, 145 definition 8 parameter passing 128 indicator variables 132 table 128 storing large objects 149 string search and defining UDFs example 166 string search on BLOBs 166 string search over UDT example 167 strong typing and UDTs 176 STRSQL (Start SQL) command 220, 330 Structured Query Language 1 structured query language package creating 308 deleting 311 subquery 88 basic comparison 86 correlated 85, 88 correlated names and references 90 definition 84 examples 84 EXISTS keyword 87 IN keyword 87 notes on using with UPDATE and DELETE 88 prompting 223 quantified comparison 86 search condition 85 subselect combining with the UNION keyword, example 80 SET clause, value 34 Symmetric Multiprocessing 2 sync point manager 269 syntax check QSQCHKS 2 syntax check mode interactive SQL 223 syntax for referring to functions 169 system naming convention 3 system table name 17
T
table adding data to the end 254 changing definition 92, 256 changing information in 25 CL_SCHED (class schedule) 287
table (continued) CORPDATA.DEPARTMENT (department) 281 CORPDATA.EMP_ACT (employee to project activity) 283 CORPDATA.EMPLOYEE 282 CORPDATA.PROJECT (project) 286 creating CREATE TABLE statement 14 view 29 DB2 UDB for AS/400 sample 281 defining name 48 definition 3, 6 deleting information in 28 establishing position at the end 253 getting catalog information about column 97 getting information from multiple 23 from one 20 IN_TRAY 287 inserting information into 18 multiple rows into 69 joining 75 the WHERE clause 76 multiple creating view over 30 sample 281 used in examples CORPDATA.DEPARTMENT (department) 281 CORPDATA.EMP_ACT (employee to project activity) 283 CORPDATA.EMPLOYEE 282 CORPDATA.PROJECT (project) 286 using 14 table functions 163 contents of call-type argument 194 table name system 17 technique coding 31, 55, 69 solving database problem 253 terminology interactive SQL 3 relational database 3 relationship table *SQL 3 *SYS 3 testing authorization 249, 250 debugging your program 250 input data 249 performance verification 251 SQL statements using interactive SQL 219, 228 statements in application program 249 view 249 time format 47 specifying current value 47 timestamp format 47 specifying current value 47 tolerance, damage 246
342
trigger definition 8 event 8 trigger support 111 triggers and DB2 object extensions truncation error 37 two-phase commit 269 typing interactive SQL 221
149
U
UDFs (User-defined functions) and DB2 object extensions 149 casting 172 concepts 162 definition 160 function path 162 function selection algorithm 162 general considerations 172 implementing UDFs 160 infix notation 172 invoking examples of invocations 168 parameter markers in functions 169 qualified function reference 170 unqualified function reference 170 LOB types 172 overloaded function names 162 process of implementation 164 referring to functions 169 registering UDFs 165 examples of registering 165 schema-name and UDFs 162 sourced 177 summary of function references 171 synergy with UDTs and LOBs examples of complex applications 181 type of functions 163 unqualified reference 162 why use UDFs 160 writing your own UDF 189 UDFs and LOB types 172 UDTs (User-defined types) and DB2 object extensions 149 defining a UDT 174 defining tables 175 manipulating examples of 176 resolving unqualified UDTs 174 strong typing 176 synergy with UDFs and LOBs examples of complex applications 181 why use UDTs 173 UNION ALL, specifying 83 UNION keyword restriction 255 using to combine subselects 80 unique constraint definition 8 unit of work distributed 257
unit of work (continued) effect on open cursor 67 package creation 262 remote 257 rollback required 274 unit of work boundary package creation 262 unprotected resource 269 unqualified function reference example 170 unqualified reference 162 UPDATE statement correlated subquery, using in 91 description 33 WHERE clause 25 updating data as it is retrieved, restrictions 254 committable updates 269 previously retrieved 256 use of UDTs in UNION example 180 user auxiliary storage pool (ASP) 247 user-defined sourced functions on UDTs example 178 user profile authorization ID 3 authorization name 3 user source file member definition 11 USER special register 45 using blocked insert statement 70 cursor example 56 retrieve row 60 date value 47 index 96 null value 45 ORDER BY 51 parameter markers 215 record selection 52 sort sequence 50 time value 47 timestamp value 47 Using views 95 USING clause 212 DESCRIPTOR clause 215 using a locator to work with a CLOB value example 152 using interactive SQL 219 after first time 226 list selection function 224 prompting 221 statement entry 221 using qualified function reference example 170
varying-list SELECT statement (continued) using 204 verification performance 251 view creating 95 CREATE VIEW statement 28 on a table 29 over multiple tables 30 definition 3, 7 limiting access 28 processing data in 36 read-only 95 security 236 sort sequence 53 testing 249 using 95 WITH CASCADED CHECK 108 WITH CHECK 108 WITH LOCAL CHECK 109
W
WHENEVER NOT FOUND clause 60 WHERE clause character string 31 constant 39 description 38 example 215 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
V
validate mode interactive SQL 223 value default 14, 18 inserting into table or view 31 VALUES clause 31 varying-list SELECT statement definition 204 Index
343
344
Printed in U.S.A.