DB2 V8 Application Programming and SQL Guide
DB2 V8 Application Programming and SQL Guide
Version 8
Application Programming
and SQL Guide
SC18-7415-00
DB2 Universal Database for z/OS
®
Version 8
Application Programming
and SQL Guide
SC18-7415-00
Note
Before using this information and the product it supports, be sure to read the general information under “Notices” on page
1037.
Contents v
Coding SQL statements in a COBOL application . . . . . . . . . . . . 170
Defining the SQL communication area . . . . . . . . . . . . . . . 170
Defining SQL descriptor areas . . . . . . . . . . . . . . . . . . 171
Embedding SQL statements . . . . . . . . . . . . . . . . . . 172
| Using host variables and host variable arrays . . . . . . . . . . . . 175
Declaring host variables . . . . . . . . . . . . . . . . . . . . 176
| Declaring host variable arrays . . . . . . . . . . . . . . . . . . 183
Using host structures . . . . . . . . . . . . . . . . . . . . . 189
Determining equivalent SQL and COBOL data types . . . . . . . . . 194
Determining compatibility of SQL and COBOL data types . . . . . . . . 198
Using indicator variables and indicator variable arrays . . . . . . . . . 199
Handling SQL error return codes . . . . . . . . . . . . . . . . . 201
Coding considerations for object-oriented extensions in COBOL . . . . . 202
Coding SQL statements in a Fortran application . . . . . . . . . . . . 203
Defining the SQL communication area . . . . . . . . . . . . . . . 203
Defining SQL descriptor areas . . . . . . . . . . . . . . . . . . 204
Embedding SQL statements . . . . . . . . . . . . . . . . . . 204
Using host variables . . . . . . . . . . . . . . . . . . . . . 206
Declaring host variables . . . . . . . . . . . . . . . . . . . . 207
Determining equivalent SQL and Fortran data types . . . . . . . . . . 208
Determining compatibility of SQL and Fortran data types . . . . . . . . 211
Using indicator variables . . . . . . . . . . . . . . . . . . . . 211
Handling SQL error return codes . . . . . . . . . . . . . . . . . 212
Coding SQL statements in a PL/I application . . . . . . . . . . . . . 213
Defining the SQL communication area . . . . . . . . . . . . . . . 213
Defining SQL descriptor areas . . . . . . . . . . . . . . . . . . 214
Embedding SQL statements . . . . . . . . . . . . . . . . . . 214
| Using host variables and host variable arrays . . . . . . . . . . . . 217
Declaring host variables . . . . . . . . . . . . . . . . . . . . 217
| Declaring host variable arrays . . . . . . . . . . . . . . . . . . 220
Using host structures . . . . . . . . . . . . . . . . . . . . . 223
Determining equivalent SQL and PL/I data types . . . . . . . . . . . 224
Determining compatibility of SQL and PL/I data types . . . . . . . . . 228
Using indicator variables and indicator variable arrays . . . . . . . . . 229
Handling SQL error return codes . . . . . . . . . . . . . . . . . 230
Coding considerations for PL/I . . . . . . . . . . . . . . . . . . 232
Coding SQL statements in a REXX application . . . . . . . . . . . . . 232
Defining the SQL communication area . . . . . . . . . . . . . . . 232
Defining SQL descriptor areas . . . . . . . . . . . . . . . . . . 233
Accessing the DB2 REXX Language Support application programming
interfaces . . . . . . . . . . . . . . . . . . . . . . . . 233
Embedding SQL statements in a REXX procedure . . . . . . . . . . 235
Using cursors and statement names . . . . . . . . . . . . . . . 237
Using REXX host variables and data types . . . . . . . . . . . . . 237
Using indicator variables . . . . . . . . . . . . . . . . . . . . 241
Setting the isolation level of SQL statements in a REXX procedure . . . . 241
Contents vii
Defining a user-defined function . . . . . . . . . . . . . . . . . . 296
Components of a user-defined function definition . . . . . . . . . . . 296
Examples of user-defined function definitions . . . . . . . . . . . . 298
Implementing an external user-defined function . . . . . . . . . . . . 300
Writing a user-defined function . . . . . . . . . . . . . . . . . 300
Preparing a user-defined function for execution . . . . . . . . . . . 333
Testing a user-defined function . . . . . . . . . . . . . . . . . 335
Implementing an SQL scalar function . . . . . . . . . . . . . . . . 338
Invoking a user-defined function . . . . . . . . . . . . . . . . . . 338
Syntax for user-defined function invocation . . . . . . . . . . . . . 338
Ensuring that DB2 executes the intended user-defined function . . . . . 339
Casting of user-defined function arguments . . . . . . . . . . . . . 345
What happens when a user-defined function abnormally terminates . . . . 346
Nesting SQL Statements . . . . . . . . . . . . . . . . . . . . 346
Recommendations for user-defined function invocation . . . . . . . . . 347
Contents ix
Step 2: Compile (or assemble) and link-edit the application . . . . . . . 471
Step 3: Bind the application . . . . . . . . . . . . . . . . . . . 472
Step 4: Run the application . . . . . . . . . . . . . . . . . . . 485
Using JCL procedures to prepare applications . . . . . . . . . . . . . 489
Available JCL procedures . . . . . . . . . . . . . . . . . . . 489
Including code from SYSLIB data sets . . . . . . . . . . . . . . . 490
Starting the precompiler dynamically . . . . . . . . . . . . . . . 491
An alternative method for preparing a CICS program . . . . . . . . . 493
Using JCL to prepare a program with object-oriented extensions . . . . . 495
Using ISPF and DB2 Interactive (DB2I) . . . . . . . . . . . . . . . 495
DB2I help . . . . . . . . . . . . . . . . . . . . . . . . . 495
DB2I Primary Option Menu . . . . . . . . . . . . . . . . . . . 495
Contents xi
Declaring and using variables in an SQL procedure . . . . . . . . . . 601
Parameter style for an SQL procedure . . . . . . . . . . . . . . . 602
Terminating statements in an SQL procedure . . . . . . . . . . . . 602
Handling SQL conditions in an SQL procedure . . . . . . . . . . . . 603
Examples of SQL procedures . . . . . . . . . . . . . . . . . . 607
Preparing an SQL procedure . . . . . . . . . . . . . . . . . . 609
Writing and preparing an application to use stored procedures . . . . . . . 621
Forms of the CALL statement . . . . . . . . . . . . . . . . . . 621
Authorization for executing stored procedures . . . . . . . . . . . . 623
Linkage conventions . . . . . . . . . . . . . . . . . . . . . 623
Using indicator variables to speed processing . . . . . . . . . . . . 643
Declaring data types for passed parameters . . . . . . . . . . . . . 643
Writing a DB2 UDB for z/OS client program or SQL procedure to receive
result sets . . . . . . . . . . . . . . . . . . . . . . . . 648
Accessing transition tables in a stored procedure . . . . . . . . . . . 654
Calling a stored procedure from a REXX Procedure . . . . . . . . . . 654
Preparing a client program . . . . . . . . . . . . . . . . . . . 658
Running a stored procedure . . . . . . . . . . . . . . . . . . . 659
How DB2 determines which version of a stored procedure to run . . . . . 660
Using a single application program to call different versions of a stored
procedure . . . . . . . . . . . . . . . . . . . . . . . . 660
Running multiple stored procedures concurrently . . . . . . . . . . . 661
| Running multiple instances of a stored procedure concurrently . . . . . . 662
Accessing non-DB2 resources . . . . . . . . . . . . . . . . . . 663
Testing a stored procedure . . . . . . . . . . . . . . . . . . . . 664
Debugging the stored procedure as a stand-alone program on a workstation 664
Debugging with the Debug Tool and IBM VisualAge COBOL . . . . . . . 665
Debugging an SQL procedure or C language stored procedure with the
Debug Tool and C/C++ Productivity Tools for z/OS . . . . . . . . . 665
Debugging with Debug Tool for z/OS interactively and in batch mode . . . 666
Using the MSGFILE run-time option . . . . . . . . . . . . . . . . 668
Using driver applications . . . . . . . . . . . . . . . . . . . . 668
Using SQL INSERT statements . . . . . . . . . . . . . . . . . 669
Contents xiii
| Dynamic prefetch (PREFETCH=D) . . . . . . . . . . . . . . . . 768
List prefetch (PREFETCH=L) . . . . . . . . . . . . . . . . . . 768
Sequential detection at execution time . . . . . . . . . . . . . . . 769
Determining sort activity . . . . . . . . . . . . . . . . . . . . . 771
Sorts of data . . . . . . . . . . . . . . . . . . . . . . . . 771
Sorts of RIDs . . . . . . . . . . . . . . . . . . . . . . . . 772
The effect of sorts on OPEN CURSOR . . . . . . . . . . . . . . 772
Processing for views and nested table expressions . . . . . . . . . . . 773
Merge . . . . . . . . . . . . . . . . . . . . . . . . . . . 773
Materialization . . . . . . . . . . . . . . . . . . . . . . . . 774
Using EXPLAIN to determine when materialization occurs . . . . . . . 776
Using EXPLAIN to determine UNION activity and query rewrite . . . . . 777
Performance of merge versus materialization . . . . . . . . . . . . 778
Estimating a statement’s cost . . . . . . . . . . . . . . . . . . . 779
Creating a statement table . . . . . . . . . . . . . . . . . . . 780
Populating and maintaining a statement table . . . . . . . . . . . . 782
Retrieving rows from a statement table . . . . . . . . . . . . . . 782
Understanding the implications of cost categories . . . . . . . . . . . 782
Chapter 30. Programming for the call attachment facility (CAF) . . . . . 799
Call attachment facility capabilities and restrictions . . . . . . . . . . . 799
Capabilities when using CAF . . . . . . . . . . . . . . . . . . 799
CAF requirements . . . . . . . . . . . . . . . . . . . . . . 800
How to use CAF . . . . . . . . . . . . . . . . . . . . . . . . 802
Summary of connection functions . . . . . . . . . . . . . . . . 804
Accessing the CAF language interface . . . . . . . . . . . . . . . 805
General properties of CAF connections . . . . . . . . . . . . . . 806
CAF function descriptions . . . . . . . . . . . . . . . . . . . 807
CONNECT: Syntax and usage . . . . . . . . . . . . . . . . . . 809
OPEN: Syntax and usage . . . . . . . . . . . . . . . . . . . 813
CLOSE: Syntax and usage . . . . . . . . . . . . . . . . . . . 815
DISCONNECT: Syntax and usage . . . . . . . . . . . . . . . . 816
TRANSLATE: Syntax and usage . . . . . . . . . . . . . . . . . 818
Summary of CAF behavior . . . . . . . . . . . . . . . . . . . 819
Sample scenarios . . . . . . . . . . . . . . . . . . . . . . . 820
A single task with implicit connections . . . . . . . . . . . . . . . 820
A single task with explicit connections . . . . . . . . . . . . . . . 821
Several tasks . . . . . . . . . . . . . . . . . . . . . . . . 821
Exit routines from your application . . . . . . . . . . . . . . . . . 821
Contents xv
| Application-to-application connectivity . . . . . . . . . . . . . . . 882
Notices . . . . . . . . . . . . . . . . . . . . . . . . . . 1037
Programming interface information . . . . . . . . . . . . . . . . . 1038
Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . 1039
Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . 1041
Contents xvii
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . 1075
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . X-1
.
Important
In this version of DB2 UDB for z/OS, the DB2 Utilities Suite is available as an
optional product. You must separately order and purchase a license to such
utilities, and discussion of those utility functions in this publication is not
intended to otherwise imply that you have a license to them. See Part 1 of
DB2 Utility Guide and Reference for packaging details.
Visit the following Web site for information about ordering DB2 books and obtaining
other valuable information about DB2 UDB for z/OS:
www.ibm.com/software/data/db2/zos/library.html
When referring to a DB2 product other than DB2 UDB for z/OS, this information
uses the product’s full name to avoid ambiguity.
required_item
required_item
optional_item
If an optional item appears above the main path, that item has no effect on the
execution of the statement and is used only for readability.
optional_item
required_item
v If you can choose from two or more items, they appear vertically, in a stack.
If you must choose one of the items, one item of the stack appears on the main
path.
required_item required_choice1
required_choice2
If choosing one of the items is optional, the entire stack appears below the main
path.
required_item
optional_choice1
optional_choice2
If one of the items is the default, it appears above the main path and the
remaining choices are 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.
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.
Accessibility
Accessibility features help a user who has a physical disability, such as restricted
mobility or limited vision, to use software products. The major accessibility features
in z/OS products, including DB2 UDB for z/OS, enable users to:
v Use assistive technologies such as screen reader and screen magnifier software
v Operate specific or equivalent features by using only a keyboard
v Customize display attributes such as color, contrast, and font size
Assistive technology products, such as screen readers, function with the DB2 UDB
for z/OS user interfaces. Consult the documentation for the assistive technology
products for specific information when you use assistive technology to access these
interfaces.
Online documentation for Version 8 of DB2 UDB for z/OS is available in the DB2
Information Center, which is an accessible format when used with assistive
technologies such as screen reader or screen magnifier software. The DB2
Information Center for z/OS solutions is available at the following Web site:
http://publib.boulder.ibm.com/infocenter/db2zhelp.
www.ibm.com/software/db2zos/library.html
This Web site has a feedback page that you can use to send comments.
For more advanced topics on using SELECT statements, see Chapter 4, “Using
subqueries,” on page 49, and Chapter 20, “Planning to access distributed data,” on
page 423.
Examples of SQL statements illustrate the concepts that this chapter discusses.
Consider developing SQL statements similar to these examples and then running
them dynamically using SPUFI or DB2 Query Management Facility (DB2 QMF).
Result tables
The data retrieved through SQL is always in the form of a table, which is called a
result table. Like the tables from which you retrieve the data, a result table has rows
and columns. A program fetches this data one row at a time.
Example: SELECT statement: The following SELECT statement retrieves the last
name, first name, and phone number of employees in department D11 from the
sample employee table:
SELECT LASTNAME, FIRSTNME, PHONENO
FROM DSN8810.EMP
WHERE WORKDEPT = ’D11’
ORDER BY LASTNAME;
Data types
When you create a DB2 table, you define each column to have a specific data type.
The data type can be a built-in data type or a distinct type. This section discusses
built-in data types. For information about distinct types, see Chapter 16, “Creating
and using distinct types,” on page 349. The data type of a column determines what
you can and cannot do with the column. When you perform operations on columns,
the data must be compatible with the data type of the referenced column. For
example, you cannot insert character data, like a last name, into a column whose
data type is numeric. Similarly, you cannot compare columns containing
incompatible data types.
To better understand the concepts that are presented in this chapter, you must
understand the data types of the columns to which an example refers. As shown in
© Copyright IBM Corp. 1983, 2004 3
Figure 1, built-in data types have four general categories: datetime, string, numeric,
and row identifier (ROWID).
For more detailed information about each data type, see Chapter 2 of DB2 SQL
Reference.
Table 1 on page 5 shows whether operands of any two data types are compatible,
Y (Yes), or incompatible, N (No). Numbers in the table, either as superscript of Y or
N, or as a value in the column, indicates a note at the bottom of the table.
Example: SELECT *: The following SQL statement selects all columns from the
department table:
SELECT *
FROM DSN8810.DEPT;
Because the example does not specify a WHERE clause, the statement retrieves
data from all rows.
The dashes for MGRNO and LOCATION in the result table indicate null values.
SELECT * is recommended mostly for use with dynamic SQL and view definitions.
You can use SELECT * in static SQL, but this is not recommended; if you add a
column to the table to which SELECT * refers, the program might reference
columns for which you have not defined receiving host variables. For more
information about host variables, see “Accessing data using host variables, variable
arrays, and structures” on page 71.
If you list the column names in a static SELECT statement instead of using an
asterisk, you can avoid the problem created by using SELECT *. You can also see
the relationship between the receiving host variables and the columns in the result
table.
Example: SELECT column-name: The following SQL statement selects only the
MGRNO and DEPTNO columns from the department table:
SELECT MGRNO, DEPTNO
FROM DSN8810.DEPT;
To order the rows in a result table by the values in a derived column, specify a
name for the column by using the AS clause, and specify that name in the ORDER
BY clause. For information about using the ORDER BY clause, see “Putting the
rows in order: ORDER BY” on page 9.
Example: CREATE VIEW with AS clause: You can specify result column names in
the select-clause of a CREATE VIEW statement. You do not need to supply the
| For more information about using the CREATE VIEW statement, see “Defining a
| view: CREATE VIEW” on page 25.
Example: UNION ALL with AS clause: You can use the AS clause to give the
same name to corresponding columns of tables in a union. The third result column
from the union of the two tables has the name TOTAL_VALUE, even though it
contains data derived from columns with different names:
SELECT ’On hand’ AS STATUS, PARTNO, QOH * COST AS TOTAL_VALUE
FROM PART_ON_HAND
UNION ALL
SELECT ’Ordered’ AS STATUS, PARTNO, QORDER * COST AS TOTAL_VALUE
FROM ORDER_PART
ORDER BY PARTNO, TOTAL_VALUE;
The column STATUS and the derived column TOTAL_VALUE have the same name
in the first and second result tables, and are combined in the union of the two result
tables, which is similar to the following partial output:
STATUS PARTNO TOTAL_VALUE
======= ====== ===========
On hand 00557 345.60
Ordered 00557 150.50
.
.
.
For information about unions, see “Merging lists of values: UNION” on page 13.
Example: GROUP BY derived column: You can use the AS clause in a FROM
clause to assign a name to a derived column that you want to refer to in a GROUP
BY clause. This SQL statement names HIREYEAR in the nested table expression,
which lets you use the name of that result column in the GROUP BY clause:
SELECT HIREYEAR, AVG(SALARY)
FROM (SELECT YEAR(HIREDATE) AS HIREYEAR, SALARY
FROM DSN8810.EMP) AS NEWEMP
GROUP BY HIREYEAR;
You cannot use GROUP BY with a name that is defined with an AS clause for the
derived column YEAR(HIREDATE) in the outer SELECT, because that name does
not exist when the GROUP BY runs. However, you can use GROUP BY with a
name that is defined with an AS clause in the nested table expression, because the
| nested table expression runs before the GROUP BY that references the name. For
| more information about using the GROUP BY clause, see “Summarizing group
| values: GROUP BY” on page 11.
DB2 evaluates a predicate for each row as true, false, or unknown. Results are
unknown only if an operand is null.
Table 2 lists the type of comparison, the comparison operators, and an example of
how each type of comparison that you can use in a predicate in a WHERE clause.
Table 2. Comparison operators used in conditions
Type of comparison Comparison operator Example
Equal to = DEPTNO = ’X01’
Not equal to <> DEPTNO <> ’X01’
Less than < AVG(SALARY) < 30000
Less than or equal to <= AGE <= 25
Not less than >= AGE >= 21
Greater than > SALARY > 2000
Greater than or equal to >= SALARY >= 5000
Not greater than <= SALARY <= 5000
Equal to null IS NULL PHONENO IS NULL
| Not equal to or one IS DISTINCT FROM PHONENO IS DISTINCT FROM
| value is equal to null :PHONEHV
Similar to another value LIKE NAME LIKE ’%SMITH%’ or STATUS
LIKE ’N_’
At least one of two OR HIREDATE < ’1965-01-01’ OR SALARY
conditions < 16000
Both of two conditions AND HIREDATE < ’1965-01-01’ AND
SALARY < 16000
Between two values BETWEEN SALARY BETWEEN 20000 AND 40000
Equals a value in a set IN (X, Y, Z) DEPTNO IN (’B01’, ’C01’, ’D01’)
Note: SALARY BETWEEN 20000 AND 40000 is equivalent to SALARY >= 20000 AND
SALARY <= 40000. For more information about predicates, see Chapter 2 of DB2 SQL
Reference.
You can also search for rows that do not satisfy one of the preceding conditions by
using the NOT keyword before the specified condition.
| You can search for rows that do not satisfy the IS DISTINCT FROM predicate by
| using either of the following predicates:
| v value IS NOT DISTINCT FROM value
| v NOT(value IS DISTINCT FROM value)
| Both of these forms of the predicate create an expression where one value is equal
| to another value or both values are equal to null.
You can list the rows in ascending or descending order. Null values appear last in
an ascending sort and first in a descending sort.
DB2 sorts strings in the collating sequence associated with the encoding scheme of
the table. DB2 sorts numbers algebraically and sorts datetime values
chronologically.
Example: ORDER BY clause with a column name as the sort key: Retrieve the
employee numbers, last names, and hire dates of employees in department A00 in
ascending order of hire dates:
SELECT EMPNO, LASTNAME, HIREDATE
FROM DSN8810.EMP
WHERE WORKDEPT = ’A00’
ORDER BY HIREDATE ASC;
Example: ORDER BY clause with an expression as the sort key: The following
subselect retrieves the employee numbers, salaries, commissions, and total
compensation (salary plus commission) for employees with a total compensation
greater than 40000. Order the results by total compensation:
SELECT EMPNO, SALARY, COMM, SALARY+COMM AS "TOTAL COMP"
FROM DSN8810.EMP
WHERE SALARY+COMM > 40000
ORDER BY SALARY+COMM;
Example: ORDER BY clause using a derived column name: The following SQL
statement orders the selected information by total salary:
SELECT EMPNO, (SALARY + BONUS + COMM) AS TOTAL_SAL
FROM DSN8810.EMP
ORDER BY TOTAL_SAL;
Except for the columns that are named in the GROUP BY clause, the SELECT
statement must specify any other selected columns as an operand of one of the
aggregate functions.
Example: GROUP BY clause using one column: The following SQL statement
lists, for each department, the lowest and highest education level within that
department:
SELECT WORKDEPT, MIN(EDLEVEL), MAX(EDLEVEL)
FROM DSN8810.EMP
GROUP BY WORKDEPT;
If a column that you specify in the GROUP BY clause contains null values, DB2
considers those null values to be equal. Thus, all nulls form a single group.
When it is used, the GROUP BY clause follows the FROM clause and any WHERE
clause, and precedes the ORDER BY clause.
You can group the rows by the values of more than one column.
Example: GROUP BY clause using more than one column: The following
statement finds the average salary for men and women in departments A00 and
C01:
SELECT WORKDEPT, SEX, AVG(SALARY) AS AVG_SALARY
FROM DSN8810.EMP
WHERE WORKDEPT IN (’A00’, ’C01’)
GROUP BY WORKDEPT, SEX;
DB2 groups the rows first by department number and then (within each department)
by sex before it derives the average SALARY value for each group.
Compare the preceding example with the second example shown in “Summarizing
group values: GROUP BY” on page 11. The clause, HAVING COUNT(*) > 1, ensures
that only departments with more than one member are displayed. In this case,
departments B01 and E01 do not display because the HAVING clause tests a
property of the group.
Example: HAVING clause used with a GROUP BY clause: Use the HAVING
clause to retrieve the average salary and minimum education level of women in
each department for which all female employees have an education level greater
than or equal to 16. Assuming you only want results from departments A00 and
D11, the following SQL statement tests the group property, MIN(EDLEVEL):
SELECT WORKDEPT, AVG(SALARY) AS AVG_SALARY,
MIN(EDLEVEL) AS MIN_EDLEVEL
FROM DSN8810.EMP
WHERE SEX = ’F’ AND WORKDEPT IN (’A00’, ’D11’)
GROUP BY WORKDEPT
HAVING MIN(EDLEVEL) >= 16;
When you specify both GROUP BY and HAVING, the HAVING clause must follow
the GROUP BY clause. A function in a HAVING clause can include DISTINCT if you
have not used DISTINCT anywhere else in the same SELECT statement. You can
also connect multiple predicates in a HAVING clause with AND and OR, and you
can use NOT for any predicate of a search condition.
When you use the UNION statement, the SQLNAME field of the SQLDA contains
the column names of the first operand.
Example: UNION clause: You can obtain a combined list of employee numbers
that includes both of the following:
v People in department D11
v People whose assignments include projects MA2112, MA2113, and AD3111.
The following SQL statement gives a combined result table containing employee
numbers in ascending order with no duplicates listed:
SELECT EMPNO
FROM DSN8810.EMP
WHERE WORKDEPT = ’D11’
UNION
SELECT EMPNO
FROM DSN8810.EMPPROJACT
WHERE PROJNO = ’MA2112’ OR
PROJNO = ’MA2113’ OR
PROJNO = ’AD3111’
ORDER BY EMPNO;
If you have an ORDER BY clause, it must appear after the last SELECT statement
that is part of the union. In this example, the first column of the final result table
determines the final order of the rows.
Example: UNION ALL clause: The following SQL statement gives a combined
result table containing employee numbers in ascending order, and includes
duplicate numbers:
SELECT EMPNO
FROM DSN8810.EMP
WHERE WORKDEPT = ’D11’
UNION ALL
SELECT EMPNO
FROM DSN8810.EMPPROJACT
WHERE PROJNO = ’MA2112’ OR
PROJNO = ’MA2113’ OR
PROJNO = ’AD3111’
ORDER BY EMPNO;
| Each common table expression must have a unique name and be defined only
| once. However, you can reference a common table expression many times in the
| same SQL statement. Unlike regular views or nested table expressions, which
| derive their result tables for each reference, all references to common table
| expressions in a given statement share the same result table.
| You can use a common table expression in a SELECT statement by using the
| WITH clause at the beginning of the statement.
| Example: WITH clause in a SELECT statement: The following statement finds the
| department with the highest total pay. The query involves two levels of aggregation.
| First, you need to determine the total pay for each department by using the SUM
| function and order the results by using the GROUP BY clause. You then need to
| find the department with maximum total pay based on the total pay for each
| department.
| WITH DTOTAL (deptno, totalpay) AS
| (SELECT deptno, sum(salary+bonus)
| FROM DSN8810.EMP
| GROUP BY deptno)
| SELECT deptno
| FROM DTOTAL
| WHERE totalpay = (SELECT max(totalpay)
| FROM DTOTAL);
| The result table for the common table expression, DTOTAL, contains the
| department number and total pay for each department in the employee table. The
| fullselect in the previous example uses the result table for DTOTAL to find the
| department with the highest total pay. The result table for the entire statement looks
| similar to the following results:
| DEPTNO
| ======
| D11
| The fullselect in the previous example uses the result table for DTOTAL to find the
| departments that have a greater than average total pay. The result table is saved as
| the RICH_DEPT view and looks similar to the following results:
| DEPTNO
| ======
| A00
| D11
| D21
| The fullselect in the previous example uses the result table for VITALDEPT to find
| the manager’s number for departments that have a greater than average number of
| senior engineers. The manager’s number is then inserted into the vital_mgr table.
| See Appendix E, “Recursive common table expression examples,” on page 997 for
| examples of bill of materials applications that use recursive common table
| expressions.
Avoiding decimal arithmetic errors: For static SQL statements, the simplest way
to avoid a division error is to override DEC31 rules by specifying the precompiler
option DEC(15). In some cases you can avoid a division error by specifying D31.s.
This specification reduces the probability of errors for statements that are
embedded in the program. s is a number between one and nine and represents the
minimum scale to be used for division operations.
If the dynamic SQL statements have bind, define, or invoke behavior and the value
| of the installation option for USE FOR DYNAMICRULES on panel DSNTIP4 is NO,
you can use the precompiler option DEC(15), DEC15, or D15.s to override DEC31
rules.
For a dynamic statement, or for a single static statement, use the scalar function
DECIMAL to specify values of the precision and scale for a result that causes no
errors.
Before you execute a dynamic statement, set the value of special register
CURRENT PRECISION to DEC15 or D15.s.
Even if you use DEC31 rules, multiplication operations can sometimes cause
overflow because the precision of the product is greater than 31. To avoid overflow
from multiplication of large numbers, use the MULTIPLY_ALT built-in function
instead of the multiplication operator.
The contents of the DB2 system catalog tables can be a useful reference tool when
you begin to develop an SQL statement or an application program.
If your DB2 subsystem uses an exit routine for access control authorization, you
cannot rely on catalog queries to tell you the tables you can access. When such an
exit routine is installed, both RACF and DB2 control table access.
If you display column information about a table that includes LOB or ROWID
columns, the LENGTH field for those columns contains the number of bytes those
column occupy in the base table, rather than the length of the LOB or ROWID data.
To determine the maximum length of data for a LOB or ROWID column, include the
LENGTH2 column in your query, as in the following example:
SELECT NAME, COLTYPE, LENGTH, LENGTH2
FROM SYSIBM.SYSCOLUMNS
WHERE TBNAME = ’EMP_PHOTO_RESUME’
AND TBCREATOR = ’DSN8810’;
You must separate each column description from the next with a comma, and
enclose the entire list of column descriptions in parentheses.
Identifying defaults
If you want to constrain the input or identify the default of a column, you can use
the following values:
v NOT NULL, when the column cannot contain null values.
Each example shown in this chapter assumes that you logged on using your own
authorization ID. The authorization ID qualifies the name of each object you create.
For example, if your authorization ID is SMITH, and you create table YDEPT, the
name of the table is SMITH.YDEPT. If you want to access table DSN8810.DEPT,
you must refer to it by its complete name. If you want to access your own table
YDEPT, you need only to refer to it as YDEPT.
If you want DEPTNO to be a primary key, as in the sample table, explicitly define
the key. Use an ALTER TABLE statement, as in the following example:
ALTER TABLE YDEPT
PRIMARY KEY(DEPTNO);
You can use an INSERT statement to copy the rows of the result table of a
fullselect from one table to another. The following statement copies all of the rows
from DSN8810.DEPT to your own YDEPT work table.
INSERT INTO YDEPT
SELECT *
FROM DSN8810.DEPT;
This statement also creates a referential constraint between the foreign key in
YEMP (WORKDEPT) and the primary key in YDEPT (DEPTNO). It also restricts all
phone numbers to unique numbers.
If you want to change a table definition after you create it, use the statement ALTER
TABLE. If you want to change a table name after you create it, use the statement
RENAME TABLE.
| You can change a table definition by using the ALTER TABLE statement only in
| certain ways. For example, you can add and drop constraints on columns in a table.
| You can also change the data type of a column within character data types, within
| numeric data types, and within graphic data types. You can add a column to a
| table. However, you cannot drop a column from a table.
| For more information about changing a table definition by using ALTER TABLE, see
| Part 2 (Volume 1) of DB2 Administration Guide. For other details about the ALTER
| TABLE and RENAME TABLE statements, see Chapter 5 of DB2 SQL Reference.
Temporary tables are especially useful when you need to sort or query intermediate
result tables that contain a large number of rows, but you want to store only a small
subset of those rows permanently.
Example: You can also create this same definition by copying the definition of a
base table using the LIKE clause:
CREATE GLOBAL TEMPORARY TABLE TEMPPROD LIKE PROD;
The SQL statements in the previous examples create identical definitions, even
though table PROD contains two columns, DESCRIPTION and CURDATE, that are
defined as NOT NULL WITH DEFAULT. Unlike the PROD sample table, the
DESCRIPTION and CURDATE columns in the TEMPPROD table are defined as
NOT NULL and do not have defaults, because created temporary tables do not
support non-null default values.
After you run one of the two CREATE statements, the definition of TEMPPROD
exists, but no instances of the table exist. To drop the definition of TEMPPROD, you
must run the following statement:
DROP TABLE TEMPPROD;
An instance of a created temporary table exists at the current server until one of the
following actions occurs:
v The application process ends.
v The remote server connection through which the instance was created
terminates.
v The unit of work in which the instance was created completes.
When you run a ROLLBACK statement, DB2 deletes the instance of the created
temporary table. When you run a COMMIT statement, DB2 deletes the instance
of the created temporary table unless a cursor for accessing the created
temporary table is defined WITH HOLD and is open.
When you run the INSERT statement, DB2 creates an instance of TEMPPROD and
populates that instance with rows from table PROD. When the COMMIT statement
is run, DB2 deletes all rows from TEMPPROD. However, assume that you change
the declaration of cursor C1 to the following declaration:
EXEC SQL DECLARE C1 CURSOR WITH HOLD
FOR SELECT * FROM TEMPPROD;
In this case, DB2 does not delete the contents of TEMPPROD until the application
ends because C1, a cursor defined WITH HOLD, is open when the COMMIT
statement is run. In either case, DB2 drops the instance of TEMPPROD when the
application ends.
Before you can define declared temporary tables, you must create a special
database and table spaces for them. You do that by running the CREATE
DATABASE statement with the AS TEMP clause, and then creating segmented
table spaces in that database. A DB2 subsystem can have only one database for
declared temporary tables, but that database can contain more than one table
| space. There must be at least one table space with a 8-KB page size in the TEMP
| database to declare a temporary table.
Example: The following statements create a database and table space for declared
temporary tables:
CREATE DATABASE DTTDB AS TEMP;
CREATE TABLESPACE DTTTS IN DTTDB
SEGSIZE 4;
You can define a declared temporary table in any of the following ways:
v Specify all the columns in the table.
Unlike columns of created temporary tables, columns of declared temporary
tables can include the WITH DEFAULT clause.
v Use a LIKE clause to copy the definition of a base table, created temporary
table, or view.
If the base table or created temporary table that you copy has identity columns,
you can specify that the corresponding columns in the declared temporary table
are also identity columns. Do that by specifying the INCLUDING IDENTITY
COLUMN ATTRIBUTES clause when you define the declared temporary table.
v Use a fullselect to choose specific columns from a base table, created temporary
table, or view.
After you run a DECLARE GLOBAL TEMPORARY TABLE statement, the definition
of the declared temporary table exists as long as the application process runs. If
you need to delete the definition before the application process completes, you can
do that with the DROP TABLE statement. For example, to drop the definition of
TEMPPROD, run the following statement:
DROP TABLE SESSION.TEMPPROD;
DB2 creates an empty instance of a declared temporary table when it runs the
DECLARE GLOBAL TEMPORARY TABLE statement. You can populate the
declared temporary table using INSERT statements, modify the table using
searched or positioned UPDATE or DELETE statements, and query the table using
SELECT statements. You can also create indexes on the declared temporary table.
The ON COMMIT clause that you specify in the DECLARE GLOBAL TEMPORARY
TABLE statement determines whether DB2 keeps or deletes all the rows from the
table when you run a COMMIT statement in an application with a declared
temporary table. ON COMMIT DELETE ROWS, which is the default, causes all
Example: Suppose that you run the following statement in an application program:
EXEC SQL DECLARE GLOBAL TEMPORARY TABLE TEMPPROD
AS (SELECT * FROM BASEPROD)
DEFINITION ONLY
INCLUDING IDENTITY COLUMN ATTRIBUTES
INCLUDING COLUMN DEFAULTS
ON COMMIT PRESERVE ROWS;
EXEC
. SQL INSERT INTO SESSION.TEMPPROD SELECT * FROM BASEPROD;
.
.
EXEC
. SQL COMMIT;
.
.
Use the DROP TABLE statement with care: Dropping a table is NOT equivalent
to deleting all its rows. When you drop a table, you lose more than its data and its
definition. You lose all synonyms, views, indexes, and referential and check
constraints associated with that table. You also lose all authorities granted on the
table.
For more information about the DROP statement, see Chapter 5 of DB2 SQL
Reference.
Use the CREATE VIEW statement to define a view and give the view a name, just
as you do for a table. The view created with the following statement shows each
department manager’s name with the department data in the DSN8810.DEPT table.
CREATE VIEW VDEPTM AS
SELECT DEPTNO, MGRNO, LASTNAME, ADMRDEPT
FROM DSN8810.DEPT, DSN8810.EMP
WHERE DSN8810.EMP.EMPNO = DSN8810.DEPT.MGRNO;
When you create a view, you can reference the USER and CURRENT SQLID
special registers in the CREATE VIEW statement. When referencing the view, DB2
uses the value of the USER or CURRENT SQLID that belongs to the user of the
SQL statement (SELECT, UPDATE, INSERT, or DELETE) rather than the creator of
the view. In other words, a reference to a special register in a view definition refers
to its run-time value.
You can use views to limit access to certain kinds of data, such as salary
information. You can also use views for the following actions:
v Make a subset of a table’s data available to an application. For example, a view
based on the employee table might contain rows only for a particular department.
v Combine columns from two or more tables and make the combined data
available to an application. By using a SELECT statement that matches values in
one table with those in another table, you can create a view that presents data
from both tables. However, you can only select data from this type of view. You
cannot update, delete, or insert data using a view that joins two or more
tables.
v Combine rows from two or more tables and make the combined data available to
an application. By using two or more subselects that are connected by UNION or
UNION ALL operators, you can create a view that presents data from several
tables. However, you can only select data from this type of view. You cannot
update, delete, or insert data using a view that contains UNION operations.
v Present computed data, and make the resulting data available to an application.
You can compute such data using any function or operation that you can use in a
SELECT statement.
In each case, for every row you insert, you must provide a value for any column
that does not have a default value. For a column that meets one of the following
conditions, you can specify DEFAULT to tell DB2 to insert the default value for that
column:
v Is nullable.
v Is defined with a default value.
v Has data type ROWID. ROWID columns always have default values.
v Is an identity column. Identity columns always have default values.
The values that you can insert into a ROWID column or an identity column depend
on whether the column is defined with GENERATED ALWAYS or GENERATED BY
DEFAULT. See “Inserting data into a ROWID column” on page 30 and “Inserting
data into an identity column” on page 30 for more information.
Recommendation: For static INSERT statements, name all of the columns for
which you are providing values for because of the following reasons:
v Your INSERT statement is independent of the table format. (For example, you do
not need to change the statement when a column is added to the table.)
v You can verify that you are giving the values in order.
v Your source statements are more self-descriptive.
If you do not name the columns in a static INSERT statement, and a column is
added to the table, an error can occur if the INSERT statement is rebound. An error
will occur after any rebind of the INSERT statement unless you change the INSERT
statement to include a value for the new column. This is true even if the new
column has a default value.
When you list the column names, you must specify their corresponding values in
the same order as in the list of column names.
Example: The following statement inserts information about a new department into
the YDEPT table.
INSERT INTO YDEPT (DEPTNO, DEPTNAME, MGRNO, ADMRDEPT, LOCATION)
VALUES (’E31’, ’DOCUMENTATION’, ’000010’, ’E01’, ’ ’);
After inserting a new department row into your YDEPT table, you can use a
SELECT statement to see what you have loaded into the table. The following SQL
statement shows you all the new department rows that you have inserted:
SELECT *
FROM YDEPT
WHERE DEPTNO LIKE ’E%’
ORDER BY DEPTNO;
Example: The following statement inserts information about a new employee into
the YEMP table. Because YEMP has a foreign key, WORKDEPT, referencing the
primary key, DEPTNO, in YDEPT, the value inserted for WORKDEPT (E31) must be
a value of DEPTNO in YDEPT or null.
INSERT INTO YEMP
VALUES (’000400’, ’RUTHERFORD’, ’B’, ’HAYES’, ’E31’, ’5678’, ’1983-01-01’,
’MANAGER’, 16, ’M’, ’1943-07-10’, 24000, 500, 1900);
Example: The following statement also inserts a row into the YEMP table. Because
the unspecified columns allow nulls, DB2 inserts null values into the columns that
you do not specify. Because YEMP has a foreign key, WORKDEPT, referencing the
primary key, DEPTNO, in YDEPT, the value inserted for WORKDEPT (D11) must be
a value of DEPTNO in YDEPT or null.
The following statement copies data from DSN8810.EMP into the newly created
table:
INSERT INTO TELE
SELECT LASTNAME, FIRSTNME, PHONENO
FROM DSN8810.EMP
WHERE WORKDEPT = ’D21’;
The two previous statements create and fill a table, TELE, that looks similar to the
following table:
NAME2 NAME1 PHONE
=============== ============ =====
PULASKI EVA 7831
JEFFERSON JAMES 2094
MARINO SALVATORE 3780
SMITH DANIEL 0961
JOHNSON SYBIL 8953
PEREZ MARIA 9001
MONTEVERDE ROBERT 3780
The CREATE TABLE statement example creates a table which, at first, is empty.
The table has columns for last names, first names, and phone numbers, but does
not have any rows.
The INSERT statement fills the newly created table with data selected from the
DSN8810.EMP table: the names and phone numbers of employees in department
D21.
Before you insert data into a ROWID column, you must know how the ROWID
column is defined. ROWID columns can be defined as GENERATED ALWAYS or
GENERATED BY DEFAULT. GENERATED ALWAYS means that DB2 generates a
value for the column, and you cannot insert data into that column. If the column is
defined as GENERATED BY DEFAULT, you can insert a value, and DB2 provides a
default value if you do not supply one.
Example: Suppose that tables T1 and T2 have two columns: an integer column and
a ROWID column. For the following statement to run successfully, ROWIDCOL2
must be defined as GENERATED BY DEFAULT.
INSERT INTO T2 (INTCOL2,ROWIDCOL2)
SELECT * FROM T1;
Before you insert data into an identity column, you must know how the column is
defined. Identity columns are defined with the GENERATED ALWAYS or
GENERATED BY DEFAULT clause. GENERATED ALWAYS means that DB2
generates a value for the column, and you cannot insert data into that column. If
Example: Suppose that tables T1 and T2 have two columns: a character column
and an integer column that is defined as an identity column. For the following
statement to run successfully, IDENTCOL2 must be defined as GENERATED BY
DEFAULT.
INSERT INTO T2 (CHARCOL2,IDENTCOL2)
SELECT * FROM T1;
| Example: In addition to examples that use the DB2 sample tables, the examples in
| this section use an EMPSAMP table that has the following definition:
| CREATE TABLE EMPSAMP
| (EMPNO INTEGER GENERATED ALWAYS AS IDENTITY,
| NAME CHAR(30),
| SALARY DECIMAL(10,2),
| DEPTNO SMALLINT,
| LEVEL CHAR(30),
| HIRETYPE VARCHAR(30) NOT NULL WITH DEFAULT ’New Hire’,
| HIREDATE DATE NOT NULL WITH DEFAULT);
| Assume that you need to insert a row for a new employee into the EMPSAMP
| table. To find out the values for the generated EMPNO, HIRETYPE, and HIREDATE
| columns, use the following SELECT from INSERT statement:
| SELECT EMPNO, HIRETYPE, HIREDATE
| FROM FINAL TABLE (INSERT INTO EMPSAMP (NAME, SALARY, DEPTNO, LEVEL)
| VALUES(’Mary Smith’, 35000.00, 11, ’Associate’));
| The SELECT statement returns the DB2-generated identity value for the EMPNO
| column, the default value ’New Hire’ for the HIRETYPE column, and the value of
| the CURRENT DATE special register for the HIREDATE column.
| The INSERT statement in the FROM clause of the following SELECT statement
| inserts a new employee into the EMPSAMP table:
| SELECT NAME, SALARY
| FROM FINAL TABLE (INSERT INTO EMPSAMP (NAME, SALARY, LEVEL)
| VALUES(’Mary Smith’, 35000.00, ’Associate’));
| The SELECT statement returns a salary of 40000.00 for Mary Smith instead of the
| initial salary of 35000.00 that was explicitly specified in the INSERT statement.
| Example: You can retrieve all the values for a row that is inserted into a structure:
| EXEC SQL SELECT * INTO :empstruct
| FROM FINAL TABLE (INSERT INTO EMPSAMP (NAME, SALARY, DEPTNO, LEVEL)
| VALUES(’Mary Smith’, 35000.00, 11, ’Associate’));
| For this example, :empstruct is a host variable structure that is declared with
| variables for each of the columns in the EMPSAMP table.
| The value 12 satisfies the search condition of the view definition, and the result
| table consists of the value for C1 in the inserted row.
| If you use a value that does not satisfy the search condition of the view definition,
| the insert operation fails, and DB2 returns an error.
| Example: Inserting rows with ROWID values: To see the values of the ROWID
| columns that are inserted into the employee photo and resume table, you can
| declare the following cursor:
| EXEC SQL DECLARE CS1 CURSOR FOR
| SELECT EMP_ROWID
| FROM FINAL TABLE (INSERT INTO DSN8810.EMP_PHOTO_RESUME (EMPNO)
| SELECT EMPNO FROM DSN8810.EMP);
| Example: Using the FETCH FIRST clause: To see only the first five rows that are
| inserted into the employee photo and resume table, use the FETCH FIRST clause:
| EXEC SQL DECLARE CS2 CURSOR FOR
| SELECT EMP_ROWID
| FROM FINAL TABLE (INSERT INTO DSN8810.EMP_PHOTO_RESUME (EMPNO)
| SELECT EMPNO FROM DSN8810.EMP)
| FETCH FIRST 5 ROWS ONLY;
| Example: Using the INPUT SEQUENCE clause: To retrieve rows in the order in
| which they are inserted, use the INPUT SEQUENCE clause:
| EXEC SQL DECLARE CS3 CURSOR FOR
| SELECT EMP_ROWID
| FROM FINAL TABLE (INSERT INTO DSN8810.EMP_PHOTO_RESUME (EMPNO)
| VALUES(:hva_empno)
| FOR 5 ROWS)
| ORDER BY INPUT SEQUENCE;
| Effect on cursor sensitivity: When you declare a scrollable cursor, the cursor
| must be declared with the INSENSITIVE keyword if an INSERT statement is in the
| FROM clause of the cursor specification. The result table is generated during OPEN
| cursor processing and does not reflect any future changes. You cannot declare the
| cursor with the SENSITIVE DYNAMIC or SENSITIVE STATIC keywords. For
| information about cursor sensitivity, see “Using a scrollable cursor” on page 104.
| Example: Assume that your application declares a cursor, opens the cursor,
| performs a fetch, updates the table, and then fetches additional rows:
| EXEC SQL DECLARE CS1 CURSOR FOR
| SELECT SALARY
| FROM FINAL TABLE (INSERT INTO EMPSAMP (NAME, SALARY, LEVEL)
| SELECT NAME, INCOME, BAND FROM OLD_EMPLOYEE);
| EXEC SQL OPEN CS1;
| EXEC SQL FETCH CS1 INTO :hv_salary;
| /* print fetch result */
| ...
| EXEC SQL UPDATE EMPSAMP SET SALARY = SALARY + 500;
| while (SQLCODE == 0) {
| EXEC SQL FETCH CS1 INTO :hv_salary;
| /* print fetch result */
| ...
| }
| The fetches that occur after the update processing return the rows that were
| generated during OPEN cursor processing. However, if you use a simple SELECT
| (with no INSERT statement in the FROM clause), the fetches might return the
| updated values, depending on the access path that DB2 uses.
| Effect of WITH HOLD: When you declare a cursor with the WITH HOLD option,
| and open the cursor, all of the rows are inserted into the target table. The WITH
| HOLD option has no effect on the SELECT from INSERT statement of the cursor
| definition. After your application performs a commit, you can continue to retrieve all
| of the inserted rows. For information about held cursors, see “Held and non-held
| cursors” on page 112.
| Example: Assume that the employee table in the DB2 sample application has five
| rows. Your application declares a WITH HOLD cursor, opens the cursor, fetches two
| rows, performs a commit, and then fetches the third row successfully:
| Example: Assume that your application declares a cursor, sets a savepoint, opens
| the cursor, sets another savepoint, rolls back to the second savepoint, and then
| rolls back to the first savepoint:
| EXEC SQL DECLARE CS3 CURSOR FOR
| SELECT EMP_ROWID
| FROM FINAL TABLE (INSERT INTO DSN8810.EMP_PHOTO_RESUME (EMPNO)
| SELECT EMPNO FROM DSN8810.EMP);
| EXEC SQL SAVEPOINT A ON ROLLBACK RETAIN CURSORS; /* Sets 1st savepoint */
| EXEC SQL OPEN CS3;
| EXEC SQL SAVEPOINT B ON ROLLBACK RETAIN CURSORS; /* Sets 2nd savepoint */
| ...
| EXEC SQL ROLLBACK TO SAVEPOINT B; /* Rows still in DSN8810.EMP_PHOTO_RESUME */
| ...
| EXEC SQL ROLLBACK TO SAVEPOINT A; /* All inserted rows are undone */
| Example: Assume that the employee table of the DB2 sample application has one
| row, and that the SALARY column has a value of 9 999 000.00.
| EXEC SQL SELECT EMPNO INTO :hv_empno
| FROM FINAL TABLE (INSERT INTO EMPSAMP (NAME, SALARY)
| SELECT FIRSTNAME || MIDINIT || LASTNAME,
| SALARY + 10000.00
| FROM DSN8810.EMP)
| The addition of 10000.00 causes a decimal overflow to occur, and no rows are
| inserted into the EMPSAMP table.
| During OPEN cursor processing: If the insertion of any row fails during the
| OPEN cursor processing, all previously successful insertions are undone. The result
| table of the INSERT is empty.
| During FETCH processing: If the FETCH statement fails while retrieving rows
| from the result table of the insert operation, a negative SQLCODE is returned to the
| application, but the result table still contains the original number of rows that was
| determined during the OPEN cursor processing. At this point, you can undo all of
| the inserts.
You cannot update rows in a created temporary table, but you can update rows in a
declared temporary table.
The SET clause names the columns that you want to update and provides the
values you want to assign to those columns. You can replace a column value in the
SET clause with any of the following items:
v A null value
The column to which you assign the null value must not be defined as NOT
NULL.
v An expression
An expression can be any of the following items:
– A column
– A constant
– A fullselect that returns a scalar
– A host variable
– A special register
In addition, you can replace one or more column values in the SET clause with the
column values in a row that is returned by a fullselect.
If you omit the WHERE clause, DB2 updates every row in the table or view with
the values you supply.
Example: The following statement supplies a missing middle initial and changes the
job for employee 000200.
UPDATE YEMP
SET MIDINIT = ’H’, JOB = ’FIELDREP’
WHERE EMPNO = ’000200’;
The following statement gives everyone in department D11 a raise of 400.00. The
statement can update several rows.
UPDATE YEMP
SET SALARY = SALARY + 400.00
WHERE WORKDEPT = ’D11’;
The following statement sets the salary and bonus for employee 000190 to the
average salary and minimum bonus for all employees.
UPDATE YEMP
SET (SALARY, BONUS) =
(SELECT AVG(SALARY), MIN(BONUS)
FROM EMP)
WHERE EMPNO = ’000190’;
You can use DELETE to remove all rows from a created temporary table or
declared temporary table. However, you can use DELETE with a WHERE clause to
remove only selected rows from a declared temporary table.
This DELETE statement deletes each row in the YEMP table that has an employee
number 000060.
DELETE FROM YEMP
WHERE EMPNO = ’000060’;
When this statement executes, DB2 deletes any row from the YEMP table that
meets the search condition.
If DB2 finds an error while executing your DELETE statement, it stops deleting data
and returns error codes in the SQLCODE and SQLSTATE host variables or related
fields in the SQLCA. The data in the table does not change.
If the statement executes, the table continues to exist (that is, you can insert rows
into it), but it is empty. All existing views and authorizations on the table remain
intact when using DELETE. By comparison, using DROP TABLE drops all views
and authorizations, which can invalidate plans and packages. For information about
the DROP statement, see “Dropping tables: DROP TABLE” on page 25.
DB2 supports the following types of joins: inner join, left outer join, right outer join,
and full outer join. You can specify joins in the FROM clause of a query.
The examples in this section use the following two tables to show various types of
joins:
The PARTS table The PRODUCTS table
PART PROD# SUPPLIER PROD# PRODUCT PRICE
======= ===== ============ ===== =========== =====
WIRE 10 ACWF 505 SCREWDRIVER 3.70
OIL 160 WESTERN_CHEM 30 RELAY 7.55
MAGNETS 10 BATEMAN 205 SAW 18.90
PLASTIC 30 PLASTIK_CORP 10 GENERATOR 45.75
BLADES 205 ACE_STEEL
Figure 2 illustrates how these two tables can be combined using the three outer join
functions.
Figure 2. Three outer joins from the PARTS and PRODUCTS tables
The result table contains data joined from all of the tables, for rows that satisfy the
search conditions.
The result columns of a join have names if the outermost SELECT list refers to
base columns. But, if you use a function (such as COALESCE or VALUE) to build a
column of the result, that column does not have a name unless you use the AS
clause in the SELECT list.
Example: You can join the PARTS and PRODUCTS tables on the PROD# column
to get a table of parts with their suppliers and the products that use the parts.
To do this, you can use either one of the following SELECT statements:
SELECT PART, SUPPLIER, PARTS.PROD#, PRODUCT
FROM PARTS, PRODUCTS
WHERE PARTS.PROD# = PRODUCTS.PROD#;
SELECT PART, SUPPLIER, PARTS.PROD#, PRODUCT
FROM PARTS INNER JOIN PRODUCTS
ON PARTS.PROD# = PRODUCTS.PROD#;
In either case, the number of rows in the result table is the product of the number
of rows in each table.
You can specify more complicated join conditions to obtain different sets of results.
For example, to eliminate the suppliers that begin with the letter A from the table of
parts, suppliers, product numbers and products, write a query like the following
query:
The result of the query is all rows that do not have a supplier that begins with A.
The result table looks like the following output:
PART SUPPLIER PROD# PRODUCT
======= ============ ===== ==========
MAGNETS BATEMAN 10 GENERATOR
PLASTIC PLASTIK_CORP 30 RELAY
The following SQL statement joins table DSN8810.PROJ to itself and returns the
number and name of each major project followed by the number and name of the
project that is part of it:
SELECT A.PROJNO, A.PROJNAME, B.PROJNO, B.PROJNAME
FROM DSN8810.PROJ A, DSN8810.PROJ B
WHERE A.PROJNO = B.MAJPROJ;
In this example, the comma in the FROM clause implicitly specifies an inner join,
and it acts the same as if the INNER JOIN keywords had been used. When you
use the comma for an inner join, you must specify the join condition on the WHERE
clause. When you use the INNER JOIN keywords, you must specify the join
condition on the ON clause.
The join condition for a full outer join must be a simple search condition that
compares two columns or an invocation of a cast function that has a column name
as its argument.
Example: The following query performs a full outer join of the PARTS and
PRODUCTS tables:
SELECT PART, SUPPLIER, PARTS.PROD#, PRODUCT
FROM PARTS FULL OUTER JOIN PRODUCTS
ON PARTS.PROD# = PRODUCTS.PROD#;
The result table from the query looks similar to the following output:
The product number in the result of the example for “Full outer join” on page 41 is
null for SCREWDRIVER, even though the PRODUCTS table contains a product
number for SCREWDRIVER. If you select PRODUCTS.PROD# instead, PROD# is
null for OIL. If you select both PRODUCTS.PROD# and PARTS.PROD#, the result
contains two columns, both of which contain some null values. You can merge data
from both columns into a single column, eliminating the null values, by using the
COALESCE function.
With the same PARTS and PRODUCTS tables, the following example merges the
non-null data from the PROD# columns:
SELECT PART, SUPPLIER,
COALESCE(PARTS.PROD#, PRODUCTS.PROD#) AS PRODNUM, PRODUCT
FROM PARTS FULL OUTER JOIN PRODUCTS
ON PARTS.PROD# = PRODUCTS.PROD#;
The AS clause (AS PRODNUM) provides a name for the result of the COALESCE
function.
As in an inner join, the join condition can be any simple or compound search
condition that does not contain a subquery reference.
Example: To include rows from the PARTS table that have no matching values in
the PRODUCTS table, and to include prices that exceed $10.00 , run the following
query:
SELECT PART, SUPPLIER, PARTS.PROD#, PRODUCT, PRICE
FROM PARTS LEFT OUTER JOIN PRODUCTS
ON PARTS.PROD#=PRODUCTS.PROD#
AND PRODUCTS.PRICE>10.00;
A row from the PRODUCTS table is in the result table only if its product number
matches the product number of a row in the PARTS table and the price is greater
than $10.00 for that row. Rows in which the PRICE value does not exceed $10.00
are included in the result of the join, but the PRICE value is set to null.
In this result table, the row for PROD# 30 has null values on the right two columns
because the price of PROD# 30 is less than $10.00. PROD# 160 has null values on
the right two columns because PROD# 160 does not match another product
number.
As in an inner join, the join condition can be any simple or compound search
condition that does not contain a subquery reference.
Example: To include rows from the PRODUCTS table that have no corresponding
rows in the PARTS table, execute this query:
SELECT PART, SUPPLIER, PRODUCTS.PROD#, PRODUCT, PRICE
FROM PARTS RIGHT OUTER JOIN PRODUCTS
ON PARTS.PROD# = PRODUCTS.PROD#
AND PRODUCTS.PRICE>10.00;
A row from the PARTS table is in the result table only if its product number matches
the product number of a row in the PRODUCTS table and the price is greater than
10.00 for that row.
Because the PRODUCTS table can have rows with nonmatching product numbers
in the result table, and the PRICE column is in the PRODUCTS table, rows in which
PRICE is less than or equal to 10.00 are included in the result. The PARTS
columns contain null values for these rows in the result table.
A join operation is part of a FROM clause; therefore, for the purpose of predicting
which rows will be returned from a SELECT statement containing a join operation,
assume that the join operation is performed first.
Example: Suppose that you want to obtain a list of part names, supplier names,
product numbers, and product names from the PARTS and PRODUCTS tables. You
want to include rows from either table where the PROD# value does not match a
PROD# value in the other table, which means that you need to do a full outer join.
You also want to exclude rows for product number 10. Consider the following
SELECT statement:
SELECT PART, SUPPLIER,
VALUE(PARTS.PROD#,PRODUCTS.PROD#) AS PRODNUM, PRODUCT
FROM PARTS FULL OUTER JOIN PRODUCTS
ON PARTS.PROD# = PRODUCTS.PROD#
WHERE PARTS.PROD# <> ’10’ AND PRODUCTS.PROD# <> ’10’;
DB2 performs the join operation first. The result of the join operation includes rows
from one table that do not have corresponding rows from the other table. However,
the WHERE clause then excludes the rows from both tables that have null values
for the PROD# column.
For this statement, DB2 applies the WHERE clause to each table separately. DB2
then performs the full outer join operation, which includes rows in one table that do
not have a corresponding row in the other table. The final result includes rows with
the null value for the PROD# column and looks similar to the following output:
PART SUPPLIER PRODNUM PRODUCT
======= ============ ======= ===========
OIL WESTERN_CHEM 160 -----------
BLADES ACE_STEEL 205 SAW
PLASTIC PLASTIK_CORP 30 RELAY
------- ------------ 505 SCREWDRIVER
DB2 determines the intermediate and final results of the previous query by
performing the following logical steps:
1. Join the employee and project tables on the employee number, dropping the
rows with no matching employee number in the project table.
2. Join the intermediate result table with the department table on matching
department numbers.
3. Process the select list in the final result table, leaving only four columns.
Using more than one join type: You can use more than one join type in the
FROM clause. Suppose that you want a result table that shows employees whose
last name begins with ’S’ or a letter after ’S’, their department names, and the
projects that they are responsible for, if any. You can use the following SELECT
statement:
SELECT EMPNO, LASTNAME, DEPTNAME, PROJNO
FROM DSN8810.EMP INNER JOIN DSN8810.DEPT
ON WORKDEPT = DSN8810.DEPT.DEPTNO
LEFT OUTER JOIN DSN8810.PROJ
ON EMPNO = RESPEMP
WHERE LASTNAME > ’S’;
DB2 determines the intermediate and final results of the previous query by
performing the following logical steps:
1. Join the employee and department tables on matching department numbers,
dropping the rows where the last name begins with a letter before ’S’.
2. Join the intermediate result table with the project table on the employee number,
keeping the rows with no matching employee number in the project table.
3. Process the select list in the final result table, leaving only four columns.
The correlated references are valid because they do not occur in the table
expression where CHEAP_PARTS is defined. The correlated references are from a
table specification at a higher level in the hierarchy of subqueries.
Example of using a nested table expression as the left operand of a join: The
following query contains a fullselect as the left operand of a left outer join with the
PRODUCTS table. The correlation name is PARTX.
SELECT PART, SUPPLIER, PRODNUM, PRODUCT
FROM (SELECT PART, PROD# AS PRODNUM, SUPPLIER
FROM PARTS
WHERE PROD# < ’200’) AS PARTX
LEFT OUTER JOIN PRODUCTS
ON PRODNUM = PROD#;
Example: Using a table function as an operand of a join: You can join the
results of a user-defined table function with a table, just as you can join two tables.
For example, suppose CVTPRICE is a table function that converts the prices in the
PRODUCTS table to the currency you specify and returns the PRODUCTS table
with the prices in those units. You can obtain a table of parts, suppliers, and product
prices with the prices in your choice of currency by executing a query similar to the
following query:
SELECT PART, SUPPLIER, PARTS.PROD#, Z.PRODUCT, Z.PRICE
FROM PARTS, TABLE(CVTPRICE(:CURRENCY)) AS Z
WHERE PARTS.PROD# = Z.PROD#;
Example: In this example, the correlated reference T.C2 is valid because the table
specification, to which it refers, T, is to its left.
SELECT T.C1, Z.C5
FROM T, TABLE(TF3(T.C2)) AS Z
WHERE T.C3 = Z.C4;
If you specify the join in the opposite order, with T following TABLE(TF3(T.C2), then
T.C2 is invalid.
Example: In this example, the correlated reference D.DEPTNO is valid because the
nested table expression within which it appears is preceded by TABLE and the table
specification D appears to the left of the nested table expression in the FROM
clause.
SELECT D.DEPTNO, D.DEPTNAME,
EMPINFO.AVGSAL, EMPINFO.EMPCOUNT
FROM DEPT D,
TABLE(SELECT AVG(E.SALARY) AS AVGSAL,
COUNT(*) AS EMPCOUNT
FROM EMP E
WHERE E.WORKDEPT=D.DEPTNO) AS EMPINFO;
Conceptual overview
Suppose that you want a list of the employee numbers, names, and commissions of
all employees working on a particular project, whose project number is MA2111.
The first part of the SELECT statement is easy to write:
SELECT EMPNO, LASTNAME, COMM
FROM DSN8810.EMP
WHERE EMPNO
.
.
.
But you cannot proceed because the DSN8810.EMP table does not include project
number data. You do not know which employees are working on project MA2111
without issuing another SELECT statement against the DSN8810.EMPPROJACT
table.
To better understand the results of this SQL statement, imagine that DB2 goes
through the following process:
1. DB2 evaluates the subquery to obtain a list of EMPNO values:
(SELECT EMPNO
FROM DSN8810.EMPPROJACT
WHERE PROJNO = ’MA2111’);
The result is in an interim result table, similar to the one shown in the following
output:
from EMPNO
=====
200
200
220
2. The interim result table then serves as a list in the search condition of the outer
SELECT. Effectively, DB2 executes this statement:
SELECT EMPNO, LASTNAME, COMM
FROM DSN8810.EMP
WHERE EMPNO IN
(’000200’, ’000220’);
This kind of subquery is uncorrelated. In the previous query, for example, the
content of the subquery is the same for every row of the table DSN8810.EMP.
Subqueries that vary in content from row to row or group to group are correlated
subqueries. For information about correlated subqueries, see “Using correlated
subqueries” on page 53. All of the following information that precedes the section
about correlated subqueries applies to both correlated and uncorrelated subqueries.
Subqueries can also appear in the predicates of other subqueries. Such subqueries
are nested subqueries at some level of nesting. For example, a subquery within a
subquery within an outer SELECT has a nesting level of 2. DB2 allows nesting
down to a level of 15, but few queries require a nesting level greater than 1.
The relationship of a subquery to its outer SELECT is the same as the relationship
of a nested subquery to a subquery, and the same rules apply, except where
otherwise noted.
Basic predicate
You can use a subquery immediately after any of the comparison operators. If you
do, the subquery can return at most one value. DB2 compares that value with the
value to the left of the comparison operator.
Example: The following SQL statement returns the employee numbers, names, and
salaries for employees whose education level is higher than the average
company-wide education level.
SELECT EMPNO, LASTNAME, SALARY
FROM DSN8810.EMP
WHERE EDLEVEL >
(SELECT AVG(EDLEVEL)
FROM DSN8810.EMP);
If a subquery that returns one or more null values gives you unexpected results,
see the description of quantified predicates in Chapter 2 of DB2 SQL Reference.
To satisfy this WHERE clause, the column value must be greater than all of the
values that the subquery returns. A subquery that returns an empty result table
satisfies the predicate.
Now suppose that you use the <> operator with ALL in a WHERE clause like this:
WHERE (column1, column1, ... columnn) <> ALL (subquery)
To satisfy this WHERE clause, each column value must be unequal to all of the
values in the corresponding column of the result table that the subquery returns. A
subquery that returns an empty result table satisfies the predicate.
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) that the subquery
returns. A subquery that returns an empty result table does not satisfy the predicate.
Now suppose that you use the = operator with SOME in a WHERE clause like this:
WHERE (column1, column1, ... columnn) = SOME (subquery)
To satisfy this WHERE clause, each column value must be equal to at least one of
the values in the corresponding column of the result table that the subquery returns.
A subquery that returns an empty result table does not satisfy the predicate.
IN keyword
You can use IN to say that the value or values on the left side of the IN operator
must be among the values that are returned by the subquery. Using IN is equivalent
to using = ANY or = SOME.
EXISTS keyword
In the subqueries presented thus far, DB2 evaluates the subquery and uses the
result as part of the WHERE clause of the outer SELECT. In contrast, when you
use the keyword EXISTS, DB2 simply checks whether the subquery returns one or
more rows. Returning one or more rows satisfies the condition; returning no rows
does not satisfy the condition.
Example: The search condition in the following query is satisfied if any project that
is represented in the project table has an estimated start date that is later than 1
January 2005:
The result of the subquery is always the same for every row that is examined for
the outer SELECT. Therefore, either every row appears in the result of the outer
SELECT or none appears. A correlated subquery is more powerful than the
uncorrelated subquery that is used in this example because the result of a
correlated subquery is evaluated for each row of the outer SELECT.
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 can 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 can code the following clause:
WHERE NOT EXISTS (SELECT ...);
For this example, you need to use a correlated subquery, which differs from an
uncorrelated subquery. An uncorrelated subquery compares the employee’s
education level to the average of the entire company, which requires looking at the
entire table. A correlated subquery evaluates only the department that corresponds
to the particular employee.
In the subquery, you tell DB2 to compute the average education level for the
department number in the current row. A query that does this follows:
SELECT EMPNO, LASTNAME, WORKDEPT, EDLEVEL
FROM DSN8810.EMP X
WHERE EDLEVEL >
(SELECT AVG(EDLEVEL)
FROM DSN8810.EMP
WHERE WORKDEPT = X.WORKDEPT);
Consider what happens when the subquery executes for a given row of
DSN8810.EMP. Before it executes, X.WORKDEPT receives the value of the
WORKDEPT column for that row. Suppose, for example, that the row is for
Christine Haas. Her work department is A00, which is the value of WORKDEPT for
that row. Therefore, the following is the subquery that is executed for that row:
(SELECT AVG(EDLEVEL)
FROM DSN8810.EMP
WHERE WORKDEPT = ’A00’);
The subquery produces the average education level of Christine’s department. The
outer SELECT then compares this average to Christine’s own education level. For
some other row for which WORKDEPT has a different value, that value appears in
the subquery in place of A00. For example, in the row for Michael L Thompson, this
value is B01, and the subquery for his row delivers the average education level for
department B01.
The result table produced by the query is similar to the following output:
EMPNO LASTNAME WORKDEPT EDLEVEL
====== ========= ======== =======
000010 HASS A00 18
000030 KWAN C01 20
000070 PULASKI D21 16
000090 HENDERSON E11 16
When you use a correlated reference in a subquery, the correlation name can be
defined in the outer SELECT or in any of the subqueries that contain the reference.
Suppose, for example, that a query contains subqueries A, B, and C, and that A
contains B and B contains C. The subquery C can use a correlation reference that
is defined in B, A, or the outer SELECT.
You can define a correlation name for each table name in a FROM clause. Specify
the correlation name after its table name. Leave one or more blanks between a
table name and its correlation name. You can include the word AS between the
table name and the correlation name to increase the readability of the SQL
statement.
The following example demonstrates the use of a correlated reference in the select
list of a subquery:
UPDATE BP1TBL T1
SET (KEY1, CHAR1, VCHAR1) =
(SELECT VALUE(T2.KEY1,T1.KEY1), VALUE(T2.CHAR1,T1.CHAR1),
VALUE(T2.VCHAR1,T1.VCHAR1)
FROM BP2TBL T2
WHERE (T2.KEY1 = T1.KEY1))
WHERE KEY1 IN
(SELECT KEY1
FROM BP2TBL T3
WHERE KEY2 > 0);
To process this statement, DB2 determines for each project (represented by a row
in the DSN8810.PROJ table) whether or not the combined staffing for that project is
less than 0.5. If it is, DB2 deletes that row from the DSN8810.PROJ table.
To continue this example, suppose DB2 deletes a row in the DSN8810.PROJ table.
You must also delete rows related to the deleted project in the DSN8810.PROJACT
table. To do this, use:
DELETE FROM DSN8810.PROJACT X
WHERE NOT EXISTS
(SELECT *
FROM DSN8810.PROJ
WHERE PROJNO = X.PROJNO);
DB2 determines, for each row in the DSN8810.PROJACT table, whether a row with
the same project number exists in the DSN8810.PROJ table. If not, DB2 deletes the
row in DSN8810.PROJACT.
This example uses a copy of the employee table for the subquery.
To use SPUFI, select SPUFI from the DB2I Primary Option Menu as shown in
Figure 149 on page 496
From then on, when the SPUFI panel displays, the data entry fields on the panel
contain the values that you previously entered. You can specify data set names and
processing options each time the SPUFI panel displays, as needed. Values you do
not change remain in effect.
Enter the output data set name: (Must be a sequential data set)
4 DATA SET NAME..... ===> RESULT
| Fill out the SPUFI panel. You can access descriptions for each of the fields in the
| panel in the DB2I help system. See “DB2I help” on page 495 for more information
| about the DB2I help system.
If you want to change the current default values, specify new values in the fields of
| the panel. All fields must contain a value. The DB2I help system contains detailed
| descriptions of each of the fields of the CURRENT SPUFI DEFAULTS panel.
When you have entered your SPUFI options, press the ENTER key to continue.
SPUFI then processes the next processing option for which you specified YES. If all
other processing options are NO, SPUFI displays the SPUFI panel.
If you press the END key, you return to the SPUFI panel, but you lose all the
changes you made on the SPUFI Defaults panel. If you press ENTER, SPUFI
saves your changes.
On the panel, use the ISPF EDIT program to enter SQL statements that you want
to execute, as shown in Figure 5 on page 61.
Move the cursor to the first input line and enter the first part of an SQL statement.
You can enter the rest of the SQL statement on subsequent lines, as shown in
You can put more than one SQL statement in the input data set. You can put an
SQL statement on one line of the input data set or on more than one line. DB2
executes the statements in the order you placed them in the data set. Do not put
more than one SQL statement on a single line. The first one executes, but DB2
ignores the other SQL statements on the same line.
In your SPUFI input data set, end each SQL statement with the statement
terminator that you specified in the CURRENT SPUFI DEFAULTS panel.
When you have entered your SQL statements, press the END PF key to save the
file and to execute the SQL statements.
Pressing the END PF key saves the data set. You can save the data set and
continue editing it by entering the SAVE command. Saving the data set after every
10 minutes or so of editing is recommended.
Figure 5 shows what the panel looks like if you enter the sample SQL statement,
followed by a SAVE command.
You can bypass the editing step by resetting the EDIT INPUT processing option:
EDIT INPUT ... ===> NO
| However, you can use the CHAR function to explicitly request the result as
| character data. Instead of using G1 as an item in the select list, use CHAR(G1):
| SELECT CHAR(G1) FROM T1;
| The result of the CHAR function is a UTF-8 string (CCSID 1208) that is then
| converted to EBCDIC when the value is returned to SPUFI. The CCSID of the
| converted data depends on the value of the application-encoding BIND option for
| the SPUFI package. In most cases, the SPUFI result is the EBCDIC system
| CCSID.
Use a character other than a semicolon if you plan to execute a statement that
contains embedded semicolons. For example, suppose you choose the character #
as the statement terminator. Then a CREATE TRIGGER statement with embedded
semicolons looks like this:
CREATE TRIGGER NEW_HIRE
AFTER INSERT ON EMP
FOR EACH ROW MODE DB2SQL
BEGIN ATOMIC
UPDATE COMPANY_STATS SET NBEMP = NBEMP + 1;
END#
Be careful to choose a character for the SQL terminator that is not used within the
statement.
You can bypass the DB2 processing step by resetting the EXECUTE processing
option:
EXECUTE ..... ===> NO
Your SQL statement might take a long time to execute, depending on how large a
table DB2 must search, or on how many rows DB2 must process. To interrupt
DB2’s processing, press the PA1 key and respond to the prompting message that
What happens to the output data set? This depends on how much of the input data
set DB2 was able to process before you interrupted its processing. DB2 might not
have opened the output data set yet, or the output data set might contain all or part
of the results data that are produced so far.
At the end of the data set are summary statistics that describe the processing of the
input data set as a whole.
For SELECT statements executed with SPUFI, the message “SQLCODE IS 100”
indicates an error-free result. If the message SQLCODE IS 100 is the only result,
DB2 is unable to find any rows that satisfy the condition specified in the statement.
For all other types of SQL statements executed with SPUFI, the message
“SQLCODE IS 0” indicates an error-free result.
Other messages that you could receive from the processing of SQL statements
include:
v The number of rows that DB2 processed, that either:
– Your SELECT statement retrieved
– Your UPDATE statement modified
– Your INSERT statement added to a table
– Your DELETE statement deleted from a table
v Which columns display truncated data because the data was too wide
In addition to these basic requirements, you should also consider the following
special topics:
v Cursors — Chapter 7, “Using a cursor to retrieve a set of rows,” on page 93
discusses how to use a cursor in your application program to select a set of rows
and then process the set either one row at a time or one rowset at a time.
© Copyright IBM Corp. 1983, 2004 69
v DCLGEN — Chapter 8, “Generating declarations for your tables using DCLGEN,”
on page 121 discusses how to use DB2’s declarations generator, DCLGEN, to
obtain accurate SQL DECLARE statements for tables and views.
This section includes information about using SQL in application programs written in
assembler, C, C++, COBOL, Fortran, PL/I, and REXX.
Some of the examples vary from these conventions. Exceptions are noted where
they occur.
For REXX, precede the statement with EXECSQL. If the statement is in a literal string,
enclose it in single or double quotation marks.
Example: Use EXEC SQL and END-EXEC. to delimit an SQL statement in a COBOL
program:
EXEC SQL
an SQL statement
END-EXEC.
You do not need to declare tables or views, but doing so offers advantages. One
advantage is documentation. For example, the DECLARE statement specifies the
structure of the table or view you are working with, and the data type of each
column. You can refer to the DECLARE statement for the column names and data
types in the table or view. Another advantage is that the DB2 precompiler uses your
declarations to make sure that you have used correct column names and data
types in your SQL statements. The DB2 precompiler issues a warning message
when the column names and data types do not correspond to the SQL DECLARE
statements in your program.
For example, the DECLARE TABLE statement for the DSN8810.DEPT table looks
like the following DECLARE statement in COBOL:
EXEC SQL
DECLARE DSN8810.DEPT TABLE
(DEPTNO CHAR(3) NOT NULL,
DEPTNAME VARCHAR(36) NOT NULL,
MGRNO CHAR(6) ,
ADMRDEPT CHAR(3) NOT NULL,
LOCATION CHAR(16) )
END-EXEC.
When you declare a table or view that contains a column with a distinct type,
declare that column with the source type of the distinct type, rather than with the
distinct type itself. When you declare the column with the source type, DB2 can
check embedded SQL statements that reference that column at precompile time.
A host variable is a data item that is declared in the host language for use within an
SQL statement. Using host variables, you can:
v Retrieve data into the host variable for your application program’s use
v Place data into the host variable to insert into a table or to change the contents
of a row
v Use the data in the host variable when evaluating a WHERE or HAVING clause
v Assign the value that is in the host variable to a special register, such as
CURRENT SQLID and CURRENT DEGREE
| A host variable array is a data array that is declared in the host language for use
| within an SQL statement. Using host variable arrays, you can:
| v Retrieve data into host variable arrays for your application program’s use
| v Place data into host variable arrays to insert rows into a table
To optimize performance, make sure that the host language declaration maps as
closely as possible to the data type of the associated data in the database. For
more performance suggestions, see Part 6, “Additional programming techniques,”
on page 525.
You can use a host variable to represent a data value, but you cannot use it to
represent a table, view, or column name. (You can specify table, view, or column
names at run time using dynamic SQL. See Chapter 24, “Coding dynamic SQL in
application programs,” on page 535 for more information.)
Host variables follow the naming conventions of the host language. A colon (:) must
precede host variables that are used in SQL statements so DB2 can distinguish a
variable name from a column name. A colon must not precede host variables
outside of SQL statements.
For more information about declaring host variables, see the appropriate language
section:
v Assembler: “Declaring host variables” on page 133
v C and C++: “Declaring host variables” on page 147
v COBOL: “Declaring host variables” on page 176
v Fortran: “Declaring host variables” on page 207
v PL/I: “Declaring host variables” on page 217
v REXX: “Using REXX host variables and data types” on page 237.
If you do not know how many rows DB2 will return, or if you expect more than one
row to return, you must use an alternative to the SELECT ... INTO statement. The
DB2 cursor enables an application to return a set of rows and fetch either one row
at a time or one rowset at a time from the result table. For information about using
cursors, see Chapter 7, “Using a cursor to retrieve a set of rows,” on page 93.
Example: Retrieving a single row: Suppose you are retrieving the LASTNAME
and WORKDEPT column values from the DSN8810.EMP table for a particular
employee. You can define a host variable in your program to hold each column and
then name the host variables with an INTO clause, as in the following COBOL
example:
MOVE ’000110’ TO CBLEMPNO.
EXEC SQL
SELECT LASTNAME, WORKDEPT
INTO :CBLNAME, :CBLDEPT
FROM DSN8810.EMP
WHERE EMPNO = :CBLEMPNO
END-EXEC.
Note that the host variable CBLEMPNO is preceded by a colon (:) in the SQL
statement, but it is not preceded by a colon in the COBOL MOVE statement. In the
DATA DIVISION section of a COBOL program, you must declare the host variables
CBLEMPNO, CBLNAME, and CBLDEPT to be compatible with the data types in the
columns EMPNO, LASTNAME, and WORKDEPT of the DSN8810.EMP table.
You can use a host variable to specify a value in a search condition. For this
example, you have defined a host variable CBLEMPNO for the employee number,
so that you can retrieve the name and the work department of the employee whose
number is the same as the value of the host variable, CBLEMPNO; in this case,
000110.
If the SELECT ... INTO statement returns more than one row, an error occurs, and
any data that is returned is undefined and unpredictable.
To prevent undefined and unpredictable data from being returned, you can use the
FETCH FIRST 1 ROW ONLY clause to ensure that only one row is returned. For
example:
EXEC SQL
SELECT LASTNAME, WORKDEPT
INTO :CBLNAME, :CBLDEPT
FROM DSN8810.EMP
FETCH FIRST 1 ROW ONLY
END-EXEC.
| When you specify both the ORDER BY clause and the FETCH FIRST clause,
| ordering is done first and then the first row is returned. This means that the ORDER
| BY clause determines which row is returned. If you specify both the ORDER BY
| clause and the FETCH FIRST clause, ordering is performed on the entire result set
| before the first row is returned.
The following results have column headings that represent the names of the host
variables:
EMP-NUM PERSON-NAME EMP-SAL EMP-RAISE EMP-TTL
======= =========== ======= ========= =======
000220 LUTZ 29840 4476 34316
Example: Specifying summary values in the SELECT clause: You can request
| summary values to be returned from aggregate functions. For example:
MOVE ’D11’ TO DEPTID.
EXEC SQL
SELECT WORKDEPT, AVG(SALARY)
INTO :WORK-DEPT, :AVG-SALARY
FROM DSN8810.EMP
WHERE WORKDEPT = :DEPTID
END-EXEC.
| To insert multiple rows, you can use the form of the INSERT statement that selects
| values from another table or view. You can also use a form of the INSERT
| statement that inserts multiple rows from values that are provided in host variable
| arrays. For more information, see “Inserting multiple rows of data from host variable
| arrays” on page 79.
| Example: The following example inserts a single row into the activity table:
| EXEC SQL
| INSERT INTO DSN8810.ACT
| VALUES (:HV-ACTNO, :HV-ACTKWD, :HV-ACTDESC)
| END-EXEC.
Retrieving data and testing the indicator variable: When DB2 retrieves the value
of a column into a host variable, you can test the indicator variable that is
associated with that host variable:
v If the value of the indicator variable is less than zero, the column value is null.
The value of the host variable does not change from its previous value. If it is
null because of a numeric or character conversion error, or an arithmetic
expression error, DB2 sets the indicator variable to -2. See “Handling arithmetic
or conversion errors” on page 84 for more information.
v If the indicator variable contains a positive integer, the retrieved value is
truncated, and the integer is the original length of the string.
v If the value of the indicator variable is zero, the column value is nonnull. If the
column value is a character string, the retrieved value is not truncated.
An error occurs if you do not use an indicator variable and DB2 retrieves a null
value.
You can specify an indicator variable, preceded by a colon, immediately after the
host variable. Optionally, you can use the word INDICATOR between the host
You can then test INDNULL for a negative value. If it is negative, the corresponding
value of PHONENO is null, and you can disregard the contents of CBLPHONE.
When you use a cursor to fetch a column value, you can use the same technique to
determine whether the column value is null.
Inserting null values into columns by using host variable indicators: You can
use an indicator variable to insert a null value from a host variable into a column.
When DB2 processes INSERT and UPDATE statements, it checks the indicator
variable (if one exists). If the indicator variable is negative, the column value is null.
If the indicator variable is greater than -1, the associated host variable contains a
value for the column.
For example, suppose your program reads an employee ID and a new phone
number, and must update the employee table with the new number. The new
number could be missing if the old number is incorrect, but a new number is not yet
available. If the new value for column PHONENO might be null, you can use an
indicator variable in the UPDATE statement. For example:
EXEC SQL
UPDATE DSN8810.EMP
SET PHONENO = :NEWPHONE:PHONEIND
WHERE EMPNO = :EMPID
END-EXEC.
Testing for a null column value: You cannot determine whether a column value is
null by comparing it to a host variable with an indicator variable that is set to -1. To
| test whether a column has a null value, use the IS NULL predicate or the IS
| DISTINCT FROM predicate. For example, the following code does not select the
employees who have no phone number:
MOVE -1 TO PHONE-IND.
EXEC SQL
SELECT LASTNAME
INTO :PGM-LASTNAME
FROM DSN8810.EMP
WHERE PHONENO = :PHONE-HV:PHONE-IND
END-EXEC.
You can use the IS NULL predicate to select employees who have no phone
number, as in the following statement:
| To select employees whose phone numbers are equal to the value of :PHONE-HV
| and employees who have no phone number (as in the second example), you would
| need to code two predicates, one to handle the non-null values and another to
| handle the null values, as in the following statement:
| EXEC SQL
| SELECT LASTNAME
| INTO :PGM-LASTNAME
| FROM DSN8810.EMP
| WHERE (PHONENO = :PHONE-HV AND PHONENO IS NOT NULL AND :PHONE-HV IS NOT NULL)
| OR
| (PHONENO IS NULL AND :PHONE-HV:PHONE-IND IS NULL)
| END-EXEC.
| You can simplify the preceding example by coding the statement using the NOT
| form of the IS DISTINCT FROM predicate, as in the following statement:
| EXEC SQL
| SELECT LASTNAME
| INTO :PGM-LASTNAME
| FROM DSN8810.EMP
| WHERE PHONENO IS NOT DISTINCT FROM :PHONE-HV:PHONE-IND
| END-EXEC.
When you use a DECLARE VARIABLE statement in a program, put the DECLARE
VARIABLE statement after the corresponding host variable declaration and before
your first reference to that host variable.
Because the application encoding scheme for the subsystem is EBCDIC, the
retrieved data is EBCDIC. To make the retrieved data Unicode, use DECLARE
VARIABLE statements to specify that the data that is retrieved from these columns
is encoded in the default Unicode CCSIDs for the subsystem. Suppose that you
want to retrieve the character data in Unicode CCSID 1208 and the graphic data in
Unicode CCSID 1200. Use DECLARE VARIABLE statements like these:
EXEC SQL BEGIN DECLARE SECTION;
char hvpartnum[11];
EXEC SQL DECLARE :hvpartnum VARIABLE CCSID 1208;
| sqldbchar hvjpnname[11];
EXEC SQL DECLARE :hvjpnname VARIABLE CCSID 1200;
struct {
short len;
char d[30];
} hvengname;
EXEC SQL DECLARE :hvengname VARIABLE CCSID 1208;
EXEC SQL END DECLARE SECTION;
The BEGIN DECLARE SECTION and END DECLARE SECTION statements mark
the beginning and end of a host variable declare section.
| For more information about declaring host variable arrays, see the appropriate
| language section:
| v C or C++: “Declaring host variable arrays” on page 153
| v COBOL: “Declaring host variable arrays” on page 183
| v PL/I: “Declaring host variable arrays” on page 220
| This section describes the following ways to use host variable arrays:
| v “Retrieving multiple rows of data into host variable arrays”
| v “Inserting multiple rows of data from host variable arrays” on page 79
| v “Using indicator variable arrays with host variable arrays” on page 79
| Example: You can insert the number of rows that are specified in the host variable
| NUM-ROWS by using the following INSERT statement:
| EXEC SQL
| INSERT INTO DSN8810.ACT
| (ACTNO, ACTKWD, ACTDESC)
| VALUES (:HVA1, :HVA2, :HVA3)
| FOR :NUM-ROWS ROWS
| END-EXEC.
| Assume that the host variable arrays HVA1, HVA2, and HVA3 have been declared
| and populated with the values that are to be inserted into the ACTNO, ACTKWD,
| and ACTDESC columns. The NUM-ROWS host variable specifies the number of
| rows that are to be inserted, which must be less than or equal to the dimension of
| each host variable array.
| Retrieving data and using indicator arrays: When you retrieve data into a host
| variable array, if a value in its indicator array is negative, you can disregard the
| contents of the corresponding element in the host variable array. If a value in an
| indicator array is:
| -1 The corresponding row in the column that is being retrieved is null.
| -2 DB2 returns a null value because an error occurred in numeric conversion
| or in an arithmetic expression in the corresponding row.
| -3 DB2 returns a null value because a hole was detected for the
| corresponding row during a multiple-row FETCH operation.
| For information about the multiple-row FETCH operation, see “Step 4: Execute SQL
| statements with a rowset cursor” on page 99. For information about holes in the
| result table of a cursor, see “Holes in the result table of a scrollable cursor” on page
| 109.
| Example: Suppose that you declare a scrollable rowset cursor by using the
| following statement:
| For information about using rowset cursors, see “Accessing data by using a
| rowset-positioned cursor” on page 98.
| After the multiple-row FETCH statement, you can test each element of the
| INDNULL array for a negative value. If an element is negative, you can disregard
| the contents of the corresponding element in the CBLPHONE host variable array.
| Inserting null values by using indicator arrays: You can use a negative value in
| an indicator array to insert a null value into a column.
| Example: Assume that host variable arrays hva1 and hva2 have been populated
| with values that are to be inserted into the ACTNO and ACTKWD columns. Assume
| the ACTDESC column allows nulls. To set the ACTDESC column to null, assign -1
| to the elements in its indicator array:
| /* Initialize each indicator array */
| for (i=0; i<10; i++) {
| ind1[i] = 0;
| ind2[i] = 0;
| ind3[i] = -1;
| }
|
| EXEC SQL
| INSERT INTO DSN8810.ACT
| (ACTNO, ACTKWD, ACTDESC)
| VALUES (:hva1:ind1, :hva2:ind2, :hva3:ind3)
| FOR 10 ROWS;
| DB2 ignores the values in the hva3 array and assigns the values in the ARTDESC
| column to null for the 10 rows that are inserted.
You can declare a host structure yourself, or you can use DCLGEN to generate a
COBOL record description, PL/I structure declaration, or C structure declaration that
corresponds to the columns of a table. For more detailed information about coding
a host structure in your program, see Chapter 9, “Embedding SQL statements in
host languages,” on page 129. For more information about using DCLGEN and the
restrictions that apply to the C language, see Chapter 8, “Generating declarations
for your tables using DCLGEN,” on page 121.
In this example, EMP-IND is an array containing six values, which you can test for
negative values. If, for example, EMP-IND(6) contains a negative value, the
corresponding host variable in the host structure (EMP-BIRTHDATE) contains a null
value.
Because this example selects rows from the table DSN8810.EMP, some of the
values in EMP-IND are always zero. The first four columns of each row are defined
NOT NULL. In the preceding example, DB2 selects the values for a row of data into
a host structure. You must use a corresponding structure for the indicator variables
to determine which (if any) selected column values are null. For information on
using the IS NULL keyword phrase in WHERE clauses, see “Selecting rows using
search conditions: WHERE” on page 8.
See Appendix C of DB2 SQL Reference for a description of all the fields in the
SQLCA.
The meaning of SQLCODEs other than 0 and 100 varies with the particular product
implementing SQL.
You can declare SQLCODE and SQLSTATE (SQLCOD and SQLSTA in Fortran) as
stand-alone host variables. If you specify the STDSQL(YES) precompiler option,
these host variables receive the return codes, and you should not include an
SQLCA in your program.
The WHENEVER statement is not supported for REXX. For information on REXX
error handling, see “Embedding SQL statements in a REXX procedure” on page
235.
The WHENEVER statement must precede the first SQL statement it is to affect.
However, if your program checks SQLCODE directly, you must check SQLCODE
after each SQL statement.
For rows in which a conversion or arithmetic expression error does occur, the
indicator variable indicates that one or more selected items have no meaningful
value. The indicator variable flags this error with a -2 for the affected host variable
and an SQLCODE of +802 (SQLSTATE ’01519’) in the SQLCA.
| Use the GET DIAGNOSTICS statement to handle multiple SQL errors that might
| result from the execution of a single SQL statement. First, check SQLSTATE (or
| SQLCODE) to determine whether diagnostic information should be retrieved by
| Even if you use only the GET DIAGNOSTICS statement in your application program
| to check for conditions, you must either include the instructions required to use the
| SQLCA or you must declare SQLSTATE (or SQLCODE) separately in your program.
| To retrieve condition information, you must first retrieve the number of condition
| items (that is, the number of errors and warnings that DB2 detected during the
| execution of the last SQL statement). The number of condition items is at least one.
| If the last SQL statement returned SQLSTATE ’00000’ (or SQLCODE 0), the
| number of condition items is one.
| In Figure 7 on page 86, the first GET DIAGNOSTICS statement returns the number
| of rows inserted and the number of conditions returned. The second GET
| DIAGNOSTICS statement returns the following items for each condition:
| SQLCODE, SQLSTATE, and the number of the row (in the rowset that was being
| inserted) for which the condition occurred.
|
Figure 7. Using GET DIAGNOSTICS to return the number of rows and conditions returned
and condition information
| In the activity table, the ACTNO column is defined as SMALLINT. Suppose that you
| declare the host variable array hva1 as an array with data type long, and you
| populate the array so that the value for the fourth element is 32768.
| If you check the SQLCA values after the INSERT statement, the value of
| SQLCODE is equal to 0, the value of SQLSTATE is ’00000’, and the value of
| SQLERRD(3) is 9 for the number of rows that were inserted. However, the INSERT
| statement specified that 10 rows were to be inserted.
| The GET DIAGNOSTICS statement provides you with the information that you need
| to correct the data for the row that was not inserted. The printed output from your
| program looks like this:
| Number of rows inserted = 9
| SQLCODE = -302, SQLSTATE = 22003, ROW NUMBER = 4
| The value 32768 for the input variable is too large for the target column ACTNO.
| You can print the MESSAGE_TEXT condition item, or see DB2 Messages and
| Codes for information about SQLCODE -302.
| For a complete description of the GET DIAGNOSTICS items, see Chapter 5 of DB2
| SQL Reference.
You can find the programming language-specific syntax and details for calling
DSNTIAR on the following pages:
For Assembler programs, see page 142
For C programs, see page 169
For COBOL programs, see page 201
For Fortran programs, see page 212
For PL/I programs, see page 230
DSNTIAR takes data from the SQLCA, formats it into a message, and places the
result in a message output area that you provide in your application program. Each
time you use DSNTIAR, it overwrites any previous messages in the message output
area. You should move or print the messages before using DSNTIAR again, and
before the contents of the SQLCA change, to get an accurate view of the SQLCA.
Figure 8 shows the format of the message output area, where length is the 2-byte
total length field, and the length of each line matches the logical record length (lrecl)
you specify to DSNTIAR.
When you call DSNTIAR, you must name an SQLCA and an output message area
in the DSNTIAR parameters. You must also provide the logical record length (lrecl)
as a value between 72 and 240 bytes. DSNTIAR assumes the message area
contains fixed-length records of length lrecl.
When loading DSNTIAR from another program, be careful how you branch to
DSNTIAR. For example, if the calling program is in 24-bit addressing mode and
DSNTIAR is loaded above the 16-MB line, you cannot use the assembler BALR
instruction or CALL macro to call DSNTIAR, because they assume that DSNTIAR is
in 24-bit mode. Instead, you must use an instruction that is capable of branching
into 31-bit mode, such as BASSM.
You can dynamically link (load) and call DSNTIAR directly from a language that
does not handle 31-bit addressing (OS/VS COBOL, for example). To do this, link a
second version of DSNTIAR with the attributes AMODE(24) and RMODE(24) into
another load module library. Alternatively, you can write an intermediate assembler
language program that calls DSNTIAR in 31-bit mode and then call that
intermediate program in 24-bit mode from your application.
For more information on the allowed and default AMODE and RMODE settings for a
particular language, see the application programming guide for that language. For
details on how the attributes AMODE and RMODE of an application are determined,
see the linkage editor and loader user’s guide for the language in which you have
written the application.
In your error routine, you write a section that checks for SQLCODE -911 or -913.
You can receive either of these SQLCODEs when a deadlock or timeout occurs.
When one of these errors occurs, the error routine closes your cursors by issuing
the statement:
EXEC SQL CLOSE cursor-name
An SQLCODE of 0 or -501 resulting from that statement indicates that the close
was successful.
To use DSNTIAR to generate the error message text, first follow these steps:
1. Choose a logical record length (lrecl) of the output lines. For this example,
assume lrecl is 72 (to fit on a terminal screen) and is stored in the variable
named ERROR-TEXT-LEN.
2. Define a message area in your COBOL application. Assuming you want an area
for up to 10 lines of length 72, you should define an area of 720 bytes, plus a
2-byte area that specifies the total length of the message output area.
01 ERROR-MESSAGE.
02 ERROR-LEN PIC S9(4) COMP VALUE +720.
02 ERROR-TEXT PIC X(72) OCCURS 10 TIMES
INDEXED BY ERROR-INDEX.
77 ERROR-TEXT-LEN PIC S9(9) COMP VALUE +72.
To display the contents of the SQLCA when SQLCODE is 0 or -501, call DSNTIAR
after the SQL statement that produces SQLCODE 0 or -501:
CALL ’DSNTIAR’ USING SQLCA ERROR-MESSAGE ERROR-TEXT-LEN.
You can then print the message output area just as you would any other variable.
Your message might look like this:
DSNT408I SQLCODE = -501, ERROR: THE CURSOR IDENTIFIED IN A FETCH OR
CLOSE STATEMENT IS NOT OPEN
DSNT418I SQLSTATE = 24501 SQLSTATE RETURN CODE
DSNT415I SQLERRP = DSNXERT SQL PROCEDURE DETECTING ERROR
DSNT416I SQLERRD = -315 0 0 -1 0 0 SQL DIAGNOSTIC INFORMATION
DSNT416I SQLERRD = X’FFFFFEC5’ X’00000000’ X’00000000’
X’FFFFFFFF’ X’00000000’ X’00000000’ SQL DIAGNOSTIC
INFORMATION
| When you execute a SELECT statement, you retrieve a set of rows. That set of
| rows is called the result table of the SELECT statement. In an application program,
| you can use either of the following types of cursors to retrieve rows from a result
| table:
| v A row-positioned cursor retrieves at most a single row at a time from the result
| table into host variables. At any point in time, the cursor is positioned on at most
| a single row. For information about how to use a row-positioned cursor, see
| “Accessing data by using a row-positioned cursor.”
| v A rowset-positioned cursor retrieves zero, one, or more rows at a time, as a
| rowset, from the result table into host variable arrays. At any point in time, the
| cursor can be positioned on a rowset. You can reference all of the rows in the
| rowset, or only one row in the rowset, when you use a positioned DELETE or
| positioned UPDATE statement. For information about how to use a
| rowset-positioned cursor, see “Accessing data by using a rowset-positioned
| cursor” on page 98.
Your program can have several cursors, each of which performs the previous steps.
The following example shows a simple form of the DECLARE CURSOR statement:
You can use this cursor to list select information about employees.
More complicated cursors might include WHERE clauses or joins of several tables.
For example, suppose that you want to use a cursor to list employees who work on
a certain project. Declare a cursor like this to identify those employees:
EXEC SQL
DECLARE C2 CURSOR FOR
SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, SALARY
FROM DSN8810.EMP X
WHERE EXISTS
(SELECT *
FROM DSN8810.PROJ Y
WHERE X.EMPNO=Y.RESPEMP
AND Y.PROJNO=:GOODPROJ);
| Declaring cursors for tables that use multilevel security: You can declare a
| cursor that retrieves rows from a table that uses multilevel security with row-level
| granularity. However, the result table for the cursor contains only those rows that
| have a security label value that is equivalent to or dominated by the security label
| value of your ID. Refer to Part 3 (Volume 1) of DB2 Administration Guide for a
| discussion of multilevel security with row-level granularity.
Updating a column: You can update columns in the rows that you retrieve.
Updating a row after you use a cursor to retrieve it is called a positioned update. If
you intend to perform any positioned updates on the identified table, include the
FOR UPDATE clause. The FOR UPDATE clause has two forms:
v The first form is FOR UPDATE OF column-list. Use this form when you know in
advance which columns you need to update.
v The second form is FOR UPDATE, with no column list. Use this form when you
might use the cursor to update any of the columns of the table.
For example, you can use this cursor to update only the SALARY column of the
employee table:
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, SALARY
FROM DSN8810.EMP X
WHERE EXISTS
(SELECT *
FROM DSN8810.PROJ Y
WHERE X.EMPNO=Y.RESPEMP
AND Y.PROJNO=:GOODPROJ)
FOR UPDATE OF SALARY;
If you might use the cursor to update any column of the employee table, define the
cursor like this:
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, SALARY
FROM DSN8810.EMP X
WHERE EXISTS
(SELECT *
DB2 must do more processing when you use the FOR UPDATE clause without a
column list than when you use the FOR UPDATE clause with a column list.
Therefore, if you intend to update only a few columns of a table, your program can
run more efficiently if you include a column list.
The precompiler options NOFOR and STDSQL affect the use of the FOR UPDATE
clause in static SQL statements. For information about these options, see Table 63
on page 462. If you do not specify the FOR UPDATE clause in a DECLARE
CURSOR statement, and you do not specify the STDSQL(YES) option or the
NOFOR precompiler options, you receive an error if you execute a positioned
UPDATE statement.
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
identify the row that is to be updated.
Read-only result table: Some result tables cannot be updated—for example, the
result of joining two or more tables. The defining characteristics of a read-only result
tables are described in greater detail in the discussion of DECLARE CURSOR in
Chapter 5 of DB2 SQL Reference.
Two factors that influence the amount of time that DB2 requires to process the
OPEN statement are:
v Whether DB2 must perform any sorts before it can retrieve rows
v Whether DB2 uses parallelism to process the SELECT statement of the cursor
For more information, see “The effect of sorts on OPEN CURSOR” on page 772.
Your program must anticipate and handle an end-of-data whenever you use a
cursor to fetch a row. For more information about the WHENEVER NOT FOUND
statement, see “Checking the execution of SQL statements” on page 82.
The SELECT statement within DECLARE CURSOR statement identifies the result
table from which you fetch rows, but DB2 does not retrieve any data until your
application program executes a FETCH statement.
When your program executes the FETCH statement, DB2 positions the cursor on a
row in the result table. That row is called the current row. DB2 then copies the
current row contents into the program host variables that you specify on the INTO
clause of FETCH. This sequence repeats each time you issue FETCH, until you
process all rows in the result table.
The row that DB2 points to when you execute a FETCH statement depends on
whether the cursor is declared as a scrollable or non-scrollable. See “Scrollable and
non-scrollable cursors” on page 103 for more information.
When you query a remote subsystem with FETCH, consider using block fetch for
better performance. For more information see “Use block fetch” on page 440. Block
fetch processes rows ahead of the current row. You cannot use a block fetch when
you perform a positioned update or delete operation.
A positioned UPDATE statement updates the row on which the cursor is positioned.
A positioned DELETE statement deletes the row on which the cursor is positioned.
When you finish processing the rows of the result table, and the cursor is no longer
needed, you can let DB2 automatically close the cursor when the current
transaction terminates or when your program terminates.
Recommendation: To free the resources that are held by the cursor, close the
cursor explicitly by issuing the CLOSE statement.
| Your program can have several cursors, each of which performs the previous steps.
| To determine the number of retrieved rows, use either of the following values:
| v The contents of the SQLERRD(3) field in the SQLCA
| v The contents of the ROW_COUNT item of GET DIAGNOSTICS
| For information about GET DIAGNOSTICS, see “Using the GET DIAGNOSTICS
| statement” on page 84.
| If you declare the cursor as dynamic scrollable, and SQLCODE has the value 100,
| you can continue with a FETCH statement until no more rows are retrieved.
| Additional fetches might retrieve more rows because a dynamic scrollable cursor is
| sensitive to updates by other application processes. For information about dynamic
| cursors, see “Types of cursors” on page 103.
| You must use the WITH ROWSET POSITIONING clause of the DECLARE
| CURSOR statement if you plan to use a rowset-positioned FETCH statement.
| When your program executes a FETCH statement with the ROWSET keyword, the
| cursor is positioned on a rowset in the result table. That rowset is called the current
| rowset. The dimension of each of the host variable arrays must be greater than or
| equal to the number of rows to be retrieved.
| Declare the SQLDA: You must first declare the SQLDA structure. The following
| SQL INCLUDE statement requests a standard SQLDA declaration:
| EXEC SQL INCLUDE SQLDA;
| Your program must also declare variables that reference the SQLDA structure, the
| SQLVAR structure within the SQLDA, and the DECLEN structure for the precision
| and scale if you are retrieving a DECIMAL column. For C programs, the code looks
| like this:
| struct sqlda *sqldaptr;
| struct sqlvar *varptr;
| struct DECLEN {
| unsigned char precision;
| unsigned char scale;
| };
| Allocate the SQLDA: Before you can set the fields in the SQLDA for the column
| values to be retrieved, you must dynamically allocate storage for the SQLDA
| structure. For C programs, the code looks like this:
| sqldaptr = (struct sqlda *) malloc (3 * 44 + 16);
| The size of the SQLDA is SQLN * 44 + 16, where the value of the SQLN field is the
| number of output columns.
| Set the fields in the SQLDA: You must set the fields in the SQLDA structure for
| your FETCH statement. Suppose you want to retrieve the columns EMPNO,
| LASTNAME, and SALARY. The C code to set the SQLDA fields for these columns
| looks like this:
| strcpy(sqldaptr->sqldaid,"SQLDA");
| sqldaptr->sqldabc = 148; /* number bytes of storage allocated for the SQLDA */
| sqldaptr->sqln = 3; /* number of SQLVAR occurrences */
| sqldaptr->sqld = 3;
| varptr = (struct sqlvar *) (&(sqldaptr->sqlvar[0])); /* Point to first SQLVAR */
| varptr->sqltype = 452; /* data type CHAR(6) */
| varptr->sqllen = 6;
| varptr->sqldata = (char *) hva1;
| varptr->sqlind = (short *) inda1;
| varptr->sqlname.length = 8;
| varptr->sqlname.data = X’0000000000000014’; /* bytes 5-8 array size */
| varptr = (struct sqlvar *) (&(sqldaptr->sqlvar[0]) + 1); /* Point to next SQLVAR */
| varptr->sqltype = 448; /* data type VARCHAR(15) */
| varptr->sqllen = 15;
| varptr->sqldata = (char *) hva2;
| varptr->sqlind = (short *) inda2;
| varptr->sqlname.length = 8;
| varptr->sqlname.data = X’0000000000000014’; /* bytes 5-8 array size */
| varptr = (struct sqlvar *) (&(sqldaptr->sqlvar[0]) + 2); /* Point to next SQLVAR */
| varptr->sqltype = 485; /* data type DECIMAL(9,2) */
| ((struct DECLEN *) &(varptr->sqllen))->precision = 9;
| ((struct DECLEN *) &(varptr->sqllen))->scale = 2;
| varptr->sqldata = (char *) hva3;
| varptr->sqlind = (short *) inda3;
| varptr->sqlname.length = 8;
| varptr->sqlname.data = X’0000000000000014’; /* bytes 5-8 array size */
| For information about using the SQLDA in dynamic SQL, see Chapter 24, “Coding
| dynamic SQL in application programs,” on page 535. For a complete layout of the
| SQLDA and the descriptions given by the INCLUDE statement, see Appendix C of
| DB2 SQL Reference.
| Open the cursor: You can open the cursor only after all of the fields have been
| set in the output SQLDA:
| EXEC SQL OPEN C1;
| Fetch the rows: After the OPEN statement, the program fetches the next rowset:
| EXEC SQL
| FETCH NEXT ROWSET FROM C1
| FOR 20 ROWS
| USING DESCRIPTOR :*sqldaptr;
| The USING clause of the FETCH statement names the SQLDA that describes the
| columns that are to be retrieved.
| When the UPDATE statement is executed, the cursor must be positioned on a row
| or rowset of the result table. If the cursor is positioned on a row, that row is
| updated. If the cursor is positioned on a rowset, all of the rows in the rowset are
| updated.
| When the DELETE statement is executed, the cursor must be positioned on a row
| or rowset of the result table. If the cursor is positioned on a row, that row is deleted,
| and the cursor is positioned before the next row of its result table. If the cursor is
| positioned on a rowset, all of the rows in the rowset are deleted, and the cursor is
| positioned before the next rowset of its result table.
| When you finish processing the rows of the result table, and you no longer need the
| cursor, you can let DB2 automatically close the cursor when the current transaction
| terminates or when your program terminates.
| Recommendation: To free the resources held by the cursor, close the cursor
| explicitly by issuing the CLOSE statement.
Types of cursors
| You can declare cursors, both row-positioned and rowset-positioned, as scrollable
or not scrollable, held or not held, and returnable or not returnable. The following
sections discuss these characteristics:
v “Scrollable and non-scrollable cursors”
v “Held and non-held cursors” on page 112
A non-scrollable cursor always moves sequentially forward in the result table. When
the application opens the cursor, the cursor is positioned before the first row (or first
rowset) in the result table. When the application executes the first FETCH, the
cursor is positioned on the first row (or first rowset). When the application executes
subsequent FETCH statements, the cursor moves one row ahead (or one rowset
ahead) for each FETCH. After each FETCH statement, the cursor is positioned on
the row (or rowset) that was fetched.
If you want to order the rows of the cursor’s result set, and you also want the cursor
to be updatable, you need to declare the cursor as scrollable, even if you use it
only to retrieve rows (or rowsets) sequentially. You can use the ORDER BY clause
in the declaration of an updatable cursor only if you declare the cursor as scrollable.
Declaring a scrollable cursor with the INSENSITIVE keyword has the following
effects:
v The size, the order of the rows, and the values for each row of the result table do
not change after the application opens the cursor.
v The result table is read-only. Therefore, you cannot declare the cursor with the
FOR UPDATE clause, and you cannot use the cursor for positioned update or
delete operations.
Static scrollable cursor: Both the INSENSITIVE cursor and the SENSITIVE
STATIC cursor follow the static cursor model:
v The size of the result table does not grow after the application opens the cursor.
Rows that are inserted into the underlying table are not added to the result table.
v The order of the rows does not change after the application opens the cursor.
If the cursor declaration contains an ORDER BY clause, and the columns that
are in the ORDER BY clause are updated after the cursor is opened, the order of
the rows in the result table does not change.
| Dynamic scrollable cursor: When you declare a cursor as SENSITIVE, you can
| declare it either STATIC or DYNAMIC. The SENSITIVE DYNAMIC cursor follows
| the dynamic cursor model:
| v The size and contents of the result table can change with every fetch.
| The base table can change while the cursor is scrolling on it. If another
| application process changes the data, the cursor sees the newly changed data
| when it is committed. If the application process of the cursor changes the data,
| the cursor sees the newly changed data immediately.
| v The order of the rows can change after the application opens the cursor.
If the OPEN statement executes with no errors or warnings, DB2 does not set
SQLWARN0 when it sets SQLWARN1, SQLWARN4, or SQLWARN5. See Appendix
| C of DB2 SQL Reference for specific information about fields in the SQLCA.
| For more information about the GET DIAGNOSTICS statement, see “Using the
| GET DIAGNOSTICS statement” on page 84.
Notes:
| 1. The cursor position applies to both row position and rowset position, for example, before
| the first row or before the first rowset.
2. ABSOLUTE and RELATIVE are described in greater detail in the discussion of FETCH in
Chapter 5 of DB2 SQL Reference.
Example: To use the cursor that is declared in Figure 9 on page 104 to fetch the
fifth row of the result table, use a FETCH statement like this:
EXEC SQL FETCH ABSOLUTE +5 C1 INTO :HVDEPTNO, :DEPTNAME, :MGRNO;
To fetch the fifth row from the end of the result table, use this FETCH statement:
EXEC SQL FETCH ABSOLUTE -5 C1 INTO :HVDEPTNO, :DEPTNAME, :MGRNO;
Determining the number of rows in the result table for a static scrollable
cursor: You can determine how many rows are in the result table of an
INSENSITIVE or SENSITIVE STATIC scrollable cursor. To do that, execute a
FETCH statement, such as FETCH AFTER, that positions the cursor after the last
row. You can then examine the fields SQLERRD(1) and SQLERRD(2) in the
SQLCA (fields sqlerrd[0] and sqlerrd[1] for C and C++) for the number of rows in
| the result table. Alternatively, you can use the GET DIAGNOSTICS statement to
| retrieve the number of rows in the ROW_COUNT statement item.
| FETCH statement interaction between row and rowset positioning: When you
| declare a cursor with the WITH ROWSET POSITIONING clause, you can intermix
| row-positioned FETCH statements with rowset-positioned FETCH statements. For
| information about using a multiple-row FETCH statement, see “Using a multiple-row
| FETCH statement with host variable arrays” on page 99.
| Table 9 summarizes the sensitivity values and their effects on the result table of a
| scrollable cursor.
| Table 9. How sensitivity affects the result table for a scrollable cursor
| DECLARE
| sensitivity FETCH INSENSITIVE FETCH SENSITIVE
| INSENSITIVE No changes to the underlying Not valid.
| table are visible in the result
| table. Positioned UPDATE and
| DELETE statements using the
| cursor are not allowed.
| SENSITIVE STATIC Only positioned updates and All updates and deletes are visible
| deletes that are made by the in the result table. Inserts made by
| cursor are visible in the result other processes are not visible in
| table. the result table.
| SENSITIVE Not valid. All committed changes are visible
| DYNAMIC in the result table, including
| updates, deletes, inserts, and
| changes in the order of the rows.
|
The following examples demonstrate how delete and update holes can occur when
you use a SENSITIVE STATIC scrollable cursor.
Creating a delete hole with a static scrollable cursor: Suppose that table A
consists of one integer column, COL1, which has the values shown in Figure 12 on
page 110.
Now suppose that you declare the following SENSITIVE STATIC scrollable cursor,
which you use to delete rows from A:
EXEC SQL DECLARE C3 SENSITIVE STATIC SCROLL CURSOR FOR
SELECT COL1
FROM A
FOR UPDATE OF COL1;
The positioned delete statement creates a delete hole, as shown in Figure 13.
After you execute the positioned delete statement, the third row is deleted from the
result table, but the result table does not shrink to fill the space that the deleted row
creates.
Creating an update hole with a static scrollable cursor: Suppose that you
declare the following SENSITIVE STATIC scrollable cursor, which you use to update
rows in A:
EXEC SQL DECLARE C4 SENSITIVE STATIC SCROLL CURSOR FOR
SELECT COL1
FROM A
WHERE COL1<6;
After you execute the searched UPDATE statement, the last row no longer qualifies
for the result table, but the result table does not shrink to fill the space that the
disqualified row creates.
Removing a delete hole or an update hole: You can remove a delete hole or an
update hole in specific situations.
If you try to fetch from a delete hole, DB2 issues an SQL warning. If you try to
update or delete a delete hole, DB2 issues an SQL error. You can remove a delete
hole only by opening the scrollable cursor, setting a savepoint, executing a
positioned DELETE statement with the scrollable cursor, and rolling back to the
savepoint.
If you try to fetch from an update hole, DB2 issues an SQL warning. If you try to
delete an update hole, DB2 issues an SQL error. However, you can convert an
update hole back to a result table row by updating the row in the base table, as
shown in Figure 15 on page 112. You can update the base table with a searched
UPDATE statement in the same application process, or a searched or positioned
UPDATE statement in another application process. After you update the base table,
if the row qualifies for the result table, the update hole disappears.
If the scrollable cursor creates the hole, the hole is visible when you execute a
FETCH statement for the row that contains the hole. The FETCH statement can be
FETCH INSENSITIVE or FETCH SENSITIVE.
If an update or delete operation outside the scrollable cursor creates the hole, the
hole is visible at the following times:
v If you execute a FETCH SENSITIVE statement for the row that contains the hole,
the hole is visible when you execute the FETCH statement.
v If you execute a FETCH INSENSITIVE statement, the hole is not visible when
you execute the FETCH statement. DB2 returns the row as it was before the
update or delete operation occurred. However, if you follow the FETCH
INSENSITIVE statement with a positioned UPDATE or DELETE statement, the
hole becomes visible.
| After a commit operation, the position of a held cursor depends on its type:
| v A non-scrollable cursor that is held is positioned after the last retrieved row and
| before the next logical row. The next row can be returned from the result table
| with a FETCH NEXT statement.
If the program abnormally terminates, the cursor position is lost. To prepare for
restart, your program must reposition the cursor.
The following restrictions apply to cursors that are declared WITH HOLD:
v Do not use DECLARE CURSOR WITH HOLD with the new user signon from a
DB2 attachment facility, because all open cursors are closed.
v Do not declare a WITH HOLD cursor in a thread that might become inactive. If
you do, its locks are held indefinitely.
IMS
You cannot use DECLARE CURSOR...WITH HOLD in message processing
programs (MPP) and message-driven batch message processing (BMP). Each
message is a new user for DB2; whether or not you declare them using WITH
HOLD, no cursors continue for new users. You can use WITH HOLD in
non-message-driven BMP and DL/I batch programs.
CICS
In CICS applications, you can use DECLARE CURSOR...WITH HOLD to
indicate that a cursor should not close at a commit or sync point. However,
SYNCPOINT ROLLBACK closes all cursors, and end-of-task (EOT) closes all
cursors before DB2 reuses or terminates the thread. Because
pseudo-conversational transactions usually have multiple EXEC CICS
RETURN statements and thus span multiple EOTs, the scope of a held cursor
is limited. Across EOTs, you must reopen and reposition a cursor declared
WITH HOLD, as if you had not specified WITH HOLD.
You should always close cursors that you no longer need. If you let DB2 close
a CICS attachment cursor, the cursor might not close until the CICS
attachment facility reuses or terminates the thread.
The following cursor declaration causes the cursor to maintain its position in the
DSN8810.EMP table after a commit point:
EXEC SQL
DECLARE EMPLUPDT CURSOR WITH HOLD FOR
SELECT EMPNO, LASTNAME, PHONENO, JOB, SALARY, WORKDEPT
Figure 17 on page 116 shows how to retrieve data backward with a cursor.
Figure 17. Performing cursor operations with a SENSITIVE STATIC scrollable cursor
Figure 18 on page 117 shows how to update an entire rowset with a cursor.
|
| Figure 18. Performing positioned update with a rowset cursor
|
Figure 19 on page 118 shows how to update specific rows with a rowset cursor.
|
| Figure 19. Performing positioned update and delete with a sensitive rowset cursor (Part 1 of
| 2)
|
Figure 19. Performing positioned update and delete with a sensitive rowset cursor (Part 2 of
| 2)
You must use DCLGEN before you precompile your program. Supply the table or
view name to DCLGEN before you precompile your program. To use the
declarations generated by DCLGEN in your program, use the SQL INCLUDE
statement. For more information about the INCLUDE statement, see Chapter 5 of
DB2 SQL Reference.
DB2 must be active before you can use DCLGEN. You can start DCLGEN in
several different ways:
v From ISPF through DB2I. Select the DCLGEN option on the DB2I Primary Option
Menu panel.
v Directly from TSO. To do this, sign on to TSO, issue the TSO command DSN,
and then issue the subcommand DCLGEN.
v From a CLIST, running in TSO foreground or background, that issues DSN and
then DCLGEN.
v With JCL. Supply the required information, using JCL, and run DCLGEN in batch.
If you want to start DCLGEN in the foreground, and your table names include
DBCS characters, you must provide and display double-byte characters. If you
do not have a terminal that displays DBCS characters, you can enter DBCS
characters using the hex mode of ISPF edit.
| The DB2I help system contains detailed descriptions of the fields of the DCLGEN
| panel. For more information about the DB2I help system, see “DB2I help” on page
| 495.
If you are using an SQL reserved word as an identifier, you must edit the DCLGEN
output in order to add the appropriate SQL delimiters.
DCLGEN produces output that is intended to meet the needs of most users, but
occasionally, you will need to edit the DCLGEN output to work in your specific case.
For example, DCLGEN is unable to determine whether a column that is defined as
NOT NULL also contains the DEFAULT clause, so you must edit the DCLGEN
output to add the DEFAULT clause to the appropriate column definitions.
Notes:
1. For a distinct type, DCLGEN generates the host language equivalent of the source data type.
2. If your C compiler does not support the decimal data type, edit your DCLGEN output, and replace the decimal
data declarations with declarations of type double.
3. For a BLOB, CLOB, or DBCLOB data type, DCLGEN generates a LOB locator.
4. DCLGEN chooses the format based on the character you specify as the DBCS symbol on the COBOL Defaults
panel.
5. This declaration is used unless a date installation exit routine exists for formatting dates, in which case the length
is that specified for the LOCAL DATE LENGTH installation option.
6. This declaration is used unless a time installation exit routine exists for formatting times, in which case the length
is that specified for the LOCAL TIME LENGTH installation option.
For more details about the DCLGEN subcommand, see Part 3 of DB2 Command
Reference.
The COBOL Defaults panel is then displayed, as shown in Figure 22. Fill in the
COBOL Defaults panel as necessary. Press Enter to save the new defaults, if any,
and return to the DB2I Primary Option menu.
Figure 22. The COBOL defaults panel. Shown only if the field APPLICATION LANGUAGE on
the DB2I Defaults panel is IBMCOB.
Fill in the fields as shown in Figure 23 on page 126, and then press Enter.
Figure 23. DCLGEN panel—selecting source table and destination data set
DB2 again displays the DCLGEN screen, as shown in Figure 25. Press Enter to
return to the DB2I Primary Option menu.
For each language, this chapter provides unique instructions or details about:
v Defining the SQL communications area
v Defining SQL descriptor areas
v Embedding SQL statements
v Using host variables
v Declaring host variables
v Declaring host variable arrays for C or C++, COBOL, and PL/I
v Determining equivalent SQL data types
v Determining if SQL and host language data types are compatible
v Using indicator variables or host structures, depending on the language
v Handling SQL error return codes
For information about reading the syntax diagrams in this chapter, see “How to read
the syntax diagrams” on page xx.
For information about writing embedded SQL application programs in Java, see
DB2 Application Programming Guide and Reference for Java.
DB2 sets the SQLCODE and SQLSTATE values after each SQL statement
executes. An application can check these values to determine whether the last SQL
statement was successful. All SQL statements in the program must be within the
scope of the declaration of the SQLCODE and SQLSTATE variables.
If your program is reentrant, you must include the SQLCA within a unique data area
that is acquired for your task (a DSECT). For example, at the beginning of your
program, specify:
PROGAREA DSECT
EXEC SQL INCLUDE SQLCA
As an alternative, you can create a separate storage area for the SQLCA and
provide addressability to that area.
See Chapter 5 of DB2 SQL Reference for more information about the INCLUDE
statement and Appendix C of DB2 SQL Reference for a complete description of
SQLCA fields.
You must place SQLDA declarations before the first SQL statement that references
the data descriptor, unless you use the precompiler option TWOPASS. See Chapter
5 of DB2 SQL Reference for more information about the INCLUDE statement and
Appendix C of DB2 SQL Reference for a complete description of SQLDA fields.
Each SQL statement in an assembler program must begin with EXEC SQL. The
EXEC and SQL keywords must appear on one line, but the remainder of the
statement can appear on subsequent lines.
| Multiple-row FETCH statements: You can use only the FETCH ... USING
| DESCRIPTOR form of the multiple-row FETCH statement in an assembler program.
| The DB2 precompiler does not recognize declarations of host variable arrays for an
| assembler program.
Continuation for SQL statements: The line continuation rules for SQL statements
are the same as those for assembler statements, except that you must specify
EXEC SQL within one line. Any part of the statement that does not fit on one line
can appear on subsequent lines, beginning at the continuation margin (column 16,
the default). Every line of the statement, except the last, must have a continuation
character (a non-blank character) immediately after the right margin in column 72.
Declaring tables and views: Your assembler program should include a DECLARE
statement to describe each table and view the program accesses.
Margins: The precompiler option MARGINS allows you to set a left margin, a right
margin, and a continuation margin. The default values for these margins are
columns 1, 71, and 16, respectively. If EXEC SQL starts before the specified left
margin, the DB2 precompiler does not recognize the SQL statement. If you use the
default margins, you can place an SQL statement anywhere between columns 2
and 71.
Names: You can use any valid assembler name for a host variable. However, do
not use external entry names or access plan names that begin with ’DSN’ or host
variable names that begin with ’SQL’. These names are reserved for DB2.
The first character of a host variable that is used in embedded SQL cannot be an
underscore. However, you can use an underscore as the first character in a symbol
that is not used in embedded SQL.
Statement labels: You can prefix an SQL statement with a label. The first line of an
SQL statement can use a label beginning in the left margin (column 1). If you do
not use a label, leave column 1 blank.
WHENEVER statement: The target for the GOTO clause in an SQL WHENEVER
statement must be a label in the assembler source code and must be within the
scope of the SQL statements that WHENEVER affects.
CICS
An example of code to support reentrant programs, running under CICS,
follows:
DFHEISTG DSECT
DFHEISTG
EXEC SQL INCLUDE SQLCA
*
DS 0F
SQDWSREG EQU R7
SQDWSTOR DS (SQLDLEN)C RESERVE STORAGE TO BE USED FOR SQLDSECT
.
.
.
TSO
The sample program in prefix.SDSNSAMP(DSNTIAD) contains an example
of how to acquire storage for the SQLDSECT in a program that runs in a
TSO environment.
CICS
A CICS application program uses the DFHEIENT macro to generate the
entry point code. When using this macro, consider the following:
– If you use the default DATAREG in the DFHEIENT macro, register 13
points to the save area.
– If you use any other DATAREG in the DFHEIENT macro, you must
provide addressability to a save area.
For example, to use SAVED, you can code instructions to save, load,
and restore register 13 around each SQL statement as in the following
example.
ST 13,SAVER13 SAVE REGISTER 13
LA 13,SAVED POINT TO SAVE AREA
EXEC SQL . . .
L 13,SAVER13 RESTORE REGISTER 13
You can precede the assembler statements that define host variables with the
statement BEGIN DECLARE SECTION, and follow the assembler statements with
the statement END DECLARE SECTION. You must use the statements BEGIN
DECLARE SECTION and END DECLARE SECTION when you use the precompiler
option STDSQL(YES).
You can declare host variables in normal assembler style (DC or DS), depending on
the data type and the limitations on that data type. You can specify a value on DC
or DS declarations (for example, DC H’5’). The DB2 precompiler examines only
packed decimal declarations.
An SQL statement that uses a host variable must be within the scope of the
statement that declares the variable.
Numeric host variables: Figure 27 on page 134 shows the syntax for declarations
of numeric host variables. The numeric value specifies the scale of the packed
decimal variable. If value does not include a decimal point, the scale is 0.
variable-name DC H
DS 1 L2
F
L4
P ’value’
Ln
E
L4
EH
L4
EB
L4
D
L8
DH
L8
DB
L8
For floating-point data types (E, EH, EB, D, DH, and DB), DB2 uses the FLOAT
| precompiler option to determine whether the host variable is in IEEE binary
| floating-point or System/390® hexadecimal floating-point format. If the precompiler
option is FLOAT(S390), you need to define your floating-point host variables as E,
EH, D, or DH. If the precompiler option is FLOAT(IEEE), you need to define your
floating-point host variables as EB or DB. DB2 converts all floating-point input data
| to System/390 hexadecimal floating-point before storing it.
Character host variables: The three valid forms for character host variables are:
v Fixed-length strings
v Varying-length strings
v CLOBs
The following figures show the syntax for forms other than CLOBs. See Figure 34
on page 136 for the syntax of CLOBs.
variable-name DC C
DS 1 Ln
variable-name DC H , CLn
DS 1 L2 1
Graphic host variables: The three valid forms for graphic host variables are:
v Fixed-length strings
v Varying-length strings
v DBCLOBs
The following figures show the syntax for forms other than DBCLOBs. See
Figure 34 on page 136 for the syntax of DBCLOBs. In the syntax diagrams, value
denotes one or more DBCS characters, and the symbols < and > represent shift-out
and shift-in characters.
variable-name DC G
DS Ln
’<value>’
Ln’<value>’
variable-name DS H , GLn
DC L2 ’m’ ’<value>’
Result set locators: Figure 32 shows the syntax for declarations of result set
locators. See Chapter 25, “Using stored procedures for client/server processing,” on
page 569 for a discussion of how to use these host variables.
variable-name DC F
DS 1 L4
Table Locators: Figure 33 shows the syntax for declarations of table locators. See
“Accessing transition tables in a user-defined function or stored procedure” on page
328 for a discussion of how to use these host variables.
LOB variables and locators: Figure 34 on page 136 shows the syntax for
declarations of BLOB, CLOB, and DBCLOB host variables and locators. See
Chapter 14, “Programming for large objects (LOBs),” on page 281 for a discussion
of how to use these host variables.
If you specify the length of the LOB in terms of KB, MB, or GB, you must leave no
spaces between the length and K, M, or G.
ROWIDs: Figure 35 shows the syntax for declarations of ROWID host variables.
See Chapter 14, “Programming for large objects (LOBs),” on page 281 for a
discussion of how to use these host variables.
Table 11. SQL data types the precompiler uses for assembler declarations (continued)
SQLTYPE of SQLLEN of
Assembler data type host variable host variable SQL data type
Notes:
1. m is the number of bytes.
2. n is the number of double-byte characters.
3. This data type cannot be used as a column type.
Table 12 on page 138 helps you define host variables that receive output from the
database. You can use Table 12 on page 138 to determine the assembler data type
that is equivalent to a given SQL data type. For example, if you retrieve
TIMESTAMP data, you can use the table to define a suitable host variable in the
program that receives the data value.
Table 12 on page 138 shows direct conversions between DB2 data types and host
data types. However, a number of DB2 data types are compatible. When you do
assignments or comparisons of data that have compatible data types, DB2 does
conversions between those compatible data types. See Table 1 on page 5 for
information about compatible data types.
Table 12. SQL data types mapped to typical assembler declarations (continued)
SQL data type Assembler equivalent Notes
Table locator SQL TYPE IS Use this data type only in a user-defined
TABLE LIKE function or stored procedure to receive
table-name rows of a transition table. Do not use this
AS LOCATOR data type as a column type.
BLOB locator SQL TYPE IS Use this data type only to manipulate data
BLOB_LOCATOR in BLOB columns. Do not use this data
type as a column type.
CLOB locator SQL TYPE IS Use this data type only to manipulate data
CLOB_LOCATOR in CLOB columns. Do not use this data
type as a column type.
DBCLOB locator SQL TYPE IS Use this data type only to manipulate data
DBCLOB_LOCATOR in DBCLOB columns. Do not use this data
type as a column type.
BLOB(n) SQL TYPE IS 1≤n≤2147483647
BLOB(n)
CLOB(n) SQL TYPE IS 1≤n≤2147483647
CLOB(n)
DBCLOB(n) SQL TYPE IS n is the number of double-byte characters.
DBCLOB(n) 1≤n≤1073741823
ROWID SQL TYPE IS ROWID
Notes:
1. IEEE floating-point host variables are not supported in user-defined functions and stored
procedures.
Host graphic data type: You can use the assembler data type “host graphic” in
SQL statements when the precompiler option GRAPHIC is in effect. However, you
cannot use assembler DBCS literals in SQL statements, even when GRAPHIC is in
effect.
Special purpose assembler data types: The locator data types are assembler
language data types and SQL data types. You cannot use locators as column types.
For information about how to use these data types, see the following sections:
When your program uses X to assign a null value to a column, the program should
set the indicator variable to a negative number. DB2 then assigns a null value to the
column and ignores any value in X.
You declare indicator variables in the same way as host variables. You can mix the
declarations of the two types of variables in any way that seems appropriate. For
more information about indicator variables, see “Using indicator variables with host
variables” on page 75 or Chapter 2 of DB2 SQL Reference.
Example: The following example shows a FETCH statement with the declarations
of the host variables that are needed for the FETCH statement:
EXEC SQL FETCH CLS_CURSOR INTO :CLSCD, X
:DAY :DAYIND, X
:BGN :BGNIND, X
:END :ENDIND
variable-name DC H
DS 1 L2
| You can also use the MESSAGE_TEXT condition item field of the GET
| DIAGNOSTICS statement to convert an SQL return code into a text message.
| Programs that require long token message support should code the GET
| DIAGNOSTICS statement instead of DSNTIAR. For more information about GET
| DIAGNOSTICS, see “Using the GET DIAGNOSTICS statement” on page 84.
DSNTIAR syntax
CALL DSNTIAR,(sqlca, message, lrecl),MF=(E,PARM)
where MESSAGE is the name of the message output area, LINES is the
number of lines in the message output area, and LRECL is the length of each
line.
lrecl
A fullword containing the logical record length of output messages, between 72
and 240.
CICS
If your CICS application requires CICS storage handling, you must use the
subroutine DSNTIAC instead of DSNTIAR. DSNTIAC has the following syntax:
CALL DSNTIAC,(eib,commarea,sqlca,msg,lrecl),MF=(E,PARM)
DSNTIAC has extra parameters, which you must use for calls to routines that
use CICS commands.
eib EXEC interface block
commarea communication area
You must define DSNTIA1 in the CSD. If you load DSNTIAR or DSNTIAC, you
must also define them in the CSD. For an example of CSD entry generation
statements for use with DSNTIAC, see member DSN8FRDO in the data set
prefix.SDSNSAMP.
The assembler source code for DSNTIAC and job DSNTEJ5A, which
assembles and link-edits DSNTIAC, are also in the data set
prefix.SDSNSAMP.
DB2 sets the SQLCODE and SQLSTATE values after each SQL statement
executes. An application can check these values to determine whether the last SQL
statement was successful. All SQL statements in the program must be within the
scope of the declaration of the SQLCODE and SQLSTATE variables.
A standard declaration includes both a structure definition and a static data area
named ’sqlca’. See Chapter 5 of DB2 SQL Reference for more information about
the INCLUDE statement and Appendix C of DB2 SQL Reference for a complete
description of SQLCA fields.
Unlike the SQLCA, more than one SQLDA can exist in a program, and an SQLDA
can have any valid name. You can code an SQLDA in a C program, either directly
or by using the SQL INCLUDE statement. The SQL INCLUDE statement requests a
standard SQLDA declaration:
EXEC SQL INCLUDE SQLDA;
A standard declaration includes only a structure definition with the name ’sqlda’.
See Chapter 5 of DB2 SQL Reference for more information about the INCLUDE
statement and Appendix C of DB2 SQL Reference for a complete description of
SQLDA fields.
You must place SQLDA declarations before the first SQL statement that references
the data descriptor, unless you use the precompiler option TWOPASS. You can
place an SQLDA declaration wherever C allows a structure definition. Normal C
scoping rules apply.
Each SQL statement in a C program must begin with EXEC SQL and end with a
semicolon (;). The EXEC and SQL keywords must appear on one line, but the
remainder of the statement can appear on subsequent lines.
In general, because C is case sensitive, use uppercase letters to enter all SQL
keywords. However, if you use the FOLD precompiler suboption, DB2 folds
lowercase letters in SBCS SQL ordinary identifiers to uppercase. For information
about host language precompiler options, see Table 63 on page 462.
You must keep the case of host variable names consistent throughout the program.
For example, if a host variable name is lowercase in its declaration, it must be
lowercase in all SQL statements. You might code an UPDATE statement in a C
program as follows:
EXEC SQL
UPDATE DSN8810.DEPT
SET MGRNO = :mgr_num
WHERE DEPTNO = :int_dept;
Comments: You can include C comments (/* ... */) within SQL statements wherever
you can use a blank, except between the keywords EXEC and SQL. You can use
single-line comments (starting with //) in C language statements, but not in
embedded SQL. You cannot nest comments.
Declaring tables and views: Your C program should use the DECLARE TABLE
statement to describe each table and view the program accesses. You can use the
DB2 declarations generator (DCLGEN) to generate the DECLARE TABLE
statements. For more information, see Chapter 8, “Generating declarations for your
tables using DCLGEN,” on page 121.
You cannot nest SQL INCLUDE statements. Do not use C #include statements to
include SQL statements or C host variable declarations.
Margins: Code SQL statements in columns 1 through 72, unless you specify other
margins to the DB2 precompiler. If EXEC SQL is not within the specified margins,
the DB2 precompiler does not recognize the SQL statement.
Names: You can use any valid C name for a host variable, subject to the following
restrictions:
Nulls and NULs: C and SQL differ in the way they use the word null. The C
language has a null character (NUL), a null pointer (NULL), and a null statement
(just a semicolon). The C NUL is a single character that compares equal to 0. The
C NULL is a special reserved pointer value that does not point to any valid data
object. The SQL null value is a special value that is distinct from all non-null values
and denotes the absence of a (nonnull) value. In this chapter, NUL is the null
character in C and NULL is the SQL null value.
Sequence numbers: The source statements that the DB2 precompiler generates
do not include sequence numbers.
Trigraph characters: Some characters from the C character set are not available
on all keyboards. You can enter these characters into a C source program using a
sequence of three characters called a trigraph. The trigraph characters that DB2
supports are the same as those that the C compiler supports.
WHENEVER statement: The target for the GOTO clause in an SQL WHENEVER
statement must be within the scope of any SQL statements that the statement
WHENEVER affects.
Special C considerations:
v Using the C/370™ multi-tasking facility, in which multiple tasks execute SQL
statements, causes unpredictable results.
v You must run the DB2 precompiler before running the C preprocessor.
v The DB2 precompiler does not support C preprocessor directives.
v If you use conditional compiler directives that contain C code, either place them
after the first C token in your application program, or include them in the C
program using the #include preprocessor directive.
Refer to the appropriate C documentation for more information about C
preprocessor directives.
| Precede C statements that define the host variables and host variable arrays with
| the BEGIN DECLARE SECTION statement, and follow the C statements with the
| END DECLARE SECTION statement. You can have more than one host variable
| declaration section in your program.
| A colon (:) must precede all host variables and all host variable arrays in an SQL
| statement.
| The names of host variables and host variable arrays must be unique within the
| program, even if the variables and variable arrays are in different blocks, classes, or
| procedures. You can qualify the names with a structure name to make them unique.
| An SQL statement that uses a host variable or host variable array must be within
| the scope of the statement that declares that variable or array. You define host
| variable arrays for use with multiple-row FETCH and INSERT statements.
Numeric host variables: Figure 37 shows the syntax for declarations of numeric
host variables.
| float
auto const double
extern volatile int
static short
sqlint32
int
long
int
long long
decimal ( integer )
, integer
| ,
variable-name ;
*pointer-name =expression
| Notes:
| 1. The SQL statement coprocessor is required if you use a pointer as a host
| variable.
Character host variables: The four valid forms for character host variables are:
v Single-character form
v NUL-terminated character form
v VARCHAR structured form
v CLOBs
The following figures show the syntax for forms other than CLOBs. See Figure 46
on page 153 for the syntax of CLOBs.
Figure 38 on page 148 shows the syntax for declarations of single-character host
variables.
| ,
char variable-name ;
auto const unsigned *pointer-name =expression
extern volatile
static
| Notes:
| 1. The SQL statement coprocessor is required if you use a pointer as a host
| variable.
char
auto const unsigned
extern volatile
static
| ,
variable-name [ length ] ;
*pointer-name =expression
Notes:
1. On input, the string contained by the variable must be NUL-terminated.
2. On output, the string is NUL-terminated.
3. A NUL-terminated character host variable maps to a varying-length character
string (except for the NUL).
| 4. The SQL statement coprocessor is required if you use a pointer as a host
| variable.
int
struct { short var-1 ;
auto const tag
extern volatile
static
| ,
variable-name ;
*pointer-name ={expression, expression}
Notes:
1. var-1 and var-2 must be simple variable references. You cannot use them as
host variables.
2. You can use the struct tag to define other data areas that you cannot use as
host variables.
| 3. The SQL statement coprocessor is required if you use a pointer as a host
| variable.
Example: The following examples show valid and invalid declarations of the
VARCHAR structured form:
EXEC SQL BEGIN DECLARE SECTION;
Graphic host variables: The four valid forms for graphic host variables are:
v Single-graphic form
v NUL-terminated graphic form
v VARGRAPHIC structured form.
v DBCLOBs
| You can use the C data type sqldbchar to define a host variable that inserts,
updates, deletes, and selects data from GRAPHIC or VARGRAPHIC columns.
The following figures show the syntax for forms other than DBCLOBs. See
Figure 46 on page 153 for the syntax of DBCLOBs.
Figure 41 on page 150 shows the syntax for declarations of single-graphic host
variables.
| ,
sqldbchar variable-name ;
auto const *pointer-name =expression
extern volatile
static
| Notes:
| 1. The SQL statement coprocessor is required if you use a pointer as a host
| variable.
| ,
Notes:
1. length must be a decimal integer constant greater than 1 and not greater than
16352.
2. On input, the string in variable-name must be NUL-terminated.
3. On output, the string is NUL-terminated.
4. The NUL-terminated graphic form does not accept single-byte characters into
variable-name.
| 5. The SQL statement coprocessor is required if you use a pointer as a host
| variable.
Figure 43 on page 151 shows the syntax for declarations of graphic host variables
that use the VARGRAPHIC structured form.
int
struct { short var-1 ;
auto const tag
extern volatile
static
| ,
;
Notes:
1. length must be a decimal integer constant greater than 1 and not greater than
16352.
2. var-1 must be less than or equal to length.
3. var-1 and var-2 must be simple variable references. You cannot use them as
host variables.
4. You can use the struct tag to define other data areas that you cannot use as
host variables.
| 5. The SQL statement coprocessor is required if you use a pointer as a host
| variable.
Example: The following examples show valid and invalid declarations of graphic
host variables that use the VARGRAPHIC structured form:
EXEC SQL BEGIN DECLARE SECTION;
Result set locators: Figure 44 on page 152 shows the syntax for declarations of
result set locators. See Chapter 25, “Using stored procedures for client/server
processing,” on page 569 for a discussion of how to use these host variables.
| ,
variable-name ;
*pointer-name = init-value
Table Locators: Figure 45 shows the syntax for declarations of table locators. See
“Accessing transition tables in a user-defined function or stored procedure” on page
328 for a discussion of how to use these host variables.
| ,
variable-name ;
*pointer-name init-value
LOB Variables and Locators: Figure 46 on page 153 shows the syntax for
declarations of BLOB, CLOB, and DBCLOB host variables and locators. See
Chapter 14, “Programming for large objects (LOBs),” on page 281 for a discussion
of how to use these host variables.
SQL TYPE IS
auto const
extern volatile
static
register
| ,
;
ROWIDs: Figure 47 shows the syntax for declarations of ROWID host variables.
See Chapter 14, “Programming for large objects (LOBs),” on page 281 for a
discussion of how to use these host variables.
| Numeric host variable arrays: Figure 48 on page 154 shows the syntax for
| declarations of numeric host variable arrays.
|
| float
auto const unsigned double
extern volatile int
static long
short
int
long long
decimal ( integer )
, integer
variable-name [ dimension ] ;
,
= { expression }
| Note:
| 1. dimension must be an integer constant between 1 and 32767.
| Character host variable arrays: The three valid forms for character host variable
| arrays are:
| v NUL-terminated character form
| v VARCHAR structured form
| v CLOBs
| The following figures show the syntax for forms other than CLOBs. See Figure 53
| on page 158 for the syntax of CLOBs.
char
auto const unsigned
extern volatile
static
= { expression }
| Notes:
| 1. On input, the strings contained in the variable arrays must be NUL-terminated.
| 2. On output, the strings are NUL-terminated.
| 3. The strings in a NUL-terminated character host variable array map to
| varying-length character strings (except for the NUL).
| 4. dimension must be an integer constant between 1 and 32767.
int
struct { short var-1 ;
auto const
extern volatile
static
variable-name [ dimension ] ;
,
= { expression }
| Notes:
| 1. var-1 must be a simple variable reference, and var-2 must be a variable array
| reference.
| 2. You can use the struct tag to define other data areas, which you cannot use as
| host variable arrays.
| 3. dimension must be an integer constant between 1 and 32767.
| Example: The following examples show valid and invalid declarations of VARCHAR
| host variable arrays:
| EXEC SQL BEGIN DECLARE SECTION;
| /* valid declaration of VARCHAR host variable array */
| struct VARCHAR {
| short len;
| char s[18];
| } name[10];
|
| /* invalid declaration of VARCHAR host variable array */
| struct VARCHAR name[10];
| Graphic host variable arrays: The two valid forms for graphic host variable arrays
| are:
| v NUL-terminated graphic form
| v VARGRAPHIC structured form.
| You can use the C data type sqldbchar to define a host variable array that inserts,
| updates, deletes, and selects data from GRAPHIC or VARGRAPHIC columns.
| Figure 51 shows the syntax for declarations of NUL-terminated graphic host variable
| arrays.
|
sqldbchar
auto const unsigned
extern volatile
static
= { expression }
| Notes:
| 1. length must be a decimal integer constant greater than 1 and not greater than
| 16352.
| 2. On input, the strings contained in the variable arrays must be NUL-terminated.
| 3. On output, the string is NUL-terminated.
| 4. The NUL-terminated graphic form does not accept single-byte characters into
| the variable array.
| 5. dimension must be an integer constant between 1 and 32767.
| Figure 52 on page 157 shows the syntax for declarations of graphic host variable
| arrays that use the VARGRAPHIC structured form.
|
int
struct { short var-1 ;
auto const
extern volatile
static
variable-name [ dimension ] ;
,
= { expression }
| Notes:
| 1. length must be a decimal integer constant greater than 1 and not greater than
| 16352.
| 2. var-1 must be a simple variable reference, and var-2 must be a variable array
| reference.
| 3. You can use the struct tag to define other data areas, which you cannot use as
| host variable arrays.
| 4. dimension must be an integer constant between 1 and 32767.
| Example: The following examples show valid and invalid declarations of graphic
| host variable arrays that use the VARGRAPHIC structured form:
| EXEC SQL BEGIN DECLARE SECTION;
| /* valid declaration of host variable array vgraph */
| struct VARGRAPH {
| short len;
| sqldbchar d[10];
| } vgraph[20];
|
| /* invalid declaration of host variable array vgraph */
| struct VARGRAPH vgraph[20];
| LOB variable arrays and locators: Figure 53 on page 158 shows the syntax for
| declarations of BLOB, CLOB, and DBCLOB host variable arrays and locators. See
| Chapter 14, “Programming for large objects (LOBs),” on page 281 for a discussion
| of how to use LOB variables.
|
SQL TYPE IS
auto const
extern volatile
static
register
variable-name [ dimension ] ;
,
= { expression }
| Note:
| 1. dimension must be an integer constant between 1 and 32767.
| ROWIDs: Figure 54 shows the syntax for declarations of ROWID variable arrays.
| See Chapter 14, “Programming for large objects (LOBs),” on page 281 for a
| discussion of how to use these host variable arrays.
|
| Note:
| 1. dimension must be an integer constant between 1 and 32767.
In this example, target is the name of a host structure consisting of the c1, c2, and
c3 fields. c1 and c3 are character arrays, and c2 is the host variable equivalent to
the SQL VARCHAR data type. The target host structure can be part of another host
structure but must be the deepest level of the nested structure.
struct {
auto const packed tag
extern volatile
static
float var-1 ; }
double
int
short
sqlint32
int
long
int
long long
decimal ( integer )
, integer
varchar structure
vargraphic structure
SQL TYPE IS ROWID
LOB data type
char var-2 ;
unsigned [ length ]
sqldbchar var-5 ;
[ length ]
variable-name ;
=expression
Figure 56 on page 160 shows the syntax for VARCHAR structures that are used
within declarations of host structures.
int
struct { short var-3 ;
tag signed
Figure 57 shows the syntax for VARGRAPHIC structures that are used within
declarations of host structures.
| int
struct { short var-6 ; sqldbchar var-7 [ length ] ; }
tag signed
Figure 58 shows the syntax for LOB data types that are used within declarations of
host structures.
Table 13. SQL data types the precompiler uses for C declarations (continued)
SQLTYPE of host SQLLEN of host
C data type variable variable SQL data type
float 480 4 FLOAT (single
precision)
double 480 8 FLOAT (double
precision)
Single-character form 452 1 CHAR(1)
NUL-terminated 460 n VARCHAR (n-1)
character form
VARCHAR structured 448 n VARCHAR(n)
form 1<=n<=255
VARCHAR structured 456 n VARCHAR(n)
form
n>255
Single-graphic form 468 1 GRAPHIC(1)
NUL-terminated 400 n VARGRAPHIC (n-1)
graphic form
| (sqldbchar)
VARGRAPHIC 464 n VARGRAPHIC(n)
structured form
1<=n<128
VARGRAPHIC 472 n VARGRAPHIC(n)
structured form
n>127
SQL TYPE IS 972 4 Result set locator2
RESULT_SET
_LOCATOR
Table 13. SQL data types the precompiler uses for C declarations (continued)
SQLTYPE of host SQLLEN of host
C data type variable variable SQL data type
Notes:
1. p is the precision; in SQL terminology, this the total number of digits. In C, this is called
the size.
s is the scale; in SQL terminology, this is the number of digits to the right of the decimal
point. In C, this is called the precision.
| C++ does not support the decimal data type.
2. Do not use this data type as a column type.
3. n is the number of double-byte characters.
4. No exact equivalent. Use DECIMAL(19,0).
Table 14 helps you define host variables that receive output from the database. You
can use the table to determine the C data type that is equivalent to a given SQL
data type. For example, if you retrieve TIMESTAMP data, you can use the table to
define a suitable host variable in the program that receives the data value.
Table 14 shows direct conversions between DB2 data types and host data types.
However, a number of DB2 data types are compatible. When you do assignments
or comparisons of data that have compatible data types, DB2 does conversions
between those compatible data types. See Table 1 on page 5 for information about
compatible data types.
Table 14. SQL data types mapped to typical C declarations
SQL data type C data type Notes
SMALLINT short int
INTEGER long int
DECIMAL(p,s) or decimal You can use the double data type if your C
NUMERIC(p,s) compiler does not have a decimal data
type; however, double is not an exact
equivalent.
REAL or FLOAT(n) float 1<=n<=21
DOUBLE PRECISION or double 22<=n<=53
FLOAT(n)
CHAR(1) single-character form
CHAR(n) no exact equivalent If n>1, use NUL-terminated character form
VARCHAR(n) NUL-terminated character form If data can contain character NULs (\0),
use VARCHAR structured form. Allow at
least n+1 to accommodate the
NUL-terminator.
VARCHAR structured form
GRAPHIC(1) single-graphic form
GRAPHIC(n) no exact equivalent If n>1, use NUL-terminated graphic form. n
is the number of double-byte characters.
C data types with no SQL equivalent: C supports some data types and storage
| classes with no SQL equivalents, for example, register storage class, typedef, long
| long, and the pointer.
SQL data types with no C equivalent: If your C compiler does not have a decimal
data type, no exact equivalent exists for the SQL DECIMAL data type. In this case,
to hold the value of such a variable, you can use:
v An integer or floating-point variable, which converts the value. If you choose
integer, you will lose the fractional part of the number. If the decimal number can
exceed the maximum value for an integer, or if you want to preserve a fractional
value, you can use floating-point numbers. Floating-point numbers are
approximations of real numbers. Therefore, when you assign a decimal number
to a floating-point variable, the result might be different from the original number.
v A character-string host variable. Use the CHAR function to get a string
representation of a decimal number.
v The DECIMAL function to explicitly convert a value to a decimal data type, as in
this example:
long duration=10100; /* 1 year and 1 month */
char result_dt[11];
Special Purpose C Data Types: The locator data types are C data types and SQL
data types. You cannot use locators as column types. For information about how to
use these data types, see the following sections:
PREPARE or DESCRIBE statements: You cannot use a host variable that is of the
| NUL-terminated form in either a PREPARE or DESCRIBE statement when you use
| the DB2 precompiler. However, if you use the SQL statement coprocessor for either
| C or C++, you can use host variables of the NUL-terminated form in PREPARE,
| DESCRIBE, and EXECUTE IMMEDIATE statements.
Truncation: Be careful of truncation. Ensure that the host variable you declare can
contain the data and a NUL terminator, if needed. Retrieving a floating-point or
decimal column value into a long integer host variable removes any fractional part
of the value.
In SQL, you can use double quotes to delimit identifiers and apostrophes to delimit
string constants. The following examples illustrate the use of apostrophes and
quotes in SQL.
Quotes
SELECT "COL#1" FROM TBL1;
Apostrophes
SELECT COL1 FROM TBL1 WHERE COL2 = ’BELL’;
Character data in SQL is distinct from integer data. Character data in C is a subtype
of integer data.
Varying-length strings: For varying-length BIT data, use the VARCHAR structured
form. Some C string manipulation functions process NUL-terminated strings and
other functions process strings that are not NUL-terminated. The C string
manipulation functions that process NUL-terminated strings cannot handle bit data
because these functions might misinterpret a NUL character to be a NUL-terminator.
Using indicator variables: If you provide an indicator variable for the variable X,
when DB2 retrieves a null value for X, it puts a negative value in the indicator
variable and does not update X. Your program should check the indicator variable
before using X. If the indicator variable is negative, you know that X is null and any
value you find in X is irrelevant.
When your program uses X to assign a null value to a column, the program should
set the indicator variable to a negative number. DB2 then assigns a null value to the
column and ignores any value in X. For more information about indicator variables,
see “Using indicator variables with host variables” on page 75.
| Using indicator variable arrays: When you retrieve data into a host variable array,
| if a value in its indicator array is negative, you can disregard the contents of the
| corresponding element in the host variable array. For more information about
| indicator variable arrays, see “Using indicator variable arrays with host variable
| arrays” on page 79.
Declaring indicator variables: You declare indicator variables in the same way as
host variables. You can mix the declarations of the two types of variables in any
way that seems appropriate.
Example: The following example shows a FETCH statement with the declarations
of the host variables that are needed for the FETCH statement:
EXEC SQL FETCH CLS_CURSOR INTO :ClsCd,
:Day :DayInd,
:Bgn :BgnInd,
:End :EndInd;
,
int
short variable-name ;
auto const signed = expression
extern volatile
static
Declaring indicator variable arrays: Figure 60 shows the syntax for declarations
| of an indicator array or a host structure indicator array.
int
short
auto const signed
extern volatile
static
variable-name [ dimension ] ;
= expression
| You can also use the MESSAGE_TEXT condition item field of the GET
| DIAGNOSTICS statement to convert an SQL return code into a text message.
| Programs that require long token message support should code the GET
| DIAGNOSTICS statement instead of DSNTIAR. For more information about GET
| DIAGNOSTICS, see “Using the GET DIAGNOSTICS statement” on page 84.
DSNTIAR syntax
rc = dsntiar(&sqlca, &message, &lrecl);
where error_message is the name of the message output area, data_dim is the
number of lines in the message output area, and data_len is the length of each
line.
&lrecl
A fullword containing the logical record length of output messages, between 72
and 240.
For C, include:
#pragma linkage (dsntiar,OS)
CICS
If your CICS application requires CICS storage handling, you must use the
subroutine DSNTIAC instead of DSNTIAR. DSNTIAC has the following syntax:
rc = DSNTIAC(&eib, &commarea, &sqlca, &message, &lrecl);
DSNTIAC has extra parameters, which you must use for calls to routines that
use CICS commands.
&eib EXEC interface block
&commarea
communication area
You must define DSNTIA1 in the CSD. If you load DSNTIAR or DSNTIAC, you
must also define them in the CSD. For an example of CSD entry generation
statements for use with DSNTIAC, see job DSNTEJ5A.
The assembler source code for DSNTIAC and job DSNTEJ5A, which
assembles and link-edits DSNTIAC, are in the data set prefix.SDSNSAMP.
| Declaring host variable arrays: For both C and C++, you cannot specify the
| _packed attribute on the structure declarations for varying-length character arrays,
| varying-length graphic arrays, or LOB arrays that are to be used in multiple-row
| INSERT and FETCH statements. In addition, the #pragma pack(1) directive cannot
| be in effect if you plan to use these arrays in multiple-row statements.
Except where noted otherwise, this information pertains to all COBOL compilers
supported by DB2 UDB for z/OS.
v An SQLCODE variable declared as PIC S9(9) BINARY, PIC S9(9) COMP-4, PIC
S9(9) COMP-5, or PICTURE S9(9) COMP
v An SQLSTATE variable declared as PICTURE X(5)
Alternatively, you can include an SQLCA, which contains the SQLCODE and
SQLSTATE variables.
DB2 sets the SQLCODE and SQLSTATE values after each SQL statement
executes. An application can check these values to determine whether the last SQL
statement was successful. All SQL statements in the program must be within the
scope of the declaration of the SQLCODE and SQLSTATE variables.
When you use the precompiler option STDSQL(YES), you must declare an
SQLCODE variable. DB2 declares an SQLCA area for you in the
WORKING-STORAGE SECTION. DB2 controls the structure and location of the
SQLCA.
You can specify INCLUDE SQLCA or a declaration for SQLCODE wherever you
can specify a 77 level or a record description entry in the WORKING-STORAGE
SECTION. You can declare a stand-alone SQLCODE variable in either the
WORKING-STORAGE SECTION or LINKAGE SECTION.
See Chapter 5 of DB2 SQL Reference for more information about the INCLUDE
statement and Appendix C of DB2 SQL Reference for a complete description of
SQLCA fields.
Unlike the SQLCA, a program can have more than one SQLDA, and an SQLDA
can have any valid name. The SQL INCLUDE statement does not provide an
SQLDA mapping for COBOL. You can define the SQLDA using one of the following
two methods:
v For COBOL programs compiled with any compiler except the OS/VS COBOL
compiler, you can code the SQLDA declarations in your program. For more
information, see “Using dynamic SQL in COBOL” on page 568. You must place
SQLDA declarations in the WORKING-STORAGE SECTION or LINKAGE
SECTION of your program, wherever you can specify a record description entry
in that section.
v For COBOL programs compiled with any compiler, you can call a subroutine
(written in C, PL/I, or assembler language) that uses the INCLUDE SQLDA
statement to define the SQLDA. The subroutine can also include SQL statements
for any dynamic SQL functions you need. For more information on using dynamic
SQL, see Chapter 24, “Coding dynamic SQL in application programs,” on page
535.
You must place SQLDA declarations before the first SQL statement that references
the data descriptor. An SQL statement that uses a host variable must be within the
scope of the statement that declares the variable.
Notes:
1. When including host variable declarations, the INCLUDE statement must be in the
WORKING-STORAGE SECTION or the LINKAGE SECTION.
Each SQL statement in a COBOL program must begin with EXEC SQL and end
with END-EXEC. If the SQL statement appears between two COBOL statements,
the period is optional and might not be appropriate. If the statement appears in an
IF...THEN set of COBOL statements, omit the ending period to avoid inadvertently
ending the IF statement. The EXEC and SQL keywords must appear on one line,
but the remainder of the statement can appear on subsequent lines.
EXEC SQL
UPDATE DSN8810.DEPT
SET MGRNO = :MGR-NUM
WHERE DEPTNO = :INT-DEPT
END-EXEC.
| In addition, you can include SQL comments in any embedded SQL statement.
Continuation for SQL statements: The rules for continuing a character string
constant from one line to the next in an SQL statement embedded in a COBOL
program are the same as those for continuing a non-numeric literal in COBOL.
However, you can use either a quote or an apostrophe as the first nonblank
character in area B of the continuation line. The same rule applies for the
continuation of delimited identifiers and does not depend on the string delimiter
option.
Declaring tables and views: Your COBOL program should include the statement
DECLARE TABLE to describe each table and view the program accesses. You can
use the DB2 declarations generator (DCLGEN) to generate the DECLARE TABLE
statements. You should include the DCLGEN members in the DATA DIVISION. For
more information, see Chapter 8, “Generating declarations for your tables using
DCLGEN,” on page 121.
If you are using the DB2 precompiler, you cannot nest SQL INCLUDE statements.
In this case, do not use COBOL verbs to include SQL statements or host variable
declarations, and do not use the SQL INCLUDE statement to include CICS
preprocessor related code. In general, if you are using the DB2 precompiler, use
the SQL INCLUDE statement only for SQL-related coding. If you are using the
COBOL SQL coprocessor, none of these restrictions apply.
Margins: You must code EXEC SQL in columns 12 through 72, otherwise the DB2
precompiler does not recognize the SQL statement. Continued lines of a SQL
statement can be in columns 8 through 72.
Names: You can use any valid COBOL name for a host variable. Do not use
external entry names or access plan names that begin with ’DSN’, and do not use
host variable names that begin with ’SQL’. These names are reserved for DB2.
Sequence numbers: The source statements that the DB2 precompiler generates
do not include sequence numbers.
WHENEVER statement: The target for the GOTO clause in an SQL statement
WHENEVER must be a section name or unqualified paragraph name in the
PROCEDURE DIVISION.
Because stored procedures use CAF, you must also compile COBOL stored
procedures with the option NODYNAM.
v If a COBOL program contains several entry points or is called several times, the
USING clause of the entry statement that executes before the first SQL
statement executes must contain the SQLCA and all linkage section entries that
any SQL statement uses as host variables.
| v If you use the DB2 precompiler, the REPLACE statement has no effect on SQL
| statements. It affects only the COBOL statements that the precompiler generates.
| If you use the SQL statement coprocessor, the REPLACE statement replaces
| text strings in SQL statements as well as in generated COBOL statements.
| v If you use the DB2 precompiler, no compiler directives should appear between
| the PROCEDURE DIVISION and the DECLARATIVES statement.
v Do not use COBOL figurative constants (such as ZERO and SPACE), symbolic
characters, reference modification, and subscripts within SQL statements.
v Observe the rules in Chapter 2 of DB2 SQL Reference when you name SQL
identifiers. However, for COBOL only, the names of SQL identifiers can follow the
rules for naming COBOL words, if the names do not exceed the allowable length
for the DB2 object. For example, the name 1ST-TIME is a valid cursor name
because it is a valid COBOL word, but the name 1ST_TIME is not valid because
it is not a valid SQL identifier or a valid COBOL word.
v Observe these rules for hyphens:
– Surround hyphens used as subtraction operators with spaces. DB2 usually
interprets a hyphen with no spaces around it as part of a host variable name.
– You can use hyphens in SQL identifiers under either of the following
circumstances:
- The application program is a local application that runs on DB2 UDB for
OS/390 Version 6 or later.
- The application program accesses remote sites, and the local site and
remote sites are DB2 UDB for OS/390 Version 6 or later.
v If you include an SQL statement in a COBOL PERFORM ... THRU paragraph and
also specify the SQL statement WHENEVER ... GO, the COBOL compiler returns
the warning message IGYOP3094. That message might indicate a problem. This
usage is not recommended.
v If you are using the DB2 precompiler and VS COBOL II or later (with the
compiler option NOCMPR2), the following additional restrictions apply:
– All SQL statements and any host variables they reference must be within the
first program when using nested programs or batch compilation.
– DB2 COBOL programs must have a DATA DIVISION and a PROCEDURE
DIVISION. Both divisions and the WORKING-STORAGE section must be
present in programs that contain SQL statements.
If you pass host variables with address changes into a program more than once,
the called program must reset SQL-INIT-FLAG. Resetting this flag indicates that the
storage must initialize when the next SQL statement executes. To reset the flag,
insert the statement MOVE ZERO TO SQL-INIT-FLAG in the called program’s
PROCEDURE DIVISION, ahead of any executable SQL statements that use the
host variables.
If you use the COBOL SQL statement coprocessor, the called program does not
need to reset SQL-INIT-FLAG.
| program’s DATA DIVISION. You must explicitly declare each host variable and host
| variable array before using them in an SQL statement.
| You can precede COBOL statements that define the host variables and host
| variable arrays with the statement BEGIN DECLARE SECTION, and follow the
| statements with the statement END DECLARE SECTION. You must use the
| statements BEGIN DECLARE SECTION and END DECLARE SECTION when you
| use the precompiler option STDSQL(YES).
| A colon (:) must precede all host variables and all host variable arrays in an SQL
| statement.
| The names of host variables and host variable arrays should be unique within the
| source data set or member, even if the variables and variable arrays are in different
| blocks, classes, or procedures. You can qualify the names with a structure name to
| make them unique.
| An SQL statement that uses a host variable or host variable array must be within
| the scope of the statement that declares that variable or array. You define host
| variable arrays for use with multiple-row FETCH and INSERT statements.
| You can specify OCCURS when defining an indicator structure, a host variable
| array, or an indicator variable array. You cannot specify OCCURS for any other type
| of host variable.
Numeric host variables: The three valid forms of numeric host variables are:
v Floating-point numbers
v Integers and small integers
v Decimal numbers
Figure 61 shows the syntax for declarations of floating-point or real host variables.
01 variable-name COMPUTATIONAL-1
77 IS COMP-1
level-1 USAGE COMPUTATIONAL-2
COMP-2
.
IS
VALUE numeric-constant
Notes:
1. level-1 indicates a COBOL level between 2 and 48.
2. COMPUTATIONAL-1 and COMP-1 are equivalent.
3. COMPUTATIONAL-2 and COMP-2 are equivalent.
Figure 62 shows the syntax for declarations of integer and small integer host
variables.
IS
01 variable-name PICTURE S9(4)
77 PIC S9999 IS
level-1 S9(9) USAGE
S999999999
BINARY .
COMPUTATIONAL-4 IS
COMP-4 VALUE numeric-constant
COMPUTATIONAL-5
COMP-5
COMPUTATIONAL
COMP
Notes:
1. level-1 indicates a COBOL level between 2 and 48.
2. The COBOL binary integer data types BINARY, COMPUTATIONAL, COMP,
COMPUTATIONAL-4, and COMP-4 are equivalent.
3. COMPUTATIONAL-5 (and COMP-5) are equivalent to the other COBOL binary
integer data types if you compile the other data types with TRUNC(BIN).
4. Any specification for scale is ignored.
IS
01 variable-name PICTURE picture-string
77 PIC IS
level-1 USAGE
PACKED-DECIMAL
COMPUTATIONAL-3 IS
COMP-3 VALUE numeric-constant
IS CHARACTER
DISPLAY SIGN LEADING SEPARATE
.
Notes:
1. level-1 indicates a COBOL level between 2 and 48.
2. PACKED-DECIMAL, COMPUTATIONAL-3, and COMP-3 are equivalent. The
picture-string that is that is associated with these types must have the form
S9(i)V9(d) (or S9...9V9...9, with i and d instances of 9) or S9(i)V.
3. The picture-string that is associated with SIGN LEADING SEPARATE must have
the form S9(i)V9(d) (or S9...9V9...9, with i and d instances of 9 or S9...9V with i
instances of 9).
Character host variables: The three valid forms of character host variables are:
v Fixed-length strings
v Varying-length strings
v CLOBs
The following figures show the syntax for forms other than CLOBs. See Figure 70
on page 182 for the syntax of CLOBs.
Figure 64 shows the syntax for declarations of fixed-length character host variables.
IS
01 variable-name PICTURE picture-string
77 PIC
level-1
.
DISPLAY IS
IS VALUE character-constant
USAGE
Notes:
1. level-1 indicates a COBOL level between 2 and 48.
| 2. The picture-string that is associated with these forms must be X(m) (or XX...X,
| with m instances of X), with 1 <= m <= 32767 for fixed-length strings. However,
| the maximum length of the CHAR data type (fixed-length character string) in
| DB2 is 255 bytes.
01 variable-name .
level-1
IS
49 var-1 PICTURE S9(4) BINARY
PIC S9999 IS COMPUTATIONAL-4
USAGE COMP-4
COMPUTATIONAL-5
COMP-5
COMPUTATIONAL
COMP
.
IS
VALUE numeric-constant
IS
49 var-2 PICTURE picture-string
PIC DISPLAY
IS
USAGE
.
IS
VALUE character-constant
Notes:
1. level-1 indicates a COBOL level between 2 and 48.
2. DB2 uses the full length of the S9(4) BINARY variable even though COBOL with
TRUNC(STD) only recognizes values up to 9999. This can cause data
truncation errors when COBOL statements execute and might effectively limit
the maximum length of variable-length character strings to 9999. Consider using
the TRUNC(BIN) compiler option or USAGE COMP-5 to avoid data truncation.
3. For fixed-length strings, the picture-string must be X(m) (or XX...X, with m
instances of X), with 1 <= m <= 32767; for other strings, m cannot be greater
than the maximum size of a varying-length character string.
4. You cannot directly reference var-1 and var-2 as host variables.
5. You cannot use an intervening REDEFINE at level 49.
Graphic character host variables: The three valid forms for graphic character host
variables are:
v Fixed-length strings
v Varying-length strings
v DBCLOBs
The following figures show the syntax for forms other than DBCLOBs. See
Figure 70 on page 182 for the syntax of DBCLOBs.
Figure 66 shows the syntax for declarations of fixed-length graphic host variables.
IS
01 variable-name PICTURE picture-string
77 PIC
level-1
DISPLAY-1 .
IS NATIONAL IS
USAGE VALUE graphic-constant
Notes:
1. level-1 indicates a COBOL level between 2 and 48.
2. For fixed-length strings, the picture-string is G(m) or N(m) (or, m instances of
GG...G or NN...N), with 1 <= m <= 127; for other strings, m cannot be greater
than the maximum size of a varying-length graphic string.
3. Use USAGE NATIONAL only for Unicode UTF-16 data. In the picture-string for
USAGE NATIONAL, you must use N in place of G. USAGE NATIONAL is
supported only through the SQL statement coprocessor.
Figure 67 on page 181 shows the syntax for declarations of varying-length graphic
host variables.
01 variable-name .
level-1
IS
49 var-1 PICTURE S9(4) BINARY
PIC S9999 IS COMPUTATIONAL-4
USAGE COMP-4
COMPUTATIONAL-5
COMP-5
COMPUTATIONAL
COMP
.
IS
VALUE numeric-constant
IS
49 var-2 PICTURE picture-string DISPLAY-1
PIC IS NATIONAL
USAGE
.
IS
VALUE graphic-constant
Notes:
1. level-1 indicates a COBOL level between 2 and 48.
2. DB2 uses the full length of the S9(4) BINARY variable even though COBOL with
TRUNC(STD) only recognizes values up to 9999. This can cause data
truncation errors when COBOL statements execute and might effectively limit
the maximum length of variable-length character strings to 9999. Consider using
the TRUNC(BIN) compiler option or USAGE COMP-5 to avoid data truncation.
3. For fixed-length strings, the picture-string is G(m) or N(m) (or, m instances of
GG...G or NN...N), with 1 <= m <= 127; for other strings, m cannot be greater
than the maximum size of a varying-length graphic string.
4. Use USAGE NATIONAL only for Unicode UTF-16 data. In the picture-string for
USAGE NATIONAL, you must use N in place of G. USAGE NATIONAL is
supported only through the SQL statement coprocessor.
5. You cannot directly reference var-1 and var-2 as host variables.
Result set locators: Figure 68 on page 182 shows the syntax for declarations of
result set locators. See Chapter 25, “Using stored procedures for client/server
processing,” on page 569 for a discussion of how to use these host variables.
Table Locators: Figure 69 shows the syntax for declarations of table locators. See
“Accessing transition tables in a user-defined function or stored procedure” on page
328 for a discussion of how to use these host variables.
LOB Variables and Locators: Figure 70 shows the syntax for declarations of
BLOB, CLOB, and DBCLOB host variables and locators. See Chapter 14,
“Programming for large objects (LOBs),” on page 281 for a discussion of how to
use these host variables.
ROWIDs: Figure 71 shows the syntax for declarations of ROWID host variables.
See Chapter 14, “Programming for large objects (LOBs),” on page 281 for a
discussion of how to use these host variables.
| Numeric host variable arrays: The three valid forms of numeric host variable
| arrays are:
| v Floating-point numbers
| v Integers and small integers
| v Decimal numbers
| Figure 72 shows the syntax for declarations of floating-point host variable arrays.
|
.
IS
VALUE numeric-constant
| Notes:
| 1. level-1 indicates a COBOL level between 2 and 48.
| 2. COMPUTATIONAL-1 and COMP-1 are equivalent.
| 3. COMPUTATIONAL-2 and COMP-2 are equivalent.
| 4. dimension must be an integer constant between 1 and 32767.
| Figure 73 on page 184 shows the syntax for declarations of integer and small
| integer host variable arrays.
|
IS
level-1 variable-name PICTURE S9(4)
PIC S9999 IS
S9(9) USAGE
S999999999
| Notes:
| 1. level-1 indicates a COBOL level between 2 and 48.
| 2. The COBOL binary integer data types BINARY, COMPUTATIONAL, COMP,
| COMPUTATIONAL-4, and COMP-4 are equivalent.
| 3. COMPUTATIONAL-5 (and COMP-5) are equivalent to the other COBOL binary
| integer data types if you compile the other data types with TRUNC(BIN).
| 4. Any specification for scale is ignored.
| 5. dimension must be an integer constant between 1 and 32767.
| Figure 74 shows the syntax for declarations of decimal host variable arrays.
|
IS
level-1 variable-name PICTURE picture-string
PIC IS
USAGE
PACKED-DECIMAL
COMPUTATIONAL-3
COMP-3
IS CHARACTER
DISPLAY SIGN LEADING SEPARATE
OCCURS dimension .
TIMES IS
VALUE numeric-constant
| Notes:
| 1. level-1 indicates a COBOL level between 2 and 48.
| 2. PACKED-DECIMAL, COMPUTATIONAL-3, and COMP-3 are equivalent. The
| picture-string that is associated with these types must have the form S9(i)V9(d)
| (or S9...9V9...9, with i and d instances of 9) or S9(i)V.
| 3. The picture-string that is associated with SIGN LEADING SEPARATE must have
| the form S9(i)V9(d) (or S9...9V9...9, with i and d instances of 9 or S9...9V with i
| instances of 9).
| 4. dimension must be an integer constant between 1 and 32767.
| Character host variable arrays: The three valid forms of character host variable
| arrays are:
| v Fixed-length character strings
| v Varying-length character strings
| v CLOBs
| The following figures show the syntax for forms other than CLOBs. See Figure 79
| on page 189 for the syntax of CLOBs.
| Figure 75 shows the syntax for declarations of fixed-length character string arrays.
|
IS
level-1 variable-name PICTURE picture-string
PIC DISPLAY
IS
USAGE
OCCURS dimension .
TIMES IS
VALUE character-constant
| Notes:
| 1. level-1 indicates a COBOL level between 2 and 48.
| 2. The picture-string that is associated with these forms must be X(m) (or XX...X,
| with m instances of X), with 1 <= m <= 32767 for fixed-length strings. However,
| the maximum length of the CHAR data type (fixed-length character string) in
| DB2 is 255 bytes.
| 3. dimension must be an integer constant between 1 and 32767.
IS
49 var-1 PICTURE S9(4) BINARY
PIC S9999 IS COMPUTATIONAL-4
USAGE COMP-4
COMPUTATIONAL-5
COMP-5
COMPUTATIONAL
COMP
SYNCHRONIZED .
SYNC IS
VALUE numeric-constant
IS
49 var-2 PICTURE picture-string
PIC DISPLAY
IS
USAGE
.
IS
VALUE character-constant
| Notes:
| 1. level-1 indicates a COBOL level between 2 and 48.
| 2. DB2 uses the full length of the S9(4) BINARY variable even though COBOL with
| TRUNC(STD) recognizes only values up to 9999. This can cause data
| truncation errors when COBOL statements execute and might effectively limit
| the maximum length of variable-length character strings to 9999. Consider using
| the TRUNC(BIN) compiler option or USAGE COMP-5 to avoid data truncation.
| 3. The picture-string that is associated with these forms must be X(m) (or XX...X,
| with m instances of X), with 1 <= m <= 32767 for fixed-length strings; for other
| strings, m cannot be greater than the maximum size of a varying-length
| character string.
| 4. You cannot directly reference var-1 and var-2 as host variable arrays.
| 5. You cannot use an intervening REDEFINE at level 49.
| 6. dimension must be an integer constant between 1 and 32767.
| Graphic character host variable arrays: The three valid forms for graphic
| character host variable arrays are:
| v Fixed-length strings
| v Varying-length strings
| v DBCLOBs
| The following figures show the syntax for forms other than DBCLOBs. See
| Figure 79 on page 189 for the syntax of DBCLOBs.
| Figure 77 shows the syntax for declarations of fixed-length graphic string arrays.
|
IS IS
level-1 variable-name PICTURE picture-string USAGE DISPLAY-1
PIC NATIONAL
OCCURS dimension .
TIMES IS
VALUE graphic-constant
| Notes:
| 1. level-1 indicates a COBOL level between 2 and 48.
| 2. For fixed-length strings, the picture-string is G(m) or N(m) (or, m instances of
| GG...G or NN...N), with 1 <= m <= 127; for other strings, m cannot be greater
| than the maximum size of a varying-length graphic string.
| 3. Use USAGE NATIONAL only for Unicode UTF-16 data. In the picture-string for
| USAGE NATIONAL, you must use N in place of G. USAGE NATIONAL is
| supported only through the SQL statement coprocessor.
| 4. dimension must be an integer constant between 1 and 32767.
| Figure 78 on page 188 shows the syntax for declarations of varying-length graphic
| string arrays.
|
IS
49 var-1 PICTURE S9(4) BINARY
PIC S9999 IS COMPUTATIONAL-4
USAGE COMP-4
COMPUTATIONAL-5
COMP-5
COMPUTATIONAL
COMP
SYNCHRONIZED .
SYNC IS
VALUE numeric-constant
IS IS
49 var-2 PICTURE picture-string USAGE DISPLAY-1
PIC NATIONAL
.
IS
VALUE graphic-constant
| Notes:
| 1. level-1 indicates a COBOL level between 2 and 48.
| 2. DB2 uses the full length of the S9(4) BINARY variable even though COBOL with
| TRUNC(STD) recognizes only values up to 9999. This can cause data
| truncation errors when COBOL statements execute and might effectively limit
| the maximum length of variable-length character strings to 9999. Consider using
| the TRUNC(BIN) compiler option or USAGE COMP-5 to avoid data truncation.
| 3. For fixed-length strings, the picture-string is G(m) or N(m) (or, m instances of
| GG...G or NN...N), with 1 <= m <= 127; for other strings, m cannot be greater
| than the maximum size of a varying-length graphic string.
| 4. Use USAGE NATIONAL only for Unicode UTF-16 data. In the picture-string for
| USAGE NATIONAL, you must use N in place of G. USAGE NATIONAL is
| supported only through the SQL statement coprocessor.
| 5. You cannot directly reference var-1 and var-2 as host variable arrays.
| 6. dimension must be an integer constant between 1 and 32767.
| LOB variable arrays and locators: Figure 79 on page 189 shows the syntax for
| declarations of BLOB, CLOB, and DBCLOB host variable arrays and locators. See
| Chapter 14, “Programming for large objects (LOBs),” on page 281 for a discussion
| of how to use LOB variables.
|
| Notes:
| 1. level-1 indicates a COBOL level between 2 and 48.
| 2. dimension must be an integer constant between 1 and 32767.
| ROWIDs: Figure 80 shows the syntax for declarations of ROWID variable arrays.
| See Chapter 14, “Programming for large objects (LOBs),” on page 281 for a
| discussion of how to use these host variables.
|
| Notes:
| 1. level-1 indicates a COBOL level between 2 and 48.
| 2. dimension must be an integer constant between 1 and 32767.
A host structure name can be a group name whose subordinate levels name
elementary data items. In the following example, B is the name of a host structure
consisting of the elementary items C1 and C2.
01 A
02 B
03 C1 PICTURE ...
03 C2 PICTURE ...
When you write an SQL statement using a qualified host variable name (perhaps to
identify a field within a structure), use the name of the structure followed by a
period and the name of the field. For example, specify B.C1 rather than C1 OF B or
C1 IN B.
The precompiler does not recognize host variables or host structures on any
subordinate levels after one of these items:
v A COBOL item that must begin in area A
v Any SQL statement (except SQL INCLUDE)
v Any SQL statement within an included member
When the precompiler encounters one of the preceding items in a host structure, it
considers the structure to be complete.
level-1 variable-name .
Figure 82 shows the syntax for numeric-usage items that are used within
declarations of host structures.
COMPUTATIONAL-1
IS COMP-1 IS
USAGE COMPUTATIONAL-2 VALUE constant
COMP-2
Figure 83 on page 191 shows the syntax for integer and decimal usage items that
are used within declarations of host structures.
BINARY
IS COMPUTATIONAL-4
USAGE COMP-4
COMPUTATIONAL-5
COMP-5
COMPUTATIONAL
COMP
PACKED-DECIMAL
COMPUTATIONAL-3
COMP-3
IS
DISPLAY SIGN LEADING SEPARATE
CHARACTER
IS
VALUE constant
Figure 84 shows the syntax for CHAR inner variables that are used within
declarations of host structures.
IS
PICTURE picture-string
PIC DISPLAY
IS
USAGE
IS
VALUE constant
Figure 85 on page 192 shows the syntax for VARCHAR inner variables that are
used within declarations of host structures.
IS
49 var-2 PICTURE S9(4) BINARY
PIC S9999 IS COMPUTATIONAL-4
USAGE COMP-4
COMPUTATIONAL-5
COMP-5
COMPUTATIONAL
COMP
.
IS
VALUE numeric-constant
IS
49 var-3 PICTURE picture-string
PIC DISPLAY
IS
USAGE
.
IS
VALUE character-constant
Figure 86 on page 193 shows the syntax for VARGRAPHIC inner variables that are
used within declarations of host structures.
IS
49 var-4 PICTURE S9(4) BINARY
PIC S9999 IS COMPUTATIONAL-4
USAGE COMP-4
COMPUTATIONAL-5
COMP-5
COMPUTATIONAL
COMP
.
IS
VALUE numeric-constant
IS
49 var-5 PICTURE picture-string DISPLAY-1
PIC IS NATIONAL
USAGE
.
IS
VALUE graphic-constant
Notes:
1. For fixed-length strings, the picture-string is G(m) or N(m) (or, m instances of
GG...G or NN...N), with 1 <= m <= 127; for other strings, m cannot be greater
than the maximum size of a varying-length graphic string.
2. Use USAGE NATIONAL only for Unicode UTF-16 data. In the picture-string for
USAGE NATIONAL, you must use N in place of G. USAGE NATIONAL is
supported only through the SQL statement coprocessor.
Figure 87 shows the syntax for LOB variables and locators that are used within
declarations of host struc