Professional Documents
Culture Documents
You should be very careful to ensure that the use of this information and/or software material complies with the
laws, rules, and regulations of the jurisdictions with respect to which it is used.
The information contained herein is subject to change without notice. Revisions may be issued to advise of such
changes and/or additions.
Notice to U.S. Government End Users: This is commercial computer software or hardware documentation developed
at private expense. Use, reproduction, or disclosure by the Government is subject to the terms of Unisys standard
commercial license for the products, and where applicable, the restricted/limited rights provisions of the contract
data rights clauses.
Unisys and ClearPath are registered trademarks of Unisys Corporation in the United States and other countries.
All other brands and products referenced in this document are acknowledged to be the trademarks or registered
trademarks of their respective holders.
Contents
Section 1. Introduction to Enterprise Relational Database
Server
iv 7830 8160–027
Contents
7830 8160–027 v
Contents
vi 7830 8160–027
Contents
7830 8160–027 ix
Contents
x 7830 8160–027
Contents
7830 8160–027 xi
Contents
Appendix A. Keywords
7830 8160–027 xv
Contents
Index ..................................................................................................... 1
E–1. Error Status and Auxiliary Information in ASCII FORTRAN ................................... E–2
xx 7830 8160–027
Section 1
Introduction to Enterprise Relational
Database Server
This manual mentions other Unisys products that have been renamed (for example,
MAPPER, now BIS or Business Information Server). Because experienced users of
these products are more familiar with the former product names, the former names
have been retained throughout this manual.
This manual describes the RDMS implementation of standard and RDMS extended
SQL. It presents every available standard and RDMS extended SQL statement, clause,
and option in the form of syntax diagrams and descriptions. It also provides a sample
database and examples illustrating the use of SQL statements.
This manual is intended primarily for programmers and software system engineers
who use SQL to access RDMS databases. This includes, among others, database
administrators, programmers who use languages like COBOL and C to build and
maintain applications that interact with relational databases, and developers who
access SQL databases through an interface such as IPF SQL or MAPPER.
As a user of this manual, you should have a working knowledge of relational database
and SQL concepts and terminology, the operating system environment, and any
high-level programming languages you are using to interact with the database. You
should also be familiar with basic UDS Control, Repository for ClearPath OS 2200
(UREP), and Integrated Recovery Utility (IRU) operations.
Choices for Two or more choices for required syntax elements are enclosed in
required braces { } . You must select one of the choices. For example:
elements { CLOSE | RELEASE [ CURSOR ] }
Variables Names of items you must supply (variables) are in italics. For
example:
cursor-name
Repeating Syntax elements that you can repeat are followed by ellipses. For
elements example:
[ column-name [ , column-name ] ... ]
Note: In illustrations of syntax, spaces before and after keywords are only for
readability.
You can find further information on syntax notation conventions for SQL statements in
Section 5.
http://www.support.unisys.com/all/ple/19055949
Note: If you are not logged into the Product Support site, you will be asked to do
so.
SQL divorces the application program or end user from the physical and location
attributes of the data. Data manipulation commands are expressed in logical terms.
An SQL query declares an action to be applied to the data of interest. It makes no
difference where the data is located or how it is arranged. The data of interest is
identified only in logical terms, which includes the following:
• Identifying the rows to be selected from the tables. Rows are selected through
specifications that identify the rows of interest. The specifications include column
names whose associated value in the row can be compared or included in an
expression that is compared to other like expressions. Whether these statements
are true or false for a row determines whether the row is to be included in the
“set of interest.” Optionally, columns can be qualified by a table and schema.
• Identifying the columns on which the action (retrieval or update) is specified. The
specifications include column names whose associated value is to be presented
or included in an expression of a column or columns for presentation from the
rows in the tables selected. For update actions, column names are associated with
corresponding values for assignment to the columns of the selected row set. In all
cases, the column names can be qualified by a table and schema name.
Table HOUSES contains a house identifier (HNO), the location of the house
(LOCATION), the asking price (PRICE), and a brief description of each house on the
market (DESCRIPTION).
The RDMS_DUMMY table is guaranteed to exist and contain exactly one record. The
record value is 1,NULL. You can use this table to construct SELECT statements that
return the values of RDMS built-in functions. For a SELECT statement that contains a
built-in function to return a record, the table in the FROM clause must contain exactly
one record (because there is no WHERE clause); otherwise RDMS returns a no-find or
cardinality violation error.
For example, to return the number of days until Christmas, issue the following
single-row SELECT statement:
SELECT current_date,datediff('Day',current_date,
datename('year',current_date)||'-12-25'),'shopping days'
FROM rdms.rdms_dummy
• Name
Each table has a name.
• Columns and rows
Each table has a specified number of named columns and any number of unnamed
rows. Each row contains different types of information about one thing. For
example, each row of table HOUSES contains information about one house.
• Data items
The intersection of a column and a row is a data item. The specific value of a data
item is a data value. The data items in one column must be of the same type. For
example, the column LOCATION in table HOUSES contains character data.
• Data types
Each column in a relational table is defined to hold a specific type of data. The
three basic types of data are character, numeric, and datetime. Numeric data can
be either exact or approximate. The following are characteristics of the RDMS
data types:
ᔭ Character data
Columns defined as character data are assumed to be standard ASCII
characters with an implicit binary ordering sequence. Columns can be defined
as belonging to a specific character set (for example, ISO 8859-1). Columns
can also be defined with a specific collation, or collating sequence (for
example, fr_FR.ISO8859-1); in such a case, this explicit collation is used for any
comparison, grouping, and ordering for the column.
ᔭ Exact numeric data types
Columns defined as exact NUMERIC data types hold precisely the value you
store in them. For example, if you store the value 10000 in a column defined as
an exact numeric type and then test to see whether that column is equal to
10000, the result is TRUE. The exact numeric data types are as follows:
DECIMAL
NUMERIC
INTEGER
SMALLINT
ᔭ Approximate numeric data types
On the other hand, columns defined as approximate numeric data types may
not pass such a test. Some approximate numeric data types can hold very
large numbers, however, much larger than the exact types. The approximate
numeric data types are as follows:
REAL
FLOAT
DOUBLE PRECISION
ᔭ Numeric ranges and precision
Numeric data types are characterized by their ranges and precision. Range
refers to how large a number they can store. Precision refers to how many
actual decimal places can be accurately recorded regardless of the range of
the number. For example, some approximate numeric data types can store a
number on the order of 10300, but can provide only about 18 decimal places of
precision. By carefully evaluating an application, you can determine which
numeric data types best suit your needs.
ᔭ Datetime data types
Columns defined as datetime data types can be classified as DATE, TIME, and
TIMESTAMP types. The DATE data type contains the year, month, and day.
The TIME data type contains the hour, minute, and second. The TIMESTAMP
data type contains the year, month, day, hour, minute, and second. The value
of each datetime field conforms to the valid value of calendar data.
You can also rearrange data and combine tables to suit your needs. How you structure
a query determines how the data is rearranged. RDMS supports three relational
operations:
• Restrictions
A restriction selects some or all rows from one or more tables.
• Projections
A projection selects some or all columns from one or more tables.
• Joins
A join combines columns from two or more tables.
1.3.5. Views
A relational view is similar to a relational table. The main difference is that a table
contains its own data and a view does not. Instead, a view represents the restriction,
projection, or join of one or more tables. A relational view is a virtual table that
provides a window into selected parts of the database.
You can use views to establish an uncomplicated look at portions of the database that
are logically independent from the underlying database structure. You can also use
views for security reasons by allowing other users to access only the rows and
columns of tables that are visible through the view.
The difference between a table and a view is transparent to users. Users access
views and tables in the same manner.
1.3.6. Terminology
From a data processing perspective, a table is roughly equivalent to a file where a row
corresponds to a record and a column corresponds to a field. Most users and the
literature, however, seldom use the terms file, record, and field. Preferred terms are
table, row, and column, which are the terms used in this manual.
• Base tables
Base tables physically contain rows and columns of data.
• Global temporary tables
Global temporary tables are identical in structure to base tables, but their data is
local to the thread. When a thread first references the global temporary table, the
table has zero rows. When the thread ends, all records are removed from the
temporary table. Multiple users can use the same temporary table, with each user
having different data.
The general term “table” can refer to a base table, a global temporary table, or a view.
The specific terms base table, global temporary table, and view are used in this guide
if a distinction is necessary.
• UDS Control
• Relational Data Management System (RDMS), including the Relational Syntax
Analyzer (RSA), which is a component of RDMS
• Repository for ClearPath OS 2200 (UREP)
UDS Control, RDMS, and UREP work together in many ways to support database
activities.
• Thread control
• Application groups
• Error message handling
• Recovery options
• Concurrency control
All RDMS interfaces support basic relational operations including the retrieval,
insertion, deletion, and updating of data from within application programs. This
includes the ability to define, alter, and drop, and to assign security requirements to
the relational entities (tables) used to model the information. It also includes the ability
to define transaction boundaries, and thus allows for multiple operations to be treated
as one unit of work.
RDMS users do not have to know how specific data items are stored, and they do not
have to understand RDMS data.
RDMS also provides system tables that contain authorization and statistical
information concerning all tables defined within the application group. This information
is available to authorized users through any of the supported relational interfaces.
Interpreter Interface
You can access RDMS through the interpreter interface, where RDMS interprets each
SQL statement each time it encounters the statement during the execution of a
program.
Application Programs
The following Unisys programming languages provide access to RDMS, by
incorporating SQL statements passed as arguments to RDMS on a procedure call:
• ASCII COBOL
• ASCII FORTRAN
• UCS COBOL
• UCS C
• UCS FORTRAN
You can design MAPPER runs that use SQL statements directly from the MAPPER
system, or you can use MAPPER runs through MRI. For more information, see the
MRI Administration and User’s Guide.
UniAccess Software
The UniAccess Transaction Client for OS 2200 and the UniAccess Transaction Server
for OS 2200 process requests from clients using Sybase Open Client software. The
UniAccess and Sybase software products use the Tabular Data Stream (TDS) protocol.
The UniAccess ODBC Server allows ODBC-compliant tools for the workstation to
access an RDMS database.
Embedded SQL
You can embed SQL statements in UCS COBOL and UCS C programs. Embedded
SQL (ESQL) has some features and considerations that differ from SQL when it is
interpreted during program execution. For details, see 2.11.
Module Programs
Module procedures enable UCS FORTRAN programs to access an RDMS database
(see 2.12).
• Interactive
• Dynamic ESQL
• Static ESQL
IPF SQL, MRI, ODBC, and JDBC always use the interactive interface. UCS COBOL and
UCS C programs can use any of the types, exclusively or in combination.
HVTIP has a control program that calls subprograms. The BEGIN THREAD command is
performed in the control program, and the same thread is used by the subprograms.
Therefore, anything RDMS performs as part of the thread is available to the control
program and all subprograms.
After you perform a dynamic PREPARE, the prepared statement is available until a
COMMIT, or until ROLLBACK or END THREAD if the prepared statement is a
RETENTION CURSOR. Dynamic ESQL is therefore as effective in an HVTIP
environment as it is within the other environments, such as batch.
1. Interactive
2. Dynamic ESQL
3. Static ESQL that auto-recompiles
4. Static ESQL (fastest)
Internal Processing
The following table shows the delegation of work between compile time and
execution time for the RDMS interface categories.
Bindings
There are three bindings that affect flexibility:
Table
Host Definition
Language Table Must Exist at
Interface Variables Syntax Definition Compile Time
The binding of host language variables to an SQL statement specifies how many
variables there are, their data types, and the names or memory locations of all
variables. Execution-time binding to host language variables can be done only using
the interactive interface. The other interfaces fix these values during the compile of
the UCS COBOL or UCS C program. Host language variables (sometimes called
program variables) are described in 2.10.
When syntax is bound, it is parsed and turned into an encoded format called the
RDMS command module. For example, the binding of the clause “WHERE col1 = 5”
fixes the fact that a column named COL1 is being referenced within the WHERE
clause. After binding, it is not possible to reference COL2 instead of COL1.
The result of the SQL CREATE and ALTER TABLE statements is an internal RDMS
encoded format of the table definition called the Relational Definition Table (RDT).
Within the RDT, each column and index is assigned a number. Binding to a table
definition causes the replacement of the symbolic column names with their
corresponding numbers. Access paths are selected from the currently existing
indexes and specified using the assigned number of the index. When binding is done
at execution time, the table definitions may differ for each execution. When binding is
done at compile time, the RDT used during execution must exactly match the RDT
used during the compile (the RDT timestamps must be identical). If the RDT
timestamp at compile time is not identical to the RDT timestamp at execution time,
auto-recompile is attempted.
The table definition must exist at compile time, in the application group for which the
program is being compiled, when static ESQL syntax is used. The table definition does
not have to exist at compile time when dynamic ESQL or interactive syntax is used.
This means that it is easier to transfer programs that use only the dynamic ESQL or
interactive interfaces to other run-time environments (application groups or systems)
than when static ESQL syntax is used.
Static ESQL is the easiest and most explicit to use for these reasons:
1. You specify the COBOL or C variables directly as part of the syntax, rather than
specifying parameter markers as part of the syntax and then specifying the
variables elsewhere.
2. A single statement is necessary. With dynamic ESQL, you have to issue two
statements, PREPARE and EXECUTE.
3. You do not have to code strings within strings. Consider this example static ESQL
statement:
EXEC SQL DELETE FROM houses
WHERE hno = 'H101';
In dynamic ESQL, you must use adjacent quotes to send a quote to RDMS:
When you compile a program that contains static ESQL syntax, the tables used by that
program must be created before the program is compiled. If application programs
must be moved between application groups or systems without being recompiled and
without auto-recompiling, the database administrator’s job is much more complicated
than with the other interfaces. This is because all tables must be created or altered
using static ESQL CREATE TABLE or ALTER TABLE statements, and the object
modules for these programs must be maintained by the database administrator and
executed in the same order on the production system as they were executed on the
development system. For more information and procedures for porting ESQL or
module language programs, see the Relational Database Server for ClearPath
OS 2200 Administration Guide.
Instead of porting ESQL programs, you can recompile the programs that create the
tables, or create the tables using the interactive interface. This ensures that the RDT
timestamp is different between the development system and the production system.
Because the timestamps are different, all static ESQL statements are auto-recompiled
by RDMS as they are executed. The recompiled structure is retained until the thread
exits, so any statement only auto-recompiles once per thread. For optimal
performance, you may wish to recompile just those programs on the production
system that use a large amount of system resources. You cannot recompile programs
if there is no compiler on the production system; for security reasons, some sites do
not allow compilers on the production system. To find out which programs are being
auto-recompiled, use the SUDS AR keyin; see the Universal Data System
Administration and Support Reference Manual.
Static ESQL has some flexibility; like dynamic ESQL, it can respond to changes to the
table definition:
• If the table definition changes and a static ESQL program has not been recompiled,
RDMS attempts to rebind an SQL statement to the updated table definition. This
succeeds unless the SQL statement explicitly references a dropped column, or if a
SELECT * was performed. If the rebinding succeeds, the new section (the
structure that is the output of the RDMS optimizer) is saved as part of the thread.
If the same static ESQL statement is reexecuted by the program within a loop that
saved section is used; no auto-recompile is done.
• When the XREF feature is enabled, UREP contains cross-references between
tables and the programs that reference them.
• The UREP commands REPORT COBOL and REPORT C can create COPY elements
matching RDMS table definitions.
LOCATE and OPEN CURSOR are the only statements that pass actual program variable
values as parameters to RDMS. For other statements, such as the INSERT statement,
the Relational Syntax Analyzer (RSA) converts the value of a variable into a constant
before passing it to RDMS, so your program might just as well build up the SQL
statement without using program variables. If this is done, RSA does not have to
match the number of placeholder variables referenced in the statement with the
number of program variables supplied on the rsa() call. This makes coding easier.
If program variables are being passed, an arbitrary number can be passed to RSA
using the UCS C rsa_param function or the UCS COBOL RSA$PARAM procedure; see
Appendix H for more information. An interactive program can thus be made to
respond automatically to added or dropped columns.
More flexible:
rsa_param(&var1);
rsa_param(&var2);
rsa_param(&var3);
rsa("insert into t1 values($p1, $p2, $p3);", error_code, &aux_info);
You can use the EXECUTE IMMEDIATE statement to issue some SQL statements
(such as INSERT, UPDATE, DELETE) in a manner similar to the interactive interface; that
is, you can build up the syntax including the program variable values as constants.
However, you cannot retrieve any data using EXECUTE IMMEDIATE; instead, you must
use PREPARE, ALLOCATE, OPEN, and FETCH.
The OPEN and FETCH statements must have the same number of parameters, and
their data types must match the SELECT list. The EXECUTE statement must include a
USING clause with a one-to-one relationship between parameter markers and host
program variables. To respond to an added column without recompiling your program,
you must include multiple versions of the same EXECUTE statement, each with a
different number of parameters of different data types. Dynamic ESQL cannot
respond to added and dropped columns if program variable usage must be changed.
Because program variables are bound at compile time with dynamic ESQL, programs
cannot respond to added or deleted columns when those values must go through a
program variable (for example, when a SELECT * is performed).
• Use static ESQL when you know the syntax of the statement and you know that
table definition changes will not affect the syntax.
• When you do not know the syntax of the statement, use dynamic ESQL or the
interactive interface.
Choose dynamic ESQL for any of these reasons:
− Standards conformance is an issue.
− You want to be able to PREPARE a statement once and EXECUTE it multiple
times.
− Execution-time binding of program variables is not an issue.
Choose the interactive interface for any of these reasons:
− You do not want to deal with the complexity of separate PREPARE and
EXECUTE statements.
− You require execution-time binding for program variables.
− Your table definition changes regularly and the changes affect the syntax.
• Consider the “80/20 rule.” This rule suggests that only 20 percent of programs are
performance-critical. This could mean, for example, that you could allow 80
percent of your programs to auto-recompile, without noticing any performance
difference from a system on which all of the programs containing static SQL had
been recompiled.
1.7.3. Locks
Table 1–3 describes the SQL statements used for table locking.
This section presents concepts with which you must be familiar before proceeding to
the statement syntax presented in Sections 5 through 10.
• End SQL statements with a semicolon ( ; ) if you are working from either
A third–generation programming language through the interpreter interface
An MRI run
• RDMS accepts characters in the ASCII/ISO (International Standards Organization)
character set.
• Each SQL statement issued from a third–generation programming language (such
as COBOL, FORTRAN, or C) must be placed in one of the following:
A separate procedure call statement, if used with the interpreter interface
An EXEC SQL statement, if used with the ESQL interface (see 2.11)
• All statement characters are from the ASCII character set. You can use uppercase
and lowercase characters interchangeably. The exception is when the letters are
enclosed in double quotation marks ( “ ) or single quotation marks ( ‘ ).
• Fieldata characters are not supported. Any attempt to pass Fieldata characters
from a program to RDMS results in an abnormal error status.
• Two consecutive hyphens ( -- ) in an SQL statement signal a comment. The text
of a comment is for information only; the text is not part of the statement.
In static ESQL (see 2.11.1), the comment ends at the end of the line.
In dynamic ESQL (see 2.11.6) and in the interpreter interface, the comment
extends to the end of the string or parameter that contains the SQL
statement.
A comment can also be enclosed within the delimiters /* (beginning of comment)
and */ (end of comment). For example
EXEC SQL PREPARE rb FROM
'DELETE FROM sample_table /* remove all rows */';
• Columns
• Constraints
• Correlation names
• Cursors
• Indexes and keys
• Qualifiers for tables, views, routines, and triggers
• Scalar functions
• Schemas
• Statements
• Role names
• Routines
• Tables
• Triggers
• Title names
• Variables
• Views
You can also specify the following entities unique to RDMS in SQL statements:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
_ (underscore)
• A name must begin with a letter.
• A name can use either lowercase or uppercase letters; lowercase letters are
treated as though they were uppercase. For example, avg_pay is the same as
AVG_PAY.
• A name cannot be a reserved word. See Appendix A for a list of reserved words.
• You can specify kanji names (see Relational Database Server for ClearPath
OS 2200 Administration Guide).
To avoid all of these naming rules, you can enclose a name in double quotation marks
( " )(042). Names enclosed in quotation marks are called delimited identifiers.
Lowercase letters are not equivalent to uppercase letters in names enclosed in
quotation marks. For example, the name "ABC" is the same as the name ABC, but it is
not the same as "aBc" or "abc". Blanks are allowed in delimited identifiers except for
schemas, qualifiers, storage-areas, tables and versions.
customers
avg_pay
t1
"@#!"
"%RATE"
dollar$sign
2table
this_is_too_long_to_be_a_legal_name
Format
[schema.]table-name[:version-name]
where:
schema
is the name of the schema containing the table. If you omit the schema name,
RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses the
default schema name RDMS or the value of the user ID of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAULT-QUALIFIER. For additional information, see the Repository for
ClearPath OS 2200 Administration Guide.
table–name
is the name of the table or view in the database.
version–name
is the version of the data you want to reference. If you omit the version name,
RDMS uses the value you specified on the USE DEFAULT VERSION statement. If
you have not established a default version, RDMS uses the default version name
PRODUCTION.
Examples
The following is an example of an unqualified table name for table CUSTOMERS:
customers
The following table specification includes the qualifier REALESTATE and version-name
JACQUES for table HOUSES:
realestate.houses:jacques
Version Names
When you create a table, you state in which storage area the table is to be stored.
You can have many versions of a table. This means that you can have a single table
definition, but several different sets of data that fit that definition. For example, the
real estate information in tables CUSTOMERS and HOUSES can have one table
definition for houses, but also have a separate set of data for Minnesota, Wisconsin,
Illinois, and so on. Each such set of data is called a version of the table.
Each version of a table requires a storage area version. In turn, each storage area
version requires its own Exec or TIP file. You create Exec files with the @CAT
statement. You link Exec files with storage area versions using UREP.
For more information about storage areas and versions, see the Repository for
ClearPath OS 2200 Administration Guide.
The storage area version name is the same as the table version name. The only time
the storage area version name is not the same as the table version name is when the
table version name is PRODUCTION. The table version name PRODUCTION is
associated with the blank storage area version name.
Example
Suppose a large university makes computer time and services available to the many
student organizations on campus. Many organizations take advantage of this by
requesting rosters of their members. Naturally, the university also needs a master
student directory. One way to implement such a system is as follows:
1. Catalog a file.
For this example, name the file DBA*STUDENT–DATA.
2. Use UREP to link DBA*STUDENT–DATA with a storage area named ROSTER. For
the storage area version name, specify MASTER.
3. Also use UREP to specify a schema name. For this example, name the schema
UNIVERSITY.
4. Use the SQL CREATE TABLE statement to create a table named
UNIVERSITY.STUDENTS in ROSTER.
You cannot specify a version name with the CREATE TABLE statement.
You now have a base table named UNIVERSITY.STUDENTS:MASTER. You can populate
the table and use it as needed. (Assume that the primary key of
UNIVERSITY.STUDENTS is a student identification number and that each student
knows and uses this number frequently.)
Now suppose the debate club on campus wants to create a roster of its members.
The debate club just needs to provide you with a list of student identification numbers
of their members. You use the following procedure to create the debate club roster:
You now have a version of the table named UNIVERSITY.STUDENTS:DEBATE. You can
use the student identification numbers the debate club gave you to retrieve rows from
UNIVERSITY.STUDENTS:MASTER to populate this new version. You can also create a
user–id for the debater's membership officer to use to maintain the table as students
join or leave the club.
Version names require some care in their use with the DECLARE CURSOR, GRANT,
OPEN, and REVOKE statements.
ESQL Considerations
The version name can be supplied by an embedded variable. The following table
specification, for example, cannot be resolved until the variable VERSION–VAR is
assigned a value and the ESQL statement containing this table specification is
executed:
houses::version-var
The first of the two colons serves as the separator between the table name and the
version name. The second colon is the embedded variable prefix.
Format
[table-specification.]column-name
where:
table–specification
is the name of the table containing the column, as defined in 2.2.2.
column–name
is the name of the column.
Examples
The following are examples of column name specifications:
houses.price
customers.cno
realestate.houses:roger.location
x.location
hno
Note that a function you create in a schema can have the same name as an RDMS
scalar built-in function. It cannot have the same name as an RDMS aggregate built-in
function, because the aggregate built-in function names are reserved words.
The following statement finds the procedure lower in the schema schema2 if it exists:
CALL schema2.lower(namevar)
Examples
USE DEFAULT SCHEMA global1
RDMS looks for the function lower as a scalar built-in function, finds it, and executes
it. If RDMS does not find the name as a scalar built-in function, it looks in the schema
RDMS or in the schema whose name matches the current user. If you want RDMS to
find the function lower in the schema global1, you must specify it as a qualified name:
RDMS does not find proc1 as a scalar built-in function, so it looks in the default
schema global1. If RDMS finds it in global1, it executes the function.
Format
[schema-name.]storage-area-name
where:
schema-name
is the name of the schema in which the storage area was created. If you omit the
schema name, RDMS uses the name of the schema on the table being created or
altered. If you omit a schema name on the table, RDMS uses the value you have
specified on the USE DEFAULT SCHEMA statement. If you have not established a
default schema name, RDMS uses the default schema name RDMS or the value of
the user ID of the current run, depending on the value of the UREP configuration
attribute RDMS-DEFAULT-QUALIFIER. For additional information, see the
Repository for ClearPath OS 2200 Administration Guide.
storage-area-name
is the name of the storage area to use.
Examples
The following statement creates the table HOUSES in the schema REALESTATE and
uses the storage area APPLEVALLEY in the schema REALESTATE.
The following statement creates the table HOUSES in the schema RDMS and uses the
storage area MINNEAPOLIS in the schema RDMS. This example assumes the value of
the UREP configuration attribute RDMS-DEFAULT-QUALIFIER is set to RDMS.
The following statement creates the table HOUSES in the schema REALESTATE and
uses the storage area ROSEVILLE in the schema REALESTATE.
The following statement creates the table HOUSES in the schema TEST and uses the
storage area SHOREVIEW in the schema TEST. Note that because the schema name
was omitted from the storage area name, RDMS uses the table’s schema name.
A role name can consist of numbers between 1 and 29 ASCII (not UNICODE or KANJI),
characters from A-Z, 0-9, period, and hyphen. The best practice is to use an invalid
user ID as a role name (to do this, use a name between 13 and 29 characters). Do not
use the prefix "RDMS-", because it is used by RDMS predefined roles.
2.3. Literals
This subsection includes the following topics:
String delimiters are not part of the actual string. Within a string literal, two single
quotation marks in a row mean that one quotation mark is part of the string and the
second one is not used.
The character sequence in a string literal can include any character belonging to a
supported character set. For more information on supported character sets, see The
I18N Assistant.
Examples
The following example is a string literal that contains five characters: j, o, e, ', and s:
'joe''s'
The next example is the string literal “a1 at lloyd's”. The quotation marks are part of
the string, which is 15 characters long (including blanks).
'"a1 at lloyd''s"'
The final example shows the use of characters with diacritical marks:
Integer Literals
Integer literals are simply strings of up to 21 digits. This 21-digit limit does not include
the optional leading sign.
Examples
The following are examples of integer literals:
-9
481567890231457849201
Do not place a space between the leading sign (if present) and the first digit of an
integer literal. Similarly, do not place any spaces or commas between the digits of an
integer literal.
Real Literals
Real literals are strings of digits containing a decimal point. You can write them with or
without a leading sign. A literal of this form can contain no more than 21 digits. This
21-digit limit does not include the leading sign if used or decimal point if used.
Do not place a space between the leading sign (if present) and the first digit of a real
literal. Similarly, do not place any spaces or commas between the digits of a real
literal.
You can also express real literals in a form similar to scientific notation by employing
an exponentiation suffix. The suffix is the letter E (either uppercase or lowercase),
followed by an integer exponent. The integer exponent can have a leading sign, and
cannot exceed three digits in length.
When expressed in this way, the portion of the literal to the left of the E suffix is
called the mantissa. The portion to the right of the E suffix is the exponent. The
expression mantissaEexponent is read “mantissa times ten to the exponent power.”
The mantissa can have no more than 21 digits. This 21-digit limit does not include the
leading sign or decimal point.
Examples—Zeros
The following are examples of zeros:
0.0
0.0e6
9.0e0
+9.e-12
0.9e+1
.9e1
1223.487743e22
3.14159265
base'value'
where:
base
specifies the base of the value and is one of the following letters:
B Binary
O Octal
X Hexadecimal
value
is an unsigned integer value enclosed in single quotation marks. If the value is
negative, precede the B, O, or X with a minus sign. A plus sign for a positive value
is optional.
Alternate based literals can be used in INSERT, UPDATE, and SELECT statements; the
WHERE clause and DEFAULT clause; in arithmetic expressions, including BIF
arguments; and as a partitioned table column-upper-bound.
Maximum
Literal Type Length of value Allowed Characters in value
Examples
b'010' Value of 2 decimal
o'127' Value of 87 decimal
x'123a' Value of 4666 decimal
x'Ab' Value of 171 decimal
x'aB' Value of 171 decimal
x'ab' Value of 171 decimal
-b'101' Value of -5 decimal
+O'123' Value of +83 decimal
2.3.3. Nulls
Occasionally, a particular data item may not yet have a value associated with it. In
table HOUSES, for example, a new entry may be created for a house for which no
price is yet established. Another example may be a customer who has no location
requirement. Even though columns exist for this information, the information is not yet
available, appropriate, or applicable. The application must take special steps to handle
“dummy” data in these data items.
To address these kinds of situations, SQL provides for “null” data. Nulls are
placeholders for unavailable or nonexistent data. As such, they have no value.
When you design tables, decide which columns you want to be able to hold nulls.
When you use the ALTER TABLE and CREATE TABLE statements, you can specify in
which columns to allow nulls to be stored.
To store nulls in rows using the INSERT and UPDATE statements, you can use either
the NULL keyword or indicator variables (see 2.10.4). Third-generation programming
languages retrieve nulls through indicator variables. For information about other ways
to retrieve nulls, see the RDMS and IPF SQL Interface End Use Guide and the
UNLOAD statement in this manual.
You can find the rules for how nulls behave in expressions, functions, comparisons,
query specifications, and as parameter values in the following subsections:
2.4 Expressions
2.4.10 Functions
2.5.1 IS NULL operations
2.7 Query specifications, specifically with the DISTINCT keyword and GROUP BY
clause
2.10.4 Indicator variables
3.3 Passing a null value as a parameter
YYYY-MM-DD
or
DD.MM.YYYY
or
DDMONYYYY
where:
YYYY
is the year in the range 0001 to 9999.
MM
is the month in the range 01 to 12.
MON
MON is a 3 char ASCII representation of the month.
For example:
12Jan2012
10Dec1985
23Nov2000
DD
is the day in the range 01 to 31. The day is further constrained by the value of the
month and year, in accordance with the Gregorian calendar.
HH:MM:SS[.[FFFFFF]]
where:
HH
is the hour in the range 00 to 23.
MM
are the minutes in the range 00 to 59.
SS
are the seconds in the range 00 to 59.
FFFFFF
(optional) is the fractional portion (from 0 to 6 digits) of the seconds in the range
.000000 to .999999.
YYYY-MM-DD HH:MM:SS[.[FFFFFF]]
Examples
The following examples are valid datetime literals:
DATE '1998-12-31'
TIME '23:12:56'
TIME '09:58:45.123456'
TIME '10:23:15.96'
The following examples are valid date, time, and timestamp values:
1998-12-31
23:12:56
09:58:45.123456
10:23:15.96
1998-12-31 23:59:59
1998-01-01 12:45:56.
YYYY-MM-DD-HH.MM.SS[.[FFFFFF]]
TIMESTAMP '1998-12-31-23.59.59'
TIMESTAMP '1998-12-31-23.59.59.'
TIMESTAMP '1998-12-31-23.59.59.123456'
TIMESTAMP '1998-12-31-23:59:59.123456'
'1998-12-31-23.59.59'
'1998-12-31-23.59.59.'
'1998-12-31-23.59.59.123456'
'1998-12-31 23.59.59.123456'
'1998-12-31-23:59:59.123456'
RDMS does not generate this format when returning timestamp information.
In addition, the character separating the hour and minute fields must be the same as
the character separating the minute and second fields. Both must be either a '.' or a ':'.
If this alternative format is needed on output, you must use a combination of existing
functions to transform the current RDMS timestamp format to this new format. The
following is one of the several techniques that may accomplish this transformation.
This results in
2006-06-06 06:06:06.123456 new format = 2006-06-06-
06.06.06.123456
Format
INTERVAL [ { + │ ─ } ] 'interval-value' interval-qualifier
where:
+ or –
is the unary sign (+ or Ä) indicating whether the interval value is positive or
negative. If the sign is omitted, + is assumed.
interval–value
is the value of the interval, preceded by an optional unary sign (+ or –). If the sign
is omitted, + is assumed.
interval–qualifier
specifies the datetime fields (YEAR, MONTH, DAY, HOUR, MINUTE, and SECOND)
to include in the interval–value. For more details about interval qualifiers, see 3.8.
The following table illustrates the correlation between interval values and
qualifiers.
Value Qualifier
For the valid range of values for each interval data type field and the memory
requirements, see 3.8.
Valid Examples
The following examples are valid.
Invalid Examples
The following examples are invalid for the reasons indicated.
2.4. Expressions
This subsection includes the following topics:
• What is an expression?
• Boolean expressions
• Universal quantifiers
• Order of precedence for operations
• Evaluation and rounding of arithmetic expressions
• Arithmetic result types
• Datetime arithmetic expressions
• Built–in functions
Examples
The following expression states the value of 2:
'ab'
The following expression is a column name that expresses the value in the column:
hno
5 + .06 * 1200
5 + .06 * $p1
6 = 8
The following expression contains a column name and an embedded host program
variable in ESQL:
price * :commission
The following expression contains a column name and a dynamic ESQL variable
marker:
maxprice < ?
The following expression states a value for the date in column 1 (C1) that is before or
on 1 May 1994:
‘Alpha’ || ‘Beta’
CAST(:tstmp AS TIMESTAMP(6))
The following expression extracts the exact numeric value 10 from the MONTH field
of a DATE value:
• A value expression with character values followed by the LIKE or NOT LIKE
operator and a pattern-matching operation. See section 2.5.4.
• A value expression followed by the IS NULL or IS NOT NULL operator. See section
2.5.1.
• A value expression separated from either a list of values or a subquery by the IN
or NOT IN operator. See section 2.5.5.
• A subquery parameter embedded within the Boolean EXISTS function call (that is,
a Boolean existential function), to create more complex Boolean expressions
(see 2.5.9). Parentheses can be used to alter the precedence of arithmetic
operations in evaluating comparison operands, or to alter the precedence of
Boolean operations in evaluating the Boolean operands, or for both reasons.
Examples
The following two examples illustrate simple predicates:
a <= b
c = d
a BETWEEN c AND d
If you are using a subquery as a comparison operand within a predicate, you express
the subquery as the right-side operand of the comparison operator, as in this example:
For more complex Boolean expressions, use the NOT, AND, and OR operators, as in
the following two examples:
a <= b AND c = d
Then...X OR Y
If X is... And Y is... is... X AND Y is... NOT X is...
Then...X OR Y
If X is... And Y is... is... X AND Y is... NOT X is...
The number of predicates and logical operators together cannot exceed 511.
SOME
ANY
ALL
Format
value-expression comparison-operator [ NOT ] { ANY | ALL | SOME } subquery
where:
value–expression
is a numeric, character, or datetime value.
comparison-operator
is any one of the arithmetic comparison operators: =, <>, ^=, !=, >, <, >= or <= .
NOT
makes the result TRUE if no rows from the set value list or subquery match the
value expression.
subquery
is as described in 2.7.4.
When you use a universal quantifier, the operand on the right must be a subquery
(see 2.7.4).
• The number of items in the left-hand row operand is always equal to the number
of items in the right-hand row operand.
• row1 = row2 is TRUE if row1(i) = row2(i) is TRUE for all i.
• row1 =row2 is FALSE if NOT (row1(i) = row2(i)) is TRUE for some i.
• row1 <comp op> row2 is UNKNOWN if row1 <comp op> row2 is neither TRUE nor
FALSE.
Examples
The following example evaluates to TRUE whenever a customer's maximum price is
greater than or equal to the price of at least one house:
AND
The binary operator bitwise AND ( & ) performs a bitwise AND operation that sets bits
in the result value. A bit in the result is set if and only if each of the corresponding bits
in the converted operands is set. That is, if both bits are 1 bits, the bit in the result is
set to 1. Otherwise, the bit in the result is set to 0.
OR
The binary operator bitwise OR ( | ) performs a bitwise inclusive OR operation that
sets bits in the result value. A bit in the result is set if and only if at least one of the
corresponding bits in the converted operands is set. That is, if one of the bits is a 1 bit,
the bit in the result is set to 1. If both bits are 0 bits, the result bit is set to 0.
XOR
The binary operator bitwise XOR ( ^ ) performs a bitwise exclusive OR operation that
sets bits in the result value. A bit in the result is set if and only if exactly one of the
corresponding bits in the converted operands is set. That is, if exactly one bit is a 1 bit,
the bit in the result is set to 1. If both bits are 1 bits, or if both bits are 0 bits, the result
bit is set to 0.
Examples
B'1001' & B'1100' = B'1000'
Intermediate Formats
RDMS converts the operands to 72-bit long intermediate formats before performing
the bitwise operations, as follows.
* The RDMS NUMERIC format stores values as a binary integer (fixed-point) value, multiplying
the value by the declared number of decimal places (scale) to eliminate any fractional value.
For example, if the scale is 3, RDMS multiplies the value by 103 to convert the floating-point
number into a binary integer representation. So the fractional number 2.345 is multiplied by
1000 and stored in the database as the binary integer value 2345.
Result Types
After performing the bitwise operations, RDMS converts the result value into the
resulting data type format. The resulting data types differ slightly from the arithmetic
result types (see Table 2–5); for bitwise operations, the resulting data types are as
shown in Table 2–2. To use the table, first find the code for the left operand in the
leftmost column and then the code for the right operand in the top row. The code for
the result of a bitwise operation between that pair of numeric types is found at the
intersection of the row and column you selected.
SI I DI D N R F DP
SI SI I DI D N R F DP
I I I DI D N R F DP
DI DI DI DI D N R F DP
D D D D D N R F DP
N N N N N N R F DP
R R R R R R R F DP
F F F F F F F F DP
DP DP DP DP DP DP DP DP DP
Legend:
D DECIMAL
DI Double precision INTEGER
DP DOUBLE PRECISION
F FLOAT
I INTEGER
N NUMERIC
R REAL
SI SMALLINT
Table 2–3 lists the operations and operators accepted by RDMS and their order of
precedence. You can use parentheses to change the order of precedence, if
necessary (see 2.4.6).
*/ Second
− Third
IS [ NOT ] NULL
[ NOT ] LIKE
[ NOT ] IN
AND Sixth
OR Seventh
Note: All operators, except for IS [NOT] NULL (2.5.1) and [NOT] EXISTS (2.5.9)
must have an expression preceding and following them. A single expression must
precede IS [NOT] NULL. When one of the universal quantifiers—SOME, ANY, ALL
(2.4.3—is combined with a comparison operator as illustrated, a subquery (2.7.4)
must follow. A subquery can also follow IN and must follow EXISTS.
This order of evaluation lets you know which operands (or even “subexpressions”)
belong to each operator. It does not necessarily mean that RDMS performs the
operations in this order. RDMS may be able to optimize the calculation of an
expression by executing the operators in a different order. Write expressions,
therefore, that do not depend on RDMS to execute them in a particular order.
Table 2–4 illustrates how RDMS evaluates an expression with and without
parentheses.
a + b * c + -d a + (b * c) + (-d)
a < b - c * d a < (b - (c * d))
a < b OR c >= -d (a < b) OR (c >= (-d))
NOT a < b OR c = d AND e > f (NOT (a < b)) OR ((c = d) AND (e > f))
Rounding
Rounding during the evaluation of arithmetic expressions occurs when the precision
of the result is less than the precision of either or both operands.
RDMS uses the following three algorithms to determine the size of the result during
the evaluation of arithmetic expressions. The parameters s, s1, and s2 denote the
sizes of the numbers (whole number part plus fractional number part). The parameters
f, f1, and f2 denote the sizes of the fractional portions of the numbers. The value of f
indicates the precision of the result.
Note: For DECIMAL items defined in an owned schema, the number of decimal
digits is one greater than the number of decimal digits in the original definition. This
is because of the difference in the semantics of this value between the SQL
standard and RDMS. For more information, see 2.8.2.
Sometimes, the fractional size of the multiplication or division result may be reduced
by more than two decimal digits due to the 21 digits size limitation of the MAX or MIN
function. For example, 4 digits to the right of the decimal point reduced to 0 digits. The
result will be more accurate using double precision floating point arithmetic than using
exact numeric arithmetic of the DECIMAL or NUMERIC data types.
GET DESCRIPTION can help to identify this situation. You have lost accuracy if
A loss of accuracy is most apparent when the arithmetic is performed as part of the
operand of the SUM aggregate function.
To force RDMS to use double precision floating point arithmetic, enclose one of the
operators of the multiplication or division in the double() BIF. For Example,
Change
SUM(a_numeric_14_2 * (1 - my_numeric_14_2_tax))
to
SUM(double(a_numeric_14_2) * (1 - my_numeric_14_2_tax))
f = MAX(f1,f2)
s = MIN (21,MAX (s1 ─ f1,s2 ─ f2) + k) + f
IF s > 21
THEN f = 21 + f ─ s
s = 21
Multiplication
The rounding algorithm for multiplication is
f = f1 + f2
s = s1 - f1 + s2 - f2 + f
IF s > 21
THEN IF f > 0 and this is the last operation in the expression
THEN min-precision = 1
ELSE min-precision = 0
f = MAX( min-precision, 21 + f - s)
s = 21
f = f1 + f2
s = s1 - f1 + s2 - f2 + f
IF s > 21
THEN f = MAX(0, 21 + f - s)
s = 21
Division
The rounding algorithm for division is
f = 21 ─ MIN(21,s1 ─ f1 + f2)
s = 21
Example
Let item W be NUMERIC(7,3)
Let item X be NUMERIC(21,2)
Let item Y be NUMERIC(11,10)
Let item Z be NUMERIC(5,0)
The size of the resulting value and its fractional portion (the precision) of the result of
each of the following expressions is as follows.
X + Y 21 1
W + Z + Z 9 3
Y * W 18 13
(Y/Z) + W 21 16
The nature of the algorithm for division is to produce a maximum–sized result with
just enough space for the largest possible integer portion. All of the rest of the result
is devoted to the fractional portion. If the dividend has a large size and a small
fractional portion or the divisor has a large fractional portion, the resulting quotient
ends up with a small fractional portion. The quotient can thus "lose" a fair amount of
precision. If the quotient is used as an operand in subsequent operations in the same
arithmetic expression, this loss of precision is propagated. (Note that the result of the
SUM and AVG functions end up with large sizes but may have relatively small
fractional sizes.)
Addition and subtraction are the only arithmetic operations involved in datetime value
expressions; hence, RDMS does not perform rounding because it is not necessary.
For further details on arithmetic operations on datetime items, see 2.4.8.
Suppose, for example, that the precision and scale of a column are defined as
5 and 2 (5,2) and that the column contains a value of 38.42. If the program variable X is
compared to the column in a WHERE clause, RDMS considers X to be equal to the
value 38.42 only if X falls in the range
If a program variable is compared with more than one column in a WHERE clause,
RDMS rounds it only once and uses the rounded value in all comparisons. If the
columns do not have the same precision, RDMS rounds the program variable to the
precision of the column with the least precision.
SI I D N R F DP DT IV
SI D D D D R DP DP
I D D D D R DP DP
D D D D D R DP DP
N D D D N R DP DP
R R R R R R DP DP
F DP DP DP DP DP DP DP
DP DP DP DP DP DP DP DP
DT DT
IV DT
Legend:
D DECIMAL
DP DOUBLE PRECISION
DT Datetime (DATE, TIME, and TIMESTAMP)
F FLOAT
I INTEGER
IV INTERVAL
N NUMERIC
R REAL
SI SMALLINT
Scientific notation literals are of type DOUBLE PRECISION. All other numeric literals
are of type DECIMAL.
Note: As discussed above, comparison for equality where one operand is of type
REAL, FLOAT, or DOUBLE PRECISION can generate misleading results, because
these data types contain approximate values. See the discussion on approximate
numeric data types in 2.8.2.
datetime-operand + [ { + │ - } ] interval-operand
datetime-operand - [ { + │ - } ] interval-operand
[ { + │ - } ] interval-operand + datetime-operand
where:
datetime–operand
is a datetime data type item. It can be a datetime function, a CAST function, a
column reference, or a datetime literal.
interval–operand
is an interval data type item. It can be an interval literal or a CAST function.
• You cannot define a column as an interval data type (see 3.8). The interval operand
can be an interval literal or a CAST function that specifies an interval data type as
the target.
• The interval operand cannot include a datetime field that is not contained in the
datetime operand. For example, CURRENT_TIME + INTERVAL '99' YEAR is an error.
• If either operand is null, the result of the arithmetic expression is null.
• The result of the arithmetic operation uses the same set of datetime fields as the
datetime operand, with the same precision and scale.
1. The value of each datetime field of the interval operand is added to or subtracted
from the corresponding datetime field of the datetime operand. This can mean
carrying from or to the next significant datetime field.
If the data type of the datetime operand is TIME, the HOUR field is divided by
24 and the remainder is kept. For example, the following expression results in
a time of 01:00:00:
If the data type of the datetime operand is DATE and the data type of the
interval operand is a year–month interval, the DAY field of the result is the
same as the DAY field of the datetime operand.
2. If, after the preceding step, any datetime field of the result is outside the
permissible range of values for the field or the result is invalid based on the
Gregorian calendar system, an error is returned. RDMS verifies the datetime value
after each arithmetic operation within a datetime arithmetic expression.
Examples
The following expressions state datetime values using arithmetic expressions:
The following expression evaluates to the DATE value DATE ‘1995–02–28’. The DAY
field value is carried to the MONTH field.
Format
string1 || string2
where string1 is either a character string type or a BLOB. If string1 is a character string
type, then string2 must also be a character string type. If string1 is a BLOB, then
string2 must also be a BLOB.
See Table 3–1 for allowed data type combinations and the result data type.
If string1 is a scalar built-in function, it can return a length of zero, which is interpreted
as a null string.
When used in a select list, built–in functions return summary information about the set
of rows selected.
For information on expression operands, see 2.5. For information on built–in functions,
see Section 3.
If you add, subtract, multiply, or divide by a null, the result is null. If you compare a
non-null (like the number 6) with a null, the result is UNKNOWN. It is neither TRUE nor
FALSE. Nulls are treated differently by GROUP BY clauses (see 2.7), functions
(see 2.4.9), and ORDER BY clauses (see 7.4.3).
For example, if a data item of column A has the character value 'X' and a data item of
column B is null, the values of the following expressions are as follows:
5 + b (NULL)
A = 'X' (TRUE)
a = B (UNKNOWN)
For more information on how RDMS processes expressions that contain character
values, see 2.9.1.
To determine whether a data item is or is not null, you can use the IS NULL and
IS NOT NULL comparison operators.
Using DEFAULT on an INSERT statement causes RDMS to write ‘abcd’ to the column:
Alternatively, omitting the column name mycol from the insert column list also causes
RDMS to write the default value ‘abcd’ to the column.
If an existing column in a table has a value, including the value NULL, you can change it
to the default value using the DEFAULT keyword. For example,
p BETWEEN q AND r
Format
character-expression [ NOT ] LIKE pattern-expression [ ESCAPE { string-constant-2 |
variable-specification-2 } ]
where:
character-expression
is a CHARACTER or NCHARACTER valued expression. This is typically
a CHARACTER or an NCHARACTER column but may also be a
character-valued scalar BIF (see section 3). The left operand is a column or a BIF,
not a name. The concatenation operator (||) is not allowed.
NOT
makes the result TRUE for each row in which the column specification does not
match the pattern.
pattern-expression
string-constant-1 | variable-specification-1 | pattern-scalar-BIF
string–constant–1
is a pattern enclosed in apostrophes.
variable–specification–1
is a data variable (see 2.10) that contains a pattern.
pattern-scalar-BIF
is a scalar built-in-function (see section 3) which returns a CHARACTER
or an NCHARACTER result. The argument or arguments of a pattern-scalar-BIF are
expressions whose operands are either literals or pattern-scalar-BIFs.
Consequently, you may not have a column-name as (part of) a pattern-scalar-BIF
argument.
ESCAPE
defines the escape character to use, and includes the wild card characters
themselves in search patterns.
string–constant–2
is a single character or NCHARACTER enclosed in apostrophes.
variable–specification–2
is a data variable (see 2.10) that contains a single character or NCHARACTER.
The percent sign (%) and underscore character ( _ ) have special meaning in the
pattern string for the LIKE operator. The % is used to match any number of characters.
The _ is used to match exactly one character. The % and _ characters are often
referred to as “wildcard” characters.
Consecutive percent signs (for example, %%, %%%) are equivalent to a single %
wildcard character. All redundant % wildcard characters are ignored.
Example
DECLARE c1 CURSOR SELECT veg FROM seed1 WHERE veg like 'br%%%li';
is evaluated as
DECLARE c1 CURSOR SELECT veg FROM seed1 WHERE veg like 'br%li';
broccoli
The percent sign is also a special character in IPF and must be preceded by an IPF
escape character in the IPF SQL Interface. For more information, see the RDMS and
IPF SQL Interface End Use Guide.
Setting Result
FALSE (default) Traditional: Ignore trailing blanks in column values and pattern
strings.
TRUE Standard: Use trailing blanks in column values and pattern strings in
match; pad column values with spaces to their full defined length
(that is, apply SQL 92 standard rules).
Examples
The following example evaluates to TRUE if the string “3 Bed” appears anywhere in
column DESCRIPTION.
The next example evaluates to TRUE if column CNAME begins with the letter J as in
“Jones” and “Johnson.”
The next example evaluates to TRUE if column CNAME begins with the letter “J” and
is exactly five characters long. “Jones” qualifies, but “Johnson” and “jones” do not.
The next example evaluates to TRUE if the value in column LOCATION is at least four
characters long and the fourth character from the right is b as in “Woodbury.”
The next example evaluates to TRUE if the string “mall” does not appear anywhere in
column DESCRIPTION. Rows with the word “Small” or “small” in column
DESCRIPTION are not selected.
The next example illustrates a DECLARE CURSOR statement using LIKE with logical
operators from a UCS COBOL program using ESQL:
This sequence of statements declares a cursor that selects all rows from table
HOUSES with the word “house” anywhere in the description (thus eliminating
duplexes and condominiums) which are also located in a city ending with “polis” (such
as Minneapolis or Annapolis).
If % or _ is part of the data you are trying to find, use an escape character to indicate
that the following special character is not to be used as a wild card, but as a character
to be matched with itself.
Whenever the escape character appears in the pattern string, RDMS substitutes the
escape character and the character immediately following it with a literal
representation of the second character. For example, if the escape character is #,
RDMS treats the pattern string “RATE IS %#%” as “RATE IS %%” with the second %
representing a literal percent sign. In order for a column value to match this pattern
string, it must start with “RATE IS” and end with %. The escape character cannot
appear as the last character of the pattern string.
This evaluates to TRUE if the string “9% assumable” appears anywhere in column
DESCRIPTION.
2.5.5. IN Operator
The IN operator tests for membership in a set by allowing you to specify a set
operation in a Boolean expression.
Format 1
value-expression [ NOT ] IN { (set-value-list) │ subquery }
• If the value expression is equal to at least one value in the set value list or
subquery, the result is TRUE.
• If the value expression is not equal to any value in the set value list or subquery,
the result is FALSE.
• If the subquery is empty, the result is FALSE.
• If none of these conditions apply, the result is UNKNOWN.
Format 2
(value-expression [, value-expression]...) [ NOT ] IN subquery
where:
value–expression
is a numeric, character, or datetime value.
NOT
A NOT IN B is equivalent to NOT(A IN B).
set–value–list
is a list of any combination of string literals, numeric constants, datetime literals,
CAST functions, variable specifications, the keyword USER, or the datetime
functions CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP, as long
as the list is composed of operands of compatible t`ypes.
Note: For compatibility, RDMS allows NULL in the set value list; however, the
use of null here is nonstandard and meaningless. IN(NULL) does not select
records because it is equivalent to =NULL, which is always FALSE.
subquery
is as described in 2.7.4.
• If the row defined by the list of value expressions is equal to a row returned from
the subquery, the result is TRUE.
• If the row defined by the list of value expressions is not equal to any row returned
from the subquery, the result is FALSE.
• If the row defined by the list of value expressions or subquery is empty, the result
is FALSE.
• If none of these conditions apply, the result is UNKNOWN.
Examples
The following example has an IN operator with a set value list:
The next example has an IN operator with a subquery, where the Boolean expression
evaluates to TRUE for every customer where no available house exists in the
customer's desired location:
The following example uses a table that has a four-column primary key. The IN clause
selects the records returned by the subquery.
x NOT IN subquery
NOT x IN subquery
Format
{ AVG │ MAX │ MIN │ SUM }
( DISTINCT column-specification) }|
You cannot nest aggregate functions. The size and scale of the result of aggregate
functions generally depends on the argument type of the function, as follows.
Examples
The following example finds the average price of all houses in table HOUSES,
regardless of location, counts all houses available, and determines the number of
cities in which the houses are located:
The result is
91000 5 4
If you place the SELECT clause in a DECLARE CURSOR statement and follow it with
two FETCH NEXT statements, you get the preceding result on the first FETCH
statement and an end of cursor status on the second FETCH statement.
Since arithmetic expressions are allowed with AVG, MAX, MIN, and SUM, you can also
calculate the total of sales commissions of selected houses, as in the following
example:
The result is the gross commission that would be earned if all houses listed in
Woodbury were sold by agents of the company.
The next example finds the lowest and highest prices of all houses listed, and also
finds the midpoint of the price range of the houses listed:
Format
CURRENT_DATE
SYSDATE
CURRENT_TIME [ (time-precision) ]
CURRENT_TIMESTAMP [ (timestamp-precision) ]
SYSTIMESTAMP
where:
time–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the column after the decimal point. If omitted, 0 is assumed.
timestamp–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the column after the decimal point. If timestamp-precision is omitted, 6 is
assumed.
The following table summarizes the format of the values returned for datetime
functions.
CURRENT_DATE ccyy–mm–dd
Example:
2006-03-05
SYSDATE ccyy-mm-dd
Example :
2006-03-05
CURRENT_TIME hh:mm:ss
Examples:
09:23:12
12:22:31.322983
2006-12-31 23:59:59.999999
The interactions described below for columns also apply to the assignment of a value
in a routine or trigger using the FETCH, RETURN, SET, and SELECT statements.
You can determine the size and scale of function call results from the following table.
Examples
For this example, assume the following table definition:
The following query displays the origination date for all mortgages in the table whose
value is not equal to the date on which the query is executed:
Format
USER
You can use this keyword wherever a string literal or user ID is permitted, with one
exception: You cannot use USER in place of the user ID in a GRANT or REVOKE
statement. Its value is a 12-character, blank-filled, left-justified ASCII string. You can,
for example, use the USER keyword with the OWNER IS clause of the CREATE TABLE
statement.
You may also want to store the current user’s user ID in one column of a table so that
you can track people who made updates to each row; or you may want to provide
row level security on views.
Example
You can override the owner user ID of a table by making the user ID in a view USER to
allow users to see only data that pertains to them, as in the following example:
CREATE VIEW v1
AS SELECT * FROM employees
WHERE emp_userid=USER
WITH CHECK OPTION
Format
[ NOT ] EXISTS subquery
Example
The following example selects all customers whose maximum price equals or
exceeds $100,000 and for which a house is available in the customer's desired
location:
2.6. Sequences
Primary key values can be input to the application, for example a social security
number, or can be generated by the application. If the value is generated it is often
generated as a sequence, either as a sequence of monotonically increasing values (for
example, the BIF unique_id()) , or as a sequence of non-repeating random values (for
example, the BIF permuted_id()). These sequence implementations have
disadvantages. It is not guaranteed when sequentially fetching records from the table,
and having just fetched record n, that all records smaller than n have been inserted.
This is often referred to as the concept of "order". Also, with monotonically increasing
sequences, records are inserted at the end of the table and the inserts are therefore
prone to queuing and deadlock.
Refer to "6.2 CREATE TABLE" for more information on syntax and usage examples of
generated defaults.
See the Relational Database Server for ClearPath OS 2200 Administration Guide for
more information on deciding the appropriate sequence method.
Dynamic preconditioning, in conjunction with 1-record per data page, reduces the
possibility of queuing and deadlock when generated defaults are used. Dynamic
preconditioning is done internally by RDMS as records are inserted into tables
containing a generated default (such as an identity column.) RDMS predicts the key
value of future inserts and creates (and internally commits) empty data pages on the
right-hand side of the B-tree to contain these records. This eliminates the need for
subsequent inserts to perform page splits, and therefore increases concurrency. See
the Relational Database Server for ClearPath OS 2200 Administration Guide for more
information.
The results of the following two query specifications are the same:
SELECT a, d, b, c
FROM r1, r2
WHERE b = r2.b
The next example lists pairs of identically priced houses. It specifies X and Y as
correlation names for the single table HOUSES.
SELECT x.hno,y.hno
FROM houses x,houses y
WHERE x.price = y.price
AND NOT (x.hno = y.hno)
The second part of the Boolean expression, namely NOT (X.HNO = Y.HNO), ensures
that no house is paired with itself.
To get a list of the average price of houses in each town (LOCATION) where houses
are listed, you can use the following query specification:
The following table illustrates the data selected from table HOUSES.
LOCATION AVG(Price)
Woodbury 85000
Westchester 90000
Parkway Heights 85000
Turtle Creek 110000
Note that the database has one row for each location except Woodbury.
To find the locations where the average price of a house is higher than $100,000, use
the following query specification:
The following example shows a query that takes sales record rows for one
salesperson, groups them by price into groups of thousands of dollars, discards
groups that have fewer than eight sales (excluding the five thousand dollar group) and
returns the groups’ “rounded off” dollar amount and number of sales.
You can also use the query specification to specify how to group the data and
whether duplicate sets of data should be returned.
Syntax
query-specification
(with-clause)
SELECT [ ALL | DISTINCT ] {select-list | * }
FROM table-reference-list
[ WHERE Boolean-expression ]
[HAVING Boolean-expression ]
where:
with-clause
Defines one or more common table expressions. For restrictions and usage, see
2.7.5.
WITH cte
cte
query-name [ ( column-name [, column-name])] AS ( query-
expression-order-fetch )
ALL
directs RDMS to select all rows identified by the FROM, WHERE, GROUP BY, and
HAVING clauses. If neither ALL nor DISTINCT is used, ALL is assumed.
DISTINCT
directs RDMS to select only distinct rows. Nulls are considered equal for the
purpose of determining distinct rows.
If a column identified in select–list is defined with a COLLATE clause (see 2.9.3),
RDMS uses the rules in the named collation to determine whether values are
equal or not equal.
In some collations, for example, the following two values are considered equal:
Cæsar
Caesar
* (asterisk)
directs RDMS to select all columns of the tables listed in the FROM clause.
select–list
is a list of items in the form
where:
select–expression
is a numeric, character, or datetime value expression, or column specification.
AS
is the keyword for the title name clause that refers to an item in select-list.
You can use this name to generate reports and descriptions, to simplify sort
descriptions in the ORDER BY clause, and to specify the group item in the
GROUP BY clause.
title–name
is any descriptive name you provide to replace a column name, to name a
column of a derived table, to identify a result of an arithmetic expression, to
identify a constant, or to identify the result of a function.
The name of the title appears in the description returned by the GET
DESCRIPTION statement, in the description section of the UNLOAD statement,
and in the column headings produced by the IPF SQL Interface for the SELECT
Multirow statement. For more information, see the RDMS and IPF SQL End
User Guide.
table–specification.*
is a shorthand notation that specifies all columns of the table specified in the
order they were defined.
You may have up to 510 items in the SELECT clause whether specified explicitly by
select-expressions or implicitly by * or table-specification.* .
table–reference–list
consists of a list of table-references
You can include a maximum of 14 table references in the table reference list. Use
commas to separate entries in the table reference list.
where:
table-reference
identifies [or references] a table, view, joined table, query name, or derived
table.
table-primary | joined-table
table-primary
identifies [or references] a table, view, joined table, query name, or derived
table.
table-specification
is as defined in 2.2.2.
query-name
is the name of a common table expression defined using a WITH clause.
See 2.7.5.
derived-column-list
is a list of column names. The number of column names must be the same
as the number of columns in the table or derived table. The derived
column name overrides the name of the column within the table or derived
table such that only the derived column name may be used to reference
the column.
derived-table
( query-expression-order-fetch )
A derived table is a conceptual table defined by a query.
The derived table query cannot reference tables listed in the FROM clause
in which it appears. It can reference tables in the FROM clauses of outer
nesting levels.
A derived table must have a correlation–name.
A cursor containing a derived table is nonscrollable.
correlation–name
is an alias for a table within the query specification. The most common use
for correlation names is to easily identify each instance of a table that is
joined to it.
joined-table
table-primary join-type JOIN table-primary join-condition
join-type
join-condition
ON Boolean-expression
restricts the rows selected for the join. The Boolean expression for
an outer join may not contain predicates with a subquery. All columns
referenced in the Boolean-expression must be columns of the
table-primaries referenced in the joined-table clause.
WHERE Boolean–expression
restricts the rows selected. Boolean expressions are defined in 2.4.2. The Boolean
expression specifies the criteria that a row must meet for inclusion. Indicator
variables (see 2.10.4) are not allowed in the WHERE clause.
where group-by-item is
The GROUP BY clause describes how to separate rows into distinct groups. All
rows in which the set of values in the group-by-item list are equal form one group.
The GROUP BY clause instructs RDMS to construct one row for each group. Each
such row contains summary information about the group.
This clause is typically used to select a single row for each group. The select list
can contain any combination of group-by-items, literals, or aggregate functions.
HAVING Boolean–expression
One grouped table row is formed for each group that satisfies the HAVING clause.
The Boolean expression in the HAVING clause can refer to any literal value,
aggregate function, group-by-item found in the GROUP BY clause, or if the
HAVING clause appears within a subquery, it can be an outer reference. See the
explanation of GROUP BY in this section for the restriction on HAVING if a
scalar-bif-reference is used in the GROUP BY clause.
For more information about built-in functions, see 2.4.10; for more information
about subqueries and outer references, see 2.7.4.
If you have a HAVING clause but no GROUP BY clause, all rows derived from the
FROM and WHERE clauses comprise a single group, and the resulting grouped
table consists of zero or one row.
Order of Rows
A query specification defines a set of rows but does not impose an order to those
rows. The rows retrieved from the sets of two very similar query specifications can
come out in very different orders. Unless you use the ORDER BY clause (in
statements where it is permitted), you should assume that the order of retrieval of
rows is arbitrary.
DISTINCT Keyword
The SQL 92 entry level syntax allows the use of the DISTINCT keyword only once in a
query specification. RDMS provides two extensions to this restriction:
• Duplicate DISTINCT keywords are allowed in the arguments of the MAX and MIN
functions. DISTINCT is essentially ignored for these functions, anyway.
• A query specification can have, at most, one function with DISTINCT if the “global”
DISTINCT (namely, SELECT DISTINCT) is used.
The derived table query cannot reference tables listed in the FROM clause. It can
reference tables in FROM clauses of outer nesting levels. For example, the query
is not allowed because table a and derived table d_table are in the same FROM clause.
Therefore, d_table may not reference table a as it does in the WHERE clause.
On the other hand, the reference to table a in the following query’s innermost WHERE
clause is acceptable because table a is not listed in the same FROM clause that
d_table is listed.
SELECT * FROM a
WHERE EXISTS(SELECT * FROM (SELECT * FROM b WHERE b.c1 = a.c1)d_table)
A derived table may not contain another derived table. A derived table may not contain
a UNION or be declared within a UNION.
You can use OUTER/INNER join operation within a derived table but you cannot use it
for joining a derived table with the other tables. For example, the query
is not allowed. A derived table can be inner joined with other tables by using a comma
instead of the INNER JOIN keywords.
Those special cases where RDMS allows you to specify a query or define a view with
a subordinate view or views that contain aggregate operations are as follows:
• A query specification can contain either the DISTINCT keyword in the select list or
a WHERE clause, or both, even if the query specification’s FROM clause
references a view with grouping operations, with the following limitations:
The view must be the only table name in the query specification’s FROM
clause.
The query specification cannot contain any grouping operations.
If a query specification contains the DISTINCT keyword in the select list, RDMS
replaces view column references in the select list with the underlying table
columns, expressions, and functions, and applies the DISTINCT operation to
the modified select list.
If a query specification contains the WHERE clause, RDMS appends the
WHERE clause conditions to the HAVING clause of the referenced view.
• A query specification with the DISTINCT keyword in the select list can reference
one or more views with the DISTINCT keyword in the select list, with the
following limitations:
None of the referenced views can contain any grouping operations if the
query specification's FROM clause references multiple table names.
The query specification cannot contain any grouping operations.
In this case, RDMS replaces view column references in the select list with the
underlying table columns, expressions, and functions, and applies the DISTINCT
operation to the modified select list. The referenced view can also contain the
DISTINCT keyword in the select list, even though it is redundant and ignored by
RDMS.
• Even if a query specification does not contain the DISTINCT keyword in the select
list, it can join views that contain the DISTINCT keyword in the select list, with the
following limitations:
Each table name in the query specification’s FROM clause must identify a
view.
Each referenced view must contain the DISTINCT keyword in the select list.
None of the referenced views can contain grouping operations if the query
specification's FROM clause references multiple views.
The query specification cannot contain any grouping operations.
In this case, RDMS first removes duplicates after considering all items specified in
the select lists of the referenced views, and then returns the values of the items
specified in the select lists of the queries and views.
Notes:
• You cannot specify a query or define a view that joins a view with grouping
operations to another table or view.
• You cannot specify a query or define a view that contains a grouping operation
along with a subordinate view that contains aggregate operations as well.
• You cannot include a column whose data type is BLOB in the
column-specification-list or Boolean-expression in the WHERE, GROUP BY, and
HAVING clauses.
The following cursor declaration, for example, is invalid because both the cursor and
view contain aggregate operations:
This view definition is also invalid because both views contain aggregate operations:
Now suppose the following view with the DISTINCT keyword in the select list:
The following cursor definition is valid. Note the redundant DISTINCT keyword in view
DISTVIEW's select list; it is ignored by RDMS.
Now suppose another view with the DISTINCT keyword in the select list:
The following cursor is invalid because view DISTVIEW contains the DISTINCT
keyword in the select list but table CUSTOMERS is not a view:
On the other hand, the following cursor is valid since both DISTVIEW and
DIST_DESLOC are views that contain the DISTINCT keyword in the select list:
• RDMS removes duplicates and considers the two items, DISTVIEW.LOCATION and
DIST_DESLOC.DESIREDLOC.
• View column DIST_DESLOC.DESIREDLOC is not specified in the cursor's select list,
but it is considered when removing duplicates since it is in the definition of view
DIST_DESLOC.
DECLARE distview_with_dist_desloc CURSOR
SELECT distview.location
FROM distview, dist_location
WHERE distview.location = dist_desloc.desiredloc
The following two queries are semantically identical. You may find the INNER JOIN
query easier to understand.
SELECT *
FROM houses, customers
WHERE location = desiredloc AND maxprice > 100000
SELECT *
FROM houses INNER JOIN customers ON location = desiredloc
WHERE maxprice > 100000
If you want to join these results with loan packages available for various ranges of
prices, you can change the query to
SELECT *
FROM houses INNER JOIN customers ON location = desiredloc
LEFT OUTER JOIN loans
ON price BETWEEN minprin AND maxprin
WHERE maxprice > 100000
Note that price, a column in table Houses, may be referenced in the second ON clause
because it is part of the JOIN clause (the second one). This JOIN clause includes a
subordinate JOIN clause (the first one) that in turn includes table Houses. You will not
be able to reference table Loans in the first ON clause because Loans is not one of the
tables listed in that JOIN clause.
2.7.3. Execution
The query specification specifies
1. The FROM clause specifies the tables to be used. Think of the result of the FROM
clause as a new conceptual table that consists of all listed tables joined together.
(Remember that the result is conceptual only; it does not physically exist.)
2. If a WHERE clause is used, all rows not meeting its requirements are discarded
from the conceptual table created in step 1. If the WHERE clause contains a
subquery, the subquery is evaluated against each candidate row of the conceptual
table in this same order of steps. Depending on whether the requirements are
met, rows are included or discarded from the conceptual table.
3. If a GROUP BY clause is used, the grouped conceptual table is formed based on
the rows remaining after step 2. If no GROUP BY clause is used, a HAVING clause
yields zero or one row.
4. If a HAVING clause is used, all rows in the grouped table created in step 3 that do
not meet the requirements of the HAVING clause are discarded. If the HAVING
clause contains a subquery, the subquery is evaluated for each group of the
grouped table according to this same scheme, and this evaluation determines
what is to be included in or discarded from the grouped table.
5. The select list then determines which columns of the remaining rows are to be
used.
2.7.4. Subqueries
As illustrated in 2.4.2, a subquery consists of a query specification that can be used as
an operand of a Boolean expression.
Subqueries impose a simple recursive structure for using the results of one query to
help resolve the results of another query. This powerful single construct, however,
does introduce some subtle syntax differences between a query specification and a
subquery specification. It introduces, as well, some restrictions on how subqueries are
used and where they can appear.
Format
( SELECT [ ALL │ DISTINCT ] { * │ select-expression | select-list }
FROM table-reference-list
[ WHERE Boolean-expression ]
[ GROUP BY group-by-item [, group-by-item]...
[ HAVING Boolean-expression ] )
[ ORDER BY sort-specification-list ]
[ FETCH FIRST m ROWS ONLY ]
where group-by-item is
sort-specification-list
are the sort specifications, separated by commas, in the form
[ COLLATE collation-name ]
[ ASCENDING │ DESCENDING ]
where:
column-specification or title-name
must reference columns contained in tables that are listed in the
FROM clause.
unsigned-integer
specifies the position of the element in select-list if one of the
columns to sort is not a column specification but an expression (such
as MAXPRICE * 1.1).
collation-name
is the collation to use for ordering the values. The collation here is
independent of the column definition. The column’s character set must
match the collation's character set. This clause applies only to columns
with data type CHARACTER.
scalar-bif-reference
is a reference to a scalar built-in-function. A column must be
referenced in each scalar-bif-reference in the ORDER BY clause.
You define a subquery specification just as you define a query specification, with the
following exceptions:
If a subquery is the argument of an EXISTS function (see 2.5.9), you can use an
asterisk ( * ) as in the following example:
WHERE EXISTS (SELECT * FROM t1...).
Subqueries can appear as part of a Boolean expression contained within the scope of
an outer query's or subquery’s WHERE clause or HAVING clause.
Examples
The following example is invalid because SELECT * is only allowed in the select list of
a subquery if the predicate is an EXISTS function:
The preceding example can be corrected by specifying LOCATION in the select list of
the subquery:
Scope of References
The name of a table specified within a query or subquery specification and its
associated column name or names are defined in the corresponding select expression
or expressions and can be referenced anywhere within the scope of the query
specification. Any subqueries, therefore, contained within the scope of a query
specification can reference these tables and columns as an outer reference.
References, however, within the outer query to tables and columns defined in inner
level subqueries are not allowed.
The scope of references for tables and columns defined within a query and its
subqueries can be modeled as in nested procedures, each defining global variables at
their own level of nesting. The innermost procedure can reference all variables
defined outward. The outermost procedure, however, can reference only those
variables defined within its own body. Variables defined within the nested subroutines
are not available to it.
Example
The following example illustrates an outer reference within a subquery specification.
The retrieved rows represent houses whose price is affordable for all customers who
want to buy in that location:
The next example is invalid because the outer query refers to a column in a table that
is defined (specified) in the inner subquery:
Examples
In the following query specification, the subquery portion of the Boolean expression is
executed for each unique customer name with a customer number greater than C201:
In the following query specification, the subquery portion of the Boolean expression is
evaluated for each row of table CUSTOMER to see whether it is included in the
resulting query:
Rules of Evaluation
Assume S represents the result of a subquery whose number of projected items is
equal to 1 and number of rows is at most equal to 1. X represents the result of an
(arithmetic) expression.
Next, assume S represents the result of a subquery whose number of projected items
is equal to 1, the number of rows in the set S is not restricted by a WHERE clause, and
Si represents those values in the set S. X represents the result of an (arithmetic)
expression.
• If the comparison is FALSE for at least one value Si in S, the following comparison
evaluates to FALSE:
X comparison-operator ALL S
• If the comparison is TRUE for at least one value Si in S, the following comparison
evaluates to TRUE:
X comparison-operator { SOME │ ANY } S
You want to evaluate the operands S and X by the comparison operator IN:
• When a subquery containing the FETCH FIRST m ROWS ONLY clause is specified
within the context of the existential operator EXISTS, the clause is ignored and the
value of m is set to 0.
- A way to rewrite such a query, as in the following example:
SELECT * FROM houses
WHERE price EXISTS (SELECT maxprice FROM customers
FETCH FIRST 20 ROWS ONLY)
becomes
SELECT * FROM HOUSES
WHERE price = ANY (SELECT maxprice FROM customers
FETCH FIRST 20 ROWS ONLY)
If the subquery does not contain a GROUP BY clause and the set expression
does include an aggregate function, then each column referenced in the
expression must be specified as an input parameter to an aggregate function.
To illustrate this, the following subquery specification is invalid because C2 is
not part of an aggregate function:
(SELECT MIN(c1) + c2 FROM t1 WHERE...)
If the subquery table specification list contains a grouped view, the select
expression cannot contain an aggregate function.
• A SQL statement can contain only a single WITH clause which must be at the
beginning of the outer-most query-expression.
• A WITH clause may contain only one CTE.
• The WITH clause is allowed only in the following SQL statements: DECLARE
CURSOR, PREPARE of a cursor specification, SELECT multi-row and SELECT
single-row. You can UNLOAD from a cursor that contains a CTE.
• Column-names returned must be unique within the common table expression.
• At most 510 columns may be returned by a common table expression.
• A CTE may not include UNION, nor may a CTE be referenced within a UNION.
• A CTE may not be in a VIEW, nor may it reference any views, nor may the SQL
statement containing the CTE reference any views.
For example
DECLARE houselist CURSOR
WITH okhouses( okprice,oklocation ) AS
(SELECT maxprice,desiredloc FROM customers),
oksellers( okprice,oklocation ) AS
(SELECT price, location FROM houses )
SELECT 'buyers want ' ,okhouses.okprice ,
'sellers offer' ,oksellers.okprice
FROM okhouses ,
oksellers
WHERE okhouses.oklocation = oksellers.oklocation ;
NCHARACTER [ (size) ]
where:
size
must be a positive integer unless omitted, in which case 1 is assumed.
CHARACTER data types contain ASCII or any other 9-bit data. NCHARACTER data
types contain 16-bit character data, such as kanji.
For CHARACTER, RDMS treats each byte as one character. Thus, size defines both
the number of bytes and the number of characters a column can hold.
For NCHARACTER, RDMS treats each pair of bytes as one character. Thus, size
defines the number of characters and one-half the number of bytes a column can
hold.
character-set-specification
(default RDMS_TEXT) identifies the character set for the values in the column, and
can be either a standard-character-set-name or an
implementation-defined-character-set-name, where:
standard–character–set–name
can be the name of any character set supported by the I18N service library,
including but not limited to the most heavily used character sets ASCII and
ISO8859-1.
implementation–defined–character–set–name
can be any of the following character set names: SQL_TEXT, RDMS_TEXT
(default), SQL_CHARACTER, ASCII_GRAPHIC, LATIN1, or ASCII_FULL.
You can use the abbreviations CHAR for CHARACTER and NCHAR for NCHARACTER.
For an explanation of the characters included in each character set, see The I18N
Assistant.
Character set names must be installed on the system and must be legal values for the
CCS_NAME_TO_CCS_NUMBER service routine provided by the I18N service library to
be allowable at RDMS execution time. The I18N character sets installed on your
system determine the legal values. For further information, see The I18N Assistant.
If the name contains a hyphen, you must enclose it in quotation marks (for example,
“ISO8859-1”).
Character set names are case-sensitive in RDMS; therefore, they may have to be
enclosed in quotation marks. RDMS is not otherwise case-sensitive.
Examples
CHARACTER(20)
NCHARACTER(40)
If you use ASCII COBOL or ASCII FORTRAN programs to pass 16-bit kanji data, you
must split the kanji character into two 8-bit halves and pass each half as a separate
alphanumeric character. RDMS reassembles the data correctly on output as kanji. This
means that you need two ASCII COBOL or ASCII FORTRAN character positions to
store the information that is usually stored in one NCHARACTER position.
RDMS compresses all character strings when they are stored by removing all trailing
blanks from the string. RDMS compresses a string of all blanks to a single blank to
decrease storage requirements and to increase character manipulation speed.
When RDMS compares character strings, it adds blanks (ASCII character 040) to the
shorter string to make both strings the same length, unless an explicit collation is
specified (see 2.9.2).
When you request character data (for example, using the FETCH or SELECT
statements), RDMS finds the character string, expands it with blanks to its defined
length as specified in the table definition, and returns the requested data.
RDMS provides a synonym for a character column with a character set “UCS-2”. For
example, the following two column definitions are equivalent:
UNICODE (10)
DECIMAL [ (decimal-digits-precision[,scale]) ]
NUMERIC [ (digits-precision[,scale]) ]
INTEGER
SMALLINT
where:
decimal–digits–precision
depends on whether it appears in an item definition in an unowned or an owned
schema. If the value is part of a definition in an owned schema, the system adds 1
to the value before storing the definition in the UREP metadatabase and file
RDT$FILE. This means that all subsequent reporting of the definition by the UREP
commands PROCESS TABLE REPORT and REPORT TABLE, the RDMS catalog, and
the GET DESCRIPTION and UNLOAD (WITH DESCRIPTION) statements indicate a
value one greater than the original definition. For a description of owned and
unowned schemas, see 6.10.
For unowned schemas, it is the number of digits in an item, including the leading
sign. This must be an integer between 2 and 22. If decimal-digits-precision is
omitted, 2 is assumed. Two examples follow:
• An item defined as DECIMAL(3) can contain integer values from –99 to +99,
inclusive. DECIMAL(3) is the same as DECIMAL(3,0).
• An item defined as DECIMAL(3,2) can contain values from –.99 to +.99.
DECIMAL(3,2) is the same as DECIMAL(3.0002) or DECIMAL(3,0002).
For owned schemas, it is the number of digits in an item, excluding the leading
sign. This must be an integer between 1 and 21. If decimal-digits-precision is
omitted, 1 is assumed. Two examples follow:
• An item defined as DECIMAL(3) can contain integer values from –999 to +999,
inclusive. DECIMAL(3) is the same as DECIMAL(3,0).
• An item defined as DECIMAL(3,2) can contain values from –9.99 to +9.99.
DECIMAL(3,2) is the same as DECIMAL(3.0002) or DECIMAL(3,0002).
digits–precision
is the number of digits in the item, a positive integer up to 21. If digits-precision is
omitted, 11 is assumed.
scale
is a nonnegative integer that indicates the number of digits for the fractional
portion of the item. If scale is omitted, zero is assumed.
You can use the abbreviations DEC for DECIMAL and INT for INTEGER.
Table 2–7 shows the largest and smallest values for exact numeric data types.
REAL
FLOAT [ (binary-precision) ]
DOUBLE [ PRECISION ]
• REAL—27 bits. You can store values of 8 and sometimes 9 digits of precision.
• FLOAT—At least the minimum specified in binary–precision. RDMS frequently
provides more precision than specified, up to a maximum of 60 bits. This means
that you can store any values of up to 18 digits of precision. You can actually store
some 19-digit values.
• DOUBLE PRECISION—60 bits. This means that you can store any values of up to
18 digits of precision. You can actually store some 19-digit values.
Table 2–8 shows the largest- and smallest-magnitude positive and negative values
that can be used with approximate data types.
REAL
Positive 1.70141182E+38 1.46936794E–39
Negative -1.70141182E+38 -1.46936794E–38
FLOAT
Positive 8.988465674311579551E+307 2.781342323134001732E–309
Negative -8.988465674311579551E+307 -2.781342323134001732E–309
DOUBLE PRECISION
Positive 8.988465674311579551E+307 2.781342323134001732E–309
Negative -8.988465674311579551E+307 -2.781342323134001732E–309
You can also store zero in the approximate numeric data type items.
• Range refers to how far apart the maximum and minimum values are for a data
type. As you can see from the listed maxima and minima, SMALLINT has the
smallest range and DOUBLE PRECISION has the largest range. If you know the
range of values an item must store, you may be able to narrow the field of
appropriate numeric data types for that item.
• Precision refers to the number of significant digits that "fit" in the item.
Table 2–9 gives the number of digits and bits for each numeric data type. A plus
sign (+) indicates that, in some cases, an additional digit or bit of precision is
available. For instance, 10+ in the table means “at least 10, and in some cases 11.”
Digits of
Data Type Precision Bits of Precision
• Exactness is discussed in 2.4.7 and 2.8.2. Perhaps the most important aspect of
exactness is that comparisons between exact and approximate types may give
unpredictable results.
• Memory requirements vary by numeric data type. If mass storage or main
memory space is a concern for you, you may wish to consider the memory
implications of the numeric data types you use.
Table 2–10 illustrates the basic amount of memory used for each listed data type.
In addition to the space shown, additional space is used for each item to contain
information about the item.
DECIMAL(n,s) n bytes
NUMERIC(p,s) 1 word if p <= 11;
2 words if p > 11
INTEGER 1 word
SMALLINT Half word (18 bits)
REAL 1 word
FLOAT(n) 1 or 2 words
DOUBLE PRECISION 2 words
Notes:
• For DECIMAL items defined in an owned schema, the number of decimal digits
is one greater than the number of decimal digits in the original definition. This is
because of the difference in the semantics of this value between the SQL
standard and RDMS. For a description of owned and unowned schemas,
see 6.10.
• Arithmetic and comparison operations are faster on binary data types (INTEGER,
SMALLINT, REAL, FLOAT, and DOUBLE PRECISION) than on the other data
types.
• The evaluation of expressions that include different data types uses more
overhead than the evaluation of expressions in which all operands are the same
type.
• FLOAT(n) uses one word when n <= 27; otherwise, it uses two words.
• NUMERIC(11,s) handles the values from –34359738367 to 34359738367. Use
NUMERIC(12,s) to handle numbers outside this range.
• Exact to approximate
If you store an exact value, like DECIMAL type value 10.357, into an approximate
item (for example, into a REAL item), some accuracy may be sacrificed.
Note: For DECIMAL items defined in an owned schema, the number of decimal
digits is one greater than the number of decimal digits in the original definition.
This is because of the difference in the semantics of this value between the
SQL standard and RDMS. For a description of owned and unowned schemas,
see 6.10 (CREATE SCHEMA).
• Larger exact into smaller exact
Suppose you try to store an exact value (say DECIMAL type value 12345.678) in an
exact data item that cannot accommodate it. If a value is stored in a SMALLINT or
INTEGER item, RDMS truncates the fractional portion.
If the receiving item can accommodate some, but not all of the fractional portion,
it is rounded if necessary to make it fit. For example, storing 12345.678 into a
DECIMAL(7,1) item leaves 12345.7 in the receiving item.
If the integer portion of the value does not fit the receiving item (for example,
trying to store 12345.678 into a DECIMAL(3) item) the system returns an error and
no value is stored. If this happens on an UPDATE statement, the old value remains
in the item. If it occurs on an INSERT statement, no row is created.
• Approximate to exact
When you store an approximate value into an exact item, the value is converted,
maintaining as much accuracy as possible. Fractional portions of the converted
value can be rounded off to fit into DECIMAL or NUMERIC items. Fractional
portions are truncated to fit SMALLINT or INTEGER items.
For example, when you store 3.14159265 into a DECIMAL(4,2) item, the result is
3.14. Storing 1934.88 into an INTEGER item results in 1934.
• Larger approximate into smaller approximate
If the value to be stored is within the range of the receiving item, it is stored.
However, its precision can be reduced. But if the value to be stored exceeds the
range of the receiving item, the system returns an error and no value is stored. If
this happens on an UPDATE statement, the old value remains in the item. If it
occurs on an INSERT statement, no row is inserted.
Format
The formats of datetime data types are
DATE
TIME [ (time-precision) ]
TIMESTAMP [ (timestamp-precision) ]
where:
time–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the item after the decimal point. If omitted, 0 is assumed.
timestamp–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the item after the decimal point. If omitted, 6 is assumed.
The largest and smallest values for datetime data types are as follows.
Memory Requirements
Memory requirements for datetime data types vary depending on the precision
specified. Table 2–11 illustrates the memory required for each data type based on
precision.
• SQL variables
• Literal strings
• Program variables that contain character strings in datetime format
Use the following guidelines to determine the length of the character buffer to contain
the datetime value:
If you try to store datetime data 2006–08–12 through program variables, you can use
the CAST function as follows, where the variable vdate contains the string
DATE '2006–08–12':
The length of variable VDATE should be at least 16 ASCII characters. In the preceding
example, if VDATE contains the string 2004–08–12, the length of VDATE must be at
least 10 ASCII characters. You can also use the program variable directly, and RDMS
will implicitly cast the value (to DATE in this case). For example
For more information on storing and retrieving datetime data, see 3.8.
Time Zones
Current_timestamp, now(), and getdate() always return timestamps in local time.
Getutcdate() returns a timestamp in Coordinated Universal Time (UTC). Use the
new_time() function to convert between time zones.
There are boundary conditions to be aware of when seasonal time zone shifts are
made (this is called changing between standard time and day light savings time in the
United States).
With no time zone shift, timestamps are monotonically increasing. This is not true
during the seasonal time zone shift as shown below.
Format
BINARY LARGE OBJECT ( size ) [IN storage-area-name]
or
where:
size
is the maximum length for the BLOB, in bytes. The value can be in the range 1 to
4,294,967,296 (4G) bytes. The maximum length can be specified as a simple
integer representing the number of bytes or as an integer followed by one of the
following suffixes:
K Kilobytes (210 or 1,024 bytes)
M Megabytes (220 or 1,048,576 bytes)
G Gigabytes (230 or 1,073,741,824 bytes; 2G is interpreted as 231)
IN
When the IN storage-area-name clause is not specified, RDMS stores the BLOB
value as part of the record. BLOBs stored as part of the record are always stored
as varying because the amount of BLOB storage is never padded to the maximum
size BLOB. The maximum size BLOB value that can be stored in a record is similar
to the maximum size character value that can be stored in a record, approximately
28,000 bytes. Refer to the Relational Database Server for ClearPath OS 2200
Administration Guide for more information on RDMS maximum sizes.
storage-area-name
is the name of the storage area associated with the BLOB column. A storage area
name must be a valid SQL name as defined in 2.2.4.
You can use the abbreviation BLOB for Binary Large Object.
Examples
BLOB(24)
BLOB(3M) IN myschema.bstorage1
BLOB(1073741824) IN blob_area4
• You can add a column with data type BLOB to a table only if the table has explicitly
defined storage areas. For example, an IN clause must immediately follow the
table’s name on the CREATE TABLE statement. If the IN clause is present, the
table is said to have an “explicitly defined storage area.” If the IN clause is not
present, RDMS creates a storage area in which to store data and indices for the
table and the table is said to have an “implicitly defined storage area.” You cannot
add a BLOB column to a table with an implicitly defined storage area.
• BLOB storage areas (storage areas with DATA-FORMAT RSM-LOB) cannot be
shared with table indices or shared with data from columns whose data type is
not BLOB.
• With the BLOB data type, you specify a storage area for each column’s data. The
storage area can be different for each BLOB column or multiple BLOB columns
can share the same storage area. If you share one storage area among multiple
BLOB columns, you must declare each column with exactly the same size.
• You can also specify a list of storage areas on the column definition. If you include
more than one storage area, they form a storage area pool. RDMS uses the
storage area in the order you list them in the storage-area-specification list.
When the first storage area is full, RDMS stores the BLOBs in the second storage
area specified for the column, and so on. If you specify more than one storage
area, the storage area names must be enclosed in parentheses.
• You can specify up to 511 storage areas for each BLOB column.
• All BLOB storage areas must have a DATA-FORMAT of RSM-LOB.
• All BLOB storage areas must have DOMAIN UDS or USER-UDS (as is the case for
all other RDMS storage areas).
• Once storage areas have been added to a BLOB column, they cannot be removed
individually. You must use ALTER TABLE to DROP the column and ADD it again
with fewer (or different) storage areas.
• Note that a BLOB value must be able to fit entirely within one storage area. When
cataloging storage areas, you must ensure that the maximum size of the storage
area is larger than the maximum size of the BLOBs you want to store in the
storage area. RDMS does not split BLOB data across storage areas. RDMS
returns a storage area full error if the BLOB value does not all fit in a single
storage area.
In the following example, the data for the column name and the index for the name
primary key are stored in the storage area s1.data_storage. The data for column
picture is stored in s1.lob_storage_1 and can overflow into the storage area
s1.lob_storage_4. The data for column thumb_print is stored in the storage area
s1.lob_storage_2. The data for column signature is stored in storage area
s1.lob_storage_3. The column sizes are each tailored to the size of the expected data
values.
In the following example, the data for the column name and the index for the name
primary key are stored in the storage area s1.data_storage. The data for columns
thumb_print and index_finger are both stored in s1.lob_storage_1. For both columns
to be stored in the same storage area, the declared size of the columns must match.
Additionally, the column resume is stored in s1.lob_storage_6 and may overflow into
s1.lob_storage_4. Because of the sizes of the LOB columns, each column typically
uses multiple data pages. RDMS allocates “column size” amount of space in the
storage area for each BLOB value. The size of the pages in the storage areas can be
adjusted to accommodate the different column sizes without incurring excessive
overhead of wasted space for each BLOB value.
• Assigned to columns
• Compared with column values in a WHERE clause
For the UCS COBOL programming language, the discussion depends on the following
variations of the definitions of the program variables:
• A column defined with data type CHARACTER and no CHARACTER SET clause
specified. The column’s character set is implicitly RDMS_TEXT.
• A column defined with data type CHARACTER and CHARACTER SET RDMS_TEXT.
• A program variable with numeric data type (for example, int in UCS C or PIC 9 in
UCS COBOL)
• A column with data type NCHARACTER
• A UCS COBOL or UCS C variable with data type SQL TYPE IS BLOB
• A column of data type BLOB
• A column of data type NCHARACTER, because the character sets cannot match
• A UCS COBOL program variable of data type PIC X USAGE IS BYTE–I18N, because
the source is a binary value, not a character value
• A UCS COBOL program variable of data type PIC X USAGE IS DISP–2, because the
character sets cannot match
• A UCS COBOL or UCS C variable with data type SQL TYPE IS BLOB
• A column of data type BLOB
• A column of data type NCHARACTER, because the character sets cannot match
• A UCS COBOL program variable of data type PIC X USAGE IS BYTE–I18N, because
the source is a binary value, not a character value
• A UCS COBOL program variable of data type PIC X USAGE IS DISP–2, because the
character sets cannot match
• A UCS COBOL or UCS C variable with data type SQL TYPE IS BLOB
• A column of data type BLOB
If the column has a data type of BLOB, RDMS stores only the BLOB text. It does not
store the length information.
RDMS does not allow a column of data type CHARACTER with the CHARACTER SET,
or CHARACTER with the CHARACTER SET and COLLATE clauses as a data source.
If the column has a data type of BLOB, RDMS stores only the BLOB text. It does not
store the length information.
Character Strings
A character string data type is identified by the RDMS data type CHARACTER or
NCHARACTER. This discussion, however, applies only to data type CHARACTER,
whose attributes include
Every character stored in a column belongs to a character set. The character set is
either implicit or explicit. If you specify only CHARACTER for the data type, RDMS
implicitly assigns the character set RDMS_TEXT to the column. You can use the
CHARACTER SET clause with the CHARACTER data type to attach the name of a
specific character set to the values in a column.
Character set names can be names defined by national or international standards and
names defined by the OS 2200 system, both of which are available for use in RDMS.
Character set names defined by standards are referred to as “standard character set
names.” Those defined by the OS 2200 operating system are referred to as
“implementation–defined character set names.”
All character strings of a given character set are mutually comparable only if they have
the same collating sequence.
Given a collating sequence, two character strings are identical if and only if they are
equal in accordance with the collation rules.
When character strings have explicit collating sequences, the comparison of two
character strings depends on the collating sequence used for the comparison. Since
RDMS always strips trailing spaces from character column values or literals before
transforming the data to an ordering key value, the shorter value is effectively
extended to the length of the longer value by concatenating binary zeros on the right.
COLLATE Clause
The COLLATE clause has two functions:
• On a column definition, it tells RDMS how to compare and order column values
and indexes.
• In an ORDER BY clause of a DECLARE CURSOR statement, it tells RDMS how to
collate (sort) the data after it is retrieved from the database.
SQL 92 Syntax
COLLATE collation-name
Collation names must be installed on the system and must be legal values for the
LOCALE_NAME_TO_LOCALE_NUMBER service routine provided by the I18N service
library to be allowable at RDMS definition or execution time. The locales installed on
your system determine the legal values. For more information, consult The I18N
Assistant.
Collation names are case–sensitive. RDMS treats names that are not enclosed in
quotation marks as if all characters in the name were uppercase characters.
Each collation has an implicit or explicit character set associated with it. The character
set must match the implicit or explicit character set of the related RDMS column or
program variable. For example, if a table contains a column with CHARACTER SET ABC
and COLLATE COLL1, then COLL1 must be associated with character set ABC. This
association is defined by the I18N service library and can be determined by reports
from UREP. For more information about creating I18N UREP reports, see The I18N
Assistant.
Examples
COLLATE C
COLLATE "it_IT.8859-1"
Handling Expressions
The introduction of internationalization (I18N) processing changes the way character
columns can be used in expressions. This processing applies to any expression with a
comparison operator: <, <=, =, <>, ^=, !=, >=, >, BETWEEN, IN, NOT NULL, and EXISTS.
Columns with a COLLATE clause are not allowed with the LIKE operator.
Processing
How RDMS processes character string literals and columns of data type CHARACTER
depends on both of the following:
When values of unequal length that do not have explicit collating sequences are
compared, the shorter value is effectively extended to the length of the longer by
concatenation of spaces on the right. RDMS always uses the character with the octal
code of 040 (an ASCII space) for a column with an implicit binary collation.
CREATE TABLE t1
(col1 CHAR(20))
CREATE TABLE t1
(col1 CHAR(20) CHARACTER SET RDMS_TEXT)
All data entered into RDMS databases before the introduction of I18N features has an
implicit character set name of RDMS_TEXT. The implicit ordering for the character set
name follows the binary codes for the character representations.
Existing data in a column may actually be encoded in any character set. The following
examples assume that the data actually in the column uses a LATIN1 or ISO 8859–1
character set. If the data actually in the column used an ISO 646 national variant, the
results may differ.
The binary character order for the ISO 8859–1 character set is as follows:
For example, suppose columns COL1 and COL2 are defined as CHARACTER with no
explicit character set name and no explicit collation. If a data item of column COL1 has
the character value 'X' and a data item of column COL2 is NULL, the values of the
following expressions are as indicated:
Expression Value
CREATE TABLE t1
(col1 CHAR(20) CHARACTER SET "ISO8859-1")
When a column is defined with an explicit character set name, other than RDMS_TEXT,
RDMS enforces that the values inserted into the column are encoded using that
character set.
For example, if column COL1 is as defined in the preceding example, then column
COL2 must also be defined with the clause CHARACTER SET “ISO8859–1” in the
expression:
However, columns defined implicitly or explicitly with the character set name
RDMS_TEXT can be the source or destination for columns defined with any character
set name. In the preceding example, col2 could also be defined with the character set
name RDMS_TEXT. Likewise, CHARACTER columns with no explicit character set can
be the source or destination for columns defined with any character set name.
Table 2–12 summarizes the legal comparison combinations. The definitions in the first
column of the table are the first operand in a comparison expression. The definitions in
the top row of the table are the second operand in a comparison expression.
* This case is allowed only when one operand is a string literal or a program variable. RDMS
uses the explicit collation of the other operand.
** Two columns can be compared only if their character sets match and their collations match.
Example
CREATE TABLE t1
(col1 CHAR(20) CHARACTER SET "ISO8859-1" COLLATE "da_DK.8859-1")
RDMS uses I18N library service routines with the rules in the specified collation when
processing values in the column.
Example: Danish
The collation then follows the collation rules for the specified locale. For example,
"da_DK.8859–1" indicates the collation for the Danish language in Denmark. For more
details on specific locale definitions, see The I18N Assistant.
Peculiar to the Danish collating scheme are the characters that collate after z. For
collating purposes, the characters “AA” are a synonym for Å and the characters “aa”
are a synonym for å.
Some of the characters in the character set do not occur in the Danish language. The
characters Ñ, and ñ, for example, do not appear in Danish. These characters belong to
the ISO 8859–1 character set, however, and must be accommodated in the
da_DK.8859–1 ordering scheme.
For example, suppose columns COL1 and COL2 are defined as having the ISO8859–1
character set name and da_DK.8859–1 collation. If a data item of column COL1 has the
character value “X” and a data item of column COL2 is NULL, the values of the
following expressions are as indicated:
Expression Value
Example: German
The collation follows the collation rules for the specified locale. For example,
“de_DE.8859–1” indicates the collation for the German language in Germany. For more
details on specific locale definitions, see The I18N Assistant.
Peculiar to the German collating scheme, the “sharp S” or Eszet collates as if it were
“ss”. So the words “Straße” and “Strasse” compare as equal.
Some of the characters in the character set do not occur in the German language. The
characters Ñ and ñ, for example, do not appear in German.
These characters belong to the ISO 8859–1 character set, however, and must be
accommodated in the de_DE.8859–1 ordering scheme.
For example, suppose columns COL1 and COL2 are defined as having the ISO8859–1
character set name and de_DE.8859–1 collation. If a data item of column COL1 has the
character value “X” and a data item of column COL2 is NULL, the values of the
following expressions are as indicated:
Expression Value
Example: Spanish
The collation follows the collation rules for the specified locale. For example,
“es_ES.8859–1” indicates the collation for the Spanish language in Spain. For more
details on specific locale definitions, see The I18N Assistant.
Peculiar to the Spanish collating scheme, the characters CH and ch collate between
cz and da. Thus, the correct ordering of the words “chorizo,” “czar,” and “day,”
according to the Spanish collating scheme, is “czar,” followed by “chorizo,” followed
by “day.”
Similarly, the characters “LL” and “ll” collate between “lz” and “ma”. Thus, the correct
ordering of the words “llama,” “lyric,” and “man” is “lyric,” followed by “llama,”
followed by “man.”
Some of the characters in the character set do not occur in the Spanish language. The
characters Ø and ø do not appear in Spanish, for example.
These characters belong to the ISO 8859–1 character set, however, and must be
accommodated in the es_ES.8859-1 ordering scheme.
For example, suppose columns COL1 and COL2 are defined as having the ISO8859-1
character set name and es_ES.8859-1 collation. If a data item of column COL1 has the
character value “X” and a data item of column COL2 is NULL, the values of the
following expressions are as indicated:
Expression Value
If a data item of column COL1 has the character value “Chorizo”, the values of the
following expressions are as indicated:
Expression Value
• Primary keys
• Secondary indexes
• GROUP BY clause
• ORDER BY clause
• Boolean expressions
For the data type NCHARACTER, values collate according to the binary sequence of
the characters.
The COLLATE clause on the column definition determines the collating order for
column values. For more information on the collating order for the supported locales,
consult The I18N Assistant.
This character set supports the Danish, Dutch, English, Faroese, Finnish, French,
German, Icelandic, Irish, Italian, Norwegian, Portuguese, Spanish, and Swedish
languages.
US ASCII is a subset of the ISO 8859–1 character set and consists of the characters
space through tilde ( ~ ).
ASCII COBOL and ASCII FORTRAN, however, do not have kanji type variables. When
you use one of these languages to work with kanji data, use alphanumeric host
program variables to store the data. The interface routines for these languages
(ACOB$RDMR and F$RDMR) are not informed that kanji data is being passed.
RDMS treats the data as though it were ASCII data, but the kanji data remains intact.
Remember that NCHARACTER columns use two bytes to store one kanji character.
Host program variables must therefore be declared to be twice as long as the kanji
column to avoid truncation.
For more information on CHARACTER and NCHARACTER data types, and kanji data,
see 2.9.
• Hold information you are passing to RDMS using (for example, an INSERT
statement).
• Receive information retrieved by RDMS (for example, using a FETCH statement).
• Contain information from an application that is to be compared with a value in an
RDMS table. This is typically included in the WHERE clause of a query
specification.
For example, in a real estate application, a program might prompt users for a desired
location. This location is stored in a host program variable. RDMS compares that value
with the location value of the rows in table HOUSES to determine whether to retrieve
a given row.
You need a host program variable for each column into which you are inserting values,
from which you are retrieving values, or with which you are comparing values.
• Embedded variable
ESQL syntactically handles comparisons between RDMS and program data and the
moving of data to or from RDMS differently from how the interpreter interface
handles them. You prefix the host program variable name with a colon ( : ) and
embed it in the command string. Such a variable is called an embedded variable.
Host program variable names must be ASCII characters; they cannot contain kanji
or katakana characters.
• Parameter marker
ESQL permits you to place parameter markers in the SQL command string being
prepared. These are called dynamic parameter markers.
• Placeholder variable
In the interpreter interface, you must pass the SQL command string to RDMS. If
you are moving values to or from RDMS, or if RDMS is comparing a value from a
program with a value in a table, you must place markers in the SQL command
string to hold a place for values. These markers are called placeholder variables.
The call to RDMS must have a host program variable for each placeholder variable.
• Indicator variable
An indicator variable is an embedded variable, parameter marker, or placeholder
variable that contains a null value, a nonnull valid value, or the defined size of a
CHARACTER column.
All variables in an SQL statement must be of the same type; that is, they must all be
embedded variables, parameter markers, or placeholder variables.
:embedded-variable-name,...
Declare embedded variables between the BEGIN DECLARE (see 6.3) and
END DECLARE (see 8.1) statements, both of which are optional.
Example
EXEC SQL FETCH c1 INTO :house, :cust END-EXEC.
You can use an embedded variable to specify a version name in a table specification of
an ESQL statement. Since a colon ( : ) is used to prefix both an embedded variable and
a version name in a table specification, you must use two colons to correctly identify
the variable as an embedded variable containing a version name.
Use the following format to pass a version name with embedded variables:
[ qualifier.]table-specification[::variable-name]
Examples
If a host program variable VERNAME has the value OUTSTATE, the following table
specification names table Q1.HOUSES:OUTSTATE:
q1.houses::vername
When you use an embedded variable to pass a version name in connection with a
DECLARE CURSOR statement, the value of the embedded variable is not passed to
RDMS until the cursor is opened.
When a version name is passed in an embedded variable, the rules for delimited
identifiers apply (see 2.2.1). In particular, lowercase letters are not equivalent to
uppercase characters.
Although you can use more than one parameter marker in your code, you must rely on
the one–to–one correspondence of question mark to embedded program variable to
ensure which parameter marker is serving what purpose.
Example
EXEC SQL PREPARE del FROM
'DELETE customers WHERE cno = ?'
END-EXEC.
EXEC SQL EXECUTE del USING :cus-no END-EXEC.
Placeholder variable names have a leading dollar sign and the letter P to distinguish
them from other names, as follows:
$Pinteger
where integer is greater than or equal to one and has no leading sign. The placeholder
variable name cannot contain blanks.
You must pass one host program variable as a parameter for each placeholder variable
you place in the SQL command string.
Examples
The following are valid placeholder variable names:
$p1
$p5
$p10
$P
P1
$P(1)
$Pete
$P0
$ p2
$P 3
The integer portion of a placeholder variable name associates it with a host program
variable in the RDMS call.
The next example shows that placeholder variables are useful for changing parameter
values within a statement:
where $P1, $P2, $P3, and $P4 are placeholders for variables passed from the program
to RDMS.
This statement inserts a row of data that contains all four item values into table
HOUSES.
One way to use this statement is in a loop that changes the values of the associated
application program variables. With each execution of the loop, RDMS stores a new
row in table HOUSES.
Note: You can use embedded variables to pass names only for versions.
See 2.10.1.
Since both names and data can be passed to RDMS as placeholders, RDMS follows
this rule to differentiate between the two. If the placeholder variable appears where
an expression can appear, RDMS considers it to be data, not a name; otherwise,
RDMS considers it a name.
Examples
In the following statement, RDMS considers $P1 and $P2 as data:
In the next statement, RDMS considers $P1 and $P2 names because they appear
where only names can appear:
If you attempt to pass a name where an expression can appear, RDMS may return an
error or invalid results.
Example 1
The following UCS FORTRAN example illustrates the relationship of placeholder
variables to application program variables in an RDMS CALL statement:
lolim = 8000
hilim = 10000
CALL F$RDMR('DELETE houses WHERE price'//
$ 'BETWEEN $p1 AND $p2;',
$ errloc, auxinf, lolim, hilim)
In this example, the variable $P1 is a placeholder for the FORTRAN variable LOLIM.
This is in the first parameter after the error status and auxiliary information variables.
$P2 is a placeholder for HILIM, the second parameter after the error status and
auxiliary information variables.
The possible numbers in the placeholder variable names range from 1 to the number
of host program variables passed with the statement. For example, if four variables
are passed, the placeholders can be $P1, $P2, $P3, and $P4.
Example 2
The next example shows that placeholder variables can appear in any order and any
number of times:
INSERT INTO houses COLUMNS (hno = $P3, location = $p1, price = $p2,
description = $p1) ;
Assume the preceding INSERT statement is stored in the FORTRAN character variable
CMD and followed by the statement
The value of VAR1 goes into columns LOCATION and DESCRIPTION (through $P1). The
value of COST goes into column PRICE (through $P2). The value of IDNO goes into
column HNO (through $P3).
Example 3
The final example, which executes the same operation as the preceding example,
shows that you do not have to associate a placeholder variable with each host
program variable passed with a statement.
You use data variables and indicator variables, except for parameter markers, in pairs
to access columns. See the last example for the use of parameter markers.
The indicator variable returns the defined size of the column of the table whenever it
is greater than the defined size of the host program variable, even if the truncated
characters are nonsignificant trailing blanks.
Table 2–13 illustrates what different values returned by indicator variables mean.
Value of
Indicator Signifies on INSERT/UPDATE Signifies on SELECT/FETCH
-1 The corresponding data variable has The database column has a null
a null value.* value.*
Other Negative The corresponding data variable has ---
Values a value.
Note: This is the way RDMS has
always worked, but it is contrary to
SQL 2003, which states that all
negative values signify NULL.
Zero The corresponding data variable has The corresponding data variable has
a value. a value.
1 The corresponding data variable has The database value is too long for
a value, except for UPDATE the corresponding data variable and
SYNCHRONIZE, in which case the is truncated.
UPDATE does not change the
existing values in the table.
Other Positive The corresponding data variable has ---
Values a value.
You must provide a null indicator variable for each column that allows nulls. RDMS
returns an error if a null without an indicator variable is retrieved.
To use variables in a list, separate the data variable (first of the pair) from the indicator
variable with the keyword INDICATOR or a blank:
Example 1
The following two lines both link data variable $P1 and its indicator variable $P2:
$p1 $p2
$p1 INDICATOR $p2
The next two lines both link the embedded variables :DATAVAR and :INDICVAR as data
variable and indicator variable:
:DATAVAR :INDICVAR
:DATAVAR INDICATOR :INDICVAR
Example 2
The following UCS COBOL example inserts a row into table CUSTOMERS with a null in
column CNAME (the second column of the table):
MOVE -1 TO null-indic.
MOVE 'c109' TO cno.
MOVE 80000 TO max-price.
MOVE 'gotham' TO des-loc.
ENTER MASM 'ACOB$RDMR' USING
'INSERT INTO customers VALUES ($p1,$p2 $p3,$p4,$p5);',
error-code, aux-info, cno, cust-name,
null-indic, max-price, des-loc.
Example 3
The next UCS COBOL example illustrates the preceding example rewritten to use
ESQL:
MOVE -1 TO null-indic.
MOVE 'c109' TO cno.
MOVE 80000 TO max-price.
MOVE 'gotham' TO des-loc.
EXEC SQL INSERT INTO customers VALUES (:cno, :cust-name :null-indic,
:max-price, :des-loc) END-EXEC.
Example 4
The next UCS FORTRAN example illustrates the use of an indicator variable in a FETCH
statement:
Example 5
In the next example, the cursor TWOCOL has two columns, CNAME and
DESIRED_LOC. The variables NAME and DESLOC are declared as eight characters
each. The cursor is positioned to retrieve the values “Owen” and “New London.” To
retrieve a row, enter the following:
name Owen
ind1 0 No truncation occurred even though the application
program variable is smaller than the column in the table
(28-character capacity).
desloc New Lond
ind2 40 RDMS truncated the data value because the length of
the returned character value exceeded the size of the
host program variable. (The column capacity is 40
characters.)
Example 6
To use indicator variables in conjunction with a dynamic ESQL statement, use a single
parameter marker for the value of each variable, and use a pair of embedded variables
in the USING clause of the corresponding EXECUTE statement, as in the following
example:
This powerful approach allows you to write programs that take very different
measures with the database depending on the circumstances they encounter. Since
each SQL statement must be interpreted each time it is executed, however, the
overhead in calling RDMS can be significant. This is particularly true in tight loops
where some statements have to be executed many times.
You can also embed SQL statements in UCS COBOL and UCS C programs, not as an
ENTER MASM interpreter interface call, but in a form very much like any other COBOL
or C statement. SQL statements embedded in this manner are compiled instead of
interpreted. This interface is called ESQL, which takes two forms: static and dynamic.
For a closer look at dynamic ESQL, see 2.11.6.
Example
The following line is an example of a static ESQL statement:
For a summary of which SQL statements you can use with ESQL, see Section 5. For an
example ESQL program, see the COBOL Compiler Programming Reference Manual
Volume 1.
By compiling SQL statements, you avoid a great deal of overhead in RDMS when a
program encounters SQL statements during execution. This results in a significant
reduction in execution time.
When the program executes, each SQL statement in the object module is checked
during execution to ensure that it is not out of date. This prevents errors that would
otherwise occur if the database definition changed between the compilation and
execution of the program.
For details on porting a static ESQL program or module from one application group or
host to another, see the Relational Database Server for ClearPath OS 2200
Administration Guide.
Error statuses and error messages appear whenever a static ESQL statement is not
compatible with the modified table.
Whenever automatic recompilation occurs while executing static ESQL programs that
are compiled with default qualifiers and versions, the RDMS internal compilation
process uses compile time qualifiers and versions to create the execution instruction
set. For further details on qualifier and version names, see 2.2.1.
Statistical information can change, however, between compilation and execution time.
RDMS uses current statistical information if statistics is on (SET STATISTICS ON) and
automatic recompilation is performed. Therefore, if you use portable ESQL to launch
your application, the STATS$FILE may not contain valid statistics. For further
information on porting ESQL programs, refer to the Relational Database Server for
ClearPath OS 2200 Administration Guide.
To ensure that appropriate execution paths are selected, you should run statistics
whenever you make any changes to tables that are likely to invoke automatic
recompilation.
Example
EXEC SQL SQL-statement END-EXEC.
Embedded SQL statements in an ESQL UC program are bracketed with EXEC SQL and
the C statement's terminating semicolon.
Example
EXEC SQL SQL-statement ;
In either case, the ESQL statement cannot contain a semicolon. Do not break
EXEC SQL or END-EXEC across a line boundary. The SQL statement can span as many
lines as necessary.
In the interpreted and dynamic ESQL environments, these statements affect the
statements that follow them in execution. This follows from the interpreted nature of
this type of SQL interaction with the database. But ESQL statements are compiled,
and they may be compiled in an order different from the order in which they are
executed.
Certain ESQL statements, however, affect statements that follow them in the source
code for the compilation unit in which they are found. If two statements are both
found in object module A, the one that appears first in the listing affects the other.
This gives rise to some important characteristics of certain static ESQL statements:
• A SET STATISTICS statement affects all other static ESQL statements that follow it
textually in the listing until superseded by another SET STATISTICS statement.
• Likewise, a USE DEFAULT statement affects all other static ESQL statements that
follow it textually in the listing until superseded by another similar USE DEFAULT
statement. For special considerations on the use of defaults in routines and
triggers, see Section 4, 8.6 (FETCH), and 9.4 (OPEN).
• A cursor declaration must appear in the source listing before any static ESQL
reference to it.
• A WHENEVER statement affects all other static ESQL statements that follow it
textually in the listing until superseded by another WHENEVER statement.
• A static ESQL DEBUG statement causes the compiler to print compile-time
information of all subsequent static ESQL statements until another static ESQL
DEBUG statement turns off the printing.
The static ESQL statements DECLARE CURSOR, DEBUG, SET STATISTICS, USE
DEFAULT, and WHENEVER are called compile-time statements because they are acted
upon by RDMS during program compilation. Even though the statements derived from
these statements may affect the execution of the program, the statements
themselves are not executed.
Example
This example illustrates the scope of compile–time ESQL statements. Assume you
have the following UCS COBOL program source code:
The following table illustrates these characteristics for all four of the cursors in the
code fragment.
Error Handling
Cursor Name Paragraph Default Qualifier Statistics On/Off
The values of these characteristics hold regardless of the order in which the DECLARE
CURSOR statements are encountered during program execution.
Even though you cannot have ESQL DECLARE CURSOR statements with the same
cursor name in the same object module or two opened interpreter interface cursors
of the same name, you must establish certain guidelines for how duplicate cursor
names from the two interfaces or from different compilation units are resolved
(or bound):
Example
This example illustrates these cursor resolution rules.
OBJECT_MODULE_1
:
EXEC SQL DECLARE csr_3 CURSOR... .
EXEC SQL DECLARE csr_2 CURSOR... .
ENTER MASM 'ACOB$RDMR' 'DECLARE csr_1 CURSOR...',... .
EXEC SQL OPEN csr_2 END-EXEC.
ENTER MASM 'ACOB$RDMR' 'OPEN csr_3;',... . (Illegal; interpreter OPEN must
be matched by an interpreter
DECLARE)
ENTER MASM 'ACOB$RDMR' 'OPEN csr_1;',... .
ENTER MASM 'ACOB$RDMR' 'CLOSE csr_1;',... .
EXEC SQL OPEN csr_3 END-EXEC.
OBJECT_MODULE_2
:
EXEC SQL DECLARE csr_2 CURSOR... .
ENTER MASM 'ACOB$RDMR' 'OPEN csr_1;',... .
ENTER MASM 'ACOB$RDMR'
'UPDATE tbl SET c1 = 5 WHERE CURRENT OF csr_1;',... .
ENTER MASM 'ACOB$RDMR'
'UPDATE tbl SET c1 = 5 WHERE CURRENT OF csr_2;',... . (csr_2 opened in
OBJECT_MODULE_1
above)
EXEC SQL FETCH csr_3 INTO... .
The program processes the data and creates an UPDATE statement in a host program
variable. You can have the program have RDMS compile and execute the statement,
either immediately or later when the program is executed.
Example
Suppose the SQL UPDATE statement is in variable update–stmt, which contains the
string:
UPDATE houses
SET price = 119000
WHERE hno = 'H101'
You prepare it first, giving it a statement name. Then you execute the prepared
statement to actually update the database:
The prepared statement can be executed any number of times, making it especially
useful in loops. You can replace the literals in the UPDATE statement with parameter
markers:
UPDATE houses
SET price = ?
WHERE hno = ?
Prepare it once and then, within a loop, have the program solicit the user for the new
price and house number. With these values in variables, execute the UPDATE
statement, passing the variables so that their values replace the parameter markers:
ACCEPT new-price.
ACCEPT house-number.
EXEC SQL EXECUTE prepped_update USING :new-price, :house-number END-
EXEC.
Whenever the statement is not formed until the program is executed and the
statement has to be executed only once, you can use the EXECUTE IMMEDIATE
statement, which performs essentially what PREPARE and EXECUTE statements
together perform.
In the preceding UPDATE statement, for example, which contains the literal values,
you can execute the following:
DEBUG
DELETE
INSERT
LOCATE
LOCK
SET STATISTICS
UNLOCK
UPDATE
USE DEFAULT
In PREPARE Statements
Dynamic ESQL allows you to use the following SQL statements in the PREPARE
statement:
COMMIT
DELETE
INSERT
LOCATE
LOCK
ROLLBACK
SET STATISTICS
UNLOCK
UPDATE
USE DEFAULT
The use of module programs limits the method used to invoke RDMS, thus preventing
the mixing of requests from module and nonmodule programs in the same thread. It
further prevents the mixing of requests from different modules in the same thread.
The use of both a module language and another interface to access the database in
the same thread produces undefined results.
Other points to keep in mind when accessing RDMS from a module language
program:
Most SQL statements that are allowed in ESQL are allowed in module programs. See
detailed information about the individual statements in Sections 5 through 10.
The following statements, however, are allowed in ESQL but are meaningless in a
module:
BEGIN DECLARE
END DECLARE
FETCH NEXT n (module languages do not allow arrays)
USE DEFAULT
WHENEVER
The following statements are not allowed in modules because they are not allowed in
ESQL:
DROP CURSOR
EXPLAIN
GET DESCRIPTION
LEVEL
SELECT Multirow
Module language source programs are processed by the SQL module language
preprocessor (SMLP). SMLP verifies that the source program follows all syntax rules
defined in the SQL standard for modules, except one. The one exception is that the
RSA component of RDMS verifies that the SQL statement specified in a module
procedure is allowed and uses acceptable syntax. In other words, SMLP does not
parse SQL statements beyond initial keywords. SMLP produces a separate UCS
COBOL subroutine for each module procedure.
Each subroutine contains a USE DEFAULT QUALIFIER statement as well as the SQL
statement from the specific module procedure. These statements are ESQL and thus
processed by RDMS during program compilation. The SMLP flags unacceptable
occurrences of DECLARE CURSOR statements.
RDMS provides many predefined functions called built-in functions (sometimes called
BIFs or scalar functions) that can be called from an SQL statement. This section
describes the syntax and usage of these functions in detail.
The subsections of this section group functions by their general purposes, such as
functions that return character, numeric, or date and time results. Table 3–2 is an
alphabetical listing and summary of functions. This table also provides a reference to
the subsection that describes each function in detail.
SELECT UPPER(cname)
FROM s1.customers
The following example inserts the customer's name and its corresponding Soundex
value into the table s1.customers from an embedded SQL program:
• <any string data type or blob> includes CHARACTER, CHARACTER with CHARACTER
SET, CHARACTER with CHARACTER SET and COLLATION, NCHAR, and BLOB.
• <time, date, or timestamp data type > includes TIME, DATE, or TIMESTAMP data
item, a TIME, DATE, or TIMESTAMP literal string, or a character string containing a
valid time, date, or timestamp value.
• <time or timestamp data type > includes TIME or TIMESTAMP data item, a TIME
or TIMESTAMP literal string, or a character string containing a valid time or
timestamp value.
• <date, or timestamp data type > includes DATE, or TIMESTAMP data item, a DATE
or TIMESTAMP literal string, or a character string containing a valid date or
timestamp value.
3.1.3. Rules
The following are some rules that affect the operations and usage of functions.
Result Length
The functions that return values with the data type CHARACTER or NCHAR are limited
to 28,616 bytes. The functions that return values with the data type BLOB are limited
to 4,294,967,296 bytes. If the length of the return value exceeds the limit, RDMS
truncates it and returns an error message. Additionally, intermediate results may not
exceed these limits either. For example, although the following expression returns
only 10 bytes, the intermediate result of the concat function cannot exceed these
limits:
substring(concat(column1,column2),1,10)
Parameters
A parameter for a function, indicated as length, precision, start, and so on, can be any
of the following:
• An integer literal
• The result from a function of which the result data type is SMALLINT or INTEGER
• A column, parameter, or SQL variable of which the data type is SMALLINT or
INTEGER
If the data type is a numeric data type but not INTEGER, RDMS implicitly casts the
data type to INTEGER. RDMS truncates any fractional part of a floating point value.
left('abcdef',pi())
• SELECT list:
select function(a,b,c) from t1 where x=y
• HAVING clause:
select x, y, z from t1 where c1=5 having function(a,b,c) = c1
• Nested:
select concat(substring(ltrim(c1),1,5), substring(ltrim(c3),2,8))
• Constraints:
alter table t1
add c7:char(15)
add constraint con7 check(isalpha(c7)=1);
where:
a, b, c
are data items that can be literals, constants, ESQL variables, placeholder
variables, column-specifications, the name of another function, an SQL variable, or
routine parameter.
x, y, z
are column-specifications or other values currently allowed in the given context.
consvar
is a literal, constant, ESQL variable, or placeholder variable (in other words,
anything except a column-specification).
The processing of the concat function and the | | operator are influenced by the data
type. The concat function uses the materialized lengths of its string arguments. If the
data type of a string argument is CHARACTER, trailing blanks are returned to make the
string the maximum length. For example
RDMS provides two additional concat functions to emulate the semantics of the
VARCHAR data type:
The functions concat, concatrtrim, and concatstrim take any string type as input.
RDMS always generates results in columns. The RDMS optimizer figures out what the
column width should be to accommodate the longest value for the column. In the case
of functions such as space, nspace, substring, repeat, and others, one of the
arguments indicates the length of the result value:
For most functions, this length does not include trailing blanks. However, GET
DESCRIPTION would return a column size different from the actual result generated at
run time.
In the data record generated for the function result, the length is correct. You can
demonstrate this by concatenating a short literal value on either side of the function
result. For example
If the value of var_name is 3 and ∆ represents one ASCII space, the result would be as
follows:
xx∆∆∆yy
This demonstrates that the SPACE function generated 3 ASCII space characters.
Table 3–1 summarizes the allowed data type combinations and the return values.
SET 1
1. The CHARACTER SET for both strings must be the same or compatible. The COLLATION for both
strings must be the same or must be compatible. See 2.9 for more information.
2. The CHARACTER SET for both strings must be the same or compatible. The COLLATION for both
strings must be the same or must be compatible. See 2.9 for more information. The resulting
character set is the character set of the item with the collation clause.
3. The internal format of the I18N value is concatenated to the BLOB value. The character set and
collation information are both lost.
Trailing blanks in character string arguments are ignored by most functions when the
character string arguments are variables (host language variables, column names, SQL
variables) and are not ignored when the character string arguments are literals. The
exceptions are the right and concat functions, which do not ignore trailing blanks
when the character string arguments are either variables or literals.
The following table shows examples of arguments that illustrate these rules. In these
examples, COL1 has the 8-character value 'MMNNOO∆∆' (where ∆ is an ASCII space).
RDMS does not differentiate between zero-length strings and NULL strings for column
references. For example, suppose the table SEED has a character (20) column called
VARIETY. You can set the value of the column to spaces using the UPDATE statement:
RDMS stores a single space into the column. You can check the length using the
length function:
If you use rtrim(variety), the resulting length is 0 (zero), because the rtrim function
removes all trailing blanks including the original blank.
You can concatenate other character strings onto the blank value for the column
variety. For example
For example, consider using the concat function along with the rtrim function:
or
Note that this behavior of the concatrtrim function applies only in the case where
parameter 1 is a column reference. If it is the result of another function, RDMS uses
the function result with no alteration. For example
If you want a different semantic handling for the single space situation, you can use
the ifnull function to return a default value. For example
The SELECT statement returns the string “no variety hardy”. Because rtrim(variety)
returns a zero-length (NULL) string, the ifnull function returns the alternate (parameter
2) value.
See the Relational Database Server for ClearPath OS 2200 Administration Guide for
more information on how international character values are stored internally in RDMS.
• The first week of the year begins on the first day of the year. The second week of
the year begins after seven days. For example, if January 1 occurs on a Friday,
week 1 in the new year contains Friday, January 1 through Thursday, January 7.
Week 2 contains Friday, January 8 through Thursday, January 14.
See the to_char function format WW.
• The first day of the week is Sunday. The first week of the year begins on the first
Sunday of the year. All days in a new year preceding the first Sunday are
considered to be in week 0. For example, if January 1 occurs on a Friday, week 0 in
the new year contains Friday, January 1 and Saturday, January 2. Week 1 contains
Sunday, January 3 through Saturday, January 9.
In regions where the first day of the week is Monday, the calculation changes
accordingly. If January 1 occurs on a Friday, week 0 in the new year contains
Friday, January 1, Saturday, January 2, and Sunday, January 3. Week 1 contains
Monday, January 4 through Sunday, January 10.
See also
− round and trunc function formats YYYY and WW
− strftime function formats %U and %W
− week function
• (ISO rule) The first day of the week is Monday. If the week containing January 1
has four or more days in the new year, then it is considered week 1. If it does not
contain at least four days, then it is week 53 of the previous year and the next
week is week 1.
For example, if January 1 occurs on a Friday, week 53 of the previous year
contains Friday, January 1, Saturday, January 2, and Sunday, January 3. Week 1 in
the new year contains Monday, January 4 through Sunday, January 10.
See also
− round and trunc function formats IYYY and IW
− strftime function format %V
− to_char function formats IYYYY and IW
See the julian_day function and the to_date and to_char functions’ format J. See
alternate rules for establishing day zero (0) in the datediff function, datename function,
datepart function, and days function.
Purpose
Returns a 30-character ASCII string containing the value of the current default version.
This is most useful in triggers.
Example
active_version( )
returns
PRODUCTION
Purpose
Returns a 30-character ASCII string containing the value of the current default schema
(qualifier). The scalar functions, active_schema() and active_qualifier() are synonyms for
each other, and return the same value.
Example
active_schema()
returns
RDMS
See Table 3–1 for allowed data type combinations and the result data type.
Purpose
If s1 is a scalar built-in function, it can return a length of zero which concat interprets
as a null string.
Example
Suppose cname is a 20-character column with the value 'Peter'; desiredloc is a
20-character column with the value 'Roseville'
See Table 3–1 for allowed data type combinations and the result data type.
Purpose
Returns s1, with trailing spaces removed, concatenated to s2. This function is
equivalent to
concat(rtrim(s1), s2).
If either s1 or s2 is NULL, RDMS returns a null value. If s1 is a string literal, RDMS does
not remove any trailing spaces. The result is truncated if its length exceeds 28,616
bytes. If either s1 or s2 is a BLOB, RDMS uses concat() semantics.
Example
Assume that cname is a 20-character column with the value ‘Peter’ and desiredloc is a
20-character column with the value ‘Roseville’:
Note: The space before the word desires in the string literal returns the following:
See Table 3–1 for allowed data type combinations and the result data type.
Purpose
Returns s1, with trailing spaces removed and a single space inserted, concatenated
to s2. This function is equivalent to the following:
If either s1 or s2 is NULL, RDMS returns a null value. If s1 is a string literal, RDMS does
not remove any trailing spaces. The result is truncated if its length exceeds 28,616
bytes. If either s1 or s2 is a BLOB, RDMS uses concat() semantics.
Example
Suppose cname is a 20-character column with the value ‘Peter’ and desiredloc is a
20-character column with the value ‘Roseville’
Note: No space before the word desires in the string literal returns the following:
Purpose
Returns a copy of the string s1, with all the kanji shift codes deleted. The delesc
function eliminates all the shift codes by moving the non-shift-code characters to the
left and padding to the right with blanks. If s1 is NULL, RDMS returns a null value.
RDMS assumes that s1 is a kanji string irrespective of the data type of s1.
Example
delesc(acolumn)
Purpose
Returns s1 with the first letter of each word in uppercase, all other letters in
lowercase. Words are delimited by space or by characters that are not alphanumeric.
Example
initcap('minneapolis, minnesota')
Purpose
Returns a string where length characters have been deleted from s1 beginning at start
and where s2 has been inserted into s1 beginning at start.
If start is less than or equal to 0 or is NULL, RDMS uses the value 1. If start is greater
than the length of s1 RDMS appends s2 to s1 and ignores any length value.
If length is less than or equal to 0 or is NULL, RDMS uses the value 0 and deletes no
characters. If start + length extends beyond the end of the s1, RDMS removes all
characters from s1 between start and the end of s1.
If s1 or s2 is NULL, RDMS returns a null value. The result is truncated if its length
exceeds 28,616 bytes.
Example
stuff( 'He rld', 3, 1, 'llo Wo')
returns
Hello World
Purpose
Returns a copy of s1 with the kanji shift codes added to the beginning and ending of
the value, if they are not already present. The shift codes are always fixed. The fixed
shift-out code is 0223 0360. The fixed shift-in code is 0223 0361. This is the same
convention used for kanji identifier names in RDMS. See the Relational Database
Server for ClearPath OS 2200 Administration Guide for more information.
RDMS assumes that s1 is a kanji string regardless of the data type of s1.
If s1 is NULL, RDMS returns a null value.
The functions insesc and delesc are opposite functions.
Example
insesc(acolumn)
Purpose
Returns s1 with all letters in lowercase.
RDMS uses the rules for lowercasing ASCII characters. If the argument references a
column defined using CHARACTER SET and COLLATION, RDMS uses the lowercasing
rules for the specified collation. This function does not support columns defined only
with CHARACTER SET.
Example
lcase('MR. JOHN SMITH')
returns
mr. john smith
Purpose
Returns the leftmost n characters from s1 or n1. If n is less than or equal to 0, RDMS
uses the value 0 and returns a null value. If n is greater than the length of s1, RDMS
returns all the characters in s1 and space-fills to the right.
If n1 is numeric, RDMS returns a character string. See the examples for handling of
positive, negative, and fractional values. See the substring function (3.3.25) for more
examples of handling numeric values.
Examples
left( 'MR. JOHN SMITH', 3)
left(12345, 3)
Note that positive values are not preceded by a plus sign. In a negative value, a leading
minus sign is a significant character.
left(-12345, 3)
If the sign of the value is not important, use the abs function to eliminate the sign.
Purpose
Returns s1, left-padded to length length with the sequence of characters in s2
replicated as many times as necessary. If s2 is not included or is NULL, RDMS uses an
ASCII space.
If s1 is longer than length, RDMS returns the leftmost length characters of s1. If s1 is
NCHAR or CHARACTER SET is UCS-2, RDMS interprets length in double-bytes. If s1 is
NULL, RDMS returns a null value. If length is less than or equal to 0, RDMS uses the
value 0. The result is truncated if its length exceeds 28,616 bytes.
Examples
lpad( 'Page 1', 15, '*.')
returns
*.*.*.*.*Page 1
returns
Page 1
Purpose
Removes characters from the left of s1, with initial characters removed up to the first
character not in set. The value of set defaults to a single space.
Examples
ltrim('xyxXxyMr. Smith', 'xy')
returns
XxyMr. Smith
returns
Mr. Smith
Purpose
Returns a string consisting of n kanji spaces (each space is encoded as the two-byte
string 040 040).
If n is less than or equal to 0 or is NULL, RDMS uses the value 0 and returns a null
value. If n is larger than 14,308, a string of 14,308 kanji spaces is returned.
Example
nspace(4)
Purpose
Returns a string consisting of n repetitions of the string s1.
If n is less than or equal to 0 or is NULL, RDMS uses the value 0 and returns a null
value. The result is truncated if its length exceeds 28,616 bytes.
Examples
repeat('abc', 3)
returns
abcabcabc
replicate('abc', 3)
returns
abcabcabc
Purpose
Returns s1 with every occurrence of s2 replaced with s3. If s3 is omitted or is NULL,
all occurrences of s2 are removed. If s1 or s2 is NULL, s1 is returned with no changes.
If s2 is not found, s1 is returned with no changes.
If s1, s2, or s3 is a COBOL variable, you may have to use the rtrim function to remove
trailing spaces. RDMS treats trailing spaces as significant characters. The result is
truncated if its length exceeds 28,616 bytes.
Example
replace( 'JACK and JUE', 'J', 'BL')
returns
BLACK and BLUE
Purpose
Returns s1 with the characters in the reverse order. If s1 is NULL, RDMS returns a null
value.
Example
reverse('abcd')
returns
dcba
Purpose
Returns the rightmost n characters from s1 or n1. If n is less than or equal to 0 or is
NULL, RDMS uses the value 0 and returns a null value. If n is greater than the length of
s1, RDMS returns all the characters in s1 and pads the value with ASCII spaces to the
lesser of n or, if s1 is a column, to the size of the column.
If n1 is numeric, RDMS returns a character string. See the examples for handling of
positive, negative, and fractional values. See the substring function (3.3.25) for more
examples of handling numeric values.
Example 1
right( 'MR. JOHN SMITH', 3)
returns
ITH
Example 2
Suppose column c1 is defined as CHARACTER(24) with the value ‘MR. JOHN SMITH’.
The CHARACTER data type in RDMS is fixed length.
right(c1,3)
returns
' ' (three ASCII spaces)
To get the equivalent of the processing from a CHARACTER VARYING column, you
must use
right(rtrim(c1),3)
which returns
ITH
Example 3
right(12345, 3)
Purpose
Returns s1, right-padded to length length with the sequence of characters in s2
replicated as many times as necessary. If s2 is not included, RDMS uses an ASCII
space.
If s1 is longer than length, RDMS returns the leftmost length characters of s1.
If length is less than or equal to 0 or is NULL, RDMS uses the value 0 and returns a null
value. The result is truncated if its length exceeds 28,616 bytes.
Examples
rpad( 'MR. JOHN SMITH', 19, 'ab')
returns
MR. JOHN SMITHababa
returns
MR.
Purpose
Returns s1 with final characters removed after the last character not in set. The value
of set defaults to a single ASCII space.
Example
rtrim('Mr. SMITHyxXxy', 'xy')
returns
Mr. SMITHyxX
Purpose
Returns a character string of length 4 containing the phonetic representation of s1.
This function allows you to compare words that are spelled differently, but sound alike
in English. S1 must be ASCII characters. If s1 is NULL, RDMS returns a null value.
There are substantial limitations with both soundex and differences due to the
oddities of English spelling. Soundex fails to match the names Klein and Cline and
considers the word Phone an exact match with Pen, but not Fan. For these reasons,
soundex-based functions should be used cautiously in applications.
Example
SELECT cname FROM customers where soundex(cname) = soundex('SMYTHE')
returns
Smith
soundex('draw')
returns
D600
Purpose
Returns a string consisting of n ASCII spaces.
If n is less than or equal to 0 or is NULL, RDMS uses the value 0 and returns a null
value. If n is larger than 28,616, a string of 28,616 ASCII spaces is returned.
Example
space(4)
Purpose
Returns a portion of s1 or n1 beginning at character start for length characters. If start
is positive, RDMS counts from the left end of the string. If start is negative, RDMS
counts from the right end of the string. If start is 0, RDMS uses 1.
If length is omitted, RDMS returns all the characters from start to the end of s1. If the
value for length is less than or equal to 0 or is NULL, RDMS uses the value 0 and
returns a null value.
If s1 is not a BLOB, RDMS pads the value with ASCII spaces to length if s1 is less than
length characters long. If s1 is NULL, RDMS returns a null value. The result is truncated
if its length exceeds 28,616 bytes.
If n1 is numeric, RDMS returns a character string. See the examples for handling of
positive, negative, and fractional values.
returns
cd
returns
ef
returns
efg∆∆
substring(12, 3, 2)
substring(-12345, 3, 2)
If the sign of the value is not important, use the abs function to eliminate the sign.
substring(-12, 3, 2)
returns
2∆
substr(10000+col1, 3, 3)
returns
001
023
444
substr(col1+.04, 1, 7)
returns
1.04∆∆∆
23.04∆∆
444.04∆
The numeric literal .04 has a precision of 2. The numeric expression 1/20 produces an
internal result with precision 19.
substr(col1+1/20, 1, 7)
returns
1.05000
23.0500
444.050
Purpose
Returns s1 with all the letters in uppercase.
RDMS uses the rules for uppercasing ASCII characters. If the argument references a
column defined using CHARACTER SET and COLLATION, RDMS uses the uppercasing
rules for the specified collation. This function does not support columns defined only
with CHARACTER SET.
Example
upper('mr. john smith')
returns
MR. JOHN SMITH
Purpose
Returns the starting position of expression s1 in expression s2. These functions treat
wild card characters underscore (_) and percent (%) as normal characters. The
patindex function treats the wild card characters as wild card characters.
Note that the parameter order of charindex is opposite from the other two functions.
Examples
charindex( 'world', 'hello world')
returns
7
returns
7
returns
7
Purpose
The parameter cur1 is the name of the cursor. Cursor names must be passed as upper
case strings, unless the cursor was declared as a delimited identifier in which case the
string can be of mixed case.
The parameter attribute is the type of cursor information to return.
If attribute = 'OPENSTATUS'
Returns -2 if the cursor name is ambiguous. It means that there is more than one
external embedded cursors of this name and there is no interactive cursor by the
same name.
Example
cursorstatus('C1','openstatus')
returns
Purpose
Returns the length of the expression s1, in characters, ignoring any trailing spaces. If
s1 is data type BLOB, all characters, including trailing spaces are included in the
returned length.
In addition, see the octet_length function, which returns the length in bytes rather than
in characters.
Example
Suppose cname is a column with the value 'Peter':
char_length(cname)
length(cname)
datalength(cname)
returns
5
Purpose
Returns an integer value that indicates the soundex difference between the two
character strings. The values s1 and s2 must both have been created by the Soundex
function before calling difference.
There are substantial limitations with soundex and difference due to the oddities of
English spelling. Soundex fails to match the names Klein and Cline and considers the
word Phone an exact match with Pen, but not Fan. For these reasons, Soundex-based
functions must be used cautiously in applications.
Example
difference(soundex('drew'), soundex('draw'))
returns
0
Purpose
RDMS searches s1 beginning at character start-position for the mth occurrence of s2
and returns the position of the character in s1 that is the first character of this
occurrence. This function treats wild card characters underscore ( _ ) and percent ( % )
as normal characters. The patindex function treats the wild card characters as wild
card characters.
If start-position is negative, RDMS counts and searches backward from the end of s1.
If start-position is 0, RDMS uses 1.
The default values for start-position and m are both 1 meaning that RDMS starts from
the first character position in s1 for the first occurrence of s2.
If the search is unsuccessful, that is, if s1 does not appear m times after the
start-position character of s1, RDMS returns the value 0. If s1 or s2 is NULL, RDMS
returns 0.
The value of s2 must be 28,616 characters or less, even if s1 is of data type BLOB.
Examples
instr( 'CORPORATE FLOOR', 'OR', 3, 2)
returns
14
returns
2
Purpose
Returns 1 if s1 is composed entirely of alphabetic and numeric characters. Otherwise,
0 is returned.
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
Example
isalnum('Ab123')
returns
1
Purpose
Returns 1 if s1 is composed entirely of alphabetic characters. Otherwise, 0 is returned.
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
Example
isalpha('AbCdZz')
returns
1
Purpose
Returns 1 if s1 is composed entirely of control characters. Otherwise, 0 is returned.
For example, the control characters for the ASCII character set are 00 (NUL) through
037 (US) inclusive and 0177 (DEL).
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
Example
iscntrl('Ab123')
returns
0
Purpose
Returns 1 if s1 is composed entirely of numeric characters. Otherwise, 0 is returned.
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
Example
isdigit('0123456789')
returns
1
Purpose
Returns 1 if s1 is composed entirely of graphical characters. Otherwise, 0 is returned.
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
For the ASCII character set, the graphical characters are 041 ( ! ) through 0176 ( ~ )
inclusive. Note that 040 (space) is not included.
Example
isgraph('@processor,options')
returns
1
Purpose
Returns 1 if s1 is composed entirely of lowercase alphabetic characters. Otherwise, 0
is returned.
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
Example
islower('atoz')
returns
1
Purpose
Returns 1 if s1 is composed entirely of printable characters. Otherwise, 0 is returned.
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
For the ASCII character set, the printable characters are 040 (space) through 0176 ( ~ )
inclusive. Note that 040 (space) is included.
Example
isprint('@processor,options')
returns
1
Purpose
Returns 1 if s1 is composed entirely of punctuation characters. Otherwise, 0 is
returned.
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
The punctuation characters for the ASCII character set are as follows:
Note that space, alphabetic characters, and numeric characters are not included.
Examples
ispunct('@@@@')
returns
1
ispunct('Hello world')
returns
0
Purpose
Returns 1 if s1 is composed entirely of white space characters. Otherwise, 0 is
returned.
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
For the ASCII character set, the white space characters are as follows:
• 011 (FF)
• 012 (NL)
• 013 (CR)
• 014 (HT)
• 015 (VT)
• 040 (space)
Example
isspace(' ')
returns
1
Purpose
Returns 1 if s1 is composed entirely of uppercase alphabetic characters. Otherwise, 0
is returned.
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
Example
isupper('ATOZ')
returns
1
Purpose
Returns 1 if s1 is composed entirely of hexadecimal characters. Otherwise, 0 is
returned.
• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.
Example
isxdigit('0123456789abcdefABCDEF')
returns
1
Purpose
Returns the starting position of expression s2 in expression s1. This function treats
wild card characters underscore ( _ ) and percent ( % ) as normal characters. The
patindex function treats the wild card characters as wild card characters.
If start is negative, RDMS searches backward from the end of s1. If start is 0, RDMS
uses the value 1.
The return value is relative to the beginning of s1 regardless of the value of start.
If the search is unsuccessful, that is , if s1 does not appear after the start character of
s1, RDMS returns the value 0. If s1 or s2 is NULL, RDMS returns 0.
The value of s2 must be 28,616 characters or less, even if s1 is of data type BLOB. If
the value is more than 28,616 characters, it is truncated to 28,616 characters.
Examples
locate( 'CORPORATE FLOOR', 'OR', 3)
returns
5
returns
5
Purpose
Returns the length of the expression s1, in bytes, ignoring any trailing spaces. If s1 is
data type BLOB, all characters, including trailing spaces are included in the returned
length.
In addition, see the data_length function, which returns the length in characters rather
than in bytes.
Example
Suppose cname is a column with the value “Peter”:
octet_length(cname)
returns
5
Purpose
Returns the position of the first occurrence of pattern in s1. Pattern may include the
wild card characters underscore ( _ ) to indicate exactly one character and percent ( %
) to indicate zero or more characters.
If RDMS does not find pattern in s1, it returns the value 0. If pattern or s1 is NULL,
RDMS returns 0.
The patindex function is supported only for strings encoded in 7-bit or 8-bit character
sets, and for Unicode strings that convert to ISO-8859-1.
Example
patindex( 'w%rd', 'forward is the word')
returns
4
3.5. Binary-to-Character/Character-to-Binary
Conversion
The following functions perform conversions between character and binary data
formats.
Purpose
Returns the ASCII code for the first byte in s1 as an integer value. If s1 is NULL, RDMS
returns a null value.
Example
ascii('A')
returns
65
chr(Integer n) → Character
Purpose
Returns the character that has the ASCII code value specified by n. The value of n
must be between 0 and 255; if it is not, RDMS returns an ASCII space.
Example
char(65)
returns
A
Purpose
Returns the value for the first nonnull expression. Up to 200 arguments can be
included.
The data type of the return value is the data type of expr1. None of the expr values
can have data type BLOB.
When necessary, RDMS uses today’s date for the default date value and uses
00:00:00 as the default time value (see example).
Example 1
This function can be used to correct for null values in an arithmetic expression.
Example 2
The following example references a column with a data type of TIMESTAMP. Because
the replacement value has no date portion, RDMS uses today’s date.
Purpose
The decode function is similar to a series of nested IF-THEN-ELSE statements. The
expression s1 is compared to the compare1, compare2, and so forth, in sequence. If
s1 matches the i th compare item, RDMS returns the i th value. If s1 does not match
any of the compare values, RDMS returns the default value.
The data type of each compare must match or be coercible to the data type of the
expression s1. See Table 2–12 for comparison rules for character data types. These
comparison rules also apply to coercibility. All numeric types are coercible. RDMS
uses a default year of 01-01-001 when coercing TIME to TIMESTAMP and a default
time of 00:00:00 when coercing DATE to TIMESTAMP. RDMS truncates the time value
when coercing TIMESTAMP to DATE and truncates the date value when coercing
TIMESTAMP to TIME.
The data type of each value and the default must match value1.
The data type of the return value is the data type of value1 (the third parameter). None
of the compare, value, or default values can have data type BLOB.
Example
decode('abc', 'a', 1,
'b', 2,
'abc', 3,
'd', 4,
-1)
returns
3
Purpose
If the expression expr1 is NULL, RDMS returns the expression expr2, else RDMS
returns expr1. The arguments expr1 and expr2 can be any data type, but they must
match.
The data type of the return value is the data type of expr1.
Expressions with data type BLOB cannot be used with the ifnull and nvl functions.
Examples
Purpose
If the value of expr1 matches the value of expr2, then NULL is returned. Otherwise,
the value of expr1 is returned. The expressions, expr1 and expr2, must not be the
keyword NULL. If the expressions resolve to a null value, the comparison results in an
unknown value. Because unknown is not the same as true, the value of expr1 is
returned.
The data type of expr1, and expr2 must not be FLOAT, REAL, DOUBLE PRECISION or
BLOB.
The data type of each compare must match or be coercible to the data type of the
expression expr1. See Table 2–12 for comparison rules for character data types. These
rules also apply to coercibility. All numeric types are coercible. RDMS uses a default
year of 01-01-0001 when coercing TIME to TIMESTAMP and a default time of 00:00:00
when coercing DATE to TIMESTAMP. RDMS truncates the time value when coercing
TIMESTAMP to DATE and truncates the date value when coercing TIMESTAMP to
TIME.
Example 1
SELECT nullif(1957,1957)
returns
NULL
Example 2
SELECT nullif('apple', 'orange')
returns
'apple'
Purpose
Returns the absolute value of the argument. If the argument is NULL, RDMS returns a
null value.
Example
abs(-15)
returns 15
Purpose
Returns the principal value of the arc cosine of the argument, between 0 and pi. RDMS
returns an error if the argument is not between –1 and 1. If the argument is NULL,
RDMS returns a null value.
Example
acos(0)
returns
1.5708
Purpose
Returns the principal value of the arc sine of the argument, between –pi/2 and pi/2.
RDMS returns an error if the argument is not between –1 and 1. If the argument is
NULL, RDMS returns a null value.
Example
asin(1)
returns
1.5708
Purpose
Returns the principal value of the arc tangent of the argument, between –pi/2 and pi/2.
If the argument is NULL, RDMS returns a null value.
Example
atan(1)
returns
.7854
Purpose
Returns the principal value of the arc tangent of y/x using the signs of both arguments
to determine the quadrant of the return value. The result is between –pi and pi.
RDMS returns an error if both arguments are 0. If an argument is NULL, RDMS returns
a null value.
Example
atan2(1,2)
returns
.4636
Purpose
Returns the smallest integer value greater than or equal to x. If the argument is NULL,
RDMS returns a null value.
There are two exceptions to the rule that the return type is the same type as the
argument type. If the argument type is either decimal or numeric, the return type is
double precision.
Example
ceiling(13.2)
returns
14
Purpose
Returns the cosine of the argument measured in radians. If the argument is NULL,
RDMS returns a null value.
Example
cos(180*3.1415/180)
returns
-1
Purpose
Returns the hyperbolic cosine of the argument measured in radians. If the argument is
NULL, RDMS returns a null value.
Example
cosh(0)
returns
1
Purpose
Returns the cotangent of the argument measured in radians. If the argument is NULL,
RDMS returns a null value.
Example
cot(1)
returns
.6421
Purpose
Converts the argument angle from radians to degrees. If the argument is NULL, RDMS
returns a null value.
Example
degrees(1.5708)
returns
90
Purpose
Returns ex, where e is the base of the natural logarithms. If the argument is NULL,
RDMS returns a null value.
Example
exp(4)
returns
54.59815
Purpose
Returns the largest integer less than or equal to x. If the argument is NULL, RDMS
returns a null value.
There are two exceptions to the rule that the return type is the same type as the
argument type. If the argument type is either decimal or numeric, the return type is
double precision.
Example
floor(15.8)
returns
15
Purpose
Returns the hexadecimal representation of n as ASCII characters. RDMS displays the
one- or two-word OS 2200 representation of the binary value.
RDMS converts numeric literals and values of data type DECIMAL to NUMERIC and
displays the hexadecimal representation of the NUMERIC format.
Example
hex(2048)
returns
800
Purpose
Returns the expression e1 cast to data type INTEGER. If e1 results in a value larger
than can be represented by INTEGER, RDMS returns an overflow error but does not
roll back the thread. Any fractional part of e1 is truncated; for example, int(34.99)
returns 34.
Examples
integer('33')
returns
33
int(substr('abc123',4,2))
returns
12
3.7.15. ln Function
Format
ln(Double Precision) → Double Precision
Purpose
Returns the natural logarithm of the argument. The argument must be greater than 0.
If the argument is NULL, RDMS returns a null value.
Example
ln(95)
returns
4.55387
Purpose
This function has two formats:
Examples
log(95)
or
log(exp(1),95)
returns
4.55387
log(10,100)
returns
2
Purpose
Returns the logarithm, base 10, of the argument. The value n can be any positive
number. If the argument is NULL, RDMS returns a null value.
Example
log10(100)
returns
2
Purpose
Returns the remainder (modulus) of the m divided by n. If m or n is NULL, RDMS
returns a null value. If n is zero, RDMS returns an error.
Example
mod(13,4)
returns
1
Purpose
Returns the octal representation of n as ASCII characters. RDMS displays the one- or
two-word OS 2200 representation of the binary value.
RDMS converts numeric literals and values of data type DECIMAL to NUMERIC and
displays the octal representation of the NUMERIC format.
Example
octal(2048)
returns
4000
3.7.20. pi Function
Format
pi() → Double Precision
Purpose
Returns the value of pi as a 72-bit floating-point number.
Example
pi()
returns
3.1415926535897932
Purpose
Returns x raised to the power y (xy). If either argument is NULL, RDMS returns a null
value.
The following chart summarizes the results of the power function based on the data
types of the arguments. If the result exceeds the maximum value for the INTEGER or
DOUBLE PRECISION data type, RDMS returns an error. The maximum value for an
INTEGER data type is 34,359,738,367. The maximum value for DOUBLE PRECISION is
8.988,465,674,311,579,549E+307.
Data Type of y
Decimal, precision > 0 Result is double precision. Some Result is double precision.
Numeric, precision > 0 precision may be lost because Some precision may be lost
Data Type of x
Examples
power(2,8)
power(10,3)
To allow a larger result value, ensure one of the arguments is not an integer:
power(10,3.0)
power(36,0.5)
Purpose
Converts the argument angle from degrees to radians. If the argument is NULL, RDMS
returns a null value.
Example
radians(90)
returns
1.5708
Purpose
Returns a random double-precision floating-point number between 0 and 1. The
optional argument is used as a “seed” to begin a new random number sequence.
Example
rand()
returns
.3426
Purpose
Returns the expression e1 cast to data type REAL. If e1 is not within the range of
single precision REAL, RDMS returns an overflow error but does not roll back the
thread.
Examples
real('33')
returns
33.0
real(substr('abc12.3',4,4))
returns
12.3
Purpose
Rounds the argument x in such a way that its least significant digit is n digits to the
right of the decimal point (if n is omitted or is NULL, to 0 places; if n is negative, the
least significant digit is to the left of the decimal point).
Examples
round(873.625, 2)
round(873.625, 1)
round(873.625, 0)
or
round(873.625)
round(873.625, -1)
round(873.625, -2)
Purpose
Returns +1 if the argument is positive, -1 if the argument is negative, 0 if the argument
is 0. If the argument is NULL, RDMS returns a null value.
Example
sign(-233)
returns
-1
Purpose
Returns the sine of the argument, measured in radians. If the argument is NULL,
RDMS returns a null value.
Example
sin(30 * 3.14159 / 180)
returns
.5
Purpose
Returns the hyperbolic sine of the argument, measured in radians. If the argument is
NULL, RDMS returns a null value.
Example
sinh(1)
returns
1.175201
Purpose
Returns the expression e1 cast to data type SMALLINT. If e1 results in a value larger
than can be represented by SMALLINT, RDMS returns an overflow error but does not
roll back the thread. Any fractional part of e1 is truncated; for example, smallint(34.99)
returns 34.
Examples
smallint('33')
returns
33
smallint(substr('abc12.3',4,4))
returns
12
Purpose
Returns the square root of the argument. It cannot be a negative value. If the
argument is NULL, RDMS returns a null value.
Example
sqrt(81)
returns
9
Purpose
The length, if specified gives the total number of characters, including a decimal point,
and '-' sign (RDMS omits the '+' if the value is positive). RDMS space fills on the left if
length is greater than the total number of digits returned. If the value after the
conversion does not fit within the length specified, RDMS returns asterisks (*****). If
length is omitted, is NULL, or is less than or equal to zero (0), RDMS uses the value 10.
If length is greater than 22, RDMS uses 22.
The precision refers to the number of characters to the right of the decimal point. If
precision is greater than 20, RDMS uses 20. If precision is omitted, RDMS uses 2 for
data types FLOAT, REAL, and DOUBLE PRECISION; and uses the precision of n1 for
other data types. If precision is NULL, or is less than or equal to zero (0), RDMS
returns no fractional digits and no decimal point. If precision is greater than length,
RDMS returns asterisks (*****). When n1 has more than precision fractional digits,
RDMS rounds the value to precision fractional digits. When n1 has less than precision
fractional digits, RDMS zero fills the digits to the right of the decimal point.
Examples
str (-3.456)
returns
-3.456
returns
∆∆∆∆3.456000
where ∆ indicates an ASCII space. Note that RDMS zero-fills to the indicated precision.
str ( +765432.456, 5, 2)
returns
*****
str ( +3.45, 4, 1)
returns ∆3.5, where ∆ indicates an ASCII space. Note that the fractional value is
rounded up.
returns
∆3.4
returns
∆3.2
Purpose
Returns the tangent of the argument, measured in radians. If the argument is NULL,
RDMS returns a null value.
Example
tan(135 * 3.14159 / 180)
returns
-1
Purpose
Returns the hyperbolic tangent of the argument, measured in radians. If the argument
is NULL, RDMS returns a null value.
Example
tanh(.5)
returns
.462117
Purpose
Truncates the argument x in such a way that its least significant digit is n digits to the
right of the decimal point (if n is omitted or is NULL, to 0 places; if n is negative, to the
left of the decimal point).
Examples
truncate(873.627, 2)
truncate(873.627, 1)
truncate(873.627, 0)
or
truncate(873.627)
truncate(873.627, -1)
truncate(873.627, -2)
Purpose
Returns the expression e1 cast to data type DOUBLE PRECISION. If e1 is not within the
range of the double precision floating point value, RDMS returns an overflow error but
does not roll back the thread.
Examples
double('33')
returns
.33000000000000000E+002
double(substr('abc12.3',4,4))
returns
.12300000000000000E+002
Purpose
Returns d incremented or decremented by x months. If the resultant month has fewer
days than the month of d, the last day of the resultant month is returned. Any time
portion of d remains unchanged.
add_months('2001-01-08 13:13:13', 3)
returns
2001-04-08 13:13:13
add_months('2001-01-08', 3)
returns
2001-04-08
Example
add_months('2001-03-31', -1)
Purpose
Returns the argument with its data type changed to the specified target data type. The
cast function instructs RDMS to convert a character string to a datetime or interval
data type. It allows for the specification of datetime and interval values in host
program variables in application programs.
cast–target is the data type to which the value of the source operand is to be
converted.
DATE'date-value'
TIME'time-value'
TIMESTAMP'timestamp-value'
INTERVAL[ ± ]'interval-value' interval-qualifier
This allows the use of the same program variables (for example, variables created
by the UREP command REPORT COBOL or REPORT C) to fetch from and insert
into a table.
• If the fractional part of the SECOND field in the source character string contains
more digits than the data type specified in the target, RDMS truncates the lower
fractional digits for both datetime and interval data types.
• The converted value must fit in the valid value range of the specified data type,
except for the fractional digits of the SECOND field; otherwise, RDMS returns an
error.
• You cannot use the cast function in the CREATE TABLE and ALTER TABLE
statements.
• You can use the cast function to pass datetime data from program variables. The
argument for the cast function must be a CHARACTER type string that contains a
datetime or interval literal or a date, time, timestamp, or interval value.
• The target must be a datetime or interval data type.
• The cast function cannot be used as an argument for other scalar functions.
• INSERT statement
Inserting a string literal into a numeric value
• UPDATE statement
Updating a numeric with a string literal
• WHERE clause
Expression comparing a string literal with a numeric
• SET statement
Setting a numeric from a string literal
• Stored procedures
Using a string literal as an argument to a numeric
The following are examples of supported implicit string literal to numeric conversion:
In the preceding examples, $p1 corresponds to a numeric column in my_table and also
to a character value that has been initialized to the value "1234" within a program.
RDMS does not support string literal to numeric conversions in the following contexts:
Cast to Timestamp
You can cast a value to a timestamp data type.
Format
DATE
TIME [ (time-precision) ]
TIMESTAMP [ (timestamp-precision) ]
where:
time–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the item after the decimal point. If omitted, 0 is assumed.
timestamp–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the item after the decimal point. If omitted, 6 is assumed.
Example 1
Insert the date January 30, 1998, using a constant into column MYDATE of table
MYTABLE:
Insert the date, using a datetime value retrieved from column MYDATE of TABLE
mytable. Variable VDATE contains the string DATE ‘1998–01–30’. The length of the
buffer VDATE to contain the date string 1998–01–30 should be at least 10 ASCII
characters.
Example 2
The next example converts a time literal (for example, TIME ‘23:01:30.123’) or time
value (for example, 23:01:30.123) contained in the embedded character variable VAR to
a time value:
Example 3
The final example converts a character string literal to a timestamp value. The actual
value stored in the database is 1998–10–11 16:03:00.000000.
Cast to Interval
You can cast a value to an interval using the INTERVAL function.
• You can use interval types as operands within a datetime arithmetic expression.
You cannot use them as the source operand of the cast, extract, avg, count, max,
min, and functions.
• You generate interval values with the cast function and interval literals.
• You cannot define a column of data type interval. You cannot specify an
expression that results in an interval value. It follows, then, that you cannot have
an expression that evaluates to an interval type in the select list of a query
specification, and you cannot have a comparison operand that evaluates to an
interval value.
As long as you follow these guidelines, you can use interval items anywhere in SQL
statements.
Format
INTERVAL interval-qualifier
YEAR [ (leading-field-precision) ]
MONTH [ (leading-field-precision) ]
where:
leading–field–precision
is the number of digits allowed for the starting field of the interval. For the
SECOND field, it is the number of digits preceding the decimal point. Maximum is
4; default is 2.
fractional–precision
is the number of digits following the decimal point for the SECOND field.
Maximum is 6; default is 6.
• Order datetime fields as follows: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND.
• If you have a starting and ending field separated by the word TO, all included
datetime fields based on the preceding order are affected by the interval
specified.
• If the starting and ending fields are identical, the ending field is ignored.
Table 3–3 illustrates the range of values allowed for each interval type.
Type Range
* These fields can contain from 0 to 9999 (9999.999999 for SECOND), depending on the
specification of the interval qualifier, if they are specified as the starting field of an
interval type.
The amount of memory required by interval types is always 8 bytes, regardless of the
number or kinds of datetime fields involved.
Example 1
The following example converts a character string literal to an interval value. Note that
you can specify the sign in interval values.
Example 2
The next example elicits an error because the sign is specified in front of the character
string. The cast function requires a character string in a source operand.
Example 3
The next example elicits an error because the source operand does not follow both
formats, for interval literal and interval value:
Example 4
The next example elicits an error because the string literal does not fit in the value
range permissible for the target data type:
Example 5
The final example extracts an exact numeric value from the HOUR field of the result of
a datetime arithmetic expression, with a result data type of NUMERIC(2):
Purpose
Returns d formatted according to the format x.
If you use formats 0, 8, 9, 100, 108, 109, 13, 113, 14, 114, 20, 120, 21, 121, 126, or 127 with
a date value, then RDMS uses the time 00:00:00.
If you use any format except 8, 108, 14 or 114 with a time value, then RDMS uses
today’s date.
Values for x
Year Without Century Format of Value in the Converted String
Values for x
Year with Century Format of Value in the Converted String
Examples
convert('2001-02-21', 7)
convert('2001-02-21' , 107)
Purpose
Returns the current date in YYYY-MM-DD format
Example
If executed on the 12th of February 2002
curdate( )
Purpose
Example
If executed at 2:56:23 P.M.
curtime( )
Purpose
Converts d to a date value.
• A column with data type date or timestamp. If d is a time value, RDMS returns an
error.
• A valid date or timestamp literal value – see section 2.3.4.
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in one
of these formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− ddMonyyyy
− mm/dd/yyyy
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
See also strptime, to_date, to_timestamp, and timestamp_format functions which can
return values other than Date.
Examples
date('2011-09-23')
date(current_timestamp)
suppose the current_timestamp value is 2011-10-07 09:57:23, the function returns the
date 2011-10-07.
Purpose
Returns the time, date, or timestamp value produced by adding the number x of parts
datepart to d. The next higher granularity is incremented if necessary to produce a
valid result.
If you use any time datepart for a DATE value, RDMS sets the time portion to
00:00:00. If you use any date datepart for a TIME value, RDMS sets the date portion to
0001-01-01.
returns
2001-01-08 13:13:14
dateadd('day', 1, '2001-01-08')
returns
2001-01-09
If d is a datetime literal (for example, DATE ‘2001-12-24’), dateadd returns the data type
of the datetime literal.
datepart
datepart Abbreviation Valid Range of x
Examples
dateadd('day', 1, DATE '2001-01-31')
dateadd('WEEKDAY', 2, '2001-01-31')
Purpose
Returns d2 minus d1 as measured by the specified datepart. If you use any time
datepart for a DATE value, RDMS sets the time portion to 00:00:00. If you use any
date datepart for a TIME value, RDMS sets the date portion to 01,01,0001.
RDMS does not include partial units. It rounds down to a whole number of units. For
example, if the datepart is 'day' and the difference is 2 days 3 hours, RDMS returns
the value 2 (days).
datepart
datepart Abbreviation Valid Range Produced
Examples
datediff('Day', '2001-02-01', '2001-01-31')
returns
-1
Because the day value for d2 is not at least as large as the day value for d1, not an
entire month has passed. RDMS returns 0.
returns
24
Purpose
Returns the specified datepart of d as a string, converted to a name (for example,
“January”) if appropriate. RDMS uses the day and month names from the current
locale.
If you use any time datepart for a DATE value, RDMS sets the time portion to
00:00:00. If you use any date datepart for a TIME value, RDMS sets the date portion to
0001-01-01.
year yy 1753–9999
quarter qq 1–4
month mm January, February, and so on
dayofyear dy 1–366
day dd 1–31
week wk 1–54 (Sunday as the first day of the week;
RDMS considers all days prior to the first
Sunday of the year to be in week 1)
weekday dw Sunday, Monday, and so on
hour hh 0–23
minute mi 0–59
second ss 0–59
Examples
datename('week', '2001-01-05')
datename('WEEKDAY', '2001-01-05')
returns
Friday
The following example sets the current locale to fr_FR.8859-1 using CIFSUT:
@CIFSUT
set LC ALL=fr_FR.8859-1
@eof
datename('month', '2001-01-05')
returns
janvier
Purpose
Returns the specified datepart of d as an integer.
If you use any time datepart for a DATE value, RDMS sets the time portion to
00:00:00. If you use any date datepart for a TIME value, RDMS sets the date portion to
0001-01-01.
Year yy 1753–9999
Quarter qq 1–4
Month mm 1–12
Dayofyear dy 1–366
Day dd 1–31
dateasnum dn Returns the date as a numeric value
CCYYMMDD. For example, January
5, 2006 is returned as 20,060,106.
Week wk 1–54
Weekday dw 1–7 (Sunday=1)
Hour Hh 0–23
Minute Mi 0–59
Second Ss 0–59
Examples
datepart('week', '2001-01-05')
returns
1
datepart('weekday', '2001-01-05')
returns
6
datepart('month', '2001-01-05')
returns
1
Purpose
Returns the day of the month portion of d as an integer.
• A column with data type date or timestamp. If d is a time value, RDMS returns an
error.
• A valid date or timestamp literal value – see section 2.3.4.
• Another BIF or Datetime Function (see section 2.5.7), which returns a date, or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in one
of these formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
− hh:mm:ss – if the value contains only a time value, RDMS returns an error.
Additional processing rules:
Examples
day('2011-09-23')
returns 23
day(current_timestamp)
Purpose
Returns the day portion of d as a character string (Sunday, Monday, and so on),
according to the current locale.
Example 1
dayname('2001-01-05')
returns
Friday
Example 2
This example sets the current locale to fr_FR.8859-1 using CIFSUT:
@CIFSUT
set LC ALL=fr_FR.8859-1
@eof
dayname('2001-01-05')
returns
vendredi
Purpose
Returns the day portion of d as an integer in the range 1–31.
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
Example
dayofmonth('2001-01-05')
returns
5
Purpose
Returns the day portion of d as an integer in the range 1–7 (Sunday = 1).
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
returns
6
Purpose
Returns the day of the year in d as an integer in the range 1–366.
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
returns
5
Purpose
Returns one more than the number of days between January 1, 0001 and the date d.
The function projects the rules for the Gregorian calendar to all dates in the past when
calculating an elapsed number of days.
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
returns
730537
Purpose
Interprets the contents of s1 as a two-word Fieldata-encoded ER DATE$ value and
returns an RDMS timestamp value with precision 0. For more information on the ER
DATE$ format, see the Executive Requests Programming Reference Manual.
Example
erdate_to_timestamp (o'606661656064616361616065')
Purpose
Interprets the contents of s1 as a two-word binary ER DWTIME$ value or CALL
INSPECTIME$ value and returns an RDMS timestamp with precision 3. For more
information on the ER DWTIME$ format, see the Executive Requests Programming
Reference Manual. For more information on INSPECTIME$ format, see the System
Services Programming Reference Manual.
If you omit s1, RDMS performs an ER DWTIME$ and uses that value.
Example
erdwtime_to_timestamp (o'000267016710111005663120')
Purpose
Interprets the contents of s1 as a one-word binary ER TDATE$ formatted value and
returns an RDMS timestamp with precision 0. For more information on the ER TDATE$
format, see the Executive Requests Programming Reference Manual.
Example
ertdate_to_timestamp (o'061750134551')
Purpose
Interprets the contents of s1 as a one-word binary ER TIME$ formatted value and
returns an RDMS time with precision 3. For more information on the ER TIME$ format,
see the Executive Requests Programming Reference Manual.
Example
ertime_to_time (o'265041053')
where:
extract–field
is the field to be extracted from the source operand.
extract–source
is the source operand, which must be a datetime data type of one of the following
items:
• A cast function
• An aggregate function
• A datetime system function (for example, CURRENT_DATE)
• A column reference
• A routine parameter or SQL variable
• A datetime literal
• A datetime value expression
Purpose
Returns the specified portion of a time, date, or timestamp value. The extract function
lets you extract a numeric value from a datetime item or value expression.
Example 1
The following example extracts the exact numeric value of 01.224512 from the
SECOND field of a time literal, with a result data type of NUMERIC(8,6):
Example 2
The next example extracts an exact numeric value from the HOUR field of the result
of a datetime arithmetic expression, with a result data type of NUMERIC(2):
You can use the EXTRACT function to retrieve datetime data into a program variable
from RDMS. The EXTRACT function retrieves a datetime value field into a numeric
program variable.
Example 3
In the following example, assume that the variables myyear, mymonth, and myday are
declared in the user program of a data type compatible with the RDMS data type
NUMERIC. The following SQL statement retrieves a record from mytable:
After this statement is executed, example values of myyear, mymonth, and myday are
2006, 1, and 30.
now( ) → Timestamp
Purpose
Returns the current date and time as a timestamp with zero precision. This is similar
to the current_timestamp keyword function.
Example
If executed on February 21, 2007 at 1:20:24 in the afternoon
getdate( )
returns
2007-02-21 13:20:24
3.8.23. getutcdate
Format
getutcdate( ) → Timestamp
Purpose
Returns the current utc date and time as a timestamp with 6 digits of precision.
Example
select getutcdate() from rdms.rdms_dummy;
returns
2008-12-04 09:40:24.442281
Purpose
Returns the hour portion of d as an integer.
• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
Example
hour('2007-02-21 13:20:24')
returns
13
Purpose
Returns the number of days between the beginning of the Julian calendar and d.
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
Example
julian_day('2000-02-21 13:20:24')
returns
2451596
Purpose
Returns the last day of the month for the month in which d occurs.
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another scalar or datetime function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
Example
last_day('2000-02-21 13:20:24')
returns
29
Purpose
Returns the fractional portion of d as microseconds. RDMS adjusts the precision of d
to 6 and returns the value, zero-filled if necessary, to 6 digits.
• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
Additional processing rules are as follows:
Examples
microsecond('2000-02-21 13:20:24.3827')
returns
382700
microsecond('2000-02-21 13:20:24.0005')
returns
500
Purpose
Returns the number of seconds between d and the previous midnight.
If d is NULL, RDMS returns a null value.
• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
Additional processing rules are as follows:
Example
midnight_seconds('2000-02-21 13:20:24.3827')
returns
48024
Purpose
Returns the minute portion of d as an integer.
• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
Additional processing rules are as follows:
Example
minute('2000-02-21 13:20:24')
returns
20
Purpose
Returns the month portion of d as an integer.
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
Example
month('2001-02-21 13:20:24')
returns
2
Purpose
Returns the month portion of d as a character string (January, February, and so on),
according to the current locale.
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
Examples
monthname('2001-01-05')
returns
January
The following example sets the current locale to fr_FR.8859-1 using CIFSUT:
@CIFSUT
set LC ALL=fr_FR.8859-1
@EOF
monthname('2001-01-05')
returns
janvier
Purpose
Returns the number of months between d1 and d2. If both d1 and d2 have the same
day or if both are the last days of their respective months, RDMS returns an integer
result. Otherwise, the result will contain the fractional portion of a 31-day month and
also considers the time components in d1 and d2.
If d1 is later than d2, the result is positive; if d1 is earlier than d2, the result is negative.
Example
months_between('2001-01-05', '2001-05-05')
returns
-.40000000000000000E+001
Purpose
Returns the time or timestamp in time zone tz2 when the time or timestamp for d are
in time zone tz1.
returns
05:13:13
returns
2001-01-09 05:13:13
The valid values for tz1 and tz2 are defined in the following table.
Example
returns
2001-02-21 16:20:24
Purpose
Returns the date of the first day named by s1 that is later than date d. The value s1
indicates a day of the week in the language of the current locale. The time component
of d is unchanged. The case of s1 is not important.
returns
2001-01-15 13:13:13
next_day('2001-01-08', 'MONDAY')
returns
2001-01-15
Examples
This example returns the timestamp for the first Thursday after February 20, 2001.
next_day('2001-02-20 13:20:24', 'thursday')
returns
2001-02-22 13:20:24
In this example, the date d is the same day of the week as s1. The function returns the
date of the Wednesday of the following week:
next_day('2001-03-14 13:20:24', 'wednesday')
returns
2001-03-21 13:20:24
Purpose
Returns an integer between 1 and 4 representing the quarter of the year in which d
occurs.
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
Example
quarter('2000-02-21 13:20:24')
returns
1
Purpose
Rounds d to the unit specified by s1. If s1 is not specified or is NULL, RDMS uses 'dd'
which rounds d to the nearest day.
If you use a time rounding format for a date value, RDMS sets the time to 00:00:00. If
you use a date rounding format for a time value, RDMS sets the date portion to
today’s date.
The value for s1 is not case sensitive. The value for s1 can be any of the following
formats.
CC Century
YYYY, YEAR, YYY, YY, Y Year (rounds up on July 1)
IYYY, IY, I ISO year
Q Quarter (rounds up on the sixteenth day of the second
month of the quarter)
Example
This example rounds to the nearest month.
round('2001-02-20 13:20:24', 'mm')
returns
2001-03-01 00:00:00
Purpose
Returns the second portion of d as an integer.
• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
− ddMonyyyy
Examples
second('2000-02-21 13:20:24')
returns
24
second('2000-02-21 13:20:24.987')
returns
24
Purpose
Converts d to a character string according to the conversion specification string in s1.
If you omit s1, RDMS uses the format ‘%D %T’. This function calls the I18NLIB routine
of the same name.
If you use a time formatting conversion for a date value, RDMS sets the time to
00:00:00. If you use a date formatting conversion for a time value, RDMS sets the
date portion to today’s date.
The following table defines the valid values for the conversion specification s1.
This conversion
specification … Is replaced by these characters for the current locale:
This conversion
specification … Is replaced by these characters for the current locale:
Example
strftime('2000-02-21 13:20:24',
'today is: %A, %B %d, %Y at %I:%M:%S %p')
returns
today is: Wednesday, February 21, 2001 at 1:20:24 PM
The following example sets the current locale to de_DE.8859-1 using CIFSUT:
@CIFSUT
set LC_ALL=de_DE.8859-1
@eof
strftime('2000-02-21 13:20:24',
'today iF073: %A, %B %d, %Y, at %H:%M:%S')
returns
today is: Montag, Februar 21, 2000 at 13:20:24
Purpose
Returns a timestamp for the character string in s1, which has a format as defined by
the conversion specification in s2.
The strptime function calls the I18NLIB function of the same name. If I18NLIB is prior
to level 1R3E, the I18NLIB function follows the UNIX convention for dates. Any
two-digit date is 1900 + year.
If I18NLIB is level 1R3E or higher, the I18NLIB function follows the IEEE standard, as
follows:
The following are the valid values for the conversion specification s2. Conversion
specifications cannot adjoin. ‘%H%M’ is illegal; ‘%H %M’ and ‘%H:%M’ are legal.
%T Time as %H:%M:%S
%U Week number of the year as decimal [00,53] with Sunday as day 1, leading
zeros permitted
%w Weekday as decimal [0,6] with 0 representing Sunday, leading zeros
permitted
%W Week number of the year as decimal [00,53] with Monday as day 1, leading
zeros permitted
%x Date as described by the current locale's d_fmt conversion specification
%X Time as described by the current locale's t_fmt conversion specification
%y Year within the century [00,99], leading zeros permitted. This conversion
specification includes a century of 19 plus the specified year (see examples).
%Y Year, including century [0001,9999]
%% %
Examples
strptime('21.02.2001 :: 16:43:03', '%d.%m.%Y :: %H:%M:%S')
In this example, the string s1 has a date with segments separated by periods,
followed by two colons, followed by a time with colon separators. The format string
s2 has these characters plus the formatting information for the date and time
segments and returns the timestamp value
2001-02-21 16:43:03
With I18NLIB levels prior to level 1R3E, two-digit years are assumed to be in the
twentieth century, as in the following example.
returns
1901-02-21 16:43:03
For example
returns
2001-02-01 16:43:03
In the following example, the separators are the slash character ‘/’. Zeros are used
because there is no time information. Therefore,
strptime('12/4/07', '%m/%d/%y')
returns
2007-12-04 00:00:00
The following example sets the current locale to fr_FR.8859-1 using CIFSUT:
@CIFSUT
set LC_ALL=fr_FR.8859-1
@eof
2011-02-21 13:20:24
Purpose
Returns the time portion of d as a Time value.
• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
returns
13:20:24
Purpose
Returns a timestamp whose date value is taken from d and whose time value is taken
from t. The resulting timestamp has the same precision as t.
Purpose
Returns the timestamp calculated by adding x intervals of type interval to t1.
The following table explains the valid values for interval and x.
If t1 is a time value and interval specifies days, weeks, months, quarters, or years,
RDMS fills in the date portion of that timestamp with the current date before
calculating the difference between the timestamps.
Example 1
timestampadd('SQL_TSI_DAY', 2, '2000-02-21 13:20:24')
Example 2
timestampadd('SQL_TSI_MINUTE', 5, '2000-02-21 23:58:24')
Example 3
timestampadd('SQL_TSI_SECOND', 86400, '2000-02-21 13:20:24')
Example 4
timestampadd('SQL_TSI_HOUR', -15, '2000-03-01 13:20:24')
Example 5
timestampadd('SQL_TSI_DAY', 12, '13:20:24')
Because there is only a time and no date, RDMS uses today. Assume that today is July
15, 2004 and returns the timestamp
2004-07-27 13:20:24.000000
Example 6
timestampadd('SQL_TSI_HOUR', -4, '2001-03-13')
Because there is only a date and no time, RDMS uses 00:00:00 and returns the
timestamp
2001-03-12 20:00:00.000000
Example 7
timestampadd('SQL_TSI_DAY', -365, '2000-02-21 13:20:24')
Example 8
timestampadd('SQL_TSI_QUARTER', 2, '2002-02-21 13:20:24')
Purpose
Returns the integer number of intervals of type interval by which t2 is greater than t1.
The return value can be less than zero. RDMS truncates the result to the specified
interval.
SQL_TSI_FRAC_SECOND
SQL_TSI_SECOND
SQL_TSI_MINUTE
SQL_TSI_HOUR
SQL_TSI_DAY
SQL_TSI_WEEK
SQL_TSI_MONTH
SQL_TSI_QUARTER
SQL_TSI_YEAR
If either t1 or t2 is a time value and interval specifies days, weeks, months, quarters,
or years, RDMS fills in the date portion of that timestamp with the current date before
calculating the difference between the timestamps.
Example 1
timestampdiff('SQL_TSI_DAY', '2000-02-21 13:20:24', '2000-02-23 16:40:39')
Because the time of t2 is greater than the time of t1, timestampdiff returns 2.
Example 2
timestampdiff('SQL_TSI_DAY', '2000-02-21 13:20:24', '2000-02-23 08:14:22')
Because the time of t2 is not greater than the time of t1, timestampdiff returns 1.
Example 3
timestampdiff('SQL_TSI_DAY', '2000-02-23 16:40:39', '2000-02-21 09:20:24')
Because both values are timestamps, timestampdiff returns a whole number of days
as -2.
Example 4
timestampdiff('SQL_TSI_DAY', '2000-02-23', '2000-02-21')
Example 5
timestampdiff('SQL_TSI_YEAR', '2000-02-21 13:20:24', '2002-01-01
16:40:39')
Example 6
timestampdiff('SQL_TSI_HOUR', '2000-02-23 16:40:24', '2000-02-21
13:20:39')
returns
-51
Purpose
Converts the character string s1 to a timestamp value according to the format string in
s2. If you omit s2 or if it is NULL, RDMS uses the format 'MM/DD/YYYY HH24:MI:SS'.
The maximum length for s1 is 80 bytes. The maximum length for s2 is 80 bytes.
The timestamp_format function uses the same arguments as the to_date function. It is
a synonym for the to_date function. See the to_date function for more information.
See also the date, to_date, to_timestamp, and strptime functions, which also convert
strings to time, date, and timestamp values.
Example
timestamp_format('21-02-2011 13:20:24', 'DD-MM-YYYY HH24:MI:SS')
Purpose
Converts d to a character string according to the formatting string in s1. If you omit s1
or if it is NULL, RDMS uses the format 'MM/DD/YY HH24:MI:SS'
The formatting element values DAY, DY, MON, MONTH, and RM, which generate
words, are case-sensitive. The other formatting elements, which generate numbers,
are not case-sensitive.
Formatting
Element Description of Returned Value
Formatting
Element Description of Returned Value
Formatting
Element Description of Returned Value
Q Quarter of the year. For example, a date value in January through March
returns 1.
rm Month in Roman numerals. Case of the returned value is as follows:
Rm rm All letters in the month value are lowercase.
RM Rm The first letter of the month value is uppercase and the rest of
the letters are lowercase.
RM All letters of the month value are uppercase.
RR Last two digits of the year.
SS Second as decimal (00–59).
SSSSS Seconds past midnight.
WW Week of year (1–53). Week 1 starts on the first day of the year and continues
to the seventh day. Thus, the weeks do not necessarily start on Sunday
W Week of month (1–5). Weeks are defined as they are for the WW formatting
element.
X Radix character
RDMS uses the radix from the locale indicated by the LC_TIME environment
variable.
YYYY Four-digit year.
YYY, YY, Y Last three, two, or one digits of the year.
Example
To_char('2000-02-21 13:20:24', 'J "is:" Day, Month DD, YYYY "at"
HH12:MI:SS PM')
returns
2451596 is: Monday , February 21, 2000 at 1:20:24 PM
The following example sets the LC_TIME environment variable to the German locale.
@CIFSUT
set LC_ALL=de_DE.8859-1
@EOF
returns
Purpose
Converts the character string s1 to a timestamp value according to the format string in
s2.
The maximum length for s1 is 80 bytes. The maximum length for s2 is 80 bytes.
Punctuation All punctuation symbols mark the end of the previous token. The
dash ‘-‘ and forward slash ‘/’ format elements accept either a dash or
a forward slash in the corresponding character string s1. For example,
s2 containing ‘MM-DD-YYYY’ accepts the s1 string values ’10-23-2011’
and ‘10/23/2011’.
"text" RDMS skips all text in double quotes in s1 and s2
AM Ante meridiem indicator with or without periods. RDMS accepts AM
A.M. and PM in s1 and adjusts the time value accordingly.
CC Century – 2 digits
Leading zeroes may be specified for any numeric value – month, day, hour, minute,
second.
The RR format element can be used to change how a specification for a year is to be
interpreted.
For example, if the current year is 2011, ‘86’ with format ‘RR’ means 1986; however, if
the current year is 2052, it means 2086.
RDMS uses the following default values when the format string s2 does not include a
format element:
A substring of s1 may include fewer than the maximum number of digits for that
component of the timestamp that is indicated by the corresponding format element.
RDMS defaults any missing digit to zero. For example, with a format string s2 of
‘YYYY-MM-DD HH24:MI:SS’ and s1 containing ‘999-3-9 5:6:7’, RDMS generates a
timestamp value of ‘0999-03-09 05:06:07’.
Examples
to_date('2000-02-21 13:20:24', 'YYYY-MM-DD HH24:MI:SS')
returns an error because the number of formatting elements in s2 does not match the
number of tokens in s1.'
@CIFSUT
SET LC_ALL=fr_FR.8859-1
@EOF
2011-02-21 13:20:24.000000
Purpose
Converts the character string s1 to a timestamp value according to the format string in
s2. If you omit s2 or if it is NULL, RDMS uses the format 'MM/DD/YYYY HH24:MI:SS'.
The maximum length for s1 is 80 bytes. The maximum length for s2 is 80 bytes.
The to_timestamp function uses the same arguments as the to_date function. See the
to_date function for more information.
See also the date, strptime, timestamp, and timestamp_format, functions which also
create timestamp values.
Example
to_timestamp('21-02-2011 13:20:24', 'DD-MM-YYYY HH24:MI:SS')
Purpose
Returns d truncated to the unit specified by s1. If s1 is not specified or is NULL, RDMS
uses ‘dd’, which truncates d to the nearest day.
If you use a time truncation format for a date value, RDMS sets the time to 00:00:00. If
you use a date truncation format for a time value, RDMS sets the date portion to
today’s date.
CC Century
YYYY, YEAR, YYY, YY, Y Year
IYYY, IY, I ISO year
Q Quarter
MONTH, MON, MM, RM Month
WW Same day of the week as the first day of the year
IW Same day of the week as the first day of the ISO year
W Same day of the week as the first day of the month
DDD, DD, J Day
Day, DY, D Starting day of the week (Sunday)
HH, HH12, HH24 Hour
MI Minute
Example 1
This example rounds to the nearest year.
trunc('2001-02-20 13:20:24', 'year')
returns
2001-01-01 00:00:00
Example 2
trunc('2001-03-14 13:20:24', 'mi')
returns
2001-03-14 13:20:00
Example 3
trunc('2001-03-18 13:20:24', 'CC')
returns
2000-01-01 00:00:00
Purpose
Converts the character string d to a character string according to the format string in
s1. If you omit s1 or if it is NULL, RDMS uses the format 'MM/DD/YY HH24:MI:SS'.
The varchar_format function uses the same arguments as the to_char function. It is a
synonym for the to_char function. See the to_char function for more information.
Example
varchar_format('2011-02-21 13:20:24', 'DD-MM-YYYY HH24:MI:SS')
Purpose
Returns the week of the year in which d occurs, expressed as an integer between 1
and 53. Sunday is considered the first day of the week. Week 1 begins on January 1.
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
Example
week('2001-02-20 13:20:24')
returns
8
Purpose
Returns the year portion of d expressed as an integer between 1 and 9999.
• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
Example
year('2001-02-20 13:20:24')
returns
2001
Purpose
Returns the generated run-id for the current run as six ASCII characters. The value
may include trailing spaces. See also the run_id function (3.9.5).
For more information on the run_id and generated run_id, see the Executive Control
Language (ECL) and FURPUR Reference Manual.
Example
generated_run_id()
Purpose
Returns the value for the MAXIMUM-AOR-UPDATES configuration parameter for the
current application group.
Example
max_aor_updates()
Numeric(21,0)
Integer
Purpose
Returns the value for the system services function UNIQUE$ID, permuted to
counteract the monotonically increasing nature from repeated calls. The identifier is
unique across hosts in a multihost environment. For more information on UNIQUE$ID,
see the System Services Programming Reference Manual.
If you include no parameters or the keyword parameter ‘NEXT’ (default), RDMS calls
the Exec to obtain the next unique identifier. If you include the keyword parameter
‘CURRENT’, RDMS returns the same value as the previous call to the permuted_id
function. If no current value exists, RDMS creates one and returns it. RDMS keeps the
current permuted_id value for the duration of the thread. An END THREAD statement
clears the current permuted_id value.
Note: The ‘CURRENT’ and ‘NEXT’ parameters are literal strings enclosed in single
quotation marks.
The parameter n indicates the number of bits to return to the caller. The default value
for n is 72. If you include n, RDMS truncates the UNIQUE$ID value to the specified
number of bits. The UNIQUE$ID value is a structured 72-bit value:
• The first 3 bits are set to zero to ensure a positive result of no more than 21 digits.
• The next 6 bits are a randomizing value to counteract the monotonically increasing
nature of the UNIQUE$ID values.
• The next 6 bits are the host-id, to guarantee uniqueness in a multihost
environment.
• The remaining 57 bits are a counter that is incremented by 1 each time UNIQUE$ID
is called.
If n is less than 72, RDMS truncates bits from the left, following the randomizing bits,
first reducing the number of bits that represent the host-id, then reducing the number
of bits in the counter itself. RDMS concatenates the 6 randomizing bits at the
beginning of the resulting value. The smallest value for n is 12 (6-bit randomizing value
followed by a 6-bit counter). RDMS changes any n greater than 72 to 72 and changes
any value less than 12 to 12.
The parameter p indicates the number of bits to permute. The default value for p is 6.
If you include p, it must equal 6, 9, or 12. Any other value causes RDMS to use the
value 6. When p is 12, the permuted_id is not guaranteed to be unique across hosts in
an XTC environment.
Also see 3.9.7 for information about the unique_id function. The values returned by the
unique_id function always increase in value and are unique across all hosts in a
multihost environment. The values returned by the permuted_id function are
permuted and unique across all hosts in a multihost environment. For operations that
perform many inserts, the permuted_id function helps to avoid sequential inserts onto
the same database data page.
Because the system call UNIQUE$ID uses ‘microseconds since January 1, 1900’ as a
seed value, the maximum number of unique values generated for each day for each
system is 86,400,000,000. If you use the permuted_id or unique_id functions to
generate unique values for RDMS tables, you must consider this upper bound. These
functions should generate no more than 86,400,000,000 values across all RDMS tables
for each day.
Example 1
permuted_id()
returns a unique identifier, permuted to disperse the values across the B-tree.
permuted_id('current')
Example 2
Three successive calls to permuted_id() could return the following example values:
203494027282781912946
277281003577620119411
351067979872458325876
Example 3
The following is an extended example to illustrate how the unique_id function could
be used in a database with two tables, a customer order table and an order line
number table.
Fetch the rows to show that the same order_number value is inserted into both tables.
Note that permuting the value sometimes sets the high bit of the word, which makes
the value print as a negative number.
Purpose
Returns the program type, as follows:
4 Demand
5 Deadline batch
6 Batch
9 Self-destroying transaction
10 Self-initializing transaction
11 Reentrant transaction
12 Online batch
13 High-Volume Transaction Processing (HVTIP)
For more information on program type, see the Executive Control Language (ECL)
and FURPUR Reference Manual.
Example
program_type()
Purpose
Returns the original run-id for the current run as six ASCII characters. The value may
include trailing spaces. See also the generated_run_id function (3.9.1).
For more information on the run-id and generated run-id, see the Executive Control
Language (ECL) and FURPUR Reference Manual.
Example
run_id()
Purpose
Returns the UDS slot number assigned to the current transaction. The return value is
in the range between 1 and the value of the configuration parameter MAX-THREADS.
Example
uds_slot()
Purpose
Returns the value for the system services function UNIQUE$ID. The identifier is unique
across hosts in a multihost environment. For more information on UNIQUE$ID, see the
System Services Programming Reference Manual.
If you include no parameters or the keyword parameter ‘NEXT’, RDMS calls the Exec
to obtain the next unique identifier. If you include the keyword parameter ‘CURRENT’,
RDMS returns the same value as the previous call to the unique_id function. If no
current value exists, RDMS creates one and returns it. RDMS keeps the current
unique_id value for the duration of the thread. An END THREAD statement clears the
current unique_id value.
Note: The ‘CURRENT’ and ‘NEXT’ parameters are literal strings enclosed in single
quotation marks.
The parameter n indicates the number of bits to return to the caller. The default value
for n is 72. If you include n, RDMS truncates the UNIQUE$ID value to the specified
number of bits. The UNIQUE$ID value is a structured 72-bit value:
If n is less than 72, RDMS truncates bits from the left, first reducing the number of bits
that represent the host-id, then reducing the number of bits in the counter itself.
The smallest value for n is 1. RDMS reduces any n greater than 72 to 72 and changes
any value less than 1 to 1.
See also 3.9.3 for information about the permuted_id function. The values returned by
the unique_id function always increase in value and are unique across all hosts in a
multihost environment. The values returned by the permuted_id function are
permuted and unique across all hosts in a multihost environment. For operations that
perform many inserts, the permuted_id function helps to avoid sequential inserts onto
the same database data page.
Because the system call UNIQUE$ID uses ‘milliseconds since January 1, 1900’ as a
seed value, the maximum number of unique values generated per day per system is
86,400,000. If you use the permuted_id or unique_id functions to generate unique
values for RDMS tables, you must consider this upper bound. These functions should
generate no more than 86,400,000 values across all RDMS tables per day.
Example 1
unique_id()
unique_id('current')
returns the same identifier as the previous call to the unique_id function.
Example 2
Three successive calls to the unique_id function could return the following example
values:
1156221661307940821
1156221661307940822
1156221661307940823
Example 3
The following is an extended example to illustrate how the unique_id function could
be used in a database with two tables, a customer order table and an order line
number table.
Fetch the rows to show the same order_number value is inserted into both tables:
Purpose
Returns a 12-character ASCII string containing the user ID of the current user.
Example
user()
Purpose
Pages_updated() and pages_updated('STEP') returns the number of pages (blocks)
updated in this step since the last COMMIT or ROLLBACK. This includes pages
updated by RDMS, DMS, and SFS. This does not include any pages updated during
preconditioning. This is the same value as returned by RDMS in H1 of AUXINFO when
SET AUXINFO PAGE COUNT is specified.
Examples
pages_updated()
returns
pages_updated('PRECONDTIME')
returns
42
Purpose
Returns the value of a given RDMS statistic (for example, number of INSERT
statements) that is displayed by the UDS STAT trace and the UDSMON K screen. The
parameter s is the abbreviation of the statistic. Refer to the ClearPath Enterprise
Servers Universal Data System Administration and Support Reference Manual for
more information on the abbreviations and the meaning of the statistic.
The abbreviations are not case sensitive, for example, ‘Insert’ is the same as ‘INSERT’.
Refer to the following screen capture for information on abbreviations that can be
referenced from the rdms_thread_stat function. If the document ClearPath Enterprise
Servers Universal Data System Administration and Support Reference Manual
includes a blank as part of the abbreviation, you must also include it. For example, in
'Decl Cur', include the blank in the value of s.
Examples
rdms_thread_stat ('Insert')
returns
In the following example, note that there is a space between the ‘t’ and the ‘N’,
because that is the way it is described in the UDS AG.
rdms_thread_stat('Fet Next')
returns
75
---------------------------------------------------------------------------------
Purpose
Returns the value used by RDMS to verify that a COBOL or C program containing static ESQL
was compiled using the current table or view definition. This two-word value has zero for the
second word unless the table or view was last altered using the technique described in the
RDMS Administration Guide, section 6.11 Porting ESQL or Module Language Program. The case
of the schema name and table name must match the one used by RDMS; when you create table
s.t, you are actually creating table S.T.
Example:
octal(verification_timestamp('RDMS','ROLES'))
returns a value of the following form. The actual value depends on the time when the
RDMS system table RDMS.ROLES was created.
410616126310000000000000
Purpose
The partition_id function can be specified only as the generated default for a
partitioned table. Partition_id has no parameters and has the following properties:
• RDMS uses a round-robin algorithm to find the next partition_id value. Once
the maximum value for a particular partition is used the partition is marked full.
RDMS then looks for values in other partitions. For example, using the
following partition definition, after RDMS generates key values 1001 to 2555
and inserts the associated records into partition P2 it marks the partition as
full. The next key value is taken from the next ‘not’ full partition. If RDMS uses
P3, it looks for the next available value in P3. This means there is no “CYCLE”
capability within a partition, only across the set of partitions. RDMS returns a
'partition full' error when there are no more values available in any of the
partitions.
Suppose we have a partitioned table that has 3 partitions: P1 <= 1000, P2 <= 2555, P3
<= 3000. The sequence of inserts is as shown in the following table.
Suppose, the following is done: DELETE WHERE BETWEEN 1001 and 1003. The
following values are left.
Suppose you down and up the file containing partition P2. The down causes the file to
be freed from UDS. When the file is next referenced, RDMS detects that this is the
first reference to the file since it was downed, short recovered, or copied from
another system. Therefore, RDMS reads the B-tree control page to get the restart
sequence for this partition. The restart value includes the increment used to
determine the restart value.
For example, if the data type specified for the column using partition_id is integer, then
an increment value of 100 is used. The restart value is incremented from the start
value + increment. The values from 1000 to 1100 are ‘lost’.
Purpose
When a user inserts a record into a table with a generated default, RDMS assigns a
value to that column. The identity_val_local() scalar function returns the value RDMS
used during the last insert into any identity column, column GENERATED AS
(partition_id()), or GENERATED AS (expression) where the expression returns a
numeric value. This scalar function returns either the RDMS internally generated value
for the column or the user specified value for the column (when the user specifies the
value.) If this previous insert was INSERT…SELECT, the value of identity_val_local is
the value assigned to the last record inserted. The value of this scalar function is not
affected by either COMMIT or ROLLBACK.
Suppose you are inserting records into multiple tables that are related to each other
by foreign keys, and that the primary key of the foreign key owner table is an identity
column. You need the value of the identity column in order to include that value on the
insert of the member table record. To do this use the identity_val_local() function in the
VALUES clause of the member table INSERT, as follows.
RDMS keeps the last generated numeric value (for example, INTEGER, SMALLINT,
NUMERIC and the like) as a NUMERIC(21,0) value internally – and keeps it
independently of any DATE, TIME, or TIMESTAMP value. (See "Section 3.10.3,
generated_date_val_local".)
If no inserts have been done that trigger the GENERATED AS mechanism, RDMS
returns the value 0.
Example:
identity_val_local()
generated_time_val_local()→ time(6)
generated_timestamp_val_local( ) → timestamp(6)
Purpose
RDMS might generate a date, time, or timestamp value during an INSERT into a
column declared GENERATED AS (datetime function.) These functions return the last
value inserted or generated in response to the insert into such a column. The value of
the function is not affected by either COMMIT or ROLLBACK.
RDMS keeps the last generated DATE, TIME, or TIMESTAMP value as a TIMESTAMP(6)
value internally and keeps it independent of the identity_val_local() numeric value.
The precision returned as the time or timestamp value is always 6. This might be more
precision than the time or timestamp column in which it was stored. If you insert the
value into another table of the same data type and precision, RDMS implicitly rounds
the value to the proper precision in the same manner RDMS rounded the value during
the original insert. Use the CAST function to round the precision for use by the
application program.
Suppose you are inserting records into multiple tables that are related to each other
by foreign keys, and that the primary key of the foreign key owner table is an identity
column. You need the value of the identity column to include that value on the insert
of the member table record. To do this, use one of these functions in the VALUES
clause of the member table INSERT, as follows.
UPDATE and INSERT…SELECT might affect multiple records. However, the value of
the current_date, current_time, and current_timestamp is the same for all records
affected by a given SQL statement.
If no inserts that trigger the GENERATED AS mechanism have been done, then RDMS
returns the following values:
date: 0001-01-01
time: 00:00:00.000000
timestamp: 0001-01-01 00:00:00.000000
The scalar functions, curtime(), getdate(), now(), and curdate() when executed as part
of an INSERT or UPDATE statement, always cause the value returned by the
generated_nnn_val_local() scalar functions to be updated.
Example:
generated_timestamp_val_local()
Purpose
Returns the contents of the file specified by path as a BLOB. The path must be a valid
CIFS path name. Internally, RDMS does a CIFS open(), stat(), read(), and close() of the
file.
See the CIFS for ClearPath OS 2200 User, Programmer, and Administrator
Reference Manual for more information about CIFS.
Note: The value returned by the get_file function may contain a final line
terminator character. The presence and value of this character depends on the
program that was used to create the file.
If path is NULL, RDMS returns a null value. If the specified file itself is empty, RDMS
returns a null value. If the file does not exist or RDMS receives an I/O error, RDMS
issues an error and terminates processing of the command containing the get_file
function.
The function get_file may not be used in a SELECT statement or within a WHERE or
HAVING clause.
Examples
In the following example, the get_file function reads a file from the local OS 2200
system and returns the contents of the pdf file as a BLOB.
get_file('/os2200/jmp/jmp/DocBox.pdf')
Other file sources are possible, using different forms of the path parameter:
• The following example reads from a different OS 2200 system on the LAN:
get_file('//RS929.nx.unisys.com/os2200/qual/fn/DocBox.pdf')
get_file('//SERVER1/bifproj/designs/getfilebif.doc')
get_file('//RON1-PC.nx.us.unisys.com/C$/ronpic.jpg')
If access to a remote system requires a separate user ID and password, include that
information in the path parameter. For example
get_file('//myuid:mypwd@RS929.us.unisys.com/os2200/qual/filename/bl01.d
oc')
Purpose
Recalculates and returns the cyclical redundancy check (CRC) value for the BLOB
column specified by Blob. The CRC value is essentially a checksum on the BLOB value.
The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.
Examples
lob_crc (emp_picture)
returns
570732582784159490468
This function can be used with the lob_id_crc function in a SELECT statement to help
detect storage area corruption. For example
This example returns the primary key values for the BLOBs whose CRC values stored
in the lob_id do not match the newly-calculated CRC value for the BLOB stored in the
database.
Purpose
Returns the word address of the last word containing the BLOB data. It is the starting
address + lob_length - 1.
The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.
Example
lob_end_address (emp_picture)
returns
28195
Purpose
Returns the data-page number for the last page containing the BLOB value.
The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.
Example
lob_end_page(emp_picture)
returns
179
Purpose
Returns the name of the file underlying the storage area that contains this BLOB value.
The function returns either the Exec file name (qualifier*file) or the TIP file number as
a 26-character ASCII value, left-justified and space-filled.
The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.
Example
lob_file(emp_picture)
returns
APP014*SET1-SA1
Purpose
Returns the 24-byte lob_id as an octal value. The lob_id identifies this BLOB value.
The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.
Example
lob_id(emp_picture)
returns
060000000002 000001000001 000000013554 000000000005 542461440461
440461462477
Purpose
Returns the cyclical redundancy check (CRC) value from the lob_id for the BLOB
column specified by Blob. The CRC value is essentially a checksum on the BLOB value.
The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.
Examples
lob_id_crc(emp_picture)
returns
626487201579747463753
This function can be used with the lob_crc function in a SELECT statement to help
detect storage area corruption. For example
This example returns the primary key values for the BLOBs whose CRC values stored
in the lob_id do not match the newly-calculated CRC value for the BLOB stored in the
database.
Purpose
Returns the starting address (sector address, from 0) for the start of the BLOB value.
Note that the BLOB header appears one data-page before this starting sector address.
The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.
Example
lob_start_address(emp_picture)
returns
2348
Purpose
Returns the data-page number for the start of the BLOB value. Note that the BLOB
header appears one data-page before this page.
The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.
Examples
lob_start_page(emp_picture)
returns
54
Purpose
Writes the specified data item s1 to the file identified by path and returns the string
‘OK ’ (two spaces after ‘OK’). The path name must be a valid CIFS path name.
Internally, RDMS calls the CIFS creat(), write(), and close() functions.
See the CIFS for ClearPath OS 2200 User, Programmer, and Administrator
Reference Manual for more information about CIFS.
Note: A put_file function that has completed successfully cannot be undone, even
if the thread of which it is a part is rolled back.
If the file does not exist, RDMS creates the file. If the file exists, RDMS overwrites the
file. RDMS assigns permissions as follows: owner (read, write), group(read),
other(read).
If s1 is NULL, RDMS returns a null value and does not write anything to the file.
If path is NULL, RDMS returns a null value. If RDMS receives an I/O error, RDMS
issues an error and terminates processing of the command containing the get_file
function.
RDMS does not perform any data type conversion when writing s1 to the file. As a
result, some output values may not translate to environments other than OS 2200. For
example, integer or floating point numbers can be written to the output file as binary
values, but they would not be converted to equivalent integer or floating-point values
if the file is transferred to a different operating system environment.
Examples
In the following example, the get_file function writes the contents of the BLOB
column to the specified file and returns the status string 'OK'.
put_file(blob_col1, '/os2200/jmp/jmp/DocBox.pdf')
The following example concatenates the character columns, writes them to the
specified file, and returns the status string 'OK'.
put_file(rtrim(char_column1) || rtrim(char_column2),
'/os2200/jmp/jmp/description.txt')
In the preceding examples, the put_file function writes to the local OS 2200 system.
Other file destinations are possible, using different forms of the path parameter:
put_file('//RS929.nx.unisys.com/os2200/qual/fn/bl01.doc')
put_file('//SERVER1/Groups/Test/pic2.jpg')
put_file('//PC1-nx.us.unisys.com/C$/prog.exe')
If access to a remote system requires a separate user ID and password, include that
information in the path parameter. For example
put_file('//myuid:mypwd@RS929.nx.unisys.com/os2200/qual/fn/bl01.doc')
This section describes how to create routines and triggers for RDMS databases.
These are the topics contained in this section:
• Routines (4.1)
• Triggers (4.2)
• Version Names (4.3)
• Creating, Executing, and Dropping Routines (4.4)
• Creating, Executing, and Dropping Triggers (4.5)
• Parameters (4.6)
• Dynamic Result Sets (4.7)
• Stored Functions (4.8)
• System Variables (4.9)
• Error Checking (4.10)
• Transactions, Commits, and Rollbacks (4.11)
• Statements and Keywords (4.12)
• Datetime and Interval Data Types (4.13)
4.1. Routines
A routine is an executable database object that exists independently of a table. It can
be called from a client or host application.
Routines can
Routines offer many advantages, compared to executing large and complex SQL
queries from a client or host application:
• Faster execution
After their first execution, frequently used routines are resident in memory. After
compilation, they do not need to be reparsed, reoptimized, and recompiled.
• Reduced network traffic
Routines can consist of hundreds of individual statements but can be executed
with a single statement, allowing you to reduce the size of the call from the client
to the server.
• Modular programming
Routines allow you to break your work activities into smaller, more manageable
pieces.
• Reduced operator error
There is less information to pass.
• Enforced consistency
Problems associated with ad hoc data modifications are eliminated when users
access tables only through your routines.
• Automated complex or sensitive transactions
You can guarantee data integrity on certain tables by requiring all interaction with
those tables only through routines.
Whenever a routine is created, RDMS compiles, optimizes, and stores it. The first time
a routine is executed, RDMS reads it into cache memory from the database. Once the
routine resides in memory, it is easy and fast to locate and execute for future
execution during periods of heavy use.
• Synchronous means that the client program waits while the routine executes.
• Atomic means that all statements invoked in the execution path of a routine are
guaranteed to succeed or fail as a unit.
4.2. Triggers
A trigger is a specialized application created by users, but executed by RDMS.
Triggers are similar in many respects to routines. Triggers are used to specify the
processing action that RDMS is to take whenever a predetermined event (the deletion,
insertion, and/or update of information) occurs for a specific table. The processing
action that occurs may include any RDMS statements allowed within a routine
definition. The activation of a trigger may in turn cause the activation of other triggers.
Unlike routines, triggers are implicitly activated by RDMS and are not activated
through explicit reference from a user application.
Triggers can replace the execution of large and complex SQL queries and manual
processes in providing
• Synchronous means that the client program waits while the trigger executes.
• Atomic means that all statements invoked in the execution path of the trigger are
guaranteed to succeed or fail as a unit. Note that if the trigger fails, the triggering
SQL statement also fails.
The trigger, trig2, updates the row in table t2 which has the same key as an updated
row in table t1.
When the user invokes the update_col3 procedure, the following events are initiated:
The following example shows how recursive trigger processing could be used to
replace the procedure shown in the preceding example (multiple invocations of the
same trigger) (the declaration of trig2 is removed from this example to simplify the
presentation):
When the user issues an UPDATE of table t1 the following events are initiated:
The execution of the UPDATE command is complete and control is returned to the
user.
Inventory and
shipments Reorder
Row triggers can be used to assist in accomplishing some of the tasks noted above.
The trigger definitions follow.
• The person who takes the customer's order generates an INSERT command
similar to the following:
1. The user executes an INSERT command into the orders_received table, and then
the inventory_and_shipments trigger is invoked.
2. An UPDATE command of the inventory table occurs, after which the reorder
trigger is invoked.
3. If product_quantity is less than zero
a. The SELECT from the vendors table is performed.
b. The INSERT into the reorder_stock table is performed.
4. Control is returned to the inventory_and_shipments trigger.
5. INSERT into the shipments table occurs. Control is returned to the user upon
completion of the INSERT.
6. The next user request is processed.
A static ESQL USE DEFAULT statement is effective only at compile time and therefore
has no effect in a routine. You can use a USE DEFAULT VERSION statement from the
interpreter interface or dynamic ESQL to change the current default version name at
execution time.
Note, however, that the default version may be changed when a trigger is invoked. If a
trigger is invoked by a data modification statement that includes an explicit table
version reference, then the default version name is changed to that of the table
version specified on the data modification statement. This new default table version is
in effect for the duration of the trigger invocation, including all nested trigger
references that may occur. This rule is applied at each level of nested trigger
invocation, that is, if a trigger contains a data modification statement that includes a
table version and that data modification statement causes another trigger to be
invoked, then the default version is changed to this newly specified table version. In
this manner, the default version may be set and reset several times during the
processing of a trigger invocation. The default version that was in effect prior to the
initial trigger invocation is restored upon completion of the execution of the trigger.
Because table versions are resolved using the default version name, undesirable side
effects may occur if the data modification command references a specific table
version or the trigger contains explicit table version references.
If a user has issued a USE DEFAULT VERSION ARCHIVE command, however, a row is
deleted from t1:archive and immediately reinserted into t1:archive. This is not the
desired result. Similarly, when explicit versions are used, if the DELETE command
contains a version (for example, DELETE FROM t1:production WHERE …), the desired
result is achieved. If the DELETE command contains an explicit version reference to
‘archive’ (or any table version of t1 other than ‘production’), however, the desired
result is not achieved.
Example
PROCEDURE house_schema.update_house_price( )
BEGIN
UPDATE houses SET price=20000 WHERE price < 20000;
END;
For details on creating procedures, see 8.8 (FUNCTION statement) and 9.6
(PROCEDURE statement).
To execute a routine from a host application, you use the CALL statement:
CALL house_schema.update_house_price( );
For details on executing routines, see 6.5 (CALL statement) and 9.11 (SET statement).
To create a trigger
Example
The user that causes a trigger to be invoked does not need to have the privileges
necessary to perform the actions that a trigger requires. The user who created the
trigger is responsible for the actions of the trigger, regardless of who invokes it.
For example
1. From the subject table, candidate rows are read and the old transition table is
created.
2. For each row in the old transition table, every ROW level BEFORE trigger is
executed once. After all ROW level BEFORE triggers are executed, every
STATEMENT level BEFORE trigger is executed once.
3. The database modification is performed.
4. The constraints are verified.
5. AFTER triggers are executed. For each row in the old transition table, every ROW
level AFTER trigger is executed once. After all ROW level AFTER triggers are
executed, every STATEMENT level AFTER trigger is executed once.
1. From the subject table, candidate rows are read and the old transition table is
created.
2. For each candidate row, a new row is created. The set of new rows is the new
transition table.
3. BEFORE triggers are executed. For each correspondence of an old row and its
new row, every ROW level BEFORE trigger is executed once. ROW level BEFORE
triggers can modify the new row (which resides in the new transition table), by
assigning new value(s) to the item(s) in NEW ROW. After all ROW level BEFORE
triggers are executed, every STATEMENT level BEFORE trigger is executed once.
4. The database modification is performed.
5. The constraints are verified.
6. AFTER triggers are executed. For each correspondence of an old row and its new
row, every ROW level AFTER trigger is executed once. After all ROW level AFTER
triggers are executed, every STATEMENT level AFTER trigger is executed once.
One or more of each type of trigger may be associated with a table. If more than one
trigger of a specific type is associated with a table, then the execution order of those
triggers is based on the timestamp of the definition of the triggers. The order of
execution is from the earliest definition timestamp to the latest. For two or more
triggers of the same type for a given table, which have the same definition timestamp,
the order of execution is unspecified.
Although there is a prescribed order to the execution of triggers of the same type for
a given table, care should be taken in creating such triggers. If a trigger is dropped and
re-created its definition timestamp will change, thus affecting its execution order. If
the order of execution of the triggers is important, then each of the triggers would
have to be dropped and re-created in the desired order. Alternatively, the triggers
could be combined, where possible, into one trigger to ensure the desired effect.
RDMS limits the combined nesting depth of any combination of routine and trigger
invocations to 98 levels of nesting and terminates processing if that nesting depth
limit is exceeded.
Assuming that no errors occur, RDMS processes each statement in the trigger body
according to the rules of execution for an RDMS routine. If one of those statements
causes another trigger to be invoked, then each statement in that new trigger is
executed according to the same rules. Each nested trigger that is activated is
completely processed before control is returned to the trigger at the next higher
nesting level. This process continues until each statement in each of the triggers in a
string of cascading and/or recursive triggers is executed.
4.6. Parameters
Routines can accept parameters to improve their usefulness and flexibility.
Examples
PROCEDURE house_schema.select_houses
(IN max_price NUMERIC, OUT how_many NUMERIC)
BEGIN
SELECT COUNT(*) INTO how_many FROM houses
WHERE price < max_price;
END;
To execute a routine from a host application, you use the CALL statement and pass
host variables as parameters:
If you want to pass a null value as an input or output parameter, you must use an
indicator variable just as you do when you pass a null value for a host program variable
(see 2.10.4). RDMS returns an error if a null is passed without an indicator variable.
With $P3 and $P4 as indicator variables for the parameters, the preceding example is
written as follows:
To execute a routine from a routine or trigger, use the CALL statement and pass SQL
variables, parameters from the invoking routine, literals, arithmetic expressions,
datetime expressions, datetime system functions, or the NULL keyword as
parameters. (See 8.8 for more information on parameter values and nested
procedures.)
Note: When you assign a value to an OUT or INOUT parameter using the SET
statement (9.11), the FETCH statement (8.6), or the SELECT Single Row statement
(9.10), the data types (including precision and length, if applicable) of the source and
target must be compatible. If they are not compatible, exceptions, truncations,
conversions, and so forth are raised in a manner consistent with normal RDMS
handling of value assignments to columns. For further information on data type
compatibility of numeric, datetime, and character data, see the following:
• 2.7.1 (character data types)
• 2.7.2 (numeric data types)
• 2.7.3 (datetime data types)
For details on procedures, see 9.6 (PROCEDURE); for details on the CALL statement,
see 6.5.
A result set is like a cursor that is left open at the end of a stored procedure
execution. Normally such cursors are closed during the cleanup phase of stored
procedure processing. By declaring cursors WITH RETURN, you can access these
cursors after the stored procedure has concluded.
4.7.1. Requirements
This feature is not available for all types of cursors. You are only allowed to specify
WITH RETURN for cursors that also have the attributes FOR READ ONLY and FOR
RETENTION (or WITH HOLD, which is synonymous with FOR RETENTION).
• The cursor must be declared in the outermost block of the stored procedure.
• The cursor must have been opened during the stored procedure.
• The cursor must be left open when the procedure concludes.
• You must inform RDMS that you want to receive the result sets before you call a
stored procedure. You use the statement SET RESULT SETS ON for this purpose;
you only need to issue this statement once per thread.
• The stored procedure must be defined with the DYNAMIC RESULT SETS clause.
Because you may want to process result sets from different procedures at the same
time, RDMS generates a unique result set cursor name for each stored procedure
execution that returns result sets. The result set cursor name can generally be
anticipated, as can the names of the return cursors. The result set cursor name
consists of the characters “RS” followed by the number of procedure executions that
have returned result sets since the start of the thread. For the first procedure invoked,
the result set cursor name is RS1.
The individual return cursor names take the result set cursor name as a prefix; they
append an underscore and the original cursor name from the procedure definition (for
example, RS1_C1). If the original cursor name is lengthy and cannot support the prefix
without exceeding the 30-character maximum, it is replaced with the line number
within the procedure at which it was declared (for example, RS1_7).
4.7.4. Example
This example uses the following procedure. Clauses in bold type are the required
result set syntax. The procedure either returns a result set of two cursors (r1 and r2),
or just one (r2), depending on the value of the input parameter how_many.
PROCEDURE s.returns_1_or_2
(IN how_many INTEGER)
DYNAMIC RESULT SETS 2
BEGIN
DECLARE r1 CURSOR WITH HOLD WITH RETURN FOR SELECT * FROM farmer.seed
ORDER BY price FOR READ ONLY;
DECLARE r2 CURSOR WITH HOLD WITH RETURN FOR SELECT *
FROM rdms.seed FOR READ ONLY;
OPEN r2; r1 was declared first, so it will be the first result set
(if it is still open when the procedure ends), regardless
of order opened.
OPEN r1;
IF how_many < 2
THEN CLOSE r1;
END IF;
END;
RDMS returns OK. When RESULT SET CURSOR is OFF, RDMS drops the cursors
created by the stored procedure when the stored procedure completes
execution.
CALL S.RETURNS_1_OR_2(2);
RDMS returns SQLSTATE 0100C and error status 6022 (both statuses indicate
dynamic result sets returned).
AUXINFO = 2, indicating that two result set cursors were returned.
RDMS returns a cursor name in $P1 (for this example, assume that RDMS returned
RS1 as the cursor name).
AUXINFO = 2, indicating that the results cursor has two records.
5 -1 RS1_R1 S RETURNS_1_OR_2
7 -1 RS1_R2 S RETURNS_1_OR_2
FETCH NEXT RS1 INTO ...;
cname = 'RS1_R1';
cname = 'RS1_R2';
Examples
FUNCTION house_schema.select_houses2(IN max_price NUMERIC) RETURNS
NUMERIC
BEGIN
DECLARE how_many NUMERIC;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
RETURN how_many;
END;
To execute a stored function from a host application, you use the nonstandard SET
statement to indicate a variable to use for the return value and pass host variables as
parameters:
If the function result can be a null value, the executing statement must be as follows:
To execute a stored function from a routine or trigger, you use the SET statement to
indicate an SQL variable or an INOUT or OUT parameter of the invoking routine to use
for the return value and to pass SQL variables, parameters from the invoking routine,
literals, arithmetic expressions, datetime expressions, datetime system functions, or
the NULL keyword as parameters. (See 8.8 for more information on parameter values
and nested function invocations.)
For details on functions, see 8.8 (FUNCTION); for details on the nonstandard SET
statement, see 9.11.
4.9.1. RDMSAUXINFO
The system variable RDMSAUXINFO provides auxiliary information for use in routines
and triggers. RDMSAUXINFO is an RDMS keyword.
Table 4–1 shows the value that RDMSAUXINFO contains upon successful completion
of execution of the following statements.
IF RDMSAUXINFO = 0
or if used in a function:
RETURN RDMSAUXINFO;
SET RDMSAUXINFO = 2;
Example
The following example creates a procedure that increases the price of houses with a
specified value (cost) by a specified amount (increment) and returns the number of
houses affected (no_units).
4.9.2. SQLSTATE
The system variable SQLSTATE provides the SQLSTATE status information (see B.5)
for use in routines and triggers. The status information available is as follows:
Status Description
00000 Successful completion
01XXX Warning
02000 No data
All other status values cause an immediate termination of the routine or trigger
invocation.
The statements for which SQLSTATE status information is updated are as follows:
CALL
CLOSE CURSOR
DELETE Positioned
DELETE Searched
FETCH
INSERT
LOCATE
OPEN CURSOR
SELECT
SET (referred to as ASSIGNMENT in the SQL 99 standard), if the source of the set
statement is a stored function
UPDATE Positioned
UPDATE Searched
The value of SQLSTATE is ‘00000’ when a routine is invoked. The value of SQLSTATE
is updated
The use of SQLSTATE is restricted to being the source of a SET statement, a RETURN
value for a stored function, or part of a Boolean expression in an IF statement, ELSEIF
clause, or WHILE statement in the body of a routine definition. For example, the
following statements are allowed:
IF SQLSTATE = ’02000’
RETURN SQLSTATE;
Example
The following example creates a function which deletes a specified house
(house_code) if it exists in the database. The function returns a value of either
DELETED or NOT FOUND.
Errors that occur in the execution of a routine or trigger and cause an immediate
return also cause a rollback. If an error does occur sometime during trigger execution,
the name of the trigger (or each active trigger in the case of cascading triggers) are
incorporated into the issued error messages.
Example
In the following segment of code, all the INSERT statements are rolled back even
though the actual failure does not occur until the third INSERT statement (because it is
identical to the second INSERT statement):
.
.
.
PROCEDURE house_schema.insert_errors( )
BEGIN
INSERT INTO houses VALUES('IE01','Wes',99000,'Dp');
INSERT INTO houses VALUES('IE02','Wes',99000,'Dp');
INSERT INTO houses VALUES('IE02','Wes',99000,'Dp');
INSERT INTO houses VALUES('IE03','Wes',99000,'Dp');
END;
.
.
.
• Standard SQL statements and keywords used exclusively by routines and triggers
(see Table 4–2). Note that RDMSAUXINFO is a nonstandard RDMS extension.
• A subset of standard SQL statements and RDMS extended syntax (see Table 4–3).
Note that the following are nonstandard RDMS extensions:
− DECLARE cursor-name CURSOR [ FOR ] query-expression (optional FOR)
− DECLARE cursor-name CURSOR FOR RANDOM ACCESS...
− DECLARE cursor-name CURSOR FOR DIRECT ACCESS...
− FETCH CURRENT
− LOCATE
Table 4–2 lists and describes statements and keywords that are used only in routines
and triggers.
Table 4–3 lists and describes the subset of standard SQL statements available for
RDMS routines and triggers, as well as RDMS extensions.
Format
BEGIN
[declare-statement-list]
[declare-cursor-list]
compound-statement-list
END
where:
declare-statement-list
is one or more variable declaration statements (see 4.12.4). All variable
declarations must occur before any executable statement in the compound
statement. Variable declarations are optional. Any variables declared within a
compound statement can only be referenced within the compound statement.
They are local to the compound statement and are not visible to statements
outside the compound statement.
declare-cursor-list
is one or more cursor declaration statements (see 7.4). All cursor declarations
must occur after all variable declarations and before any executable statement in a
compound statement. Cursor declarations are optional. No two cursor names may
be the same within the same BEGIN statement. Any cursors declared within a
compound statement are local to that compound statement and are not visible to
statements outside the compound statement or outside of the routine. Note that
statements in an inner compound statement can reference cursors in an outer
compound statement. See 4.12.2 for a discussion of cursor name referencing
rules. Statements in an outer compound statement cannot reference cursors in an
inner compound statement. When execution control processes the END
statement of a compound statement, all cursor declarations within that compound
statement are automatically dropped. There is a limit of 16 cursor declarations
within a routine or trigger.
compound-statement-list
is one or more standard SQL statements (see 4.12). These statements must follow
all declaration statements.
Example 1
The following example creates a stored function with more than one statement. The
list of statements must therefore be part of a compound statement.
Example 2
The following example illustrates compound statements nested in a stored procedure:
PROCEDURE house_schema.select_houses4()
BEGIN
DECLARE a INTEGER;
DECLARE b INTEGER;
DECLARE c INTEGER;
.
.
.
BEGIN
DECLARE m NUMERIC;
SET m = a;
END;
BEGIN
DECLARE x NUMERIC;
SET x = b;
END;
END;
Example 3
The following example shows how a cursor and cursor manipulation statements might
be used in a routine or trigger.
When the balance in the account is insufficient, the record status is marked
“insufficient balance” and the next record is processed. The insufficient balance
records are handled separately.
The resulting balance is returned after all the scheduled transactions are processed.
Note: Any SQL error, other than a no-find condition, is expected to automatically
terminate the execution of this procedure.
PROCEDURE Banking_System.Process_Scheduled_Transactions
( IN p_account_id INTEGER,
IN p_transaction_date DATE,
IN p_transaction_time TIME(6),
INOUT p_result_balance NUMERIC(15,2),
OUT p_return_status CHARACTER(30)
)
BEGIN
DECLARE v_sequence_number INTEGER DEFAULT 0;
DECLARE v_amount NUMERIC(15,2);
DECLARE v_record_status CHARACTER(30);
DECLARE v_record_comment CHARACTER(80);
DECLARE c1 CURSOR
FOR SELECT amount, record_status, record_comment
FROM scheduled_transactions
WHERE account_id = p_account_id
AND scheduled_date <= p_transaction_date
AND scheduled_time <= p_transaction_time
AND record_status = ’scheduled’
FOR UPDATE OF record_status;
In some SQL statements in a routine or trigger (for example, in the UPDATE Searched
change-specification-list; see 10.5), the value-specification (see 10.3) can specify a
column name in a table, a parameter, or an SQL variable. In this case, the SQL
statement (for example, UPDATE) is deemed to have the innermost scope; the scope
of the table name in the table specification is the entire SQL statement. Thus, a
column reference takes precedence over a reference to an SQL parameter or SQL
variable.
Example 1
(Also see the notes that follow the example.)
UPDATE houses
SET price=price-1000 (Note 4)
WHERE hno='H299';
.
.
.
END;
.
.
.
END;
Notes on Example 1:
1. The SET statement resolves a to the SQL parameter a, and b to the SQL
variable b, defined in the same compound statement, without ambiguity.
2. The SET statement resolves a and b to the SQL variables a and b defined in the
same compound statement. The SQL parameter a and the SQL variable b
defined at the outer level are not visible at this nesting level.
3. The INSERT statement does not allow column references in the value list;
therefore, it resolves to the SQL variable price without ambiguity.
4. The UPDATE statement does allow column references in the change
specification list, and table references are considered first. Therefore, it
resolves to the column named PRICE in table HOUSES.
Example 2
(Also see the notes that follow the example.)
Notes on Example 2:
1. Any cursors declared in the thread that invokes this routine are not visible
within the routine.
2. The OPEN statement opens the cursor declared at Level 1, which is declared in
the same compound statement in which the OPEN appears.
3. The OPEN statement opens the cursor declared at Level 2. Although there is a
curs1a cursor declared in Level 1, the curs1a cursor declared in Level 2 takes
precedence, because it is in the same compound statement as the OPEN.
4. The FETCH is from the curs1a cursor declared and opened at Level 2, because
there is no curs1a cursor declared in the same compound statement as the
FETCH, and the Level 2 curs1a cursor is at the next outer level of nesting.
5. The END of the BEGIN block at Level 2 causes the cursors declared at this level
(curs1a and curs2a) to be closed.
6. The FETCH is from the curs1a cursor declared and opened at Level 1, because
that curs1a cursor is declared at the same level in which the FETCH appears.
7. At this point in the execution, all cursors declared within the routine have been
closed and effectively dropped by RDMS. They are not visible to the thread that
invoked this routine
Example
The specification of tbl1 and tbl2 in the FROM clause means that their table names and
all their column names are made available to the name resolution of this statement;
that is, these definitions are of innermost scope. Therefore, any reference within this
statement is resolved to a tbl1 or tbl2 column name first.
If this statement exists in a trigger where (for example) the new table alias is defined
as tbl2, then the definition of the new table must be selected rather than any possible
table default-qualifier.tbl2 that may exist; that is, the new table has innermost scope.
When a table is named in an SQL statement (for example, in the FROM clause of a
SELECT statement), RDMS first attempts to satisfy the reference using any table alias
names. If the relation name matches either the old or new table alias name, then all old
or new table references in that statement are resolved just as if they were references
to a normal base table or view. Unqualified column names may also be resolved to a
column in the old or new table. If the alias table name is specified first in the
statement, its columns take precedence over any other table columns; otherwise, its
precedence depends on the user-specified order in the FROM clause of the specific
referencing statement.
Note that the subject table and its columns can only be referenced explicitly in the
statements of a trigger (that is, where a table specification is permitted in SQL
statements). Also, if an old or new table alias name is identical to the subject table
name (for example, target_table), an unqualified reference to target_table is always
resolved to the old or new table alias.
Within a trigger, for any item reference that is not satisfied by the table columns
defined in the current statement, there is an attempt to resolve the reference to an
SQL variable or to a row correlation name reference.
SQL variables are always considered of a more local scope than a row correlation
name reference which belongs to the outermost level of the trigger. The precedence
of old and new row references depends on the user-specified order of their definition
in the REFERENCING phrase of the CREATE TRIGGER statement.
Example
This example presents an example for resolving names in triggers. This example
trigger operates on the target table HOUSES which has the columns HNO, LOCATION,
PRICE and DESCRIPTION.
Format
where:
variable-name
is the name for the variable, which can then be used in the body of the routine or
trigger. The name must be a valid name as defined in 2.2.1.
data-type
is any valid data type as defined in 2.8, except that the BLOB data type is not
permitted.
literal
is a literal string you specify, set by RDMS when the routine or trigger is invoked.
datetime-function
is CURRENT_DATE, CURRENT_TIME, or CURRENT_TIMESTAMP. For details,
see 2.5.7.
The implied data type of the default value must be compatible with the data type of
the variable.
Note: When you assign a value to an SQL variable using the SET statement (9.11),
the FETCH statement (8.6), or the SELECT Single Row statement (9.10), the data
types (including precision and length, if applicable) of the source and target must be
compatible. If they are not compatible, exceptions, truncations, conversions, and so
forth are raised in a manner consistent with normal RDMS handling of value
assignments to columns. For further information on data type compatibility of
numeric, datetime, and character data, see 2.8.
Examples
Format
[ ELSE statement-list ] ;
END IF ;
where:
Boolean-expression
can include parameters, SQL variables, literals, RDMSAUXINFO, SQLSTATE, OLD
and NEW ROW correlation-name.column-name references. For more information,
see the following:
• 2.4.2 (Boolean expressions)
• 4.6 (parameters)
• 4.12.4 (variables)
• 4.9.1 (RDMSAUXINFO)
statement-list
is a statement or statements (refer to 4.12.2 and Table 4–3).
• RDMS executes the THEN statement list if the Boolean expression evaluates to
TRUE. Otherwise, if the Boolean expression evaluates to FALSE or UNKNOWN,
RDMS continues and evaluates subsequent ELSEIF clauses or executes the ELSE
statement list, if specified.
• If no Boolean expressions evaluate to TRUE and if no ELSE clause is specified,
RDMS continues execution with the statement following the END IF statement.
Example 1
The following example selects houses based on a single criterion—houses located in
Minneapolis. If not enough houses are found, it broadens the search criteria.
PROCEDURE house_schema.minneapolis_houses
(OUT how_many NUMERIC, OUT metro_flag NUMERIC)
BEGIN
SET metro_flag = 0;
SELECT COUNT(*) INTO how_many FROM houses WHERE location =
"MINNEAPOLIS";
IF how_many < 10 THEN
SELECT COUNT(*) INTO how_many FROM houses WHERE location =
"TCMETRO";
SET metro_flag = 1;
END IF;
END;
Example 2
The next example selects houses whose price is lower than a specified threshold.
Note that Boolean expressions can include AND, OR, or NOT operators:
Example 3
The final example sets a maximum price based on the input salary and then selects
houses based on the maximum price:
Note: The RETURN statement must be the last statement executed in a function.
If the function terminates without executing a RETURN statement, RDMS returns an
error.
Format
RDMSAUXINFO │ SQLSTATE } ;
where:
literal
is a literal string you specify, set by RDMS when the function is invoked.
parameter-name
is the name of a parameter (see 4.6).
variable-name
is the name of an SQL variable (see 4.12.4).
expression
is an arithmetic expression, a datetime arithmetic expression (2.4.7), a datetime
function (2.5.7), an extract function (3.8.19), a cast function (3.8.2), or the result of a
scalar function (Section 3).
The data type of the value on the RETURN statement must be compatible with the
data type on the RETURNS clause of the FUNCTION statement (see 8.8). If they are
not compatible, exceptions, truncations, conversions, and so forth are raised in a
manner consistent with normal RDMS handling of value assignments to columns. For
further information on data type compatibility of numeric, datetime, and character
data, see 2.8.
Example 1
The following example determines the number of houses in a given price range:
Example 2
The next example illustrates a case where the RETURN statement may not be
executed, depending on the value of MAX_PRICE:
RDMS returns an error if MAX_PRICE is less than 20,000, because the RETURN
statement was not executed before the end of the routine.
Format
where:
target
is one of the following:
• An SQL variable
• The name of an OUT or INOUT parameter
source
is one of the following:
The data types (including precision and length, if applicable) of the source and target
must be compatible; otherwise, exceptions, truncations, conversions, and so forth are
raised in a manner consistent with normal RDMS handling of value assignments to
columns.
Notes:
• Use this standard SET statement in a routine or trigger to assign a value to a
parameter or variable.
• Use the nonstandard SET statement (see 9.11) in a host language program (for
example, COBOL) or in a routine or trigger to invoke a stored function.
Examples
Here are two stand-alone examples:
The following example sets a maximum price based on the input salary, and then
selects houses based on the maximum price:
Format
where:
character string 1
can be an SQL variable, a routine parameter, or a literal of character data type. A
system variable is not permitted.
Its value must be ‘00000’. If a value other than ‘00000’ is encountered during
execution of the SIGNAL statement, an error is issued and processing of the
routine or trigger is terminated.
character string 2
can be an SQL variable, a routine parameter, a correlation-name-qualified item, or a
literal of character data type. A system variable is not permitted.
The form of the SIGNAL statement that does not include an SQLSTATE value provides
a method of terminating a routine or trigger execution. The CALL, SET, or SQL
statement that resulted in execution of this SIGNAL statement is terminated with an
exception condition, the issuance of the text message specified as character string 2,
and rollback if any database changes were made during the processing of that
statement.
The form of the SIGNAL statement including an SQLSTATE value provides a “Print”
function. This can be used in a test environment to provide a trail of an execution path
through a routine or trigger. If SQLSTATE value is specified and character string 1
value equals ‘00000’ (a nonstandard value), then RDMS handles the command as a
“Print”; any other value is an error. RDMS issues the text message(s) specified as
character string 2 then continues to execute the routine or trigger. This form of the
SIGNAL statement is not recommended for use in a production environment since
normal RDMS error processing is used to display the SIGNAL output.
When a SIGNAL statement without the SQLSTATE value specified is encountered, one
of the following general error messages is issued:
• For routines:
• For triggers:
Example
SIGNAL ' Table s1.t1 may not be modified at this time.'
When a SIGNAL statement with the SQLSTATE value specified is encountered, one of
the following general error messages is issued.
• For routines:
Stored routine schema.name executed a SIGNAL statement and issued
the following messages.
• For triggers:
Trigger schema.name on table schema.name executed a SIGNAL statement
and issued the following messages.
This message is followed by another message (or messages) containing the character
string 2 text specified on the SIGNAL statement.
Examples
SIGNAL SQLSTATE VALUE '00000' 'No Find on Fetch First on cursor C1.'
Format
where:
Boolean-expression
can include parameters, SQL variables, literals, RDMSAUXINFO, SQLSTATE, and
OLD and NEW ROW correlation-name.column-name references. See the
following:
• 2.4.2 (Boolean expressions)
• 4.6 (parameters)
• 4.12.4 (variables)
• 4.9.1 (RDMSAUXINFO)
statement-list
is a statement or statements (see Table 4–2 and Table 4–3).
The statements in the list continue to execute until the search condition becomes
FALSE or UNKNOWN.
Example
To receive a datetime value from a routine, use an OUT parameter of type datetime
and return the datetime value into a character type host variable. RDMS automatically
converts the datetime value to character representation and stores it in the host
variable. The character representation of a datetime value is described in 2.8.3.
Example 1
The following example adds the specified DAY interval value to the current system
date and returns the result:
FUNCTION my_schema.add_days_to_current_date
(IN p1 CHAR(30)) RETURNS DATE
BEGIN
RETURN (CURRENT_DATE + CAST(p1 AS INTERVAL DAY(4)));
END;
You can call the function from a COBOL program as follows, where HOST-VAR1 is
defined as PIC X(30) and HOST-VAR2 is defined as PIC X(5):
Example 2
The following example converts the specified TIME value and performs a range search
using the HOUR-MINUTE interval value:
PROCEDURE my_schema.how_many_records
(IN p1 CHAR(30), IN p2 CHAR(30), OUT p3 INTEGER)
BEGIN
DECLARE time_var1 TIME(6);
DECLARE time_var2 TIME(6);
DECLARE time_var3 TIME(6);
SET p3 = 0;
SET time_var1 = CAST(p1 AS TIME(6));
SET time_var2 = time_var1 + CAST(p2 AS INTERVAL HOUR(4) TO MINUTE);
IF time_var1 > time_var2 THEN
SET time_var3 = time_var1;
SET time_var1 = time_var2;
SET time_var2 = time_var3;
END IF;
You can call the procedure from a COBOL program as follows, where HOST-VAR1 is
defined as PIC X(30), HOST-VAR2 is defined as PIC X(30), and HOST-VAR3 is PIC S1(36):
Sections 6 through 10 describe (in alphabetical order) each statement in the RDMS
implementation of SQL 92. RDMS offers extended syntax to some standard SQL
statements. RDMS also offers statements beyond those described in the standard.
• Interpreter Interface
Whether the statement can be used from third-generation programming
languages, the IPF SQL Interface, and the MAPPER Relational Interface (MRI)
through the interpreter interface.
• Static ESQL
Whether the statement can be embedded in UCS COBOL and UCS C programs
using static ESQL.
• Dynamic ESQL
Whether the statement can be embedded in UCS COBOL and UCS C programs
using dynamic ESQL.
• Module
Whether the statement can be used in module programs.
• XREF
Whether the statement is cross-referenced (XREF). For further information about
cross-referencing, see the Relational Database Server for ClearPath OS 2200
Administration Guide and the COBOL Compiler Programming Reference Manual
Volume 2.
• Standard
Whether the statement complies with entry, intermediate or full level SQL 92, or
the current version of SQL 99. If so, this box also indicates whether RDMS offers
extensions to the standard SQL form. The meanings of the values in the Standard
column are as follows:
In the following example for the ALLOCATE CURSOR statement, the Standard box
indicates “F/X.” The F indicates that the ALLOCATE CURSOR statement complies with
full level SQL 92. The X indicates that RDMS offers one or more extensions to this
statement.
• Syntax
• Examples
• Rules and guidelines
Note: In the table, an asterisk ( * ) indicates that you can prepare and execute the
COMMIT, END THREAD, and ROLLBACK statements only from an implicit thread
(see the BEGIN THREAD statement).
EXPLAIN Yes No No No No X
FUNCTION Yes No No No No P
(not IPF SQL)
LEVEL Yes No No No No X
(not IPF SQL)
PROCEDURE Yes No No No No P
(not IPF SQL)
This section contains reference information about the following SQL statements:
6.1.1. Syntax
SQL 92 Syntax (Intermediate Level)
ALLOCATE cursor-name CURSOR
FOR statement-name
[ FOR RETENTION ]
FOR statement-name
where:
cursor-name
is a unique name within the compilation unit.
statement-name
is any valid SQL name (see 2.2.1). It cannot be a host program variable name.
FOR RETENTION
means to keep the cursor opened after a COMMIT statement in update or
read-only threads and after a rollback (ROLLBACK statement or rollback error)
in read-only threads. If you omit this clause and execute a COMMIT statement,
or are rolled back, RDMS closes the cursor automatically. Within update
threads, a ROLLBACK statement or rollback error causes RDMS to close the
cursor automatically.
6.1.2. Example
The following ESQL statements prepare a named statement that contains the query
specification for a cursor, declare the cursor using the ALLOCATE CURSOR statement,
open the cursor, and fetch a row from the cursor:
Placement
You can place the ALLOCATE CURSOR statement anywhere in a program as long as it
textually precedes any reference to the cursor it declares.
Execution
The ALLOCATE CURSOR statement is not executed when the program is executed. It
therefore has no effect on run-time entities such as SQLSTATE (see B.5).
* The illustrated syntax is referred to as “RDMS extended syntax” because RDMS extensions
are included in the intermediate and full level SQL 92 syntax.
where:
table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.
The ALTER TABLE statement changes the definition that is common to all
versions of the table.
edit-specification-list
is a list of supported combinations of edit specifications (see 6.2.2). These edit
specifications allow you to
{ TO unsigned-integer
[column-constraints] [collate-clause] }
ADD column-definition
DROP column-name
CHECK (Boolean-expression )│
[ ( parent-column-name-list ) ] }
OWNER IS user-id
ADD partition-specification
where:
column-name
is the name of a column in the table named in the ALTER TABLE statement.
unsigned-integer
is the number of characters or the numeric precision the column is to have:
• For CHARACTER, this number must be greater than the column's current size.
• For NUMERIC, this number
− Must be greater than the current specified precision.
− Must not change the memory usage (1 word if precision is 1 to 11, 2 words
if precision is 12 to 21).
If there is a SET default clause edit specification on this column, the original
column size is used in the default value; therefore, you should issue the SET
default clause in a separate ALTER TABLE statement. You cannot change the size
of a column with data type BLOB.
NULLS ALLOWED
changes the column to allow it to contain nulls. This change is permanent. You can
alter any NOT NULL column of a primary key to NULLS ALLOWED if it is not
related to any child table through a foreign key. You cannot alter a column that is
part of a unique constraint.
SET default-clause
sets a default clause for a column. If the column is NOT NULL, the default clause
for this column cannot be NULL. For a description of default clauses, see 6.11.4.
SET generated_default_clause
makes an existing primary key column into an identity column or a column for
which a value is generated. See CREATE TABLE for a complete explanation and
description of the generated_default_clause.
If adding a new column with a generated expression you must first do an ALTER
TABLE table-name ADD COLUMN followed by a separate ALTER TABLE ..SET
generated_default_clause.
DROP DEFAULT
drops the default clause explicitly defined for the column. If the column is NULL
and the default clause is not used, the column is by default NULL. DROP DEFAULT
implicitly results in either a DROP IDENTITY—if IDENTITY is specified on the
column, or DROP EXPRESSION—if an expression is specified on the column.
DROP IDENTITY
removes the information added to the column by GENERATED AS IDENTITY
clause.
DROP EXPRESSION
removes the information added to the column by GENERATED AS (expression)
clause.
ADD column-definition
adds a new column to an existing table (see 6.11 for a detailed description of a
column definition.) Columns added by this statement automatically allow nulls.
The value of all new columns for all existing rows is NULL and can be changed
only by future UPDATE statements.
You do not have to reorganize or dump and reload a database after an ALTER
TABLE ADD statement. However, because it changes the table definition, existing
programs that access the table may be affected.
A table can contain up to 510 columns (509 columns if no primary key exists for
the table), including any dropped columns.
If you add a column with data type BLOB to a partitioned table, you must use two
ALTER TABLE statements: in the first ALTER TABLE statement, add the column; in
the second ALTER TABLE statement, add BLOB storage areas to each partition. If
the table is not partitioned, include the storage area(s) with the column definition.
You cannot add an in-record BLOB to a partitioned table. You must drop and
recreate the table to include an in-record BLOB.
DROP column-name
removes a column from the definition of the table. After using this clause, you
cannot access data in that column. If any statement attempts to refer to a
dropped column, RDMS returns an error.
The limit of 510 columns per table includes dropped columns and any implicit
primary key column. You cannot drop a column that is part of a primary key,
secondary index, unique constraint, or check constraint. You also cannot drop the
last remaining column of a table.
unique-column-list
is a list of up to 25 column names. You must also specify NOT NULL on each
column definition.
storage-area-specification
has the form
IN storage-area-name
where storage-area-name is the name for the storage area for the unique
index as defined in 2.2.5. You must create the storage area before executing
the ALTER TABLE statement. You cannot specify a storage area name if the
table was created with the CREATE TABLE statement and the storage area
was implicitly defined by RDMS (see 6.11).
Boolean-expression
is a condition that must be satisfied by every row in the table.
column-name-list
is a list of up to 25 column names that make up the foreign key. The data
types of the columns in the column name list must match the data types of
the columns in the parent column name list.
table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.
parent-column-name-list
is the list of column names in the parent table's primary key or unique
constraint. Each item in this list must correspond to the item in the same
relative position in column-name-list.
key-name
is the name of the foreign key.
parent-column-name-list
is the list of column names in the parent table's primary key or unique
constraint. Each item in this list must correspond to the item in the same
relative position in column-name-list. You can omit this list if the column name
list is identical to the parent table's primary key.
OWNER IS user-id
changes the owner of the table to user-id, where user-id is any valid user ID. Do
not use this clause if the table is in an owned schema (see 6.10 and 6.11), or if the
table references a foreign key. The user ID must be defined on the local database
system. See also 6.2.4.
• Other edit specifications are not allowed in the same ALTER TABLE statement
in which a column is renamed.
• Any privileges already granted on the column must be revoked before
renaming (the privileges can be granted again after the column is renamed).
• The table specified in the ALTER TABLE statement cannot be the base table of
a view.
The table cannot have any foreign keys, nor can it be referenced by another table's
foreign key.
All versions of the table have the same partitions and therefore have the same
ranges.
Adding a partition never affects the RDT timestamp and therefore does not
invalidate static embedded SQL programs. It is necessary to have exclusive use of
the table definition in order to add a partition.
The ADD PARTITION command fails if any row contains a key value that logically
does not meet the boundaries specified, or if any record in adjacent partitions falls
in the range of this partition.
Caution
DROP INDEX, DROP PARTITION, and DROP TABLE do not clear the storage
areas containing the partition. If you are reusing a storage area and expect
it to be empty, you must initialize it using the UREP PROCESS STORAGE
AREA … DELETE and PROCESS STORAGE AREA … INSTALL commands.
When specified, the ADD PARTITION command is generally the only edit
specification allowed in the ALTER TABLE statement. The exception is the addition
of a unique constraint to a partitioned table. A single ADD PARTITION edit
specification can generally contain only a PARTITION PRIMARY KEY clause or a
single PARTITION INDEX clause. The exception is when a nonpartitioned table is
migrated to a partitioned table. Thus, a single ALTER TABLE statement can add
partitions to the primary key or to a specified index. To add partitions to the
primary key or multiple indexes (except when migrating), use multiple ALTER
TABLE statements.
The partition being dropped can be in any of the states attached, detached, or
hidden. A partition can be dropped even if it is not empty. The partition is
removed from the table, but the storage area is not erased (meaning that the file
containing the storage area still contains the records belonging to the partition).
Foreign key references are not checked.
If the table has any secondary or unique indexes, and you drop any primary key or
index partitions that are not empty, the table is in an inconsistent state. Therefore,
it is recommended that you do not drop a partition in a table that has secondary or
unique indexes unless the partition is empty. Otherwise there will be more
records in some indexes than others, a condition that RDMS considers corrupted.
RDMS issues an RDM 63050 corruption error message when it detects such
corruption. For example, this would happen if an attempt is made to delete a
record WHERE primary_key = some value, that is in the primary key but not in the
secondary index, or RDMS attempts to retrieve a record through the secondary
index but the record does not exist in the primary key.
Dropping a partition does not affect the RDT. It therefore does not invalidate
static embedded SQL programs.
The table remains a partitioned table even after the last partition has been
dropped. It is not possible to use the table because the table is effectively in a
DOES NOT EXIST state.
Notes:
• When specified, the DROP PARTITION command is the only edit
specification allowed in the ALTER TABLE statement.
• Dropping the first partition of a primary key or index destroys the load
restart information for the table, or for the index if the LOAD INDEX
command was used. Therefore, complete all loads before dropping the first
partition.
where:
TABLE
is the keyword used if the table is not partitioned.
partition-name
is the partition to which the new BLOB storage areas are added if the table is
partitioned.
column-name
is the name of the BLOB column.
storage-area-list
identifies the storage area(s) to add to the BLOB column. Storage areas may
not be shared across partitions. If you are adding one storage area to a
column, use the following format:
storage-area-name
If you are adding several storage areas, include the list in parentheses and
separate the names with commas, as follows:
Each BLOB column in each partition can have up to 511 storage areas. (See
2.2.5 for information about storage area names.)
ALLOW MULTIPLE TABLE FILE specifies that this table can share a storage area
with other tables. You cannot specify ALLOW MULTIPLE TABLE FILE for
partitioned tables, global temporary tables, and multifile tables.
If you specify REQUIRE SINGLE TABLE FILE, UREP verifies that no other tables
share the same storage area as table-name. UREP thereafter prevents other tables
from being declared within this storage area.
The default depends on the type of table. For partitioned, global temporary, and
multifile tables, the default is REQUIRE SINGLE TABLE FILE. Otherwise, the default
is ALLOW MULTIPLE TABLE FILE.
Note: When you specify either ALLOW MULTIPLE TABLE FILE or REQUIRE
SINGLE TABLE FILE, no other edit specifications can appear in the same ALTER
TABLE statement.
6.2.3. Examples
Example 1
This example sets the default value of column DESCRIPTION in table HOUSES to
4+ BEDROOM HOUSE and adds a constraint on column PRICE:
Example 2
The next example specifies owner 123X for table HOUSES and activates data access
control:
Example 3
The next example changes the name of the column DESIREDLOC in table CUSTOMERS
to LOC_DESIRED:
Example 4
This example adds two primary key partitions to table MONTHS.
ALTER TABLE months
ADD
PARTITION PRIMARY KEY
nov1999 <= '1999-12-01-00:00:00' IN (DATA sa-data-nov-1999, INDEX sa-
primkey-nov-999)
dec1999 <= '2000-01-01-00:00:00' IN (DATA sa-data-dec-1999, INDEX sa-
primkey-dec-999)
Example 5
The following example adds two secondary index partitions to table PARTS:
Example 6
The next example shows how to convert a nonpartitioned table into a partitioned
table.
The ALTER TABLE syntax below converts the table into a partitioned table. A single
primary key partition named p1_data is created. Similarly, single secondary index
partitions are created for each of the secondary indexes. When you convert a
nonpartitioned table to a partitioned table, the primary key and all indexes must each
have a single partition specified. It is not possible to convert a table to a partitioned
table if any version of the table is locked.
The original table storage areas must be used when converting a nonpartitioned table
into a partitioned table. A nonpartitioned table cannot be converted to a partitioned
table and at the same time moved into new storage areas.
Example 7
This example drops that partition named new-id-codes2.
Example 8
This example adds a unique constraint on columns c2 and c3 to partitioned table
s.table1. Note that the unique constraint is named and that the storage area is
specified in the ADD PARTITION INDEX edit_specification.
Example 9
This example adds BLOB storage areas to a nonpartitioned table T1:
ALTER TABLE t1
ADD BLOB STORAGE TO TABLE
house_photo IN (s1.house_photo_3, s1.house_photo_4),
detail_description IN s1.house_long_desc_2
Example 10
This example adds BLOB storage areas to a partitioned table year_2000.
.
.
.
Example 11
This example adds two primary key partitions to the table softball_table.
Example 12
The following example drops the identity information for the column:
Example 13
The following example alters the table to add identity to the column. The default
values are used for generator options START, INCREMENT, MINVALUE, MAXVALUE,
CYCLE, and cache options.
Example 14
The following example alters the table to add identity to the column. Specific values
are used for the generator options and cache option.
Example 15
The following example alters the table to specify a restart value for the column using
identity. The next insert will use the restart value if default is specified for the column
value.
ALTER TABLE seed CHANGE COLUMN order_no SET RESTART WITH 107
Example 16
The following example drops the expression (for example, partition_id()) for the
column:
Example 17
The following example alters the table to add partition_id expression to the column.
Example 18
Add a partition to a table that has a multiple-column primary key, but partitions by only
the leading primary key column. See Example 8 in the CREATE TABLE section for the
definition of table mybank.today.
User ID Considerations
If a user ID starts with a number, express it as a delimited uppercase identifier as
illustrated in the following examples:
RDMS does not verify the existence of the user ID on the system. If you specify a
nonexisting user ID and data access control is active, the data is inaccessible to other
users until the user ID is defined on the local database system.
Access Conflicts
If another thread has a cursor declared that includes the table you are altering, your
thread queues until the other thread ends. If your own thread has such a cursor
declared, RDMS returns an error and does not alter the table definition.
Note: The same problem can occur if you fetch and update records from a cursor
one at a time, even if the update operation is performed using the UPDATE
SEARCHED or UPDATE Positioned statement.
• When you revoke the REFERENCES privilege from the owner of the child table
• When you enforce the security on a parent table that used to be a public access
table (that is, you give the table an owner and make data access control active)
Changes made by the ALTER TABLE statement do not invalidate previously compiled
interpreter interface programs. They do, however, invalidate previously compiled
ESQL programs.
Whenever you change the definition of a table, you should determine which programs
have to be changed and recompiled.
Effect on Triggers
The ALTER TABLE statement causes triggers to be implicitly dropped if the trigger
references the table. The implicit dropping of triggers can be prevented through the
use of the UREP configuration attribute RDMS-TRIGGER-DROPPING. RDMS-
TRIGGER-DROPPING is set to CASCADE by default. CASCADE allows RDMS to drop
any triggers associated with the altered table. Setting RDMS-TRIGGER-DROPPING to
RESTRICT, causes any ALTER statement to fail if it would cause the implicit dropping
of a trigger.
6.3.2. Example
In the following example, the variables HNO, LOC, and XTALLY can be used in ESQL
statements:
If the UCS COBOL LEVEL/SQL FLAGGER is turned on, the compiler issues warnings for
variables declared outside the BEGIN DECLARE to END DECLARE section that are used
in ESQL statements.
From most interfaces, if a BEGIN THREAD statement is not executed at the beginning
of the session, RDMS executes one implicitly. See 6.4.3.
[ READ │ RETRIEVE │
where:
thread-name
is the name for the new thread. Thread names are 12 characters (alphanumeric) or
less, begin with a letter, and can contain underscores. You cannot use an
underscore as the final character. If omitted, the default thread name is the run-id
under which the program is running.
application-name
is the name or alias of the application group you want to use. Application group
names are limited to 6 characters and alias names are limited to 12 characters.
Note: For ESQL only, the FOR [ APPLICATION ] application-name clause is optional.
If the application name is specified in an embedded BEGIN THREAD statement, a
warning is returned to the program during compilation informing the user that the
specified name is being ignored.
The recovery options are as follows. For more information about these recovery
options, see 6.4.3.
6.4.2. Examples
The following example registers an unnamed thread with application group UDSSRC.
Since it specifies no access option, it uses the default option, UPDATE(DEFERRED).
This statement does not instruct RDMS to print error messages.
The next example is like the preceding example except that it specifies the UPDATE
access option. It does not specify a recovery option, however; therefore, it uses the
default option DEFERRED.
The next example registers thread T1 with RDMS in application group UDSSRC. This
thread cannot update the database. The UDSMSG option means that if RDMS or
UDS Control detects any errors while processing this thread, it immediately prints an
appropriate error message.
The next example registers thread PUBS in application group alias ACCT_APP. This
thread can update the database. Any updates use the DEFERRED recovery option.
1. TIP connect
2. Interpreter BEGIN THREAD statement
3. Link of ESQL program
4. Link or collection of non-ESQL program
Precedence 1
Precedence 1 is the rule if the application program connects to TIP or HVTIP. The
application program must perform that connection before executing any RDMS
statement, including BEGIN THREAD. The name of the application group is therefore
determined by the TIP connection.
Precedence 2
Precedence 2 is the rule if the application program executes an interpreter BEGIN
THREAD statement. The application group name given on the BEGIN THREAD
statement is used.
Precedence 3
Precedence 3 is the rule whenever ESQL programs are compiled as follows:
@UCOB,...,APPLICATION/application-group-name
The application group in which to execute the ESQL program is bound when the
program is linked. For information on linking to application groups, see the Application
Development Programming Guide.
Link time binding means that application programs must be linked to the proper
application group. If an existing application program has an incorrect link (for example,
it erroneously links to APP$n but the application was in fact APP$m), the program is
executed in the wrong application group (in this example, APP$n instead of APP$m).
Precedence 4
Precedence 4 is an implicit RDMS thread. The application group name is determined
by which copy of element CBEP$$RSA was collected or by which copy of element
RSAC-UCSEMOM was linked. From these elements, RDMS determines which
relational intercept and connect routine (RICR) bank (UDS$RDMICR) to call.
The configuration contains this bank descriptor index (BDI) as an alias for an
application group, which in turn becomes the application group used. This implies that
it is not possible to use this method with shared I-banks, because an application group
that shares an I-bank with another application group does not have its own
UDS$RDMICR BDI.
Since the implicit BEGIN THREAD statement does not use the UDSMSG option, you
must use the GETERROR statement in the program to retrieve any error messages
generated during the thread.
You cannot use an implicit BEGIN THREAD statement with IPF SQL. The first SQL
statement must be an explicit BEGIN THREAD statement.
The BEGIN THREAD statement recovery option specified applies to all data models
used in the thread. This means that the recovery unit specified by the DMS run unit is
ignored.
Passing Parameters
When executing a BEGIN THREAD statement from a program through the interpreter
interface, do not pass any parameters beyond the standard command string, error
status, and auxiliary information. Additional parameters are reserved for Unisys
internal interfaces and may cause errors if you attempt to use them.
UPDATE(DEFERRED)
The database retains the original page P1. By the time the third update takes place, P13
is already saved (that is, set aside elsewhere, not actually saved in the database). The
first two updates (P11 and P12) are discarded.
A COMMIT or END THREAD statement executed at this time causes RDMS to discard
P1 from the database and replace it with the updated copy P13.
UPDATE(QUICKLOOKS)
The database contains P13 and the quick-look copy saves the original page P1. Here
“database” means the permanent copy of the database, including working copies of
updated pages that are not yet permanent.
A COMMIT or END THREAD statement executed at this time causes RDMS to discard
P1 (which was taken as a quick-look) and make database page P13 permanent.
UPDATE(COMMANDLOOKS)
The image of the current page is saved not only before the first update in the step
takes place, but also before each statement that updates the page.
If you update page P1 twice during the current step to P11 and then to P12, both the
original page (P1) and the copy taken just before the second update P12 are saved. The
database contains P12.
Suppose RDMS then encounters a problem with the second update statement that
results in a statement rollback. If the second update statement is undone because of
an error, the P12 copy is removed from the database and replaced with P11, the copy
saved just before the second update statement.
If the second update statement is executed successfully and the updates are
committed with a COMMIT or END THREAD statement, both backup copies (P1 and
P11) are discarded. The database contains a permanent copy of P12.
UPDATE(NONE)
No recovery occurs during the thread. This means that all changes are made directly to
the database and that UDS Control does not save original copies of updated pages in a
recovery file. You can use this option only when updating a table located in a
nonrecoverable storage area.
The use of NONE always introduces the danger of database corruption. When
UDS Control internal main storage data page buffers in the page D-banks fill up,
UDS Control writes some of the nonrecovered, updated pages to their storage areas
in mass storage to make room for new pages.
If a thread is rolled back, updated pages in the page D-banks are discarded, but pages
written to their storage areas are unaffected. This causes serious inconsistencies and
corruption in the database.
6.5. CALL
Use the CALL statement to invoke a previously defined stored procedure.
6.5.1. Syntax
SQL Syntax
CALL [schema-name.]routine-name ([ parameter [ ,parameter ] ...])
[UPDATE COUNT OFF]
where:
schema-name
is the name of the schema that contains the procedure.
routine-name
is the name of the procedure.
parameter
is the parameter or parameters to pass to the procedure. The number and type of
parameters specified here must match the number and type of parameters on the
procedure or function declaration. See your compiler documentation for
information on type compatibility.
When a CALL statement is used outside of a routine or trigger, you can use indicator
variables as parameters for specifying or retrieving null values. The use of indicator
variables in a procedure invocation is identical to their use in any other context. When
a CALL statement is used within a routine or trigger, indicator variables may not be
used.
Valid values for parameters depend on the type of formal parameter. The data type of
the actual parameter passed from the calling program, routine, or trigger must be as
indicated for the parameter in the procedure declaration. For more information on the
PROCEDURE statement, see 9.6.
You can refer to the procedure declaration or use the GET PARAMETERS statement to
determine the formal type of each parameter.
You must initialize the variables used as IN and INOUT parameters to valid values
before executing the CALL statement. RDMS returns an error on an uninitialized input
parameter if its contents are not legal for its data type.
You must use the parentheses in all cases, even if the stored procedure has no
parameters.
6.5.2. Examples
The following example, which has no parameters, calls the procedure
UPDATE_HOUSE_PRICE:
PROCEDURE house_schema.update_house_price( )
UPDATE houses SET price = 21000 WHERE price = 20000;
CALL house_schema.update_house_price( );
PROCEDURE house_schema.select_houses
(IN max_price NUMERIC, OUT how_many NUMERIC)
SELECT COUNT(*) INTO how_many FROM houses;
The final example, also based on the preceding example, passes a constant for
MAX_PRICE as a numeric literal:
Nested Invokes
You can use a CALL statement to invoke a stored procedure within a routine or
trigger. The invoked stored procedure must have either been successfully created
prior to its reference or it must be the same as the procedure being defined (recursive
reference).
Errors
If an error occurs during the execution of a stored procedure, control returns
immediately to the caller. The caller must examine the error variable for more
information (refer to Appendix B and Appendix C).
6.6. CLOSE
Use the CLOSE statement to release an opened cursor.
6.6.1. Syntax
SQL 92 Syntax (Entry Level)
CLOSE cursor-name
Note: The RELEASE [CURSOR] form is not allowed in ESQL, routines, or triggers.
6.6.2. Example
The following example releases the cursor MATCHPRICE:
CLOSE matchprice
Effect
Memory allocated to the cursor by the OPEN statement is still occupied, and the
processing performed during cursor declaration is not lost. The cursor is inaccessible
until it is reopened, however.
Usage
The CLOSE statement is optional in the interpreter interface. When you use the
interpreter interface, two consecutive OPEN statements on the same cursor imply a
CLOSE statement of the cursor before RDMS reopens it.
Performance
Opened cursors occupy space in memory. In some cases, closing an idle cursor frees
up the space it was using and can improve performance.
If you attempt to close a cursor that has not been opened, RDMS returns an error
status. This check is made during routine or trigger execution. This error terminates
the execution of a routine or trigger.
All cursors declared within a compound statement are automatically closed, if open,
and dropped when the END statement of that compound statement is executed.
6.7. COMMIT
Use the COMMIT statement to write all updates made to the database since the
beginning of the step (that is, since the last thread control statement).
6.7.1. Syntax
SQL 92 Syntax (Entry Level)
COMMIT WORK
where ADVANCE and TERMINATE are Step Control options and cause the operating
system to advance or terminate its current Integrated Recovery step. In any case,
RDMS assumes that a COMMIT statement terminates the thread’s step.
• ADVANCE advances the operating system Integrated Recovery step counter but
does not end the Integrated Recovery step, even though RDMS considers the
thread’s step ended.
• TERMINATE ends the current Integrated Recovery step.
If you do not specify ADVANCE or TERMINATE, the run’s VALTAB parameter for
transaction programs contains the default option. For all other programs, the default
option is TERMINATE, unless the program was connected to TIP before the start of
the current step; in that case, you should specify the default option when connecting
to TIP.
6.7.2. Example
The following example writes all updates for the current step (that is, since the last
thread control statement) to the database:
COMMIT WORK
For more information on recovery steps and the Integrated Recovery step counter,
consult with your database administrator and see
Effect on Locks
Committing a thread releases all locks except those set by LOCK statements.
Effect on Cursors
Committing a thread closes all opened cursors except those declared with
RETENTION specified. For more information about cursors, see the following:
Errors
If an error occurs on a COMMIT statement, you must terminate the thread with an
END THREAD statement before attempting to execute further SQL statements,
whether the thread is explicit or implicit.
ON table-specification (sort-column-list)
[ storage-area-specification ]
[ index-partition-specification ]
where:
UNIQUE
indicates that no duplicate records are allowed in the index. This is an
alternative to using the ALTER TABLE ADD CONSTRAINT UNIQUE syntax.
index-name
is the name for the index you are creating.
FLASH
indicates that this index is a flash index. A flash index links a secondary index
to the primary index to allow significant performance improvements for key
searches. When FLASH is specified and the table is partitioned, LOCAL must
also be specified.
LOCAL
indicates that this index is local rather than global (default). To have a local
index, the table must be partitioned. A local index allows you to use partition
manipulation commands such as DETACH and HIDE. See 6.8.3 for more
information about using local indexes.
table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.
sort-column-list
is a list of the columns to make up the index and their sorting order. A
secondary index can contain up to 25 columns. Use commas between items in
the list.
storage-area-specification
has the form
IN storage-area-name
where storage-area-name is the name for the storage area for the index as
defined in 2.2.5. You must create the storage area before executing the CREATE
INDEX statement. You cannot specify a storage area name if the table was
created with the CREATE TABLE statement and the storage area was implicitly
defined by RDMS (see 6.11). The storage-area-specification is allowed only for
global indexes, when the table is partitioned.
index-partition-specification
partitions a secondary index according to the leading columns specified in the
index specification followed by the leading columns of the primary key. The
index-partition-specification partitions an index constraint according to the
leading columns specified in the index specification.
This clause defines the storage areas where ranges of the index records are
placed. If specified, this is the only place you may specify a storage area for the
index or constraint. The maximum number of partitions per secondary index is
511.
Format
PARTITION INDEX index-name
index-storage-area-specification [,index-storage-area-
specification] ...
where:
index-name
is the name of the secondary index or unique constraint being partitioned.
index-storage-area-specification
is as follows:
where:
partition-name
is the name of the partition. All partitions in a table must have unique
names.
partition-range
is as follows:
The partition-range is not allowed for local indexes but is required for
global indexes.
IN storage-area-name
is the name of the storage area where the index records belonging in the
range of this partition are stored, as defined in 2.2.5. The data format must be
RSM-INDEX-ONLY.
Each index partition may have different storage area attributes, except for
the data format, directory-id, logging, and lock-strategy, which must be
identical. This allows the page-size to be different for different partitions, for
example.
The same storage area cannot be used in multiple partitions, and it cannot
contain multiple B-trees.
6.8.2. Examples
The following examples create identical indexes with ascending house numbers and
descending locations:
The partitions of index ix9 cover all possible values that can be inserted. Because of
this, an error does not occur for the CREATE INDEX statement when a value is out of
range of all partitions.
The partitions of index ix10 do not cover all possible values that can be inserted.
RDMS issues an error if the table mybank.today contains any record in which
c_check_number is greater than 199999.
Partitioned Tables
If the primary key or any index is partitioned, the table is called a partitioned table. For
a partitioned table, each primary key and index must be in its own storage area. It is
not possible for the primary key or any index of a partitioned table to share storage
areas. In a partitioned table, the primary key and all indexes must be partitioned (even
if they only have one partition whose upper bound is MAXVALUE).
When the CREATE INDEX command is issued, the partitions of the primary key can be
in the attached, detached, or hidden state. However, they are treated as though they
are in the attached state in that the index is populated with a record for every record
in the primary key, regardless of the state of the primary key partition.
Partitions created via the CREATE INDEX command begin in an attached state.
Caution
DROP INDEX, DROP PARTITION, and DROP TABLE do not clear the storage
area(s) containing the partition. If you are reusing a storage area and expect
it to be empty, you must initialize it using the UREP PROCESS STORAGE
AREA … DELETE and PROCESS STORAGE AREA … INSTALL commands.
LOCAL Indexes
For a LOCAL index, there must be an index-partition-specification clause for every
primary key partition. The partition name must be the same as the primary key
partition name. Every partition must have an index-storage-area-specification. For
LOCAL indexes, however, the partition-range is not allowed.
Example
The following is an example table definition.
To create a LOCAL index on emp_number, the index definition must include the
primary key partition keys, specified in the same order and sort direction as the
primary key partition definition.
Note: CREATE INDEX always populates pages with a 100 percent load factor.
Performance
If a table is very large, RDMS can take a long time to execute a CREATE INDEX
statement, because it must create a data structure that contains as many rows as the
table contains.
You should use the QUICKLOOKS recovery option in the BEGIN THREAD statement
when creating or dropping a secondary index, to ensure adequate performance.
Limits
You can have up to 50 secondary indexes and unique constraints in a table. A
secondary index can include up to 25 columns. The maximum number of partitions per
secondary index or unique constraint is 511.
The storage area for the secondary index should have a data format
RSM-INDEX-ONLY, or RSM if the storage area contains the primary key data pages.
For more information, see the Relational Database Server for ClearPath OS 2200
Administration Guide.
However, it is possible for a program to use RDMS SQL in such a way that the
program depends on the access path used by RDMS. In this case, when you create a
new secondary index, existing programs may no longer work as required.
• A program is dependent on the order of the rows of a cursor result set, but the
ORDER BY clause is not used on the cursor declaration.
• A program opens a sensitive or asensitive cursor, and then the program updates
the table used by the cursor. The updated rows can become part of the cursor
result set. The position of the updated rows in the result set, relative to the
current cursor position, depends on the access path, but the program assumes
that the updated rows are always before (or after) the current cursor position.
Effect on Triggers
The CREATE INDEX statement causes triggers to be implicitly dropped if the trigger
references the table. The implicit dropping of triggers can be prevented through the
use of the UREP configuration attribute RDMS-TRIGGER-DROPPING.
RDMS-TRIGGER-DROPPING is set to CASCADE by default. CASCADE allows RDMS to
drop any triggers associated with the create index table. Setting
RDMS-TRIGGER-DROPPING to RESTRICT, causes any CREATE INDEX statement to fail
if it would cause the implicit dropping of a trigger.
6.9.1. Syntax
CREATE ROLE role-name
where role-name can consist of numbers between 1 and 29 ASCII (not UNICODE or
KANJI), characters between A-Z, 0-9, period, and hyphen. The best practice is to use
an invalid user ID as a role name. To do this, use a name between 13 and 29
characters. You can also use a valid user ID, and role name of any length. Do not use
the prefix “RDMS-“, because it is used by RDMS predefined roles.
6.9.2. Examples
CREATE ROLE "ROLE-PROGRAMMER"
The grant of privileges to the role must not include WITH GRANT OPTION.
A site can create any number of roles, but it is anticipated that a given site probably
creates 10 or less.
The CREATE ROLE statement must not be included as part of a CREATE SCHEMA
statement and it cannot be executed as part of a routine or trigger.
To execute the CREATE ROLE statement the user must be a member of RDMS
predefined role "RDMS-ROLE-CREATOR." The user ID that installs UREP is the owner
of role "RDMS-ROLE-CREATOR", and therefore can always issue the CREATE ROLE
statement.
[ { table-definition │ view-definition │
privilege-definition } ]
where:
schema-name
is a valid identifier, as defined in 2.2.1. If you omit the schema name, RDMS
uses the authorization-id.
authorization-id
is your session user ID. Use uppercase letters only.
table-definition
is the standard SQL CREATE TABLE statement.
view-definition
is the standard SQL CREATE VIEW statement.
privilege-definition
is the standard SQL GRANT statement.
6.10.2. Example
The following example creates two tables, one view, and grants privileges to another
user. Assume that DRUID is a valid user ID.
This establishes authorization-id DRUID as the owner of tables and view T01, V01,
and T02. View access control is active for V01 and table access control is active for
T01 and T02. DRUID is the grantor of select privileges to JACQUES for the first table,
T01.
User IDs
If a user ID starts with a number, express it as a delimited uppercase identifier as
illustrated in the following examples:
RDMS converts undelimited lowercase user IDs to uppercase. RDMS rejects delimited
lowercase user IDs (for example, “Mary”) for the authorization-id (use “MARY”
instead).
RDMS does not verify the existence of the user ID on the system. If you specify a
nonexisting user ID and data access control is active, the data is inaccessible to other
users until the user ID is defined on the local database system.
All tables and views in an owned schema are owned by the user specified in the
authorization-id of the CREATE SCHEMA statement.
Data access control is implicitly active for all tables and views in owned schemas.
In owned schemas, ownership and security are turned on for all tables and views, and
these attributes cannot be altered. If the user ID for the current session does not
match the authorization-id specified in the CREATE SCHEMA statement, RDMS
returns an error. RDMS rejects delimited lowercase authorization-ids (for example,
“Mary”) for the authorization-id (use “MARY” instead.)
• You cannot define a foreign key on a table in an owned schema that refers to a
table in an unowned schema, and vice versa.
• You cannot create a table in an owned schema that is associated with a storage
area in an unowned schema, and vice versa.
• You cannot create a view in an owned schema that refers to a table in an
unowned schema, and vice versa.
You can create a routine or trigger in an owned schema only. A routine can access
tables and views in both owned and unowned schemas. A trigger can only access
objects that are unowned or owned by the trigger creator.
Note: For DECIMAL items defined in an owned schema, the number of decimal
digits stored in the UREP metadatabase is one greater than the number of decimal
digits in the original definition. This is because of the difference in the semantics of
this value between the SQL standard and RDMS. For more information, see 2.8.2.
If the table specification does not include a qualifier, RDMS implicitly qualifies it with
the schema name.
* RDMS supports the SQL 92 intermediate level data types DATE, TIME, and TIMESTAMP, as
well as the SQL 92 entry level data types. RDMS supports character handling from the SQL
92 intermediate and full level.
6.11.1. Syntax
SQL 92 Syntax (Entry Level)
CREATE [ GLOBAL TEMPORARY ] TABLE table-specification
( { column-definition │ table-constraint-specification }
( [ table-storage-area, ] column-definition
[ [ , ] index-specification ...]
[ partition-primary-key-specification [ partition-index-specification
]...])
Notes:
• Only one storage area specification is allowed if the table is not partitioned.
• The index specification must be the second to the last clause.
• The partition specification must be the last clause.
• ON COMMIT and ON ROLLBACK apply only to GLOBAL TEMPORARY tables.
table-specification [ table-storage-area ]
primary-key-specification
[ foreign-key-specification ...]
[ index-specification ...]
[ owner-specification ]
[ access-specification ]
[ partition-primary-key-specification [ partition-index-specification
] ...]
Notes:
• A column definition must always precede any table constraint that references
that column.
• No storage area specification is allowed for a GLOBAL TEMPORARY table.
• ON COMMIT and ON ROLLBACK apply only to GLOBAL TEMPORARY tables.
A global temporary table has a persistent definition, but the data is not persistent. By
default, a temporary table is emptied upon a commit, rollback, or END THREAD.
The ON COMMIT and ON ROLLBACK clauses apply only to global temporary tables. If
you specify ON COMMIT PRESERVE ROWS or ON ROLLBACK PRESERVE ROWS, the
table remains populated with data after a commit or rollback. The default actions are
specified by ON COMMIT DELETE ROWS and ON ROLLBACK DELETE ROWS.
For more information about using global temporary tables, see in 6.11.14.
See the following descriptions of each clause (6.11.2 through 6.11.12) for more
information.
where:
schema
is the name of the schema containing the table. If the schema is an owned
schema, only the owner can execute the CREATE TABLE command. (See 6.10
for more information about owned schemas.) If you omit the schema name,
RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses
the default schema name RDMS or the value of the user ID of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAULT-QUALIFIER. For additional information see the Repository for
ClearPath OS 2200 Administration Guide.
table–name
is the name of the table following the naming conventions in 2.2.1. Version
names are not allowed since only one definition exists for all versions of the
same table.
If you omit this clause, RDMS implicitly creates a storage area whose name matches
the table name. RDMS implicitly creates an underlying Exec file, the name of which is
created uniquely from a system counter.
If you include this clause, the storage area must have one of the following attributes:
• DATA-FORMAT RSM, if you want the storage area to hold both data pages and
index pages for the table
• DATA-FORMAT RSM-DATA-ONLY, if you want the storage area to hold only the
table’s data pages and another storage areas to hold the table’s index pages
Format
IN storage-area-name
where:
column-name
is the name for the column as defined in 2.2.3.
data-type
is a data type as defined in 2.8. Refer also to 2.9.1 and 2.9.2 for information on
character value assignment and internationalization considerations for character
data.
default-clause
is the default value for the column in the form
generated-default-clause
All columns of the primary key must be ascending when the table contains a
generated default clause. If the generated expression is on a column that is part
of an index, all columns within that index must also be ascending.
All columns that have generated defaults must be part of either the primary key or
an index.
GENERATED
GENERATED ALWAYS means that it is not possible for an application program to
specify a value for the column on the INSERT statement1 . The column must either
be omitted from the INSERT (the column-name-list or column-and-value) or must
be specified using the DEFAULT keyword. RDMS always generates the value for
the column.
AS
This clause tells RDMS how to generate the value:
CURRENT_DATE
CURRENT_TIME [ (time-precision) ]
CURRENT_TIMESTAMP [ (timestamp-precision) ]
partition_id()
IDENTITY [ ( generator-options ) ]
IDENTITY can be specified at most once per table. There is at most one
generated-default-clause for each primary key or index or unique constraint, but
only two are allowed for each table—either identity or partition_id() on the primary
key and an index whose leading column is generated as current_date,
current_time, or current_timestamp. IDENTITY and partition_id() need not be the
entire primary key; however, they must be the leading primary key column. The
nonleading primary key columns may not be data type CHARACTER WITH
CHARACTER SET and COLLATION. When IDENTITY is used, the table cannot be
partitioned. When partition_id() is used, the table must be partitioned. The primary
key column must be an ascending key. When the column is generated AS {
function }, that column must be the leading primary key or index column. All
columns of the primary key or index must be ascending.
DEFAULT CURRENT_TIMESTAMP
and
GENERATED BY DEFAULT AS (CURRENT_TIMESTAMP) CACHE 0
___________________
1
LOAD ignores GENERATED ALWAYS, so values can be specified on LOAD.
When the leading key column is IDENTITY or partition_id(), RDMS knows there is a
range. RDMS performs preconditioning such that each value of the identity column
is placed on a different page.
cache-option
For example, a very large value, such as 262143, directs RDMS to precondition as
much as is reasonable. CACHE 0 and CACHE 1 are exact, meaning RDMS
preconditions exactly 0 or 1 page respectively. When num-values-to-precondition
>= 2, RDMS rounds up, or down, to internally defined limits to get the most
preconditioning done for the same cost. For example, if a level 1 index page has
room for 10 index records, but the user specified CACHE 9 (or CACHE 11) RDMS
might operate as though CACHE 10 were specified. This enables RDMS to
completely fill the index page, so that the next user to precondition can start with
a new (empty) index page. In short, when num-values-to-precondition >= 2, RDMS
uses the specified value as a hint, but still does whatever is needed to be efficient.
When CACHE is not specified, DYNAMIC is assumed. DYNAMIC instructs RDMS to
perform dynamic preconditioning efficiently. CACHE 0 turns off dynamic
preconditioning.
The most advantageous value to use depends on many factors such as number of
records for each data or index page, data or index page size, type of disks, and so
on. NO CACHE has the same semantics as CACHE(0). CACHE must be 0,
DYNAMIC, or 1 when current_time or current_timestamp is used.
When CACHE is not specified, DYNAMIC is assumed. CACHE DYNAMIC along with
current_date, current_time or current_timestamp operates as though CACHE 1
were specified.
The CACHE clause is also one of the attributes that determines the maximum
number of values that might be lost during a system restart. Refer to Relational
Database Server for ClearPath OS 2200 Administration Guide for more
information.
generator-options
Note: The ALTER TABLE includes a RESTART keyword to enable the user to
specify the next value to use when RDMS must restart the sequence.
column-constraints
restrict the values allowed for the column. Columns with data type BLOB cannot
participate in UNIQUE, CHECK, PRIMARY KEY, or REFERENCES constraints.
Format
{ NOT NULL [ [ CONSTRAINT constraint-name ] { UNIQUE │ PRIMARY KEY } ]
│ [ CONSTRAINT constraint-name ]
where:
NOT NULL
is data to be stored in the column that cannot be null. If you attempt to store a
null in the column, RDMS returns an error message. If you do not use NOT
NULL, nulls are allowed in the column.
constraint-name
is the name for the constraint. You can specify a name for the constraint, or
you can let RDMS attach a name to it (UNIQUE$1, . . .UNIQUE$n or
CHECK$1, . . .CHECK$n or FKEY$1, . . .FKEY$n).
If you attempt to store a duplicate row in a table, RDMS returns an error. The
number of unique constraints in a table cannot exceed 10. Only one primary
key constraint is allowed.
CHECK (Boolean-expression)
establishes a condition that every data item in this column must satisfy.
Datetime functions are not allowed. Include only this specific column name in
the Boolean expression (see 2.4.2).
If you omit the name of the parent column, the parent table must contain a
primary key that consists of one column. For more information about the
correspondence between columns in parent and child tables, see the
Relational Database Server for ClearPath OS 2200 Administration Guide.
collate-clause
is the collation (sorting) order RDMS is to use for comparing and ordering data values
in a character column and the order in which to create indexes related to the column
(see 2.8.2). If you use a COLLATE clause on a column definition, you must also use a
CHARACTER SET clause. The character set on the CHARACTER SET clause must
match the character set associated with the collation name on the COLLATE clause. If
you omit this clause, the default (implicit) collation order is binary, based on the octal
character codes. With a COLLATE clause, the maximum column size is 4,085
characters.
Current_date/time/
Condition Identity Partition_id() timestamp
Identity columns are a type of default—the default that is used by the INSERT
statement, and by UPDATE when the DEFAULT keyword is specified as the new value
of the column. You cannot specify a default-clause along with a
generated-default-clause. Columns with a generated-default-clause must be NOT
NULL. NOT NULL is implicit for columns including a generated-default-clause as part of
CREATE TABLE.
The following example shows how to declare an identity column. Because none of the
generation options are explicitly specified, the following are assumed by RDMS:
• START WITH 1
• INCREMENT BY 1
• MINVALUE +1
• MAXVALUE +34359738366
• NOCYCLE
• CACHE DYNAMIC
If you define explicit storage areas for this table, you must have the following:
• merge-factor 1
• data-page-factor 1
• data-page-size 112 words
• index-page-size 1792
• lock-strategy record
Example 2
The following example shows the use of an identity column. The identity column is
used to create a unique prescription number. Assume that the prescriptions live
forever and are never deleted. We assume that there is enough concurrency so that
dynamic preconditioning is needed, but not enough concurrency to partition the table.
The first prescription is a 4 digit number, so start with 1000. Since NOMAXVALUE is
implied, the largest prescription_no is the largest value that fits within the column’s
data type NUMERIC(21,0), which is equivalent to MAXVALUE
+999999999999999999999.
• merge-factor 1
• data-page-factor 100
• page-size 896
• lock-strategy record
If explicitly defined, the storage areas must have:
• merge-factor 1
• data-page-factor 1
• data-page-size 112 words
• index-page-size 1792
• lock-strategy record
Example 3
The following example shows how to use CYCLE to implement a queue as an RDMS
table. The usage of this table is to insert records at the end and delete records from
the beginning. The storage areas must have:
• merge-factor 0
• data-page-factor 1
• page-size 896 words
• lock-strategy record
The start-value is 10000. Use merge-factor 0 for cycles because empty pages get
reused on the next cycle. Merge-factor 0 ensures that DELETE does not affect index
pages, and reduces the possibility of DELETE being involved in queuing or deadlock.
Example 4
This example demonstrates how to cause all records for a given value of the IDENTITY
column, which is the leading column of a multi-column key, to be written to the same
data page. For example, it is desired that records (1,1), (1,2), … (1,n) be written to a
single data page, provided there is room for all those records and that records (2,1),
(2,2), … (2,n) be written to a different data page. To do this, the storage-area
my_message_subscriptions_sa is defined with data-page-factor 100, and the table is
declared as follows (with the IDENTITY column being the first column of the two-
column primary key):
Example 5
This example shows the use of partitioned tables. The storage areas can have:
• merge-factor 1
• data-page-factor 100
• data-page-size 1792 words
• index-page-size 1792
This provides multiple records per data page. This means that at most the number of
concurrent inserts allowed would be equal to the number of partitions. The largest
allowable value of C1 is 2000. This becomes the implicit maximum-value for the
partition_id() column. This example also demonstrates the use of the GENERATED
clause on column C1.
CREATE TABLE t1
Columns are
C1: integer GENERATED ALWAYS AS (partition_id()),
C2: integer,
C3: integer
primary key primkey is C1 ASC
index seckey on C3
PARTITION PRIMARY KEY
P1 <= 1000 IN (DATA sa_data_p1, INDEX sa_index_p1),
P2 <= 2000 IN (DATA sa_data_p2, INDEX sa_index_p2)
PARTITION INDEX seckey
S1 <= 5000 IN sa_s1,
S2 <= 10000 IN sa_s2
Example 6
The following example shows how to inform RDMS that your leading secondary index
column is monotonically increasing, and to instruct RDMS to perform dynamic
preconditioning for that index—this reduces contention for index pages. It is useful for
RDMS to always generate the timestamp on INSERT, rather than for the user to supply
this value because it allows RDMS to synchronize the INSERT statements so that
records with lower timestamps always get inserted into the table before records with
larger timestamps. CACHE 1 indicates that RDMS is to get a single data page at a time.
This is necessary because RDMS does not know the value of the next timestamp
ahead of time. RDMS uses CACHE 1 or CACHE DYNAMIC for this case.
CREATE TABLE t1
Columns are
C1: integer GENERATED ALWAYS AS (partition_id()) NOT NULL,
C2: integer,
C3: timestamp GENERATED ALWAYS AS (CURRENT_TIMESTAMP) CACHE 1 NOT NULL
primary key primkey is C1 ASC
index seckey on C3
PARTITION PRIMARY KEY
P1 <= 1000 IN (DATA sa_data_p1, INDEX sa_index_p1),
P2 <= 2000 IN (DATA sa_data_p2, INDEX sa_index_p2)
PARTITION INDEX seckey
S1 <= 5000 IN sa_s1,
S2 <= 10000 IN sa_s2
Note: This table has two GENERATED clauses. After inserting a new row into the
table, the identity_val_local function returns the value for the column C1 since only
C1 is part of the primary key column.
Columns with data type BLOB cannot participate in UNIQUE, CHECK, PRIMARY KEY, or
FOREIGN KEY constraints.
Format
[ CONSTRAINT constraint-name ]
│ CHECK (Boolean-expression)
| standard-foreign-key-specification }
where:
constraint-name
is the name for the constraint. You can specify a name for the constraint, or
you can let RDMS attach a name to it (UNIQUE$1, . . .UNIQUE$n or
CHECK$1, . . .CHECK$n or FKEY$1, . . .FKEY$n).
unique-column-list
is a list of up to 25 column names. You must specify NOT NULL on each
column included in the list.
storage-area-specification
is the name of the storage area in which RDMS writes the index pages for the
unique constraint or primary key. If the table is partitioned, this clause is not
allowed; you must put the storage area name on the partition-primary-key-
specification clause or partition-index-specification clause instead.
If you omit this clause or if you include this clause and its name matches the
name on the table-storage-area clause, RDMS writes the index pages to the
storage area you included on the table-storage-area clause and its
DATA-FORMAT must be RSM-INDEX-ONLY. The DATA-FORMAT of the
storage area on the table-storage-area clause must be RSM-DATA-ONLY.
The same storage area can be used for multiple constraints and indexes.
Format
IN storage-area-name
sort-column-list
is the column or columns that make up the primary key and the order in which
they are to be sorted. A primary key can have up to 25 columns. Use commas
between items in the list.
Format
column-name [ ASCENDING │ DESCENDING ]
Boolean-expression
is a condition that every row in this table must satisfy. The Boolean expression
can include only columns that are in the table being created.
standard-foreign-key-specification
is the standard SQL syntax for specifying a foreign key table constraint, which has
the same effect as the RDMS extended format, in the form
[ (parent-column-name-list) ]
where:
column-name-list
is a list of up to 25 column names to make up the foreign key. The data types
of the columns in the column name list must match the data types of the
columns in the parent column name list.
table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.
parent-column-name-list
is the list of column names in a unique or primary key constraint of the parent
table. The columns in this list must correspond one-to-one with the columns in
column-name-list.
If you omit this list, the parent table must include a primary key whose
columns correspond one-to-one with the columns in column-name-list.
For more information about corresponding columns and defining foreign keys,
see the Relational Database Server for ClearPath OS 2200 Administration
Guide.
Format
INDEX index-name [LOCAL] ON sort-column-list [storage-area-specification]
where:
index-name
is the name for the index. It must be a valid name as defined in 2.2.1. You must
specify a unique name for each secondary index in the table; otherwise, RDMS
returns an error.
LOCAL can be specified only when the table is partitioned. If LOCAL is not
specified, the index is GLOBAL.
sort-column-list
is a list of the columns to make up the index and their sorting order. A secondary
index can contain up to 25 columns. Use commas between items in the list.
Format
{ column-name │ (column-name-list) } [ ASCENDING │ DESCENDING ]
A null in a secondary index column is considered greater than any non-null in the
column in determining the ascending ordering of the index, and vice versa for
descending. A secondary index should not include an approximate numeric
column.
The sort-column-list for a LOCAL index is slightly different from that for a GLOBAL
index. The leading columns of the sort-column-list for LOCAL indexes must be the
leading columns of the primary key used as the partitioning key. The partitioning
key columns in the local index cannot be sorted in a direction different from the
primary key index.
storage-area-specification
is the name of the storage area in which RDMS writes the index pages for this
secondary index. If the table is partitioned, this clause is not allowed; you must
put the storage area name on the partition-index-specification clause instead.
If you omit this clause or if you include this clause and its name matches the name
on the table-storage-area clause, RDMS writes the index pages to the storage
area you included on the table-storage-area clause, and its DATA-FORMAT must
be RSM.
If you include this clause and the storage-area-name does not match the name on
the table-storage-area clause, RDMS writes the index pages to the specified
storage area, and its DATA-FORMAT must be RSM-INDEX-ONLY. The
DATA-FORMAT of the storage area on the table-storage-area clause must be
RSM-DATA-ONLY.
The same storage area can be used for multiple constraints and indexes.
Format
IN storage-area-name
Format
PRIMARY [ KEY ] key-name IS sort-column-list [storage-area-specification]
where:
key-name
is the name for the primary key.
sort-column-list
is the column or columns to make up the primary key and the order in which they
are to be sorted. A primary key can have up to 25 columns. Use commas
between items in the list.
Format
{ column-name │ (column-name-list) } [ ASCENDING │ DESCENDING ]
storage-area-specification
is the name of the storage area in which RDMS writes the index pages for the
primary key. If the table is partitioned, this clause is not allowed; you must put the
storage area name on the partition-primary-key-specification clause instead.
If you omit this clause or if you include this clause and its name matches the name
on the table-storage-area clause, RDMS writes the index pages to the storage
area you included on the table-storage-area clause and its DATA-FORMAT must
be RSM.
If you include this clause and the storage-area-name does not match the name on
the table-storage-area clause, RDMS writes the index pages to the specified
storage area, and its DATA-FORMAT must be RSM-INDEX-ONLY. The
DATA-FORMAT of the storage area on the table-storage-area clause must be
RSM-DATA-ONLY.
The same storage area can be used for multiple constraints and indexes.
If one or more columns in your table have a data type of BLOB, you cannot use the
standard SQL syntax to create the table. You must explicitly provide a storage
area for the BLOB data, as well as explicit storage areas for the table data and any
indices.
Format
IN storage-area-name
Note: This is legacy RDMS syntax used for specifying foreign keys in RDMS
extended syntax 2 format. You cannot use this format if the CREATE TABLE
statement includes table constraint specifications or column constraints that
specify a foreign key.
You can have up to 25 foreign keys in a table. Separate foreign key clauses from one
another with at least one blank space.
Format
FOREIGN KEY key-name IS column-name-list
where:
key-name
is the name for the foreign key.
column-name-list
is a list of column names to make up the foreign key. This list can contain up to 25
column names. The data types of the columns in the column name list must
match the data types of the columns in the parent column name list.
parent-column-name-list
is the list of column names in the parent table’s unique constraint or primary key.
Each item in this list must correspond to the item in the same relative position in
the column name list. The items must appear in the same order as the list of
columns in the unique constraint or primary key clause of the parent table
definition.
You can omit this list if the column name list is identical in number, order, and type
to the parent table's primary key. If you omit this list, the parent table must define
a primary key; and the order of column names in the column name list must
correspond to the order of column names in the parent table's primary key.
table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.
The owner-specification clause establishes the owner of the table, in the form
where user-id is any valid user ID. RDMS does not verify the existence of the user ID
on the system. If you specify a nonexisting user ID and data access control is active,
the data is inaccessible to other users until the user ID is defined on the local database
system. See also 6.11.14.
Format
PARTITION PRIMARY KEY
For a LOCAL index, the index storage area is specified as part of the primary key
partition; there is no PARTITION INDEX clause.
Format
partition-name <= { column-upper-bound | ( column-upper-bound
[ ,column-upper-bound ]... ) }
IN { ( storage-area-name [ ,local-index-partition-spec]...) |
[ ,local-index-partition-spec] ... ) }
[ blob-storage-area-clause ]
where:
partition-name
is the name of the partition. All partitions in a table must have unique names,
whether or not they are partitions of the same primary key or index.
column-upper-bound
describes the range of the partition.
Format
{ string-literal | numeric-literal | alternate-based-literal |
datetime-literal | MAXVALUE }
storage-area-name
is the name of the storage area where the index records belonging in the
range of this partition are stored, as defined in 2.2.5.
Specify two storage areas if you want the primary key data pages in a different
storage area from the primary key index pages. The storage area specified for the
primary key data must be RSM-DATA-ONLY. The storage area for the primary key
index pages must be RSM-INDEX-ONLY and may not be identical to the name
specified for the RSM-DATA-ONLY storage area. This form of the syntax is used
as follows:
When only a single storage area is specified, it contains both the primary key data
and primary key index pages and therefore must have data-format RSM. This form
of the syntax is as follows:
If you specify two storage areas for one partition of the primary key, you must
specify two storage areas for each partition of the primary key.
local-index-partition-spec
identifies a LOCAL index and the index's storage area for the partition.
Format
index-name storage-area-name
index-name
is the name of a LOCAL index that was specified in an index-specification
clause. The storage-area-name that follows is used to store the LOCAL index.
There must be one local-index-partition-spec for each LOCAL index in the
table. The local-index-partition-specs must be in the same order as the
index-specifications of the indexes.
For example
If you do not want to store the primary key data pages in a separate storage
area from the primary key index pages, you use the other form of the
partition-index-specification IN clause.
For example
Each partition of the index can have different storage area attributes, except for
the data-format, directory-id, logging, and lock-strategy, which must be identical.
For example, this allows the page size to be different for different partitions.
The same storage area may not be used in multiple partitions, and it may not
contain multiple B-trees.
blob-storage-area-clause
identifies the storage areas where RDMS will store the BLOB data for each BLOB
column in the table. When there is no storage-area-list for a BLOB column, the
BLOB values of the column are stored as part of the record. For a given BLOB
column there must be a storage-area-list either for every partition or for no
partitions.
Format
blob-column-name IN storage-area-list
where:
blob-column-name
is the name of the BLOB column.
storage-area-list
identifies the storage area(s) where RDMS will store the BLOB data for this
column in this partition. The format of each storage area must be RSM-LOB.
Storage areas may not be shared across partitions. If you are adding one
storage area to a column use the format
storage-area-name
If you are adding several storage areas, include the list in parentheses and
separate the names with commas, as follows:
The storage-area-name is the name of the storage area where the BLOB data
belonging to this partition is stored, as defined in 2.2.5.
Each BLOB column in each partition can have up to 511 storage areas.
The data type of each column-upper-bound must be comparable to the data type of
the corresponding index column. A column-upper-bound need not be specified for all
the columns of the index. Normally, only a single column-upper-bound is specified,
meaning that the table is partitioned only on the first column of the index. Each
column-upper-bound must fit within 68 bytes of storage space.
If a column of the index is of data type CHAR, a string literal 68 characters or less
must be specified. If the data type is CHAR with CHARACTER SET and COLLATE, the
internal format of the string literal created for comparison purposes must be 68 bytes
or less.
If a column of the index is of data type NCHAR, a string literal 64 bytes or less can be
specified.
MAXVALUE represents a value larger than any value (including NULL) that can be
stored in a column of a given data type. Once MAXVALUE is specified as a leading
column-upper-bound, all subsequent column-upper-bounds for that partition must
have a value of MAXVALUE (for example, partition_name <= (MAXVALUE, 16) is not
allowed). It is not necessary to have partitions that cover the entire range of values of
the first column of the index; that is, MAXVALUE does not have to be specified for the
leading key partition. However, an attempt to insert a row that does not fall into any
partition results in the error 6021. The upper bound of a partition cannot be the
character string ‘MAXVALUE’. If more than one column-upper-bound is specified and
the sort directions of those columns differ, it is necessary to cover the entire range of
values for all but the leading column.
Examples
Example 1
The partition key is c1 ascending, c2 descending, c3 ascending.
Example 2
The partition key is c1 descending, c2 ascending.
It is not necessary to order (numerical or collating sequence order) the column upper
bounds. Regardless of which order they are specified to RDMS, RDMS operates as
though they were entered in the order of the corresponding index column.
Caution
DROP INDEX, DROP PARTITION, and DROP TABLE do not clear the storage
areas containing the partition. If you are reusing a storage area and expect
it to be empty, you must initialize it using the UREP PROCESS STORAGE
AREA … DELETE and PROCESS STORAGE AREA … INSTALL commands.
Note: UNIQUE constraint index records do not contain the primary key values.
This clause defines the storage areas where ranges of the index records will be
placed. If used, this is the only place you may specify a storage area for the index or
constraint. The maximum number of partitions per secondary index or UNIQUE
constraint is 511.
Format
PARTITION INDEX index-name
where:
index-name
is the name of the non-LOCAL secondary index or unique constraint being
partitioned.
index-range-specification
is the expression describing one slice of the index value range and its
corresponding storage area.
Format
partition-name <= (column-upper-bound [ , column-upper-bound ]... )
IN storage-area-name
where:
partition-name
is the name of the partition. All partitions in a table must have unique names,
whether or not they are partitions of the same primary key or index.
column-upper-bound
describes the range of the partition.
storage-area-name
is the name of the storage area where the index records belonging in the
range of this partition are stored, as defined in 2.2.5.
Each partition of the index may have different storage area attributes, except
for the data-format, directory-id, logging, and lock-strategy, which must be
identical. For example, this allows the page-size to be different for different
partitions.
The same storage area cannot be used in multiple partitions, and it cannot
contain multiple B-trees.
Example
CREATE TABLE T1
COLUMNS ARE
C1 : INTEGER,
C2 : INTEGER,
C3 : INTEGER
PRIMARY KEY primkey IS C1 ASC
index seckey ON c3
PARTITION PRIMARY KEY
P1 <= 1000 IN (DATA sa_data_p1, INDEX sa_index_p1),
P2 <= 2000 IN (DATA sa_data_p2, INDEX sa_index_p2)
PARTITION INDEX seckey
s1 <= 5000 in sa_s1,
s2 <= 10000 in sa_s2
Example 2
Suppose you are setting up a table to keep track of a company’s softball team. The
only eligible players are employees of the company. Therefore, you must ensure that
no names appear in the softball team table that are not in the personnel table. You can
write a program to enforce this, or you can let RDMS do it with foreign keys.
With this option, create the softball team table with a foreign key that refers to the
personnel table, as follows:
Example 3
This example illustrates table HOUSES created as a multifile table. Its primary key data
pages are in storage area MF.A1, which has data format RSM-DATA-ONLY. The
primary key index pages are in storage area MF.A2, which has data format
RSM-INDEX-ONLY. The secondary index IX is in storage area MF.A3, which has data
format RSM-INDEX-ONLY.
Example 4
This example illustrates the use of column constraints, a table constraint, and a
self-referencing foreign key:
• Columns AREA-CD and PHONE, through the use of column constraints, must be
numeric.
• Columns AREA-CD and PHONE together, through the use of a table constraint,
must also be unique.
• Since a manager is also an employee in the table, the relationship between an
employee and the employee's manager is defined through the use of a
self-referencing foreign key.
Example 5
In this example, a table constraint is imposed on table HOUSES, so that the value of
column MINPRICE must be less than or equal to the value of column ASKPRICE. The
default clauses require the insertion of the value MINNEAPOLIS in column LOCATION
and 2-BEDROOM RAMBLER in column DESCRIPTION if a value is not specified for
both columns on another insertion.
Example 6
Using RDMS extended syntax 1 (essentially standard SQL syntax with RDMS
extensions), this example illustrates how to create a table in an unowned schema and
specify storage areas:
Example 7
This example demonstrates the collating sequence for multicolumn partitioning. In this
example, the primary key consists of two integer columns, both in ascending order.
ANSI SQL 92 vector comparison rules are applied. Note that in partition P1 and
partition P2 the first-order key is 1000. Placement of the records into the correct
partition is determined by the second-order keys 100 and MAXVALUE. Thus, key 1000,
99 goes into P1, and key 1000,101 goes into partition P2.
Example 8
You do not have to use all the columns of the primary key for partitioning. For
example, suppose you have a database that you want to partition by day with a day
per partition, over a range of four days:
All days earlier than the 2nd of September are placed by RDMS in partition p1. An error
is issued by RDMS if an attempt is made to insert a record with c_transaction_date
greater than 2003-09-04 into this table.
You can add partitions later using the ALTER TABLE ADD PARTITION statement.
Example 9
The following example shows how to create the softball_table as a partitioned table
with two partitions, with names from A to M in the first partition, and the rest of the
names in the second partition.
(emp_number)
Example 10
The following example shows how to include BLOB columns in a nonpartitioned table.
Example 11
The following example shows how to include BLOB columns in a partitioned table.
User IDs
If a user ID starts with a number, express it as a delimited uppercase identifier as
illustrated in the following examples:
RDMS does not verify the existence of the user ID on the system. If you specify a
nonexisting user ID and data access control is active, the data is inaccessible to other
users until the user ID is defined on the local database system.
To create a single file table, use only the stand-alone format of the storage area
specification; or, if you use standard SQL syntax, do not include a storage area
specification.
To create a multifile table, you must include either a primary key storage area
specification or at least one secondary index storage area specification, or both.
Stand-alone storage areas can have data format RSM (which means that the storage
area can contain both data and index pages) or data format RSM-DATA-ONLY (which
means that the storage area can contain only primary key data pages).
If you plan to store only data pages in the file, you should specify RSM-DATA-ONLY.
If a table has only one storage area associated with it, it must have data format RSM.
Primary key and secondary index storage areas should have data format
RSM-INDEX-ONLY.
If the table is created with standard SQL syntax without a storage area specification,
the resulting storage area has data format RSM.
Storage area names need not be unique. For more information about storage area
data formats, see the Repository for ClearPath OS 2200 Programming Reference
Manual.
Partitioning is specified using CREATE TABLE syntax. RDMS requires that the user
explicitly specify storage areas on the CREATE TABLE command in order to use
partitioning (implicit storage areas are not supported). RDMS requires that the user
explicitly specify the primary key. Implicit primary keys are not supported.
Note: If the primary key or any index key is partitioned, the table is called a
partitioned table. If a table is a partitioned table, the primary and all indexes must be
partitioned. The primary key and any index of a partitioned table are not allowed to
share storage areas.
Constraints
The column definition must appear before any constraint that uses that column.
Check Constraints
The number of predicates in the check constraints, both column and table, cannot
exceed 255. That is, the sum total number of predicates in all column and table
constraints cannot exceed 255.
If you plan to use a table as the parent table in a foreign key relationship related by the
primary key, you must declare all primary key columns with the NOT NULL clause.
A null in a primary key column is treated as being greater than any non-null in the
column in determining the ascending ordering of the key.
Default Clauses
If the column is defined as NOT NULL, the default clause for this column cannot be
NULL.
If the column is defined to allow nulls and the default clause is not used, the value is
by default NULL.
If the data type for the column is exact numeric, the default clause for this column
must be an exact numeric value.
If the data type for the column is approximate numeric, the default clause for this
column can be either an approximate or exact numeric value.
Foreign Keys
A foreign key provides consistency between tables. It establishes a relationship
between the primary key or unique constraint of one table (parent table) and one or
more columns in a second table (child table). If you specify a foreign key in the
CREATE TABLE or ALTER TABLE statement, one or more columns in one table (child
table) is dependent on the primary key or unique column of another table (parent
table). You cannot create a table with a foreign key that refers to a nonexistent table
or column.
• An unowned table can have a foreign key only if it refers to another unowned
table, or if data access control is inactive, or if the REFERENCES privilege is
granted to PUBLIC.
• A table in an owned schema cannot have a foreign key that refers to a table in an
unowned schema, and vice versa.
A child table’s row satisfies the foreign key constraint if it meets one of the following
conditions:
When you access RDMS through MRI, use the user's MAPPER user ID as the basis for
table access. When accessing RDMS through TIP, use the TIP user ID (available in Exec
level 41R1 and higher) as the basis for table access.
Access Control
Your site may want to establish control over who has access to data. For example,
one user may be granted permission to retrieve data from a table, but may not be
granted permission to update any of the data.
To control access to data in tables in unowned schemas, follow these two steps:
A table without a specified owner is essentially a “public” table. This means that every
user with access to the database can access and modify the structure and contents
for such a table. Privileges can be neither granted nor revoked for tables without an
owner. A table without an owner is designated in the repository by a user ID entity
name of PUBLIC.
The table owner is identified by a user ID. This is the same user ID used to access the
system. RDMS does not verify the existence of the user ID specified in the OWNER IS
clause on the system or whether data access control is active. If the user ID does not
exist, the table is inaccessible to other users until the user ID is created on the local
database system. To establish the user ID of the run executing the CREATE TABLE
statement as the owner of the table, specify OWNER IS USER.
When you have specified an owner for a table and ensured that data access control is
active, use the GRANT and REVOKE statements to specify which users can access a
table and for what purpose (for example, retrieval and update).
You can suspend data access control by specifying DATA ACCESS CONTROL IS
INACTIVE.
• If the table owner deactivates access control, RDMS ignores the authorization
history. This allows all users all types of access. If the owner later reactivates
access control, RDMS resumes enforcing all access privileges as they were when
access control was deactivated. (You cannot execute the GRANT and REVOKE
statements while access control is deactivated.)
• UPDATE and DELETE are privileges that are effective only when the user also has
SELECT privileges for the tables involved. DELETE ALL is an exception; it does not
require the SELECT privilege because it deletes rows without looking at them.
• The authorization table is also a relational table. This means that to use GRANT and
REVOKE, you must specify the UPDATE clause in the BEGIN THREAD statement
that begins the session. Because the authorization table is recoverable, you must
use some recovery option other than NONE on the BEGIN THREAD statement.
You can use implicit BEGIN THREAD statements to begin sessions in which you
use the GRANT and REVOKE statements.
• If you use the ALTER TABLE statement to transfer ownership to another user ID,
RDMS does not delete the existing authorization history unless the new owner
revokes all privileges from the old owner.
You do not have to take special steps to control access to tables that reside in owned
schemas. These tables are implicitly access control active and implicitly owned by the
owner of the schema. If you want to establish public access to a table in an owned
schema, you can grant all privileges to PUBLIC. Access control on tables in owned
schemas cannot be deactivated, nor can the ownership of these tables be transferred.
For more information about owned and unowned schemas, see 6.10.
Records in a global temporary table are local to the thread. No other thread can see
these records. A single thread can have multiple versions of a temporary table active
concurrently.
There are never any locking conflicts with other threads over records in temporary
tables. RDMS internally treats the global temporary table as if it is explicitly locked in
EXCLUSIVE UPDATE MODE. All explicit locks on temporary tables are ignored.
A global temporary table is empty when first referenced. When a thread first
references the table, RDMS allocates a storage area for the table. This storage area is
visible only to the thread. The storage area is neither recovered nor audited.
Records can be inserted, updated, deleted, or retrieved from this table, using the
same SQL statements as with a “permanent” persistent base table; however, such
updates can be done whether the thread is read-only or updatable.
There are never any conflicts with other users of the same temporary table, because
all users have their own copies of the table.
• The table is empty (has zero records) when first referenced by the thread.
• If you specified ON COMMIT PRESERVE ROWS, the records in the table remain
after commit processing; otherwise, all records in the table are deleted on a
commit.
• If you specified ON ROLLBACK PRESERVE ROWS, the records in the table remain
after rollback processing; otherwise, all records in the table are deleted on a
rollback.
• A temporary table is emptied at END THREAD and the storage area is destroyed.
• If a rollback occurs during the update to a temporary table, all records within that
temporary table are deleted, regardless of whether ON ROLLBACK PRESERVE
ROWS was specified.
• When the user ID changes (for example, TIP multiple-inital), all records are
removed from all temporary tables even if PRESERVE ROWS was specified.
There is only one temporary table per storage area. The DELETE ALL statement for a
temporary table is therefore very efficient, because it simply reinitializes the file
control information.
• A temporary table cannot be used within the step that created the table definition.
• A temporary table cannot be altered (CREATE INDEX, DROP INDEX, ALTER TABLE).
To perform such an alteration, you must drop the table and create the table again
with the new definition.
• A temporary table definition cannot be dropped by a thread that has materialized
that table. If you want to drop a temporary table, the DROP TABLE statement
must be the first reference to the table within the thread.
• A temporary table cannot contain BLOB columns.
• It is not possible to specify separate storage areas for index and data pages or for
secondary indexes.
• Temporary tables cannot be partitioned.
This section contains reference information about the following SQL statements:
7.1.1. Syntax
CREATE TRIGGER [schema-name.]trigger-name
[REFERENCING
{ SQL-procedure-statement |
Note: The RDMS statements ALTER TABLE, CREATE INDEX, DROP INDEX, DROP
PROCEDURE, DROP FUNCTION, DROP TABLE, and DROP VIEW can cause triggers
to be implicitly dropped. The implicit dropping of triggers can be prevented through
the use of the UREP configuration attribute RDMS-TRIGGER-DROPPING. RDMS-
TRIGGER-DROPPING is set to CASCADE by default. CASCADE allows RDMS to drop
any triggers that reference an object which is dropped or modified. Setting
RDMS-TRIGGER-DROPPING to RESTRICT causes any RDMS statement to fail if it
would cause the implicit dropping of a trigger.
where:
schema-name
is the name of the schema to contain the trigger. If you do not specify a schema-
name, the current default qualifier is used as the schema name for the trigger.
trigger-name
is the name of the trigger. The name must be unique among all triggers defined for
this schema. Schema and trigger names must be valid names as defined in 2.2.1.
BEFORE
indicates that the trigger is executed prior to processing the delete, insert, or
update statement which activated the trigger. A BEFORE trigger can never modify
the database. It can modify the value of data items on their way to the database,
however. The SQL-procedure-statement(s) within a BEFORE trigger may not
include a delete, insert, or update statement.
AFTER
indicates that the trigger is executed after processing the delete, insert, or update
statement which activated the trigger. An AFTER trigger can modify the database.
There are no restrictions on the SQL-procedure-statement(s) beyond those
discussed later in this section. Because an AFTER trigger can do database updates
other triggers may be executed. Care should be taken in the use of AFTER triggers
to avoid introducing multiple recursive triggers or the excessive nesting of
cascading triggers.
table-name
is the name of the table, optionally qualified by the schema-name, to which the
trigger applies, it must adhere to standard RDMS naming conventions (see 2.2.1).
Version name is not allowed. In addition, table-name cannot be the name of a
view.
REFERENCING OLD ROW and REFERENCING NEW ROW may be specified at most
once in a trigger definition. See the tables in this section for rules pertaining to
OLD and NEW ROW referencing.
• For a before trigger, the column values of the NEW ROW reflect the values
that are about to be applied to the database but before foreign key and
constraint checking. These values can be modified by the before trigger.
• For an after trigger, the column values of the NEW ROW reflect the values that
were applied to the database.
In either case, the column values in the NEW ROW image can be referenced by
specifying correlation-name.column-name in the trigger body. The
correlation-name.column-name references can be made wherever an sql-variable
is allowed in a statement in the trigger body as long as the correlation-
name.column-name is not modified by the statement in an AFTER trigger.
RDMS obtains the OLD TABLE table-alias information in the following manner: A
snapshot of the candidate rows of the target table, which are affected by the
user’s data modification statement, is taken. This snapshot is taken prior to the
actual modification of any information in the database. The snapshot is then
viewable as if it were a read-only, temporary table.
RDMS obtains the NEW TABLE table-alias information by applying the user’s data
modification statement to the candidate rows for the statement, creating a NEW
TABLE alias-name snapshot. The rows of the NEW TABLE snapshot reflect the
effect of the user’s data modification statement on the database, plus any update
to NEW ROW made by BEFORE ROW triggers.
The rows of the NEW TABLE snapshot do not reflect the effect of any changes
made directly to the table by this trigger, or any other triggers that may have been
invoked during the processing of the user’s data modification statement. The NEW
TABLE snapshot is viewable as if it were a read-only, temporary table.
correlation-name-n
is an identifier that provides a means to uniquely identify the before or after target
row. It must adhere to standard RDMS naming conventions (see 2.2.1). The name
cannot be the same as any other correlation-name or alias-name defined within
the trigger.
References to the values in the OLD ROW or NEW ROW are made by referencing
the associated correlation-name and the desired column within the row (for
example, old_row.column-name.) Note that an unqualified reference can also be
resolved to a column in the BEFORE or AFTER target row. These references can
be made wherever an SQL variable is allowed in the trigger body, with the
following exceptions:
table-alias-n
is an identifier that provides the only means to reference the set of affected rows
of the target table. Table aliases are used for obtaining information over a range of
values; they are not designed to handle values from a single row. They must
adhere to standard RDMS naming conventions (see 2.2.1). The name cannot be the
same as any other alias-name or correlation-name defined within the trigger.
References to the values in the OLD TABLE or NEW TABLE are made by
referencing the associated table-alias through the use of a SELECT statement. For
example
Neither the OLD TABLE nor the NEW TABLE table-alias can be the subject of a
random or updatable cursor or of a data modification statement.
SQL-procedure-statement
is either a single statement or the set of statements that perform the activity for
this trigger. In either case, each statement must only be from the set of
statements allowed within a routine definition. See 4.11 for more information.
• “Reference” means that the trigger can use the value of an old or new row
column or retrieve rows from a table.
• “Modify” means that the trigger can change the value of a new row column, or it
can delete, insert, or update rows in a table.
• “NA” means “not applicable.”
Trigger General
Event Old Row New Row Old Table New Table Tables
Trigger General
Event Old Row New Row Old Table New Table Tables
Trigger General
Event Old Row New Row Old Table New Table Tables
Trigger General
Event Old Row New Row Old Table New Table Tables
7.1.3. Examples
Example 1
The following example shows the use of a BEFORE statement trigger. If you attempt
to perform an insert on table t1 and it is not during normal business hours, the trigger
(and the INSERT statement) are terminated with an error message.
Example 2
The following example shows the use of an AFTER statement trigger which also
contains a single SQL-procedure-statement.
Example 3
This example shows the use of a BEFORE row trigger. The trigger ensures that vendor
information in newly inserted rows is accurate and consistent by obtaining that
information from an approved source (the vendors table):
Example 4
The next example shows the use of an AFTER ROW trigger. The trigger ensures that if
a change is made to the vendor information in the vendors table; then the change is
also reflected in the appropriate rows of table t2:
Example 5
This example shows the use of an AFTER STATEMENT trigger that references the old
table definition and modifies a general table. The trigger implements a cascading
delete from a parent table to a child table. If a record is deleted from the
personnel_table, the parent table, the record in the softball_table, the child table, with
an equivalent emp_number is deleted, if it exists. The trigger is an alternative way to
implement foreign key cascading delete functionality. When the table to which the
trigger applies is different from all the tables updated by the trigger; the trigger is not
copying a self-referencing foreign key.
Commit
If you commit the run unit, RDMS stores the trigger in the database and the trigger
becomes active.
Cursors
You cannot create a trigger if there is an open cursor on the target table of the trigger.
Dropping a Trigger
Use the DROP TRIGGER statement to remove a trigger from the database.
IPF SQL
When you submit a CREATE TRIGGER statement from an IPF SQL session, do not
place a semicolon after the final END statement. Do not include any SQL comments in
the trigger definition.
JDBC
When you submit a CREATE TRIGGER statement through JDBC, do not place a
semicolon after the final END statement. Do not include any SQL comments in the
trigger definition.
Ownership
A trigger can only be created in an owned schema. It can reference objects in other
schemas, but if the referenced object is owned, it must be owned by the creator of
the trigger.
Rollback
If you issue a rollback command before committing a trigger definition, the trigger is
never available to other users.
System Tables
You cannot create a trigger whose target table is an RDMS system table.
Table Versions
A trigger is always associated with a specific table definition, referred to as the target
table of the trigger, and never with a specific table version.
7.2.1. Syntax
SQL 92 Syntax (Entry Level)
CREATE VIEW [schema-name.]view-name [(column-name [,column-name]...)]
AS query-specification
AS query-specification
where:
schema-name
is the name of the schema containing the view. If you omit the schema name,
RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses the
default schema name RDMS or the value of the user-id of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAUL-QUALIFIER. For additional information see the Repository for
ClearPath OS 2200 Administration Guide.
view–name
is the name of the view following the naming conventions in 2.2.1. Version names
are not allowed since only one definition exists for all versions of the same view.
column-name
is the name or names for the columns. If omitted, the default column names for
the view are the same as the column names from the select list of the query
specification. Column names are mandatory when the select list contains an
arithmetic operation, a function, a constant, or duplicate column names.
Also, if you use column names, they must be valid names and unique within the
column name list:
query-specification
is a query specification as defined in 2.7, except that it cannot contain an
embedded variable, parameter marker, or placeholder variable.
Also, since view definitions are not bound to specific versions of underlying
tables, the query specification cannot refer to a specific version of a table (that is,
the optional :version-name portion of the table specification as described in 2.2.2
is not allowed).
7.2.2. Example
The following example defines a view based on table HOUSES:
Nesting Views
Views can be made up of views or any combination of views and tables.
Read-Only Views
Views can be either updatable or read-only. A view is read-only if the CREATE VIEW
statement includes at least one of the following characteristics:
You can use the INSERT statement on updatable views in either of two cases:
You can use the DELETE statement on updatable views that include all columns of the
underlying table.
UREP Considerations
The definition of the view stored in the repository consists of the CREATE VIEW
statement text. Since the view syntax is saved in the repository in 80-character
segments, you can improve the readability of UREP reports on view definitions by
segmenting the statement into 80-character lines.
01 COMMAND.
02 FILLER PIC X(80) VALUE IS
'CREATE VIEW V1_HOUSE ' .
02 FILLER PIC X(80) VALUE IS
'(VHNO,VLOC) ' .
02 FILLER PIC X(80) VALUE IS
AS SELECT HNO, LOC FROM houses ' .
02 FILLER PIC X(80) VALUE IS
'WHERE PRICE > 150000;' .
Recompilation Errors
A recompilation error is returned at execution time for views that are referenced by
programs that use portable ESQL, if the view was not also created according to the
rules of portable ESQL.
Joined-Table
CREATE VIEW cannot include any joined-table.
For example, suppose table ORDERS contains the column MONTH that is defined to
contain a 2-digit decimal value in the range 1 to 12. MONTH is declared as a 2-digit
decimal number with no digits after the decimal point. You can enforce the constraint
by building the following view:
By using view VERIFIED_ORDERS instead of table ORDERS, you force all values of the
column MONTH to be in the range 1 to 12.
Suppose table ORDERS also contains a column PRICE that is defined to contain a
7-digit decimal value with 2 digits after the decimal point. Creating the following view
illustrates how CHECK OPTION works:
Suppose table ORDERS also contains a column QUANTITY that is defined to contain a
4-digit numeric value. Another view is created as follows:
View Security
View security provides an effective way to control access to a distinct subset of a
table's rows and columns. For example, you can create a view that lets managers see
personnel records, but only for employees in their own departments.
To activate view security for unowned schemas, use the WITH ACCESS CONTROL
clause on the CREATE VIEW statement. After activating view security, use the GRANT
and REVOKE statements to control view access.
You can also activate view security by creating the view within a CREATE SCHEMA
statement, in which case data access control is implicitly active. View security is also
implicitly activated when you create a view within an existing owned schema.
View security is similar to table security, but with the following differences:
• No view equivalent of ALTER TABLE exists. This means that the only way to
activate view security for unowned schemas is to use the WITH ACCESS
CONTROL clause of the CREATE VIEW statement. If you omit the WITH ACCESS
CONTROL clause and later wish to activate security on that view, you must drop
the view and create it again.
• You cannot create a view unless you have SELECT privileges on all tables and
views named in the CREATE VIEW statement. This privilege cannot be obtained
from a role to which the user-id creating the view is a member. It must be
explicitly granted to the user-id creating the view or explicitly granted to PUBLIC,
or the creator of the view must be the owner of the table.
• RDMS automatically drops a view if its owner loses SELECT privileges to any of its
underlying tables or views.
• RDMS automatically drops a view if any of its underlying tables or views is
dropped. For further information about automatically dropping views, see 7.11.3.
• If a view is updatable, the owner's access rights to the underlying tables and
views at view creation determine the owner's access rights to the view. For
example, if you have INSERT and UPDATE but not DELETE privileges over one of
the underlying tables or views, you also have INSERT and UPDATE but not DELETE
privileges over the view you created. If you later acquire DELETE privileges, you
must drop the view and create it again to obtain DELETE privileges for it.
• If a view was created using the WITH ACCESS CONTROL clause, the view owner
can grant any privileges the owner held under the WITH GRANT OPTION clause
when the view was created. For example, if you have DELETE privileges without
the WITH GRANT OPTION privilege on one of the underlying tables or views at the
time you create a view, you cannot grant DELETE privileges on the view to other
users. If you later obtain DELETE privileges with the WITH GRANT OPTION
privilege, you must drop the view and create it again before you can grant DELETE
privileges to other users.
• If the view being created is in an owned schema, the underlying tables and views
must also be created within an owned schema.
• If a view is read-only, no one, not even the owner, can have INSERT, UPDATE, or
DELETE privileges over it.
• If someone creates a view and does not specify WITH ACCESS CONTROL, all
users get all privileges the owner held under the WITH GRANT OPTION clause at
the time the view was created. For example, if the owner held SELECT and
UPDATE privileges, but had the grant option only on the SELECT privileges, all
other users can fetch from the view, but only the owner can update it.
• If a view is in an unowned schema, the owner of the view is always the user-id
that created the view. If a view is in an owned schema, the owner of the view is
the owner of the schema. You cannot transfer ownership to any other user-id.
• Only the owner of an owned schema can create a view in that schema.
7.3. DEBUG
Use the DEBUG statement to check the syntax of SQL statements without actually
executing them, or to dump internal information to help you to evaluate problems.
PARSE │ EXECUTE }
where:
DUMP
instructs RDMS to dump the named data structure specified in the dump
option on all subsequent statements until a DEBUG NODUMP statement
instructs RDMS to stop.
NODUMP
instructs RDMS to stop dumping the named data structure specified in the
dump option.
dump-option
is the name of an internal RDMS data structure:
COMMAND MODULE
DATA PACKET
REQUEST PACKET
RDMCA
RSP PACKET
WORK AREA
ALL Dumps (or quits dumping) all of these data structures.
SIZES Valid only for the interpreter interface, produces a
report of D-bank space allocation for the RSA work
area for Universal Compiling System (UCS) programs.
This information is useful when using the RSA$INIT
subroutine. For more information about RSA$INIT, see
the reference manual for the programming language
you are using.
STUB
instructs RDMS only to parse the statements. Use STUB to check syntax
without executing the statements.
NOSTUB
cancels DEBUG STUB. When you use DEBUG STUB, keep in mind that some
statements depend upon execution of other statements. For example, if you
begin a thread, execute DEBUG STUB and then execute an END THREAD
statement, the thread is still active. You must execute DEBUG NOSTUB before
the END THREAD statement if you want the thread to terminate normally.
PARSE
is equivalent to the following three statements:
DEBUG STUB
DEBUG DUMP COMMAND MODULE
DEBUG DUMP REQUEST PACKET
EXECUTE
is equivalent to the following three statements:
DEBUG NOSTUB
DEBUG NODUMP COMMAND MODULE
DEBUG NODUMP REQUEST PACKET
7.3.2. Examples
You can use the DEBUG STUB statement to test the syntax of a statement without
executing it.
DEBUG STUB
FETCH NEXT cursor5 INTO $p1, $p2
RDMS returns error status 0000 (no errors) without returning data from the database.
No error is returned for fetching from an undeclared cursor because the FETCH
statement was only parsed, not executed.
Assume the following statement where you forget to separate FETCH and NEXT:
RDMS returns error status 0400 (unknown statement) and error column 1.
Threads
You can execute the DEBUG statement when no thread is active.
Dynamic ESQL
You can use the DEBUG statement in dynamic ESQL only in the EXECUTE IMMEDIATE
statement. You cannot use a PREPARE statement to prepare and execute it.
Tracing Execution
The DEBUG DUMP statements print information about the compilation of SQL
statements.
To trace the actual execution of SQL statements, use the UDS Control trace control
(TRCCTL) program. For more information, see the Universal Data System
Administration and Support Reference Manual.
To trace SQL statement compilation that occurs during program execution (for
example, interpreter interface or dynamic ESQL statements), use the dynamic form:
DEBUG SIZES
Information produced by this option is valid only for UCS interpreter interface
programs.
The following DEBUG commands, with the noted exceptions, produce entries in the
UDS trace file in this situation:
The use of DEBUG STUB will not result in debug information being written to the UDS
trace file.
To write debug information to the UDS trace file, but not to the user’s PRINT$ file,
issue DEBUG DUMP NOPRINT.
Within a multi-activity program, the first DEBUG DUMP statement must be DEBUG
DUMP NOPRINT. The reason is, the writes of DEBUG DUMP information to PRINT$ are
not synchronized and can cause the program to abort.
7.4.1. Syntax
SQL 92 Syntax (Entry Level)
DECLARE cursor-name CURSOR
FOR query-expression
[ ORDER BY sort-specification-list ]
[ FOR ] query-expression
[ ORDER BY sort-specification-list ]
[ WITH DESCRIPTION ]
[ FOR ] query-expression
| [ WITHOUT HOLD ]
| [ WITHOUT RETURN ]
[ ORDER BY sort-specification-list ]
Note: The DEFINE CURSOR form is not allowed in ESQL, routines, or triggers.
where:
cursor-name
is the name for the cursor. It must be a valid name as defined in 2.2.1.
query-expression
is a query, which can include query specifications, the set operators
UNION and UNION ALL, and query terms, in the form
where:
query-term
is a separate query specification or a subexpression in parentheses of the
query expression, in the form
{ query-specification │ (query-expression-order-fetch) }
Where:
query-specification
is as defined in 2.7.
query-expression-order-fetch
query-expression
[ORDER BY sort-specification-list]
[FETCH FIRST m ROWS ONLY]
UNION [ALL]
lets you derive a result table by combining two other result tables. The
result of a UNION operation is the set of all selected rows in either table
with duplicate rows eliminated. Two rows are duplicates if each value in
the first is equal to the corresponding value in the second. Two null values
are considered equal. The result of a UNION ALL operation contains all
selected rows from both tables.
Set operations cannot be nested by parentheses deeper than 10 levels.
The select list of a UNION operand can contain column-specifications or
all columns of the table in their defined order (table-specification.*
[see 2.7]), constants, arithmetic expressions, and functions. Corresponding
columns in UNION operands must have identical data types, lengths, and
precision (if applicable). UNION operands do not have to be identical with
respect to whether they allow NULL values.
The select list of a UNION operand can also contain constants, arithmetic
expressions, and functions. Select lists of UNION operands are usually
homogeneous, which means that all corresponding positions contain the
same expression and that all items in the expressions have the same data
type, length, and precision (if applicable).
Heterogeneous select lists are allowed, provided that corresponding
positions in the UNION operands have identical internal RDMS data types.
The description of the GET DESCRIPTION statement (see 8.9) describes
external, not internal, data types, length, and precision (if applicable).
It is frequently not possible to create nonhomogeneous select lists that
meet these criteria. An attempt to use nonhomogeneous select lists can
result in an error regarding a data type mismatch, even though the GET
DESCRIPTION statements of the select lists are identical.
UNION operands of type CHARACTER must have identical character set
and collation definitions to be mutually comparable. The resulting columns
have no associated column names; therefore, ORDER BY clauses must
specify unsigned integers.
The result of a DECLARE CURSOR statement is a read-only table if UNION
[ALL] is specified. The cursor cannot contain the UNION [ALL] operator
and a FOR UPDATE OF clause.
sort-specification-list
are the sort specifications, separated by commas, in the form
[ COLLATE collation-name ]
[ ASCENDING │ DESCENDING ]
where:
column-specification
must reference columns contained in tables listed in the FROM clause
or be the name given to a selected expression by the AS title-name
clause.
unsigned-integer
specifies the position of the element in select-list if one of the
columns to sort is not a column specification but an expression (like
MAXPRICE * 1.1), or if the column is the result of a UNION operation.
collation-name
is the collation to use for ordering the values. The collation here is
independent of the column definition. The column’s character set must
match the collation's character set. This clause applies only to columns
with data type CHARACTER.
scalar-bif-reference
is a reference to a scalar built-in-function. A column must be
referenced in each scalar-bif-reference in the ORDER BY clause.
cursor-sensitivity
defines whether updates made by this thread, after the cursor is opened, are
to be included as part of this cursor.
ASENSITIVE means the cursor may or may not include updates made by this
thread. The default sensitivity is ASENSITIVE.
INSENSITIVE means the cursor does not include any updates made by this
thread after the cursor was opened. An INSENSITIVE cursor is always
read-only and nonscrollable.
SENSITIVE means the cursor includes all updates made by this thread,
provided the cursor’s currency has not already passed the updated record.
SEQUENTIAL
(default) lets you access the rows only in their defined sequence.
RANDOM or DIRECT
lets you retrieve rows sequentially and at random. (RANDOM and DIRECT are
synonymous.) If you specify RANDOM, you can use the LOCATE statement to
position the cursor on a particular row by specifying its primary key. You can
then execute a FETCH CURRENT statement to retrieve the row.
You cannot specify RANDOM or DIRECT if the cursor contains a joined-table
specification, INSENSITIVE, FETCH FIRST m ROWS ONLY, or OPTIMIZE FOR p
ROWS.
FOR UPDATE
indicates that the cursor is positional. The following conditions apply to
positional cursors:
• The FOR UPDATE clause cannot be used if the cursor is random access or
read-only.
• RDMS applies currency safeguards to the rows as they are fetched. This
means that when the cursor definition includes the FOR UPDATE clause
and a row is fetched using the cursor, RDMS automatically locks the row
until a different row is fetched.
• The positional cursor UPDATE or DELETE statement can be used without
the FOR UPDATE clause, but currency safeguards are not enforced when a
fetch is performed. RDMS does not require the use of the FOR UPDATE
clause when you use the positional UPDATE or DELETE statement;
however, its use is recommended to improve performance.
For information on performance with positional statements, refer to the
Relational Database Server for ClearPath OS 2200 Administration Guide.
column-name-list
is a list of the column names that can be updated using the UPDATE
statement with the WHERE CURRENT OF CURSOR clause. The list is
composed of column specifications.
• The columns listed in the FOR UPDATE clause must also be listed in the
query specification.
Note: FETCH PRIOR, FETCH LAST, and LOCATE cannot be executed against a
nonscrollable cursor. Therefore, cursors containing FETCH FIRST m ROWS ONLY or
OPTIMIZE FOR p ROWS may only be used by FETCH FIRST, FETCH NEXT, and
FETCH NEXT n statements.
WITH DESCRIPTION
informs RDMS that you want information about the cursor you are declaring.
Retrieve this information with the GET DESCRIPTION statement. The
information includes
• The fully qualified table and column name of each item in the select list
unless it is an arithmetic expression or constant, or if the cursor is a
UNION operation. RDMS returns blanks if it encounters an arithmetic
expression. RDMS does not return a fully qualified table and column name
for an item specified with a title name. Instead, it returns only the title
name.
• The data type of each item.
• The size of each item: number of characters for a CHARACTER or
NCHARACTER column; the total size (including one character for the sign),
and number of fractional digits for a DECIMAL column; the size (number of
digits plus 1 for sign), scale, and binary precision for a NUMERIC column;
and the number of bytes of storage for an INTEGER, SMALLINT, REAL,
FLOAT, or DOUBLE PRECISION column.
• A flag indicating whether nulls are allowed in each item.
• A flag indicating whether each item is part of the table’s primary key.
7.4.2. Examples
Example 1
The following example defines a set of rows by joining selected columns from tables
CUSTOMERS and HOUSES. The cursor is restricted to rows in which the asking price
of the house does not exceed the maximum price a customer is willing to pay.
Example 2
The preceding example is for an inner join operation. The following examples illustrate
the use of outer join with two tables.
The first example shows all the customers and the houses that are available in the
desired locations, if any.
DECLARE c1 CURSOR
SELECT cname, maxprice, desiredloc, price, description
FROM customers LEFT OUTER JOIN houses
ON customers.desiredloc = houses.location
The second example shows all the houses and the customers who are interested in
living in those locations, if any.
DECLARE c1 CURSOR
SELECT cname, maxprice, location, price, description
FROM customers RIGHT OUTER JOIN houses
ON customers.desiredloc = houses.location
Example 3
An outer join is defined as a binary operation only (that is, one that involves only two
tables). Therefore, performing an outer join operation on three or more tables may
need the parentheses to represent the nesting of such binary operation. Without the
parentheses, the outer join operation is performed from left to right as the tables are
defined in the query specification (FROM clause).
Here are examples of a three-table outer join. To do this we need a third table:
Realtors
Joining the tables in the LOCATION column results in a table of both realtors and
available housing in the customer’s desired location, if any.
The next query specifies the WHERE condition in addition to the previous query
example. The WHERE clause condition is to choose records that satisfy either that the
house price is no more than the customer’s maximum price, or that the customer
name is non-null (the house may or may not exist for the customer).
The FROM clause operation takes place first, after which the WHERE clause condition
is evaluated against the result of the FROM clause operation.
Joining the tables in the LOCATION column results in a table of all realtors residing in
the location with houses for sale, together with customers interested in that location,
if any.
Example 4
This example illustrates the use of a title name and position specification in the
ORDER BY clause:
DECLARE c1 CURSOR
SELECT cno, cname, maxprice AS cost
FROM customers
ORDER BY cost
Example 5
This example illustrates how to select house numbers, their locations, and
commissions. The rows are sorted in ascending order of commissions and
alphabetically by order of location.
DECLARE by CURSOR
SELECT hno, price * 0.06, location
FROM houses
ORDER BY 2, location
Example 6
This example uses the UNION operator to select all combinations of prices and cities
(without duplicates) from the first 200 rows of both tables, CUSTOMERS and HOUSES.
The rows are sorted alphabetically by order of the name of the city.
DECLARE pl CURSOR
(SELECT maxprice, desiredloc FROM customers
WHERE cno < 'C201') UNION
(SELECT price, location FROM houses
WHERE hno < 'H201')
ORDER BY 2
Example 7
This example illustrates an invalid union because the corresponding columns PRICE
and DESIREDLOC are different data types:
DECLARE c1 CURSOR
(SELECT cno, desiredloc FROM customers) UNION
(SELECT hno, price FROM houses)
Example 8
This example illustrates how to create more comprehensible output by using
constants:
This example is matching the houses being offered for sale with what the buyer is
looking for by location. By adding a literal constant to each SELECT clause, the
resulting table treats the literal as if it were a column. You can easily determine the
origin of rows in the result. Both literals must have the same number of characters (in
this example, 13); otherwise, RDMS returns an error.
Example 9
The following example defines a set of rows by joining selected columns from the
tables CUSTOMERS and HOUSES. The cursor is restricted to rows in which the asking
price of the house does not exceed the maximum price a customer is willing to pay,
but will not consider any houses that cost less than 350000.
Example 10
The following example defines a set of rows by joining selected columns from the
tables CUSTOMERS and HOUSES. The HOUSES table is filtered through the view
expensive_houses. The cursor is restricted to rows in which the asking price of the
house does not exceed the maximum price a customer is willing to pay, but will not
consider any houses that cost less than 350000.
Example 11
The following example defines a set of rows by joining selected columns from the
tables CUSTOMERS and HOUSES. The HOUSES table is filtered through the derived
table expensive_houses. The cursor is restricted to rows in which the asking price of
the house does not exceed the maximum price a customer is willing to pay, but will
not consider any houses that cost less than 350000.
Example 12
This example shows how to write a subquery that returns only the top 10 rows. This
query uses a table called enquiry that contains questions from customers. The query
returns the questions posed by the customers who are willing to pay the most for
their house.
Example 13
This example shows the illegal usage of ORDER BY within a query-expression. ORDER
BY and FETCH FIRST m ROWS ONLY may only be at the end of the DECLARE CURSOR
statement or as part of a query-expression that is enclosed within parentheses.
Limits
The highest level (outermost) query expression can include up to 14 base or global
temporary tables. If a base or global temporary table is specified more than once,
each specification counts towards the maximum of 14.
If a view is specified in the query expression, it does not count towards this limit;
however, each of its underlying base tables does count.
Performance
When you declare a cursor, RDMS analyzes the statement. Depending on the nature
and complexity of the query specification, this can require significant processing.
RDMS also allocates memory to the cursor that is not released until a DROP CURSOR
statement is executed. For more information, see 7.6.
The ORDER BY clause causes RDMS to sort all rows that satisfy the WHERE clause
when the cursor is opened. Opening a cursor with the ORDER BY clause takes longer
than opening a cursor without it.
In most cases, the ORDER BY clause requires RDMS to take a “snapshot” of the
cursor. This is a static image of the data when the cursor is opened. Rows retrieved
from the cursor come from the snapshot. Changes to the selected rows in the
database are not reflected in the snapshot.
If the sort specifications can be satisfied by using the primary key or secondary
indexes, RDMS does not take a snapshot.
Use the EXPLAIN statement to find out whether a snapshot was made for a given
cursor.
Use of the FETCH FIRST m ROWS ONLY and OPTIMIZE FOR p ROWS clauses
improves the performance of fetches.
Multiple Cursors
More than one cursor can be opened at the same time. For more information about
opening a cursor, see 9.4.
Read-Only Cursors
A cursor is read-only if the DECLARE CURSOR statement includes at least one of the
following characteristics:
• A HAVING clause
• An ORDER BY clause
• A FROM clause that references more than one table or view
• A FROM clause that identifies a read-only view (a view that cannot be updated)
• A subquery
• A UNION operation
• Outer joined-table specification
• A FOR READ-ONLY clause
• The INSENSITIVE keyword
• A FETCH FIRST m ROWS ONLY or OPTIMIZE FOR p ROWS clause
• A cursor containing a derived table or CTE is read only.
If these clauses are used together, the FETCH FIRST clause specifies the maximum
number of records that are returned, as usual. If the cursor is not a join, RDMS
optimizes for the minimum of m or p. If the cursor is a join, RDMS optimizes for p
records when searching the first table of the join.
Memory Usage
When a cursor is declared, RDMS allocates memory to retain the required information
about the cursor. When the cursor is opened, RDMS allocates more memory for any
additional required information.
To release this memory when a cursor does not need to be opened or even declared,
use the CLOSE or DROP CURSOR statement.
In the following SQL sequence, the cursor that is opened contains rows from
RDMS.HOUSES:OUTSTATE. The qualifier RDMS and the version name PRODUCTION
are the default values at the beginning of the example.
If the cursor is a sensitive cursor, the alterations can affect the contents of the result
set of the cursor.
Inserted or updated rows can become part of the result set of the cursor, if the
inserted or updated rows still meet the conditions needed to be a member of the
result set. The position of the inserted or updated rows in the result set, relative to
the current cursor position at the time of the inserts or updates, is dependent on the
access path used by RDMS for the cursor. Deleted rows are removed from the result
set immediately and cannot be fetched again, no matter where the cursor is currently
positioned.
Any changes to tables that cause the access path to change could affect a thread that
opens a sensitive cursor and then modifies the tables used by the cursor. The
following operations could change the access path:
For example, when you use the UPDATE Positioned statement to modify a row, and it
still meets the conditions of the cursor, the location of the row can move in the result
set so that the same row can be fetched again on a later FETCH NEXT performed
before the end of the result set is reached.
WITH RETURN can only be specified on cursors declared in the outermost compound
statement of the routine. This means that cursors declared WITH RETURN must be
declared before any other executable statement. Cursors that specify WITH RETURN
are not updatable, and they must also explicitly specify FOR READ ONLY and FOR
RETENTION.
FOR RETENTION and WITH HOLD are synonymous; either one specifies that the
cursor is a retention cursor. WITHOUT HOLD is the default. It signifies that the cursor
is automatically closed whenever the thread is committed.
Cursors declared within routines can reference any parameters of the routine as well
as any SQL variables declared within the same compound statement as the DECLARE
CURSOR or at an outer level of nesting. Cursors declared within triggers can reference
any correlation-name.column-name, as well as any SQL variables declared within the
same compound statement as the DECLARE CURSOR or at an outer level of nesting.
These references are resolved when the routine or trigger is created. Placeholder
variables and parameter markers are not allowed in the DECLARE CURSOR statement.
If either the OLD TABLE or NEW TABLE alias-name of a trigger is the target table of a
cursor declaration, then the cursor must be a read-only cursor. Further, the cursor may
not be declared with the RANDOM or DIRECT keywords.
Note:
The following are nonstandard RDMS syntax extensions:
• [ FOR ] query-expression (that is, optional FOR),
• FOR RANDOM ACCESS
• FOR DIRECT ACCESS
Outer Joined-Table
When a cursor contains outer joined-tables, then the following rules are applied:
1. The default qualifier in effect when the DECLARE CURSOR statement is processed
is implied for any column specification or table specification having no explicit
qualifier.
2. The table specifications in the FROM clause are scanned from left to right for the
first table specification that matches the table specification in the column
specification and that names a table that contains a column of the same name.
A table specification is a match if it is at least as specific as the column
specification's table specification and the explicit names (along with the implied
qualifier) match. For example, Q1.R1 matches Q1.R1 and Q1.R1:V1, but does not
match R1 or R1:V1 unless the default qualifier is Q1.
3. When the cursor is opened, the default version name in effect in any table
specification that lacks an explicit version name is used.
Example
The following is a step-by-step example of how these rules work.
Finally, when the OPEN statement is executed, rule 3 applies. This yields the
following:
Since other statements that can contain a query specification (SELECT INTO, CREATE
VIEW, and UNLOAD) are not opened, rule 3 is applied when the statement is
executed, so the following two sequences are equivalent:
Sequence 1:
USE DEFAULT QUALIFIER rdms
USE DEFAULT VERSION production
SELECT cno, rdms.customers.cname, houses:production.price
INTO :v1, :v2, :v3
FROM rdms.houses:production, customers, houses:outstate
WHERE houses:outstate.price <= maxprice
AND hno > 'H'
Sequence 2:
USE DEFAULT QUALIFIER rdms
USE DEFAULT VERSION production
SELECT rdms.customers:production.cno, rdms.customers:production.cname,
rdms.houses:production.price
INTO :v1, :v2, :v3
FROM rdms.houses:production, rdms.customers:production,
rdms.houses:outstate
WHERE rdms.houses:outstate.price <= rdms.customers:production.maxprice
AND rdms.houses:production.hno > 'H'
Note that the rows are taken from a version of table CUSTOMERS that is different
from the version in the example that uses the DECLARE CURSOR statement.
Placeholder Variables
When you are using placeholder variables in an OPEN statement, the following rules
apply:
For example, the application program variable associated with $P1 in the DECLARE
CURSOR statement’s WHERE clause must match the type and size of $P1 in the
OPEN statement. You should usually use the same application program variables
in both the DECLARE CURSOR and OPEN statements. For character value
assignment considerations, see 2.8.1.
• Before you use the OPEN statement, you must initialize the program variables
associated with the placeholder variables.
DECLARE cursor-name CURSOR FOR select * from table where column = value
FETCH INTO $p1, $p2
DECLARE cursor-name CURSOR FOR select * from table where column = $p1
OPEN cursor-name USING $p1
FETCH INTO $p1, $p2
7.5. DELETE
Use the DELETE statement to delete one or more rows from a table or view in the
database.
7.5.1. Syntax
SQL 92 Syntax (Entry Level)
DELETE FROM table-specification
where:
table-specification
is a table name as defined in 2.2.1.
WHERE
defines the rows to delete. If the WHERE clause is not used, RDMS deletes all
rows of the table. Therefore, you should always use a WHERE clause if you do not
want to delete all of the rows in the table.
CURRENT OF cursor-name deletes the row in the table that corresponds to the
row in the cursor cursor-name where the cursor pointer is currently positioned.
The rules for using the positional DELETE statement are as follows:
ALL [ROWS]
deletes every row in the table.
7.5.2. Examples
Example 1
The following two statements delete all rows from a table:
DELETE houses ALL
DELETE customers
Example 2
The following statement removes a specific row from a table:
DELETE houses
WHERE hno = 'H102'
Example 3
You can also delete rows that meet certain conditions. For example, to eliminate all
customers who are unable to spend at least $40,000 for a house from the database,
enter either one of the following statements:
DELETE customers
WHERE maxprice < 40000
DELETE customers
WHERE maxprice - 40000 < 0
Example 4
The following example deletes only those rows where the value of the PRICE column
is greater than $100,000:
DELETE houses
WHERE price > 100000
Example 5
In the following example, the first FETCH statement returns data on house H101, the
second data on house H102, and the third data on house H103; the DELETE statement
deletes the row for house H103:
If you lock a table in one of the RETRIEVAL modes, RDMS rejects the DELETE
statement.
DELETE ALL
The DELETE ALL statement implicitly locks an entire table in exclusive update mode if
you do not explicitly lock the table with a LOCK statement. If RDMS can lock the table
in exclusive update mode and the deferred recovery option is used and this is the only
table in the storage area, the DELETE ALL statement is very fast and the UDS retention
file space is not exceeded. This is because in this case, RDMS executes the DELETE
ALL statement by reinitializing the file control information. SET AUXINFO OFF further
improves performance. Refer the Relational Database Server for ClearPath OS 2200
Administration Guide for more information.
When you execute a DELETE ALL statement, the UDS retention file (a file maintained
by UDS Control for recovery purposes) might overflow. To prevent this, perform one
of the following actions:
When the table contains a GENERATED AS IDENTITY column, DELETE ALL causes the
IDENTITY sequence to restart with the START/RESTART value. When the table
contains a GENERATED AS partition_id() column, DELETE ALL causes the sequence of
the left-most partition to restart with 1 and all other partitions to restart with their
lowest possible value.
In routines and triggers, the RDMSAUXINFO system variable can be used to obtain this
information (see 4.9.1).
Foreign Keys
When you are deleting rows from a parent table involved in a foreign key constraint,
RDMS checks to ensure that no rows exist in the child table that are related to the
rows being deleted from the parent table:
For DELETE ALL or DELETE with no WHERE clause (that is, deleting all rows from
parent table), RDMS checks to ensure that if rows do exist in the child table before the
deletion, all such rows contain null values for the foreign key columns.
On deleting rows from a table that is the object of a self-referencing foreign key (that
is, a table that is both the parent and child table for the same foreign key constraint),
RDMS checks the foreign key after the deletion.
The cursor must be opened using the OPEN statement and positioned on a row by a
FETCH statement prior to the execution of the DELETE statement.
7.6.2. Example
The following example drops the cursor MATCHPRICE:
Performance
You can drop cursors when they are no longer needed again during a thread.
Dropping cursors frees space used by the thread, which in turn improves the
performance of statements that use cursors (for example, the FETCH statement).
where:
index-name-list
is a list of the names of indexes and unique constraints to be dropped, separated
by commas.
table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.
7.7.2. Example
The following example removes index IX5 from table HOUSES:
Partitions of the index being dropped can be in attached, detached, or hidden states.
Effect on Triggers
The DROP INDEX statement causes triggers to be implicitly dropped if the trigger
references the table. The implicit dropping of triggers can be prevented by using the
UREP configuration attribute RDMS-TRIGGER-DROPPING. RDMS-TRIGGER-DROPPING
is set to CASCADE by default. CASCADE allows RDMS to drop any triggers associated
with the dropped index table. Setting RDMS-TRIGGER-DROPPING to RESTRICT causes
any DROP INDEX statement to fail if it would cause the implicit dropping of a trigger.
Changes made by the DROP INDEX statement have no effect on previously compiled
interpreter interface programs (aside from performance during execution). For more
information, see 2.11.2.
Table Ownership
You must be the owner of the table from which you are removing an index.
where:
schema-name
is the name of the schema containing the table routine. If you omit the schema
name, RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses the
default schema name RDMS or the value of the user-id of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAULT-QUALIFIER. For additional information, see the Repository for
ClearPath 2200 Administration Guide.
routine-name
is the name of the routine. Schema and routine names must be valid names as
defined in 2.2.1.
CASCADE
all routines or triggers that reference the dropped stored procedure or function
are also dropped.
RESTRICT
if the dropped stored procedure or function is referenced by any other routine or
trigger, then the drop fails.
7.8.2. Examples
The first example drops function HOUSES_SCHEMA.SELECT_HOUSES and all other
routines that reference HOUSES_SCHEMA.SELECT_HOUSES:
Ownership
To remove a stored procedure or function from the database, you must own the
schema in which the procedure or function resides.
Threads
The thread in which this statement executes must be update recoverable.
Object Type
Use DROP PROCEDURE to drop a stored procedure. Use DROP FUNCTION to drop a
stored function.
7.9.1. Syntax
DROP ROLE role-name
7.9.2. Examples
DROP ROLE “ROLE-PROGRAMMER”
The DROP ROLE statement must be able to get exclusive use of all table and views
for which the role has privileges. No cursors can be declared over these tables.
* The illustrated syntax is referred to as “RDMS extended syntax” because RDMS extensions
are included in the intermediate level SQL 92 syntax.
where table-list is the table specification (see 2.2.2) indicating which table definitions
to drop, separated by commas. Table specifications cannot include versions. RDMS
drops tables in the order listed.
INCLUDING CONTENTS instructs RDMS to remove any records the table might contain
and then remove the table definition.
7.10.2. Example
The following example drops definitions for tables REALESTATE.HOUSES and
HOUSE-SCHEMA.HOUSES:
Effect on Triggers
The DROP TABLE statement causes triggers to be implicitly dropped if the trigger
references the table. If there are a large number (several hundred) such triggers
referencing the same table, this process of dropping all the triggers in a single thread
may run into D-bank space limitations. See the Relational Database Server for
ClearPath OS 2200 Administration Guide for more information regarding this
situation.
The implicit dropping of triggers can be prevented by using the UREP configuration
attribute RDMS-TRIGGER-DROPPING. RDMS-TRIGGER-DROPPING is set to CASCADE
by default. CASCADE allows RDMS to drop any triggers associated with the dropped
table. Setting RDMS-TRIGGER-DROPPING to RESTRICT causes any DROP TABLE
statement to fail if it would cause the implicit dropping of a trigger.
Foreign Keys
If you wish to drop a table that is the parent of a foreign key, you must first drop the
foreign key or drop the child table. If you are dropping a table in order to redefine it,
you can drop the foreign key relationship instead of dropping the child table or tables.
When the table is redefined and reloaded, you can reestablish the relationship. You
should ensure that the child table is not updated during this process.
Cursors
You cannot drop a table on which a cursor is declared.
Ownership Security
If a table has an owner, only the owner can drop it. All grants on the table are revoked
by RDMS.
Unowned The table must contain zero The records are deleted as part
nonpartitioned records in order to be dropped. of the DROP TABLE operation.
Records are thus not deleted as
part of the drop.
Owned The records are deleted as part The records are deleted as part
nonpartitioned of the DROP TABLE operation. of the DROP TABLE operation.
Partitioned The records remain in the The records are deleted as part
storage area after the DROP of the DROP TABLE operation.
TABLE operation.
Temporary DROP TABLE must be the DROP TABLE must be the
thread’s first reference to the thread’s first reference to the
temporary table. The table is temporary table. The table is
thus not materialized before the thus not materialized before the
DROP TABLE, and no delete is DROP TABLE, and no delete is
necessary. necessary.
The following SQL statement sequence could provide better performance than
DROP table-name INCLUDING CONTENTS:
These statements could perform better because DELETE ALL might only initialize the
file control information, while DROP TABLE removes the records one page at a time.
A global temporary table cannot be dropped by a thread that has referenced that table.
7.11.1. Syntax
DROP TRIGGER [schema.]trigger-name
where trigger-name is the optionally qualified name of the trigger defined in the
database.
7.11.2. Example
The following example drops DROP TRIGGER not_production in the default schema.
Commit
If you commit the thread, the trigger is removed from the database.
Cursors
You cannot drop a trigger if there is an open cursor on the target table of the trigger.
Ownership
You can drop a trigger only if you are the owner of that trigger.
Rollback
If you issue a rollback command, the trigger is retained in the database and remains
active.
Threads
The thread in which this statement operates must be update recoverable.
* The illustrated syntax is referred to as “RDMS extended syntax” because RDMS extensions
are included in the intermediate level SQL 92 syntax.
where schema-name.view-name is the name of the view to drop and follows the
same rules as for table names (see 2.2.2), except that version names are not allowed.
7.12.2. Example
The following example drops definitions for views V1 and V2 under schema S1, and for
view VX under schema S2:
Effect on Triggers
The DROP VIEW statement causes triggers to be implicitly dropped if the trigger
directly or indirectly references the view. The implicit dropping of triggers can be
prevented through the use of the UREP configuration attribute
RDMS-TRIGGER-DROPPING. RDMS-TRIGGER-DROPPING is set to CASCADE by
default. CASCADE allows RDMS to drop any triggers associated with the dropped
view. Setting RDMS-TRIGGER-DROPPING to RESTRICT causes any DROP VIEW
statement to fail if it would cause the implicit dropping of a trigger.
Ownership Security
Only the person who created the view can drop it. All grants on the view are
automatically revoked by RDMS.
• You drop any column in an underlying base table. (This includes base table
columns that are not part of the view.)
• You drop an underlying view or base table.
• The owner of the view loses SELECT access privileges to any underlying base
table through a REVOKE or ALTER TABLE statement.
• Access control is activated for any underlying base table that has an owner
different from that of the view.
• You change the owner of an access-controlled underlying base table, and the
view’s owner is the former owner of the table.
Any other kinds of modifications to the definition of an underlying base table do not
cause the view to be dropped.
Cursors
You cannot drop a view on which a cursor is declared.
This section contains reference information about the following SQL statements:
8.1.2. Example
In the following example, the variables HNO, LOC, and XTALLY can be used in ESQL
statements:
As an extension to standard SQL, RDMS allows variables declared outside the BEGIN
DECLARE to END DECLARE section in ESQL statements.
If the UCS COBOL LEVEL/SQL FLAGGER is turned on, the compiler issues warnings for
variables declared outside the BEGIN DECLARE to END DECLARE section that are used
in ESQL statements.
where ADVANCE and TERMINATE are Step Control options and cause the operating
system to advance or terminate its current Integrated Recovery step. In any case,
RDMS assumes that an END THREAD statement terminates the thread’s step.
• ADVANCE advances the system Integrated Recovery step counter but does not
end the Integrated Recovery step, even though RDMS considers the thread's step
ended.
• TERMINATE ends the current Integrated Recovery step.
If you do not specify ADVANCE or TERMINATE, the run’s VALTAB parameter for
programs is the default Step Control option. For all other programs, TERMINATE is the
default option, unless the program was connected to TIP before the start of the
current step. In this case, specify the default option when connecting to TIP.
8.2.2. Examples
The following example ends the current thread:
END THREAD
The following END THREAD statement, with its TERMINATE step counter option, ends
the current thread as well as the current step recovery counter:
If the thread has uncommitted changes when an implicit END THREAD statement is
executed, the thread is rolled back and a contingency (ER ERR$) is forced. If all
changes made by the thread are already committed when the implicit END THREAD
statement is executed, then the thread terminates normally.
If SFS files are opened in the thread, you must close them before executing the END
THREAD statement.
8.3. EXECUTE
Use the EXECUTE statement to execute a dynamic ESQL statement already prepared
with the PREPARE statement.
where:
statement-name
is the name of the prepared statement to be executed.
USING host-variable-list
imports the values of host program variables into a prepared statement, where
host-variable-list specifies a one-to-one relationship between parameter markers
in the prepared statement and the host program variables.
8.3.2. Example
The following example prepares and executes a DELETE statement:
Repeated Use
You can use the EXECUTE statement zero or more times for each statement you
prepare.
USING Clause
If the prepared statement contains parameter markers, you must use the USING
clause. If the prepared statement does not contain parameter markers, you must omit
the USING clause.
Naming
If the prepared statement is a query specification for the ALLOCATE CURSOR
statement, its name cannot be the same as statement-name in an EXECUTE
statement.
where:
embedded-variable
is a CHARACTER type host program variable that contains one of the following
SQL statements:
string-literal
is a string literal that contains one of the SQL statements just listed.
8.4.2. Example
The following example drops a row from table HOUSES:
No Comments
The EXECUTE IMMEDIATE statement cannot contain a comment.
No Other Variables
The EXECUTE IMMEDIATE statement cannot contain other variables (host program,
embedded, parameter marker, or placeholder).
8.5. EXPLAIN
Use the EXPLAIN statement to direct RDMS to explain the access path it plans to use
for a declared cursor.
8.5.2. Examples
Example 1
The following sequence of SQL statements yields the text that follows in the program
variables associated with $P1, $P2, and $P3:
The program variable associated with $P4 is blank-filled, which means that no further
text is to be returned.
Example 2
In the next example, this cursor declaration places the text that follows in the program
variables associated with $P1, $P2, $P3, $P4, and $P5:
In this case, the WHERE clause has no constants or program variables to help limit the
number of rows that must be retrieved to determine whether they meet the search
condition. RDMS must therefore perform a "brute force search," using each record
from table CUSTOMERS to search table HOUSES, based on the secondary index on
PRICE where PRICE >= the value of MAXPRICE, supplied from the record in table
CUSTOMERS.
Example 3
The next example illustrates the use of additional comparisons:
In this example, table CUSTOMERS is searched using the primary key WHERE
CNO > ‘6000’. The relational storage manager (RSM) performs one additional
comparison on each record (MAXPRICE > 100000) in order to decide whether to return
that record to RDMS.
Example 4
The next example illustrates how the EXPLAIN statement reveals to you whether a
cursor is to be formed by a snapshot. Assume you execute this SQL statement
followed by the EXPLAIN and GETERROR statements:
Example 5
A cursor can sometimes be defined using subqueries. The following example, which
selects all customers who can afford at least three houses, illustrates this:
To understand why the secondary index PRICE is used in an index search for HOUSES,
you must examine the overall retrieval strategy for this cursor. Whenever an outer
reference is made from within a subquery (in this case, CUSTOMERS.MAXPRICE is the
outer reference), a record that satisfies the outer query must be retrieved. This record
is then used to evaluate the subquery. When the subquery is evaluated, the reference
to column CUSTOMERS.MAXPRICE is replaced by a constant from the outer query’s
record. This allows HOUSES.PRICE to be used in an indexed search.
Example 6
A cursor can sometimes be defined by a single group query. The following example,
which finds the average price of the houses on the market, illustrates this:
Example 7
The next example illustrates how RDMS uses an accelerated method to compute the
maximum and minimum housing prices, assuming price is a secondary index. The last
two lines in this example provide the explanation of the record fetch.
Example 8
The next example illustrates how to use the EXPLAIN statement to see whether one
of the fast search methods was used. The cursor must be opened and RDMS must
have fetched records from the cursor in order for this text to be returned.
The EXPLAIN statement issued before the cursor is opened yields the following text:
EXPLAIN fis;
The access path for cursor FIS is shown below:
The relation is MF.HOUSES:PRODUCTION.
Brute force search applied to primary key K1.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
The summary record of the single group is accumulated in RSM.
-----------------------------------------------------------
After opening the cursor and fetching a record, one additional line of text appears in
the output as follows:
EXPLAIN fis;
The access path for cursor FIS is shown below:
The relation is MF.HOUSES:PRODUCTION.
Brute force search applied to primary key K1.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
The summary record of the single group is accumulated in RSM.
The fast indexed search method is used.
-----------------------------------------------------------
Example 9
The following cursor uses the hybrid hash join and yields one EQUIJOIN and one
NON-EQUIJOIN predicate:
Example 10
The following two examples illustrate different settings of RSM PK and RSM SI:
Example 11
The next example illustrates how a cursor uses nested joined-table and the EXPLAIN
command output:
DECLARE c1 CURSOR
SELECT t1.c1, t2.c2, t3.c3, t4.c4, t5.c5, t6.c6
FROM t1,
t5 LEFT OUTER JOIN ((t2 LEFT OUTER JOIN t3 ON t2.c1=t3.c1)
LEFT OUTER JOIN t4 ON t2.c1=t4.c1)
ON t5.t1=t2.c1,
T6
WHERE t1.c1=t5.c1 AND t1.c1=t6.c1 AND t5.c7='abc';
EXPLAIN c1;
Notice that RDMS transforms RIGHT OUTER JOIN to LEFT OUTER JOIN by exchanging
the left and the right table. Therefore, in an EXPLAIN command, it is reported as LEFT
OUTER JOIN.
Example 12
The next example illustrates how the EXPLAIN statement reveals whether a
correlation name is used for the table.
DECLARE c3 CURSOR SELECT veg FROM seed1 t1 WHERE t1.veg <> 'bean';
EXPLAIN c3;
Example 13
When ORDER BY is specified and the rows are fetched in the same order specified by
the ORDER BY statement, a snapshot may not be taken.
Cursor abc returns rows in customers.cno order, this order does not match the order
specified in the ORDER BY clause.
Cursor def returns rows in customers.cno order, this order matches the order
specified in the ORDER BY clause.
Example 14
RDMS takes snapshots for evaluation of ORDER BY, GROUP BY, and subquery, if
needed. Delimiters are used to clarify the reason for which the snapshot was taken.
DECLARE c1 CURSOR
SELECT desiredloc,max(maxprice) as mp FROM customers
GROUP BY desiredloc
HAVING max(maxprice) > (SELECT maxprice FROM customers
WHERE cname = 'Johnson'
FETCH FIRST 1 ROW ONLY)
ORDER BY mp
FETCH FIRST 5 ROWS ONLY;
The first snapshot is for the ORDER BY clause of the outer select statement. The text
following the delimiting dashed line shows that the second snapshot is for the
evaluation of the subquery:
Example 15
The following example defines a set of rows by joining selected columns from the
tables CUSTOMERS and HOUSES. The HOUSES table is filtered through the derived
table expensive_houses. This derived table is implemented as a snapshot. The cursor
is restricted to only the most expensive 10 houses.
Derived table
Reports the value of m from FETCH FIRST m ROWS ONLY clause. When there
was no such clause, this EXPLAIN text is not displayed.
Example 16
The following example defines a set of rows by joining selected columns from the
tables CUSTOMERS and HOUSES. The HOUSES table is filtered through the common
table expression expensive_houses. The cursor is restricted to rows in which the
asking price of the house does not exceed the maximum price a customer is willing to
pay, but will not consider any houses that cost less than 350000. It only considers the
top 10 most expensive houses. If the CTE is referenced only once, it is treated as a
derived table and this is reflected in the explain text.
Example 17
Here, the CTE is referenced in the cursor more than once. Therefore, the CTE is
displayed at the beginning of the explain text.
-----------------------------------------------------------
Relation no. 1 is RDMS.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PK1.
Additional comparisons --> RSM PK : 0, RSM SI : 0, RDM : 1
Relation no. 2 is RDMS.EXPENSIVE_HOUSES.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
A scan is performed.
-----------------------------------------------------------
The relation is RDMS.EXPENSIVE_HOUSES.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
A scan is performed.
-----------------------------------------------------------
The EXPLAIN statement returns only the error status and auxiliary information
variables.
The access path information is acquired as text using the GETERROR statement.
The IPF SQL Interface provides the message retrieval function performed by the
GETERROR statement in the interpreter interface, so that you can see the access path
information immediately after the EXPLAIN statement is executed.
Compile-Time Reporting
The EXPLAIN statement causes RDMS to display access path information at execution
time. This can sometimes be too late to be useful (for example, with static ESQL
statements).
RDMS can also generate access path information for static ESQL at compile time. The
compile time report includes the same information as that produced by the EXPLAIN
statement for static ESQL statements such as DECLARE CURSOR, SELECT, UPDATE,
DELETE, UNLOAD, and INSERT ... SELECT. The method used to join tables and the
search method is not included in the compile time report, however. The report
appears as remarks in the UCS COBOL or UCS C source compilation listing.
To produce the report, include the REMARK keyword option or S, L, or E option on the
compiler call. You can suppress the report by including the NO-REMARK keyword
option or N option on the compiler call. For further information about these listing
options, see the COBOL Compiler Programming Reference Manual Volume 2 or the
C Compiler Programming Reference Manual Volume 2.
RDMS is evaluating n predicates on each record after the record is returned by the
relational storage manager (RSM).
RDMS is evaluating n predicates before reading any records from the relation. In
many cases, the evaluation is performed when fetching the first record. The
result is saved and used in any subsequent fetches.
RDMS is finding all projected values in a secondary index and does not have to
search the primary key.
A scan is performed
A temporary table is searched without using a primary key or a secondary index.
No primary key or secondary index can be used to accelerate the search. All rows
in the relation are read.
The outer table equally joins the inner table. The join criteria must contain at least
one equal predicate, but can also contain nonequal predicates. This method scans
both tables simultaneously, builds a hash table for the outer table, and then probes
the hash table from the inner table to match the join columns.
RDMS uses this method to join the two outermost tables when both tables
equally join on nonindexed columns or on nonleading index columns. The cursor
must not be scrollable (that is, the cursor can fetch in the forward direction only).
For RDMS to display the join method, the cursor must be opened and RDMS must
have fetched records from the cursor.
where:
n
indicates the number of equal predicates (=) that join the two tables and must
be greater than 0 for hybrid hash join to be used,
m
is the number of nonequal predicates (<>, ^-, !=, >, >, <, <, BETWEEN) that join
the two tables and is greater than or equal to 0.
RDMS uses this method to equally join the two outermost tables when
• The outer and inner table join columns are in the same sequence.
• The outer table has more than an RDMS internally defined number of hit
records.
• The inner table uses an index search on the join columns.
• An ACCESS lock for the inner table is not active in the session (see 9.3).
The cursor must not be scrollable (that is, the cursor can fetch in the forward
direction only). For RDMS to display the join method, the cursor must be opened
and RDMS must have fetched records from the cursor.
The cursor is opened and RDMS is using an internal buffer to fetch multiple rows
in a single call to its storage manager. For RDMS to display this text, the cursor
must be opened and RDMS must have fetched records from the cursor.
The outer table joins the inner table. RDMS scans the outer table once and then
scans the inner table. The number of times it scans the inner table is equal to the
number of qualifying rows in the outer table.
RDMS uses this method for all joins after the first join, and for the first join if other
methods do not apply. For RDMS to display the join method, the cursor must be
opened and RDMS must have fetched records from the cursor.
k specifies the number of records RDMS is internally optimizing for. If the cursor is
not a join, this is the minimum of the value from the FETCH FIRST clause and the
OPTIMIZE FOR clause, if they exist. Alternatively, it may be 1 if RDMS determines
from the WHERE clause that only a single record can be returned. (For example, all
columns of the primary key are specified using equality.) If the cursor is a join, it is
the value from the OPTIMIZE FOR clause.
Semi-join is applied
The last table in the join has no columns projected and a “global” DISTINCT is
specified in the select list (see 2.7.1).
RDMS does not have to identify more than one row in the last table for a given
combination of rows in the other tables, thereby reducing the number of duplicate
rows that need to be eliminated during the processing of DISTINCT.
Scrollable, Nonscrollable
Indicates whether the cursor is scrollable (whether fetch current, fetch last, fetch
prior, or locate can be done).
RDMS is employing the fast indexed search to read the table. For RDMS to display
the search method, the cursor must be opened and RDMS must have fetched
records from the cursor.
RDMS is employing the fast non-indexed search to read the table. For RDMS to
display the search method, the cursor must be opened and RDMS must have
fetched records from the cursor.
RDMS is determining that the query is a candidate for trapeze fetch and is
displaying the following results pertaining to its activity and success rate. The n
value refers to how many times trapeze fetch successfully skipped data pages by
doing a B-tree search. The m value refers to how many times trapeze fetch did not
skip any data pages when doing a B-tree search. If the query is a candidate but is
not using trapeze fetch, the EXPLAIN statement displays trapeze fetch as not
active. If the query is a candidate and is also implementing trapeze fetch, the
EXPLAIN statement displays fetch as active.
-----------------------------------------------------------
Used as a delimiter to improve readability by separating attributes of a SELECT
clause from those of the union and cursor. This is helpful when the cursor contains
subqueries, GROUP BY, ORDER BY, and/or FETCH FIRST m ROWS ONLY clauses.
8.6. FETCH
Use the FETCH statement to retrieve one row from a cursor.
8.6.1. Syntax
SQL 92 Syntax (Entry Level)
FETCH cursor-name INTO variable-specification-list
where:
NEXT
(default) retrieves the next row of the cursor, relative to the pointer. If you
execute a FETCH NEXT statement immediately following an OPEN statement, you
retrieve the first row of the cursor.
FIRST
retrieves the first row of the cursor.
PRIOR
retrieves the preceding row of the cursor, relative to the current position. If you
execute a FETCH PRIOR statement immediately following an OPEN statement, you
retrieve the same row you retrieve when you execute a FETCH LAST statement.
FETCH PRIOR uses slightly more computer resources than FETCH NEXT.
LAST
retrieves the last row of the cursor.
CURRENT
(an RDMS extension; not allowed by any level of SQL 92) retrieves the current row
in the cursor. The FETCH CURRENT statement is usually used in conjunction with a
LOCATE statement.
ABSOLUTE n
retrieves the nth row from the first row of a cursor and sets the current cursor
position to the returned row. If n is zero, an error is returned.
RELATIVE n
retrieves the nth row from the current cursor position and sets the current cursor
position to the returned row. If n is zero, RDMS returns the current row. This is the
same as the FETCH CURRENT statement.
cursor-name
is the name of the cursor from which a row is to be retrieved.
variable-specification-list
is a list of placeholder or embedded variable pairs in the form shown in 2.9.
Separate list entries with commas.
The number of embedded variables in ESQL must equal the number of columns in
the cursor. For character value assignment considerations, see 2.8.1.
8.6.2. Example
In the following example, the third FETCH statement can retrieve rows with nulls.
Note the absence of commas between the last three pairs of placeholder variables.
The host program variables associated with placeholder variables $P1, $P2, $P3, and
$P4 is where RDMS returns the values of CNO, MAXPRICE, HNO, and PRICE. Variables
$P5, $P6, and $P7 contain the null indicator values for MAXPRICE, HNO, and PRICE.
The following examples show the usage of the FETCH ABSOLUTE and FETCH
RELATIVE statements:
rsa(sqlcmd, error_code,&aux_info);
rsa( "OPEN CURSOR matchprice;",error_code,&aux_info);
rsa("FETCH ABSOLUTE $p1 FROM matchprice INTO $p2, $p3, $p4, $p5;",
error_code,&aux_info, &v_abs_off, &cno, &maxprice, &hno,
&price);
rsa(“FETCH RELATIVE $p1 FROM matchprice INTO $p2, $p3, $p4, $p5;",
error_code,&aux_info, &v_rel_off, &cno, &maxprice, &hno, &price);
Cursors
Before you can use the FETCH statement to retrieve rows from a cursor, the cursor
must already be defined by a DECLARE CURSOR statement and activated by the OPEN
statement (if you used placeholder variables or declared the cursor through ESQL).
The normal use of the FETCH statement is in a program loop.
For ESQL FETCH statements, the cursor must be opened already either with an OPEN
statement or, for a cursor declared through the interpreter interface, opened implicitly
with a preceding FETCH statement through the interpreter interface.
The INTO clause must include one or two placeholders or embedded variables for
each column selected in the DECLARE CURSOR statement that defined the active
cursor.
You cannot fetch PRIOR or LAST from a cursor declared with any of the following:
There are special cases when RDMS has determined that the GROUP BY, ORDER BY,
UNION, or DISTINCT clause is redundant and has removed the redundant clause as
part of the optimization. Under these circumstances you might be permitted to use
the FETCH PRIOR, CURRENT, or LAST statements. For example, if the primary key is
specified in the select statement with a DISTINCT clause, RDMS can remove the
DISTINCT clause since the primary key is declared as distinct in the table definition.
If the cursor is positioned after the last row (for example, if after executing successive
FETCH NEXT statements, you eventually received the end-of-cursor status) and you
execute a FETCH NEXT statement, RDMS responds as follows:
• Repositions the cursor to the first row and returns that row to you if the cursor
was declared through the interpreter interface. It performs identically when you
execute a FETCH PRIOR from before the first row of the cursor.
• Returns the end-of-cursor status to you again if the cursor was declared through
ESQL. It performs identically when you execute a FETCH PRIOR from before the
first row of the cursor.
In FETCH ABSOLUTE n if the value of n is larger than the number of rows in the cursor,
no row is returned, an error is returned, and the cursor is positioned after the last row.
If the value of n is zero, no row is returned, and an error is returned.
In FETCH RELATIVE n if the value of n, when added to the current cursor position,
causes it to be larger than the number of rows in the cursor, no row is returned, an
error is returned, and the cursor is positioned after the last row. If the value of n is
zero and the cursor is on a row, the current row is returned, otherwise no row is
returned.
Performance
In the interpreter interface, RDMS keeps track of the most recent FETCH NEXT
statement it received (up to 1500 characters altogether). If the next statement is the
same, RDMS bypasses parsing and re-executes the saved statement. This improves
performance considerably. See also 8.7.
When FETCH is used in a routine, the INTO clause may only contain SQL variable
names, declared within the same compound statement as the FETCH statement or at
an outer level of nesting, or parameter names declared with the INOUT or OUT
attribute. The SQL variables and parameters must be of compatible data types and
sizes with the corresponding items in the cursor’s select list. There must be the same
number of variable names in the INTO list as there are columns in the cursor.
When used in a trigger, the INTO clause may also contain NEW ROW
correlation-name.column-name references in a Before Row Trigger. The NEW ROW
correlation-name.column-names must be of compatible data types and sizes with the
corresponding items in the cursor’s select list.
Note that when cursors are used in routines and triggers, they follow the same rules
as those specified for ESQL. If no data is returned by the FETCH statement, RDMS
returns an SQLSTATE value of 02000 (see 4.9.2).
FETCH ABSOLUTE and FETCH RELATIVE cannot be used within routines and triggers.
This returns the cursor name on a temporary table that contains information about
all the return cursors left open at the end of the stored procedure. The table
format is described in 4.7.
2. Then issue this statement:
FETCH NEXT rs INFO $P1, $P2, $P3
If you are uncertain which returning cursor is first, you can issue the statement
GET DESCRIPTION FOR CURSOR $P1 and handle the results as you would for any
other GET DESCRIPTION statement.
INTO variable-specification-list
where:
number-of-rows
is the number of rows you want to retrieve. This must be a positive integer
constant no greater than 510.
cursor-name
is the name of the cursor being fetched.
variable-specification-list
is a list of embedded variables in the form shown in 2.9. Separate list entries with
commas.
8.7.2. Example
The following example illustrates the PROCEDURE DIVISION and corresponding DATA
DIVISION of a UCS COBOL program that is fetching 10 rows of table HOUSES into an
array.
The following DATA DIVISION illustrates how the array can be declared:
01 RECA.
02 HNO OCCURS 10 PIC X(4).
02 LOCATION OCCURS 10 PIC X(28).
02 LOC-INDIC OCCURS 10 PIC S9(5).
02 PRICE OCCURS 10 PIC S9(12)V99
SIGN LEADING SEPARATE.
01 RECB.
02 PRICE-INDIC OCCURS 10 PIC S9(5).
01 RECF.
02 DESCRIPTION OCCURS 10 PIC X(40).
01 RECG.
02 DESC-INDIC OCCURS 10 PIC S9(5).
The following portion of the PROCEDURE DIVISION declares a cursor, opens the
cursor, and fetches the first 10 rows of table HOUSES:
Use
You can use the FETCH NEXT n statement only in ESQL from UCS COBOL and UCS C
programs.
Cursors
The cursor must be already defined with a DECLARE CURSOR statement and activated
with the OPEN statement before you can use the FETCH NEXT n statement to retrieve
its rows. You need at least one embedded variable for each column selected in the
DECLARE CURSOR statement that defined the active cursor.
You cannot use the FETCH NEXT n statement with cursors declared FOR RANDOM
ACCESS or FOR UPDATE OF.
When using FETCH ABSOLUTE n in addition to FETCH NEXT n, declare the cursor with
OPTIMIZE FOR n ROWS syntax for better performance.
After fetching from a cursor with the FETCH NEXT n statement, you cannot use a
regular FETCH statement on the cursor until you close and reopen the cursor with the
CLOSE and OPEN statements. However, you can use the FETCH NEXT n statement
after a regular FETCH statement.
Arrays
A parameter passed in an embedded variable must be one-dimensional. See the
example in this subsection.
The size of the array must be able to accommodate the number of rows indicated by
number-of-rows.
The value returned by RDMS in the auxiliary information variable is the number of
rows returned by the FETCH NEXT n statement: from 0 to n after the FETCH NEXT n
statement is executed. The program should always check this parameter after it
executes a FETCH NEXT n statement. Ensure also that the program handles situations
where this parameter is zero or less than n.
RDMS returns a 6001 no-find error status and an SQLCODE of +100 (see C.3) if fewer
than n rows are fetched because the end of the cursor was reached, or if the cursor
has no rows. In this case, the auxiliary information variable contains a number less
than n.
If all rows of the cursor have already been fetched, a subsequent FETCH NEXT n
results in aux-info containing 0. If some rows are left in the cursor but the number is
less than n, a FETCH NEXT n results in aux-info containing the actual number of rows
fetched.
Performance
When using the ESQL interface to UCS COBOL or UCS C to fetch a large number of
rows, you can use the FETCH NEXT n statement to load an array of host program
variables in one operation. This operation improves performance two ways:
• The number of RDMS calls from the user program may be significantly reduced
since many rows can be passed in response to a single call.
• When FETCH NEXT n is used, RDMS uses internal buffering to optimize the
internal calls to the relational storage manager (RSM). You can realize this benefit
even if n is 1.
BLOB Data
You cannot use FETCH NEXT n if a selected column is of data type BLOB.
8.8. FUNCTION
Use the FUNCTION statement to define a stored function.
where:
schema-name
is the name of the schema to contain the function. If you omit the schema name,
RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses the
default schema name RDMS or the value of the user ID of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAULT-QUALIFIER. For additional information see the Repository for
ClearPath OS 2200 Administration Guide.
routine-name
is the name of the function.
parameter
is the formal definition of a parameter for the function, in the form
where:
IN
means pass an initial value or values to the function. You can use the IN
parameter as the source for a value (for example, in a SET statement, a
WHERE clause, a values list, and so forth). You cannot use an IN parameter as
a target specification (for example, you cannot assign it a value using a SET or
a SELECT statement).
When you use the nonstandard SET statement to invoke a function outside of
a routine or trigger, you can pass a host variable, a placeholder variable, a
literal, or the NULL keyword as an IN parameter. When you use the SET
statement to invoke a function within a routine or trigger, you can pass a
parameter name, an SQL variable, a literal, an arithmetic expression, a
datetime expression, a datetime system function, or the NULL keyword as an
IN parameter.
OUT
means return a value or values to the caller after the function finishes
executing. You can assign a value to the OUT parameter using a FETCH,
SELECT, or SET statement. You can also assign a value to the OUT parameter
by passing it as an OUT or an INOUT parameter of a nested stored procedure
or function invocation. You can use an OUT parameter as a source value in an
SQL statement. This is an RDMS extension to standard SQL. When you use
the nonstandard SET statement to invoke a function outside of a routine or
trigger, you can pass a host variable or placeholder variable as an OUT
parameter. When you use the SET statement to invoke a function within a
routine or trigger, you can pass an INOUT or OUT parameter name or an SQL
variable as an OUT parameter.
INOUT
means pass values both ways, as a source or destination for a value. The
INOUT parameter combines the attributes of the IN and OUT parameters and
thus can be used wherever an IN or OUT parameter can be used. When you
use the nonstandard SET statement to invoke a function outside of a routine
or trigger, you can pass a host variable or placeholder variable as an INOUT
parameter. When you use the SET statement within a routine or trigger, you
can pass an INOUT or OUT parameter name or an SQL variable as an INOUT
parameter.
parameter-name
is the name of the parameter, which is then used in the body of the function.
The name must be a valid name as defined in 2.2.1. The name of each
parameter must be unique within the set of parameters.
data-type
is any valid data type as defined in 2.8, except data type BLOB.
stored-procedure-statement
is the statement that performs the activity for this stored function (see 4.11).
Normally this is a compound statement.
8.8.2. Examples
Example 1
Even though it is not required for functions with only one statement, functions should
start with the BEGIN keyword and end with the END keyword:
Example 2
This example returns the count of houses under a given maximum price. Note that the
data type of the variable that contains the return value is compatible with the data
type on the RETURNS clause.
Example 3
This example accepts two input parameters (a new price and house identifier), and
then uses these two values when it executes the UPDATE statement. The return
value is a count of house with the new price. If the new price is invalid, the function
returns -1 for the house count.
Example 4
This example keeps looping until at least 10 houses are found. It returns the count as
the function return value and returns the price threshold by updating the MAX_PRICE
parameter.
Example 5
This example sets a maximum price based on the input salary, and then selects
houses based on the maximum price:
Example 6
The following example illustrates a case where the RETURN statement may not be
executed, depending on the value of MAX_PRICE:
RDMS returns an error if MAX_PRICE is less than 20,000 because the RETURN
statement was not executed before the end of the routine.
Example 7
This example shows the use of a nested invocation of a stored procedure. Whenever
a data modification occurs for the houses table, a comparable data modification occurs
for the house_backup table (this scenario can be used to maintain a backup for the
houses table).
First, create the stored procedure that is going to be invoked by other routines:
IF modification = ’DELETE’
THEN
BEGIN
DELETE FROM house_backup WHERE hno = house_number;
SET status = ’OK’;
END;
END IF;
IF modification = ’UPDATE’
THEN
BEGIN
UPDATE house_backup SET price = cost, description = desc, location =
loc
WHERE hno = house_number;
SET status = ’OK’;
END;
END IF;
IF modification = ’INSERT’
THEN
BEGIN
INSERT INTO house_backup (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
SET status = ’OK’;
END;
END IF;
END;
Next, create the stored functions that make use of a nested stored procedure
invocation:
Example 8
The following example is the same as the previous example, except a nested
invocation of a stored function is used instead of a stored procedure:
First, create the stored function that is going to be invoked by other routines:
IF modification = ’DELETE’
THEN
BEGIN
DELETE FROM house_backup WHERE hno = house_number;
RETURN ’OK’;
END;
END IF;
IF modification = ’UPDATE’
THEN
BEGIN
UPDATE house_backup SET price = cost, description = desc, location =
loc
WHERE hno = house_number;
RETURN ’OK’;
END;
END IF;
IF modification = ’INSERT’
THEN
BEGIN
INSERT INTO house_backup (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
RETURN ’OK’;
END;
END IF;
RETURN ’NOT OK’;
END;
Next, create the stored functions that make use of a nested stored function
invocation:
Ownership
You must own the schema in which the function will reside.
DECLARE Statements
All DECLARE statements must immediately follow the BEGIN keyword and precede
other statements. All DECLARE variable statements must precede any DECLARE
CURSOR statements.
The RETURN statement (see 4.12.6) must be the last statement executed in the
function. If the function terminates without executing a RETURN statement, RDMS
returns an error.
The data type of the value on the RETURN statement must be compatible with the
data type on the RETURNS clause of the FUNCTION statement.
Committing
If you commit the run unit, RDMS stores the function in the database. You can
reference it later from any program.
Omitting
If you omit the run unit, the function definition is not written to the database.
Reporting
Use the GET PARAMETERS statement to retrieve information about the parameters of
an already defined function (see 8.11).
Dropping a Function
Use the DROP PROCEDURE/FUNCTION statement to remove a stored function from
the database. (See 7.8.)
Nested Invokes
A function can invoke other stored procedures or functions. The invoked stored
procedures and functions must have been successfully created prior to being
referenced in a CALL or SET statement within a function. Note that a function can
invoke itself (recursive reference).
Variables
Placeholder and host program variables are not allowed in functions.
Threads
The thread in which this statement executes must be update recoverable.
TIP
TIP Session Control must be active before you can create a stored function in a TIP
transaction. For information on establishing TIP Session Control, see the Exec
Installation and Configuration Guide.
Do not use a semicolon on the FUNCTION or BEGIN statement. Refer to the examples
for the correct use of semicolons.
When using IPF SQL or JDBC, do not put a semicolon at the end of the final END
statement. (Note that the previous examples include the semicolon and, for this
reason only, would not be accepted by RDMS when submitted from an IPF SQL
thread.)
Default version name: If any statement within the function specifies a table or view
without a version name, the version is not determined at function definition time.
Instead, it is determined from the current default version name at the time the
function is executed.
Security
Normal table security is in effect during the execution of a function.
Comments
When you submit a PROCEDURE/FUNCTION statement from an IPF SQL or JDBC
session, do not include SQL comments in the statement.
where placeholder-list must contain nine placeholder variables $P1 through $P9, as
follows:
$P5 The column’s data type, up to 16 ASCII characters, whose possible values are
as follows:
character
ncharacter
decimal
numeric
integer
smallint
real
float
double-precision
date
time
timestamp
blob
* For DECIMAL columns defined in an owned schema, the number of decimal digits
is one greater than the number of decimal digits in the original definition. This is
because of the difference in the semantics of this value between the SQL
standard and RDMS.
1 Allowed
0 Not allowed
$P9 $P9 returns the following information regarding primary key columns and
arithmetic expression results:
8.9.2. Example
Enter the following statements:
Execution $P1 $P2 $P3 $P4 $P5 $P6 $P7 $P8 $P9
Third decimal 15 2 1 2
Fifth*
Scope
Each GET DESCRIPTION statement returns information about one cursor column.
The 6001 status tells you that the previous GET DESCRIPTION statement returned the
last column’s information.
There is one exception to this rule. You can execute a GETERROR statement to
retrieve the cursor explanation error messages before you execute the GET
DESCRIPTION statement. Using the GETERROR statement for any other error
invalidates subsequent GET DESCRIPTION statements.
To get both the description of a cursor and the explanation of the cursor, you must
execute statements in the following order:
1. EXPLAIN ALL ON
2. DECLARE (cursor declaration)
3. GETERROR (EXPLAIN information)
4. GET DESCRIPTION (cursor description)
The GET DESCRIPTION statement can be used only for cursors declared through the
interpreter interface.
CHARACTER Columns
No information is returned about the character set or collation used with a column
definition.
8.10. GETERROR
Use the GETERROR statement to
• Retrieve the error message from an SQL statement and place this message into
an application program variable.
• Retrieve the cursor access path information compiled by the EXPLAIN statement.
8.10.2. Example
The following example uses the GETERROR statement in an ASCII COBOL program.
This example is set up to check whether an error condition occurred during the
processing of the GETERROR statement.
ERROR-PAR.
MOVE 0 TO ERR-END-FLAG.
MOVE Error-status TO cmd-status.
PERFORM DO-GETERROR UNTIL ERR-END-FLAG NOT EQUAL 0.
DO-GETERROR.
ENTER MASM 'ACOB$RDMR'
USING 'GETERROR INTO $p1, $p2, $p3, $p4;'
Error-status
Aux-info
Err-line(1)
Err-line(2)
Err-line(3)
Err-line(4).
IF Error-status NOT = 0
DISPLAY '*ERROR ', Error-status,
' on GETERROR request.' UPON PRINTER
MOVE 1 to ERR-END-FLAG.
PERFORM LOOK-FOR-RESULT-OF-GETERROR
VARYING i FROM 1 BY 1 UNTIL i > 4.
LOOK-FOR-RESULT-OF-GETERROR.
IF Err-line(i) NOT = SPACE
DISPLAY Err-line(i) UPON PRINTER
ELSE
MOVE 1 TO ERR-END-FLAG.
This segment of the program prints the SQL error messages after executing an SQL
statement.
Retrieved Messages
The GETERROR statement retrieves error messages for all errors returned for one
statement. This includes those detected by RDMS, UREP, and UDS Control. If you
want the program to do something with this text, use a GETERROR statement before
executing the next SQL statement.
If you pass too few or just enough variables for the message, you do not see the
blank line. If this blank line does not appear, call GETERROR again. This returns
message lines beginning at the point you left off on the previous call. Repeat this step
until a blank line appears.
If you are calling GETERROR from a UCS C program, you receive a zero-length string
instead of a blank string.
Selecting an Interface
If an error occurs in the execution of an ESQL statement, you must execute the
GETERROR statement through ESQL also.
Similarly, you must execute the GETERROR statement following an erring interpreter
interface SQL statement through the interpreter interface.
where:
schema-name
is the name of the schema that contains the routine.
routine-name
is the name of the routine.
placeholder-list
is a list of placeholder variables to receive the parameter or function result
information, as follows:
Note: For a function, the first invocation of GET PARAMETERS returns the
name of the function and the return value's attributes in $P1 through $P10. On
the second and succeeding iterations, $P1 and $P2 return information on actual
parameters.
$P3 A number that indicates the parameter type, returned as an ASCII value:
1 Input (IN)
2 Output (OUT)
3 Input/Output (INOUT)
4 Function Result
$P4 A number that indicates the parameter’s data type, returned as an ASCII
value:
01 DECIMAL
02 CHARACTER
03 REAL
04 DOUBLE PRECISION REAL
05 INTEGER
06 LONG CHARACTER
07 DOUBLE PRECISION INTEGER
08 FLOAT
09 SMALLINT
10 (Not used)
11 NUMERIC
12 DATE
13 TIME
14 TIMESTAMP
63 Unknown
CHARACTER
NCHARACTER
DECIMAL
NUMERIC
INTEGER
SMALLINT
REAL
FLOAT
DOUBLE PRECISION
DATE
TIME
TIMESTAMP
$P7 Size of the value, returned as an ASCII value, as in the following table.
$P10 Number that indicates whether nulls are allowed, returned as an ASCII
value:
0 Not allowed
1 Allowed
2 Unknown
The following steps illustrate how a calling program can retrieve parameter
information for a routine:
RDMS populates the RDMCA with the parameter information. RSA returns
information on the first parameter or function result, if one is present, or it returns
a 6001 status (last parameter) or an error condition.
2. The calling program continues by issuing the following call until a 6001 status is
returned or an error occurs:
8.11.2. Example
The following example returns information about the parameters for function
HOUSE_SCHEMA.SELECT_HOUSES:
$P1 $P2 $P3 $P4 $P5 $P6 $P7 $P8 $P9 $P10
Continue issuing the command until information about all parameters is returned.
No Parameters
For routines without parameters, RDMS returns a 6001 error status.
No Stored Procedure
If the routine does not exist, RDMS returns a 6007 error status.
where placeholder-variable is the placeholder variable ($P1) that will hold the name of
the result set cursor.
8.12.2. Example
The following example returns the name of the result set cursor that was just created
by a stored procedure, assuming that the procedure was created to produce dynamic
result sets.
CALL PROC_1( )
IF SQLSTATE = '0100C' OR '0100E' THEN GET RESULTS CURSOR NAME INTO $P1
When to Use
The GET RESULTS CURSOR NAME statement is only available through the interpreter
interface and must be the first statement executed after a call to a stored procedure
or stored function. Once another statement has been executed, the cursor name is no
longer available.
Scope
Each stored procedure that returns dynamic result sets, sets SQLSTATE to 0100C, if
the SET RESULT SET CURSOR ON statement was issued prior to the procedure call.
Naming Protocol
The result set cursor name can generally be anticipated, as can the names of the
return cursors. The result set cursor name consists of the characters “RS” followed
by the number of procedure executions that have returned result sets since the start
of the thread. For the first procedure invoked, the result set cursor name is RS1. The
individual return cursor names take the result set cursor name as a prefix; they
append an underscore and the original cursor name from the procedure definition (for
example, RS1_C1).
8.13. GRANT
Use the GRANT statement to control access by other users to a table and its data. For
tables that are owned, the GRANT statement cannot be used to give users other than
the owner the ability to perform commands such as ALTER TABLE, DROP TABLE, and
CREATE INDEX. Only the owner can execute such commands.
8.13.1. Syntax
SQL 92 Syntax (Entry Level)
GRANT { ALL PRIVILEGES │ privilege-list }
ON table-specification
TO user-id-list
| role-name
TO user-id-list
where:
privilege-list
is a list that contains any combination of the following privileges:
DELETE
FETCH
INSERT
REFERENCES [ (column-name-list) ]
SELECT
UPDATE [ (column-name-list) ]
where column-name-list is one or more simple column names from the table
named in the GRANT statement, separated by commas.
Use commas to separate items in the privilege list or column name list.
RDMS requires that users privileged to use the DELETE and UPDATE statements
must also have SELECT statement privileges. DELETE ALL does not require the
SELECT statement privilege.
table-specification
is a table name as defined in 2.2.2. The version name, if used, cannot be passed by
a variable.
user-id-list
is a list of user IDs allowed to access the table. Include the keyword PUBLIC in the
list to grant the listed privileges to all system users.
A user ID can also be a role-name. All the names in the user ID list must be either
user IDs or role-names. You cannot mix user IDs and role-names in the same
statement.
Role-name
is a role-name as defined in section 2.2.6.
8.13.2. Examples
The following example illustrates how to grant all privileges and the GRANT option on
table MASTER.PERSONNEL to users Jacques and Jack:
The next example grants SELECT and INSERT privileges on table HOUSES to John:
The next example grants the SELECT privilege to all users on table HOUSES:
GRANT SELECT
ON TABLE houses
TO PUBLIC
The next example grants the UPDATE privilege with a column name list on
CUSTOMERS to user 5XYZ:
GRANT UPDATE(maxprice,desiredloc)
ON TABLE customers
TO "5XYZ"
The next example grants the fetch privilege, on table houses, to the role named
“ROLE-PROGRAMMER”. Note that when granting privileges to a role, the role-name is
treated as a user ID.
The next example places user ID JIM in the role named “ROLE-PROGRAMMER”.
Version Names
Although the GRANT statement uses the thread default qualifier name the same way
any other statement uses it, it does not use the default version name in the same
way. The GRANT statement ignores default version names.
When you use a version name on the table specification in a GRANT statement, you
grant privileges on one version of the table. If you omit a version name, you grant
privileges on all versions of the table.
Since the REFERENCES privilege applies to all versions of a table, you cannot specify a
version name when granting this privilege.
The REFERENCES privilege controls the establishment of foreign keys. Foreign keys
apply to all versions of the related tables, thus guaranteeing integrity among all
versions of two tables on the system.
For example, two versions of table HOUSES exist, PRODUCTION and OUTSTATE. The
following GRANT statement grants privileges for both versions of the table:
On the other hand, if you use the following statement, all users can look at
HOUSES:PRODUCTION, but only the owner can look at HOUSES:OUTSTATE:
If you grant privileges to a specific table version, you must name that version when
you want to revoke privileges. Similarly, if you grant privileges without a version name,
the privileges can be revoked only by omitting the version name.
For example, you cannot grant privileges on HOUSES:PRODUCTION and revoke them
on HOUSES (without a version name). You also cannot specify a version when granting
the UPDATE privilege on columns.
Performance
Using table specifications without version names with the GRANT statement allows
faster execution.
A thread granting access to a role, on a table or view, must be able to get exclusive
access to the definition of that table or view (as also required by ALTER TABLE).
Only the owner of the role can associate the user with a role, or remove the user from
a role.
8.14. INSERT
Use the INSERT statement to add one or more rows to a new or existing table or
view.
8.14.1. Syntax
SQL 92 Syntax (Entry Level)
INSERT INTO table-specification [ (column-name-list) ]
COLUMNS (column-and-value) }
where:
table-specification
is a table name as defined in 2.2.2.
column-name-list
is a list of column names in the table. The list can be omitted if the order and
number of data items in the value list correspond to the order and number of
columns defined when the table was created by the CREATE TABLE statement.
value-list
is a list of any combination of string literals, numeric constants, datetime literals,
CAST functions, variable specifications, the keywords NULL and USER, or the
datetime functions CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP.
Use commas to separate the data items in the value list.
The order of the data items is important. If you provide a column name list, the
data items in the value list must be specified in the corresponding order. If you do
not provide a column name list, the data items in the value list must correspond to
the columns for the table specified.
column-and-value
is a list of column names from the table being updated and the data item for each
column.
column-name=value-specification
You must enclose the list in parentheses. The value specification can include
string literals, numeric constants, datetime literals, CAST functions, variable
specifications, the keywords NULL and USER, or the datetime functions
CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP. For more
information, see 2.8.
8.14.2. Examples
The first three examples insert the same row in table HOUSES; only the format of the
INSERT statement is different.
Example 1
The following example specifies the values to be inserted with the VALUES clause:
Example 2
The following example provides the values to be inserted with the COLUMNS clause:
Example 3
The following example uses the SQL format:
Example 4
To insert a row with nulls, use the NULL keyword or indicator variables:
Example 5
In this example, $P3, $P5, and $P7 indicate whether $P2, $P4, and $P6, respectively,
contain a non-null:
Example 6
In this example, two versions of table HOUSES exist, one for PRODUCTION and one
for OUTSTATE. All houses in the Chicago neighborhood are listed incorrectly in the
outstate district and must now be moved to production houses. You can do this with
the following INSERT and DELETE statements.
Example 7
In the remaining examples, assume default clause values are defined for columns
LOCATION, PRICE, and DESCRIPTION of table HOUSES. (For more information about
default clauses, see 6.11.)
The following example inserts a row with default values for columns PRICE and
LOCATION:
Example 8
This example inserts a row with default values for PRICE and DESCRIPTION:
Example 9
This example shows inserts of the same record as example 8, but uses the DEFAULT
keyword.
Example 10
Examples 9 and 10 assume another table, HOUSES2, exists with three columns
defined as HNUM, LOC, and PRICE. An insertion from table HOUSES2 into table
HOUSES results in default values for DESCRIPTION:
Example 11
This example inserts default values for PRICE and DESCRIPTION:
INSERT INTO houses (hno, location) SELECT hnum, loc FROM houses2
Prerequisites
The table or view may or may not already contain rows of data. However, it must have
been created by the CREATE TABLE or CREATE VIEW statement. Use the first form
(VALUES) when you are certain of the order of the columns; otherwise, use the
second form (COLUMNS).
Read-Only Views
You cannot insert data into a read-only view.
Permanent Changes
Permanent database changes can occur any time after an UPDATE statement is
executed if the NONE recovery option is used on the BEGIN THREAD statement.
Otherwise, RDMS does not permanently insert rows into the database until the
program executes a COMMIT or END THREAD statement.
The default table lock is step-duration UPDATE mode, and the default row lock is
step-duration EXCLUSIVE UPDATE mode. See the Relational Database Server for
ClearPath OS 2200 Administration Guide.
If the table is locked in one of the RETRIEVAL modes, RDMS rejects the INSERT
statement.
Column/Table Constraints
If one of the values you are inserting violates a column or table constraint, RDMS
returns an error.
Thread Rollbacks
Some errors during the insert operation do not cause a thread rollback unless the
INSERT statement includes a query specification. These errors include duplicate
primary key violations, column length or size violations, and constraint and referential
integrity violations.
FROM List
The FROM list in a query specification or subquery may contain the table identified in
the table specification. If the table contains a primary key or unique constraints, the
INSERT statement may terminate with a duplicate key error.
To avoid duplicate keys, use the SELECT statement to change the value of at least one
column of the primary key and at least one column of each unique constraint, as in the
following example:
INSERT INTO x
SELECT pk+1000,...unique1+1000,...
FROM x
It is recommended that you specify DISTINCT in the SELECT clause of the query
specification to avoid encountering a duplicate primary key error. DISTINCT is not
required, however, if you know that the query specification is selecting only rows with
unique primary keys for the table being inserted.
Subqueries
If query-specification contains a subquery and a character column is being inserted,
the values returned by a subquery must have the same character set as the column
into which the values are being inserted, unless either the source or destination
column is defined with the RDMS_TEXT character set. For character value assignment
considerations, see 2.8.1.
In routines, the RDMSAUXINFO system variable can be used to obtain this information.
See 4.9.1.
No Finds
If no rows are specified by the query specification, RDMS returns an OK status of
0000 or an SQLCODE of +100 (see C.3).
This section contains reference information about the following SQL statements:
• LEVEL (9.1)
• LOCATE (9.2)
• LOCK (9.3)
• OPEN (9.4)
• PREPARE (9.5)
• PROCEDURE (9.6)
• REVOKE (9.7)
• ROLLBACK (9.8)
• SELECT Multirow (9.9)
• SELECT Single Row (9.10)
• SET (9.11)
• SET AUXINFO (9.12)
• SET RESULT SET (9.13)
• SET SKIPGENERATED (9.14)
• SET STATISTICS (9.15)
9.1. LEVEL
Use the LEVEL statement to determine the internal level number of RDMS and its RSA
component.
The level number returned by the LEVEL statement corresponds to the system
number used by COMUS when RDMS was generated.
where:
RSA
(default) returns the system level number of the RSA component of RDMS.
RDMS
returns the system level number of RDMS.
placeholder
represents a CHARACTER type host program variable.
9.1.2. Example
The following UCS FORTRAN statement returns the level number of the version of
RDMS in the application group being used in variable RLEVEL:
After the statement is executed, the variable RLEVEL contains a character string
similar in form to
9.2. LOCATE
Use the LOCATE statement to position the pointer in a cursor. The LOCATE statement
does not retrieve data.
9.2.1. Syntax
RDMS Extended Syntax
LOCATE cursor-name ON table-specification
where:
cursor-name
is an opened cursor. You can use the LOCATE statement on an opened cursor only
if you specified RANDOM or DIRECT ACCESS in its DECLARE CURSOR statement.
The cursor cannot be allocated (declared) from a prepared query specification. The
cursor cannot include a subquery.
table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.
primary-key-value
is the value of the primary key for the row you want to locate. The primary key
value is a list of values of the column or columns of the table's primary key
separated by commas. The values can be any combination of string literals,
numeric constants, datetime literals, CAST functions, variable specifications, the
keywords NULL and USER, or the datetime functions CURRENT_DATE,
CURRENT_TIME, and CURRENT_TIMESTAMP. The values must be listed in the
same order as the columns in the PRIMARY KEY clause of the CREATE TABLE
statement.
9.2.2. Example
The following example locates the row in table CUSTOMERS that contains customer
number C101 in the CUST cursor:
Pointer Position
If the primary key value does not exist in the table, the cursor does not have a current
row. However, RDMS positions the cursor where the primary key value would be
located if it existed. This means, in effect, that a FETCH CURRENT does not retrieve a
row but that a FETCH NEXT or FETCH PRIOR retrieves a row if a row exists after or
before the cursor's position.
If you execute a LOCATE statement on a table using a nonexistent primary key value,
a subsequent FETCH CURRENT statement always returns a 6001 no-find error status;
however, a FETCH NEXT statement returns the row following the cursor's new
position, if such a row exists.
The LOCATE statement only positions a cursor. RDMS does not return a 6001 no-find
error status on a LOCATE statement. If a row that contains the primary key value does
not exist, however, RDMS returns a no-find SQLCODE of +100 (see C.3).
Auxiliary Information
After executing the LOCATE statement, RDMS sets the auxiliary information variable
to 1 if the row specified in the USING clause does not exist. If the row does exist,
RDMS sets the auxiliary information variable to 0.
In routines, the RDMSAUXINFO system variable can be used to obtain this information.
See 4.9.1.
The cursor must be opened using the OPEN statement prior to the execution of the
LOCATE statement.
9.3. LOCK
Use the LOCK statement to specify a lock on one or more tables during a step.
[ IN lock-specification [ MODE ] ]
where:
table-specification-list
is one or more table specifications, separated by commas. This list specifies the
base tables you want to lock. You cannot lock a view. If you need locking
protection while accessing a view, you must lock each of the base tables on which
the view depends. Locks on global temporary tables are ignored, because RDMS
implicitly locks global temporary tables in EXCLUSIVE UPDATE MODE.
lock-specification
is in the form
[mode] [usage]
where:
mode
is SHARE or SHARED (synonymous), PROTECTED, or EXCLUSIVE.
usage
is RETRIEVAL (default), ACCESS, or UPDATE.
PARTITION IN
specifies how to lock partitions of partitioned tables.
PARTITION IN can be used to specify a partition lock, both in the XTC and the
local-host environments. Partition lock is implemented to allow multiple threads
to EXCLUSIVE UPDATE or PROTECTED UPDATE to lock the partitions where they
are working. This capability improves performance in an XTC environment where
it takes time (approximately one millisecond) to call XPC-L to get a lock. Placing a
PROTECTED UPDATE lock on the partition eliminates the need to place any page
or record locks in the partition. Use of this feature does not greatly affect
performance in the single-host environment. For more information on locking and
partitions, see the Relational Database Server for ClearPath OS 2200
Administration Guide.
ON CONFLICT
along with one of the following two keywords, instructs RDMS on how to handle a
locking conflict:
Lock /
Lock and Mode Description
RETRIEVAL When you place a RETRIEVAL lock on a table, you cannot update
the table. Other users cannot place an EXCLUSIVE RETRIEVAL or
EXCLUSIVE UPDATE lock on the table; they can, however, update
the table. You therefore risk reading the same row twice and
obtaining different data values each time if another user updated
the row and committed the changes between retrievals. You
cannot retrieve a row if another user has updated it but has not
committed or rolled back the change.
SHARED Your SHARED RETRIEVAL lock is similar to a RETRIEVAL lock
RETRIEVAL except that other users cannot change retrieved rows until a
COMMIT, ROLLBACK, or END THREAD statement is executed.
This guarantees the return of identical data values if the same
row is read twice.
PROTECTED Your PROTECTED RETRIEVAL lock prevents you and other users
RETRIEVAL from making changes to the table. Other users can place only a
nonexclusive RETRIEVAL type lock. Since RDMS does not lock
individual rows in this case, you can retrieve data faster by
imposing a PROTECTED RETRIEVAL lock than by using a
RETRIEVAL, UPDATE, SHARED RETRIEVAL, or SHARED UPDATE
lock.
EXCLUSIVE Your EXCLUSIVE RETRIEVAL lock allows only you to access the
RETRIEVAL table but not to update it. Since RDMS does not lock individual
rows in this case, you can retrieve data faster by using an
EXCLUSIVE RETRIEVAL lock than by using a RETRIEVAL, UPDATE,
SHARED RETRIEVAL, or SHARED UPDATE lock.
UPDATE Your UPDATE lock allows you and other users to retrieve data
from and update the table. Other users cannot place a
PROTECTED RETRIEVAL, PROTECTED UPDATE, EXCLUSIVE
RETRIEVAL, or EXCLUSIVE UPDATE lock on the table. As with
RETRIEVAL locks, you risk reading the same row twice and
getting different data values each time if another user updated
the row and committed the change between retrievals. If you
update a row, no other user can retrieve or update the row until
you commit or roll back the change.
SHARED UPDATE Your SHARED UPDATE lock is similar to an UPDATE lock, except
that other users cannot update your retrieved rows until a
COMMIT or ROLLBACK statement is executed. Other users who
also have the table locked in SHARED UPDATE mode cannot
retrieve your retrieved rows until you commit or roll back the
changes.
Lock /
Lock and Mode Description
PROTECTED Your PROTECTED UPDATE lock allows only you to update the
UPDATE table. Other users can retrieve data from the table, but they can
place only RETRIEVAL and SHARED RETRIEVAL locks on the
table. Even though this protects the run from other users
attempting to update the table, you still cannot update a row
retrieved by another user who has a SHARED RETRIEVAL lock on
the table. Since RDMS does not lock individual rows for retrieval,
you can retrieve data faster by using a PROTECTED UPDATE lock
than by using a RETRIEVAL, UPDATE, SHARED RETRIEVAL, or
SHARED UPDATE lock.
EXCLUSIVE Your EXCLUSIVE UPDATE lock allows only you to retrieve data
UPDATE from the table and to update it. Since RDMS does not lock
individual rows in this case, you can retrieve data and update it
faster by using an EXCLUSIVE UPDATE lock than by using a
RETRIEVAL, SHARED RETRIEVAL, or any other UPDATE type lock.
ACCESS (Use only if the fast search feature is enabled.) Your ACCESS lock
prevents you from updating the table. Other users cannot place
an EXCLUSIVE RETRIEVAL or EXCLUSIVE UPDATE lock on the
table. Since you may be reading data that is currently being
updated by a transaction, you might see such data
inconsistencies as missing records, duplicate records, and
uncommitted records.
9.3.3. Examples
The following two examples lock table CUSTOMERS in different modes:
XTC
If an application group is configured for Extended Transaction Capacity (XTC), the
LOCK statement affects the entire storage area in which the table to be locked
resides. If one table in a storage area is locked, all other tables in the same storage
area (if any are present) are locked.
To prevent the LOCK statement from affecting multiple tables, it is recommended that
you place only one table in each storage area.
Duration of Lock
Locks created with the ACCESS, RETRIEVAL, SHARED RETRIEVAL, PROTECTED
RETRIEVAL, and EXCLUSIVE RETRIEVAL clauses are immediately unlocked when you
issue the UNLOCK statement.
For UPDATE, SHARED UPDATE, PROTECTED UPDATE, and EXCLUSIVE UPDATE locks,
the UNLOCK statement does not take effect until you enter a COMMIT, ROLLBACK, or
END THREAD statement.
Subsequent use of this attribute includes the new value. OPEN cursors reflect the ON
CONFLICT behavior in force at the time they are opened.
For BEGIN THREAD syntax that specifies READ or RETRIEVE, RDMS places a
PROTECTED RETRIEVAL lock on each table referenced. Other users cannot update a
table that is referenced until the changes are committed or rolled back.
A lock request can also become queued after some of the tables are locked. You can
avoid this potentially confusing situation by locking only one table per LOCK
statement.
You cannot lock a table if the thread has an opened cursor that refers to that table.
• Mode establishes how strong a lock you want on a table and its rows. EXCLUSIVE
is the strongest lock, followed by PROTECTED and SHARED.
A mode value is not allowed with the ACCESS clause.
• Usage establishes whether you are retrieving or updating data, or in the case of
the ACCESS clause, the method of data retrieval.
If you are retrieving data with the DECLARE CURSOR statement or a FETCH
statement, a RETRIEVAL lock is appropriate.
If you are altering data with the UPDATE or the INSERT statement, for example, an
UPDATE lock is necessary.
The Relational Database Server for ClearPath OS 2200 Administration Guide contains
an entire section devoted to locking. You are urged to read this section.
9.4. OPEN
Use the OPEN statement to activate a cursor defined with a DECLARE CURSOR or
ALLOCATE CURSOR statement.
9.4.1. Syntax
SQL 92 Syntax (Entry Level)
OPEN cursor-name
[ USING variable-list ]
where:
cursor-name
is the name of the cursor being opened.
variable-list
is a list of variables separated by commas.
Note: The READY [CURSOR] form is not allowed in ESQL, routines, or triggers.
9.4.2. Examples
Example 1
The following example uses the OPEN statement with a DECLARE CURSOR statement
in a UCS FORTRAN program:
This example declares a cursor to retrieve certain house numbers from table HOUSES.
Use placeholder variables in the WHERE clause to change the selection criteria from
time to time.
After declaring the cursor, you must open it. Opening the cursor fills in the blanks left
by the variables in the DECLARE CURSOR statement. The first OPEN statement places
all rows for houses in Woodbury priced at $65,000 or more in the cursor. You can then
fetch those rows.
You can use the same cursor to retrieve a different set of rows. In the same example,
the second OPEN statement modifies the cursor to retrieve rows for houses in Turtle
Creek priced at or above $100,000.
Example 2
The following example declares a cursor with a parameter marker; the OPEN
statement opens the cursor and supplies a value for the parameter marker:
If you are not using ESQL, RDMS does not return an error. Instead, RDMS
automatically closes the cursor and then reopens it. This is an extension to standard
SQL.
Allocation of Memory
When you open a cursor, RDMS allocates memory space to the cursor in addition to
that allocated when you declared the cursor.
When you close a cursor or when it is closed automatically by RDMS, the memory
space allocated upon opening is freed for other uses.
Cursor Pointer
A cursor (referred to as an “active set” in some literature) is a set of rows in a
conceptual table. Each cursor includes a pointer. In some literature, this pointer is
called a “cursor.”The pointer indicates the current row of the cursor. This pointer
tracks a user’s progress through the cursor as rows are sequentially fetched or
randomly located in it.
After an OPEN statement, RDMS positions the pointer before the first row in the
specified cursor. Unless you change the current row with a LOCATE statement, a
FETCH NEXT statement at this time retrieves the first row in the cursor. Since RDMS
uses the pointer internally, you cannot actually see it. However, you can position the
pointer with the LOCATE statement if the cursor is a random access cursor.
A cursor declared through the interpreter interface “wraps around.” That is, if you go
past the last row of the cursor and get a no-find error status and then execute a
FETCH NEXT statement, you retrieve the first row of the cursor. This does not happen
for a cursor declared or allocated through ESQL, for once a no-find status is returned
for an ESQL cursor, no further retrievals are possible until the cursor is reopened.
Similarly, sequential FETCH PRIOR statements against a cursor declared through the
interpreter interface eventually retrieve the cursor’s first row, return the no-find
status, and then start again and retrieve the cursor’s last row. Again, an ESQL cursor
retrieves no rows after the nofind status until it is reopened.
Placeholder Variables
When you are using placeholder variables in an OPEN statement, the following rules
apply:
• The size and data type of the host program variables in the OPEN statement must
match those of variables in the DECLARE CURSOR statement and the application
program.
For example, the application program variable associated with $P1 in the DECLARE
CURSOR statement’s WHERE clause must match the type and size of $P1 in the
OPEN statement. You should usually use the same application program variables in
both the DECLARE CURSOR and OPEN statements. For character value
assignment considerations, see 2.8.1.
• Before you use the OPEN statement, you must initialize the program variables
associated with the placeholder variables.
If you attempt to open a cursor that is already opened, RDMS returns an error, as
required by standard SQL. This error terminates the execution of a routine or trigger.
The USING clause is not allowed on OPEN statements in routines or triggers, because
name resolution for the SQL variables and parameters used by a cursor takes place
when the routine or trigger is created. Consequently, placeholder variables and
parameter markers are not allowed in the query-expression portion of the DECLARE
CURSOR statement.
For more information, see “Cursor Pointer” earlier in this subsection. Note that when
cursors are used in routines or triggers, they follow the same rules as those specified
for ESQL.
9.5. PREPARE
Use the PREPARE statement to compile and name an SQL statement during program
execution.
where:
statement-name
is the name of the statement you are preparing.
embedded-variable
contains one of the following items:
For the definition of a query specification, see 2.7; for the sort specification list
and column name list, see 7.4.
• One of the following SQL statements:
COMMIT (from an implicit thread only)
DELETE
END THREAD (from an implicit thread only)
INSERT
LOCATE
LOCK
ROLLBACK (from an implicit thread only)
SET AUXINFO
SET STATISTICS
UNLOCK
UPDATE
USE DEFAULT
string-literal
is a quoted character string that contains one of the SQL statements just listed.
9.5.2. Examples
The following example uses a string literal to pass the SQL statement to RDMS:
The next example uses an embedded variable that is assigned an SQL statement as its
values:
Process
During program execution, the PREPARE statement compiles, optimizes, and names a
dynamic ESQL statement. This produces a named object statement that is saved for
later execution. Once prepared, a statement can be executed any number of times
using the EXECUTE statement.
Location
You can prepare a dynamic ESQL statement in one object module and execute it in a
different one.
During program compilation, it does not matter whether the PREPARE statement is
encountered before or after an EXECUTE statement referring to the same dynamic
ESQL statement.
The PREPARE statement for a particular dynamic ESQL statement, however, must be
executed before any EXECUTE statement for that statement.
No EXECUTE Statement
If you use the PREPARE statement to prepare a cursor specification, you do not use
the EXECUTE statement on that statement.
The statement name of a prepared query specification can be used as the statement
name in the ALLOCATE CURSOR statement.
Prepared statements are not available following the execution of an END THREAD
statement.
9.6. PROCEDURE
Use the PROCEDURE statement to define a stored procedure.
stored-procedure-statement
where:
schema-name
is the name of the schema to contain the procedure. If you omit the schema name,
RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses the
default schema name RDMS or the value of the user ID of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAULT-QUALIFIER. For additional information, see the Repository for
ClearPath OS 2200 Administration Guide.
routine-name
is the name of the procedure.
Schema and routine names must be valid names as defined in 2.2.1.
parameter
is the formal definition of a parameter for the procedure, in the form
where:
IN
means pass an initial value or values to the procedure. You can use the IN
parameter as the source for a value (for example, in a SET statement, a
WHERE clause, a values list, and so forth). You cannot use an IN parameter as
a target specification (for example, you cannot assign it a value using a SET or
a SELECT statement).
When you use the CALL statement to invoke a procedure outside of a routine
or trigger, you can pass a host variable, a placeholder variable, a literal, or the
NULL keyword as an IN parameter. When you use the CALL statement to
invoke a procedure within a routine or trigger, you can pass a parameter name,
an SQL variable, a literal, an arithmetic expression, a datetime expression, a
datetime system function, or the NULL keyword as an IN parameter.
OUT
means return a value or values to the caller after the procedure finishes
executing. You can assign a value to the OUT parameter using a FETCH,
SELECT, or SET statement. You can also assign a value to the OUT parameter
by passing it as an OUT or an INOUT parameter of a nested stored procedure
or function invocation. You can use an OUT parameter as a source value in an
SQL statement. This is an RDMS extension to standard SQL. When you use
the CALL statement to invoke a procedure outside a routine or trigger, you can
pass a host variable or placeholder variable as an OUT parameter. When you
use the CALL statement to invoke a procedure within a routine or trigger, you
can pass an INOUT or OUT parameter name or an SQL variable as an OUT
parameter.
INOUT
means pass values both ways, as a source or destination for a value. The
INOUT parameter combines the attributes of the IN and OUT parameters and
thus can be used wherever an IN or OUT parameter can be used. When you
use the CALL statement to invoke a procedure outside of a routine or trigger,
you can pass a host variable or placeholder variable as an INOUT parameter.
When you use the CALL statement to invoke a procedure within a routine or
trigger, you can pass an INOUT or OUT parameter name or an SQL variable as
an INOUT parameter.
parameter-name
is the name of the parameter, which is then used in the body of the procedure.
The name must be a valid name as defined in 2.2.1. The name of each
parameter must be unique within the set of parameters.
data-type
is any valid data type as defined in 2.8 except data type BLOB.
stored-procedure-statement
is the statement that performs the activity for this stored procedure (see 4.12).
Normally this is a compound statement.
9.6.2. Examples
Example 1
Even though it is not enforced for procedures with only one statement, procedures
should start with the BEGIN keyword and end with the END keyword:
PROCEDURE house_schema.update_house_price( )
BEGIN
UPDATE houses SET price = 21000 WHERE price < 20000;
END;
Example 2
This example returns the count of houses under a given maximum price:
This procedure contains only one statement and therefore does not have to be
enclosed in a BEGIN ... END pair.
Example 3
This example accepts two input parameters (an integer and a character value), and
then uses these two values when it executes the UPDATE statement. The return
value is a count of the rows in table HOUSES with a specific price.
PROCEDURE house_schema.updateandfindhouses
(IN newprice INTEGER, IN ident CHARACTER, OUT how_many
INTEGER)
BEGIN
UPDATE houses SET price = newprice WHERE hno = ident;
SELECT COUNT(*) INTO how_many FROM houses WHERE price = newprice;
END;
Example 4
The following example shows the use of a nested invocation of a stored procedure.
Whenever a data modification occurs for the houses table, a comparable data
modification occurs for the house_backup table.
First, create the stored procedure that is going to be invoked by other routines:
IF modification = ’DELETE’
THEN
BEGIN
DELETE FROM house_backup WHERE hno = house_number;
SET status = ’OK’;
END;
END IF;
IF modification = ’UPDATE’
THEN
BEGIN
UPDATE house_backup SET price = cost, description = desc, location =
loc
WHERE hno = house_number;
SET status = ’OK’;
END;
END IF;
IF modification = ’INSERT’
THEN
BEGIN
INSERT INTO house_backup (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
SET status = ’OK’;
END;
END IF;
END;
Next, create the stored procedures that make use of a nested stored procedure
invocation:
Example 5
This example is the same as the previous example, except a nested invocation of a
stored function is used instead of a stored procedure.
First, create the stored function that is going to be invoked by other routines:
IF modification = ’DELETE’
THEN
BEGIN
DELETE FROM house_backup WHERE hno = house_number;
RETURN ’OK’;
END;
END IF;
IF modification = ’UPDATE’
THEN
BEGIN
UPDATE house_backup SET price = cost, description = desc, location =
loc
WHERE hno = house_number;
RETURN ’OK’;
END;
END IF;
IF modification = ’INSERT’
THEN
BEGIN
INSERT INTO house_backup (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
RETURN ’OK’;
END;
END IF;
RETURN ’NOT OK’;
END;
Next, create the stored procedures that make use of a nested stored function
invocation:
Ownership
You must own the schema in which the procedure is to reside.
DECLARE Statements
All DECLARE statements must immediately follow the BEGIN keyword and precede
other statements. All DECLARE variable statements must precede any DECLARE
CURSOR statements.
Reporting
Use the GET PARAMETERS statement to retrieve information about the parameters of
an already defined procedure (see 8.11).
Dropping a Procedure
Use the DROP PROCEDURE statement to remove a stored procedure from the
database (see 7.8).
Nested Invokes
A procedure can invoke other stored procedures or functions. The invoked stored
procedures and functions must have been successfully created prior to being
referenced in a CALL or SET statement. Note that a procedure can invoke itself
(recursive reference).
Variables
Placeholder and host program variables are not allowed in procedures.
Threads
The thread in which this statement executes must be update recoverable.
TIP
TIP Session Control must be active before you can create a stored function in a TIP
transaction. For information on establishing TIP Session Control. See the Exec
Installation and Configuration Guide.
When using IPF SQL or JDBC, do not put a semicolon at the end of the final END
statement. (Note that the previous examples include the semicolon and, for this
reason only, would not be accepted by RDMS when submitted from an IPF SQL
thread.)
Default Version
If any statement within the procedure specifies a table or view without a version
name, the version is not determined at procedure definition time. Instead, it is
determined from the current default version name at the time the procedure is
executed.
Security
Normal table security is in effect during the execution of a procedure.
Comments
When you submit a PROCEDURE/FUNCTION statement from an IPF SQL or JDBC
session, do not include SQL comments in the statement.
9.7. REVOKE
Use the REVOKE statement to remove user privileges from a table.
ON table-specification
FROM user-id-list
| role-name
FROM user-id-list
where:
ALL PRIVILEGES
removes all previously granted privileges from all user IDs in the FROM clause.
privilege-list
is a list that contains any combination of the following privileges:
DELETE
FETCH
INSERT
REFERENCES
SELECT
UPDATE
Use commas to separate privileges in the list.
FETCH and SELECT are synonyms. FETCH is an extension to standard SQL.
table-specification
is a table name as defined in 2.2.2. The version name, if used, cannot be passed by
a variable.
user-id-list
is a list of user IDs that have access to the table. (The keyword PUBLIC removes
the listed access privileges granted to PUBLIC.)
user-id [ ,user-id ] ...
A user ID can also be a role-name. All the names in the user ID-list must be either
user IDs or role-names. You cannot mix user IDs and role-names in the same
statement.
If a user ID starts with a number, express it as a delimited uppercase identifier, as
illustrated in the following examples:
"1BIG" "2NOT" "3NOR""
Role-name
is a role-name as defined in 2.2.6.
9.7.2. Examples
The following example illustrates how to revoke UPDATE and DELETE privileges from
user Jacques on the MASTER.PERSONNEL table:
The following example illustrates how to revoke all privileges from all users (except
those granted privileges individually by user ID) on table HOUSES:
The next example removes user ID JIM from the role named “ROLE-PROGRAMMER”.
The next example removes the fetch privilege, on table houses, from the role named
“ROLE-PROGRAMMER”. Note that when revoking privileges from a role, the
role-name is treated as a user ID.
A thread revoking privileges from a role, on a table or view, must be able to get
exclusive access to the definition of that table or view (as also required by ALTER
TABLE).
It is not possible to revoke privileges from a role, on a table or view, when a cursor is
declared over that table or view.
When you use a version name on the table specification in a REVOKE statement, you
revoke privileges on one version of the table. If you omit a version name, you revoke
privileges on all versions of the table. Note that the REFERENCES privilege applies to
all versions of a table. You cannot specify version names on the REFERENCES
privilege.
For example, suppose two versions of table HOUSES exist, PRODUCTION and
OUTSTATE. The following REVOKE statement revokes privileges for both versions of
the table:
On the other hand, if you use the following statement, all system users can look at
HOUSES:OUTSTATE, but only the owner can retrieve from HOUSES:PRODUCTION:
If you grant privileges to a specific table version, you must name that version when
you want to revoke privileges. Similarly, if you grant privileges without a version name,
the privileges can be revoked only by omitting the version name from the REVOKE
statement. For example, you cannot grant privileges on HOUSES:PRODUCTION and
revoke them on HOUSES (without a version name).
Performance
Using table specifications without version names with the REVOKE statement allows
faster execution.
Auxiliary Information
RDMS returns information to the program indicating whether any privileges were
actually revoked through the auxiliary information variable. For more information,
see the manual for the programming language you are using.
The only way to revoke privileges granted to many user IDs is to explicitly list those
user IDs in a REVOKE statement. A privilege granted to PUBLIC cannot be individually
revoked from a single user ID, or from a list of user IDs, but only from PUBLIC.
The new owner can revoke all privileges granted (even indirectly) by the original owner
by using the following statement format:
This does not apply to views because the ownership of views cannot be changed.
If you then want the user to have the privileges (but not the GRANT OPTION privilege),
execute the appropriate GRANT statement without the WITH GRANT OPTION clause.
What happens if PRES revokes VPRES's privileges with the following REVOKE
statement?
Not only does VPRES lose privileges, but those privileges granted by VPRES are also
revoked. This means that MANAGE has no privileges to access the table. The
privileges granted by VPRES to SECRET are also revoked, but those granted by PRES
are unaffected. SECRET, therefore, still has full access to the table TBL1.
9.8. ROLLBACK
Use the ROLLBACK statement to undo any updates made to the database since the
last thread control statement or rollback.
9.8.1. Syntax
SQL 92 Syntax (Entry Level)
ROLLBACK WORK
where:
KEEP
directs the operating system to resume its current Integrated Recovery step, even
though RDMS considers the current step finished. This option also directs the
system to keep the recoverable transaction message associated with the thread if
Message Control Bank (MCB) is being used.
REQUEUE
directs the operating system to terminate its current Integrated Recovery step
and requeue the recoverable transaction message associated with the thread if
MCB is being used.
DISCARD
directs the operating system to terminate its current Integrated Recovery step
and queue the recoverable transaction message to the application error program
queue if MCB is being used.
If you do not specify KEEP, REQUEUE, or DISCARD, the operating system uses the
default Step Control option. For transaction programs, the default option is specified in
the program's VALTAB parameter. For all other programs, the default is REQUEUE
unless the program was connected to TIP before the start of the step, in which case,
the default option specified on the connection to TIP is in effect.
UDS Control passes the Step Control message option to ER DMRB$ as the rollback
indicator. For more information about Executive requests (ER), see the Exec
Administration Reference Manual. Unless you are using TIP with MCB, it may not be
relevant to specify this option.
9.8.2. Examples
The following ROLLBACK statement ends the thread’s current step and discards any
updates to the database made since the last thread control statement and begins a
new step. The operating system resumes the current Integrated Recovery step if the
KEEP option was specified or assumed.
ROLLBACK WORK
This ROLLBACK statement ends both the thread’s step and the operating system’s
current Integrated Recovery step and discards both its updates and any transaction
message:
ROLLBACK DISCARD
Effect on Cursors
Rolling back a thread closes all cursors except for RETENTION cursors in a read-only
thread. For more information about cursors, see the following:
• While several updates to the database are being performed, an unexpected error
occurs. You may want to commit the changes only if all of the changes can be
applied. If any updates are unsuccessful, you can use the ROLLBACK statement to
discard all updates the step makes.
• After making temporary updates to generate “what-if” reports, you can discard all
changes to the database with a ROLLBACK statement.
Errors
If an error occurs on a ROLLBACK statement, you must terminate the thread with an
END THREAD statement before submitting further SQL statements (whether the
thread is implicit or explicit).
query-specification
[ ORDER BY sort-specification-list ]
query-specification
9.9.2. Example
In the following example, IPF SQL displays all rows in table HOUSES, where the house
is worth more than $50,000:
SELECT *
FROM houses
WHERE price > 50000
9.10.1. Syntax
SQL 92 Syntax (Entry Level)
SELECT [ ALL │ DISTINCT ] { select-list │ * }
INTO variable-specification-list
FROM table-specification-list
[ WHERE Boolean-expression ]
FROM table-specification-list
[ WHERE Boolean-expression ]
[ HAVING Boolean-expression ]
INTO variable-specification-list
where:
group-by-item
is
{ column-specification | scalar-bif-reference }
ORDER BY
INTO variable-specification-list
FROM table-specification-list
[ WHERE Boolean-expression ]
See 2.7.1 for a description of the SELECT statement and its parameters and 2.10 for
details about variables. Use commas to separate variables in the list.
9.10.2. Examples
These examples use data from the CUSTOMERS and HOUSES tables in 1.2.2.
Example 1
In the following example, the host program variables receive the data items for house
H101:
Example 2
The next example looks for a customer with a price range that matches listed house
prices:
You retrieve the following row, which is one of several that satisfies the WHERE
clause:
Example 3
To determine how many rows table HOUSES contains, you can execute this
statement:
SELECT COUNT(*)
INTO $p1
FROM houses
Because table HOUSES has five rows, $P1 receives the value 5.
Handling Variables
If the expression in the WHERE clause includes placeholder or embedded variables,
you must first assign a value to the host program variables that correspond to the
placeholder variables.
This is different from the DECLARE CURSOR statement. With the DECLARE CURSOR
statement, you supply the values for a placeholder variable in a subsequent OPEN
statement.
However, if you execute a SELECT Single Row statement from ESQL, the evaluation of
the FROM, WHERE, GROUP BY, and HAVING clauses must result in 0 or 1 rows.
Otherwise, RDMS returns an error.
• When no rows are returned, RDMS returns a 6001 no-find error status or an
SQLCODE of +100 (see C.3).
• When one row is returned, RDMS returns an error status or an SQLCODE of zero.
9.11. SET
Use the nonstandard SET statement to invoke a previously defined stored function
and assign values returned by the function to a host program variable, placeholder
variable, or (within a routine or trigger) an SQL variable.
9.11.1. Syntax
RDMS Extended Syntax
SET return-variable = [schema-name.]routine-name
where:
return-variable
is a host program variable or placeholder variable into which the function writes
the return value. The data type of the return variable must be compatible with the
data type of the RETURNS clause of the function definition (see 8.8).
When used in a routine, the return-variable is an SQL variable or parameter.
When used in a trigger, the return-variable is an SQL variable. If used in a BEFORE
ROW trigger, the return-variable is a new row correlation-name.
schema-name
is the name of the schema that contains the function.
routine-name
is the name of the function. Schema and routine names must be valid names as
defined in 2.2.1.
parameter
is the parameter or parameters to pass to the function. The number and type of
parameters specified here must match the number and type of parameters on the
function declaration. When a SET statement is used outside of a routine or trigger,
you can use indicator variables as parameters for specifying or retrieving null
values. The use of indicator variables in a function invocation is identical to their
use in any other context. When a SET statement is used within a routine or trigger,
indicator variables may not be used. Valid values for parameters depend on the
type of formal parameter.
The actual parameter passed from the calling program, routine, or trigger must be
as indicated for the parameter in the procedure declaration. For more information,
see 5.2.
UPDATE COUNT OFF
For this CALL or SET, the specification of UPDATE COUNT OFF on the CALL or SET
statement overrides a global SET RESULT SET UPDATE COUNT ON statement.
UPDATE COUNT OFF is not allowed in stored procedures or triggers or in ESQL.
You can refer to the function declaration or use the GET PARAMETERS statement to
determine the formal type of each parameter.
You must initialize the variables used as IN and INOUT parameters to valid values
before executing the SET statement. RDMS returns an error on an uninitialized input
parameter if its contents are not legal for its data type.
You must use the parentheses in all cases, even if the function has no parameters.
9.11.2. Example
In the following example, the function SELECT_HOUSES returns the number of houses
that meet the criteria in placeholder variable $P2 and places that value in the
placeholder variable $P1.
SET $p1=house_schema.select_houses($p2);
Use the standard SET statement in a routine or trigger to invoke a stored function.
Use the standard SET statement (see 9.11) in a routine or trigger to assign a value to a
variable or parameter.
Errors
If an error occurs during the execution of a routine or trigger, control returns
immediately to the caller. The caller must examine the error variable for more
information (refer to Appendix B and Appendix D).
where:
OFF
indicates no count returned in the auxiliary information parameter.
RECORD COUNT
requests only the record count returned in the auxiliary information parameter.
(This is the default.)
PAGE COUNT
requests the page count returned in H1 of the auxiliary information parameter and
record count returned in H2.
9.12.2. Example
The following example directs RDMS to return an auxiliary information parameter
value showing the page count and the record count returned on succeeding
statements where appropriate:
Use of SET AUXINFO in static ESQL has no worthwhile effect. In order to obtain the
desired count information, it must be used in either dynamic ESQL or the interpreter
interface.
Note: Do not send AUXINFO as anything other than an elementary data item;
otherwise, RDMS rejects it.
UCS COBOL
01 aux-info PIC S9(9) BINARY
01 aux-inf REDEFINES aux-info.
02 aux-info-page-count PIC S9(5) USAGE BINARY.
02 aux-info-rec-count PIC S9(5) USAGE BINARY.
If you are using the ESQL interface, aux-info should be defined as follows:
01 RDMCA.
02 ERROR-STATUS PIC 9(4).
02 aux-info PICS9(9)BINARY.
02 aux-inf REDEFINES aux-info.
03 aux-info-page-count PIC S9(5)USAGE BINARY.
03 aux-info-rec-count PIC S9(5) USAGE BINARY.
ASCII COBOL
01 aux-info PIC S9(10) USAGE COMP.
01 aux-inf REDEFINES aux-info.
02 aux-info-page-count PIC S9(5) USAGE COMP.
02 aux-info-rec-count PIC S9(5) USAGE COMP.
UCS C
int aux_info=0;
int aux_pages=0;
int aux_recs=0;
long aux;
aux=aux_info;
aux_pages=aux_info>>18;
aux_recs=aux_info & 0777777;
UCS FORTRAN
INTEGER auxinfo, auxpgs, auxrec
auxpgs=BITS(auxinf,1,18)
auxrec=BITS(auxinf,19,18)
SET UPDATE COUNT ON can be overridden on the SET return-variable = ... and
CALL statements by including the syntax UPDATE COUNT OFF.
9.13.2. Examples
SET RESULT SET ON
Usage
See 4.7 for a description of dynamic result sets.
Scope
The SET RESULT SET statement is only available through the interpreter interface.
Restrictions
SET RESULT SET UPDATE COUNT ON can only be issued if SET RESULT SET ON has
already been issued.
If both SET RESULT SET and SET RESULT SET UPDATE COUNT have been turned on,
the statement SET RESULT SET OFF turns UPDATE COUNT off as well.
Update Counts
Callers may want to know how many records were affected by each insert, update, or
delete performed by a stored procedure. By turning on UPDATE COUNT, you are
requesting RDMS to insert a record into its temporary result set table that indicates
the line number and the number of records affected each time the stored procedure
performs an INSERT, UPDATE, or DELETE statement.
22 55 SCH OUTER_PROC
27 1 SCH INNER_PROC
These results indicate that 55 records were affected by the statement at line 22 of the
procedure OUTER_PROC, and just one record was affected by the statement at line 27
of the nested procedure INNER_PROC.
If both update counts and return cursors are produced by a stored procedure
execution, all of the update count records are returned first.
9.14.2. Example
The table T contains an identity column. It is the value of the IDENTITY column that we
specify in the following examples. Runs are named A, B, and C.
The execution of runs A, B, and C were interleaved as shown in the following table.
The execution flows from left to right. Therefore, run A inserts value 1, followed by
run B which inserts value 2, followed again by run A which inserts value 3, and so on.
1 2 3 4 5 6 7
A B A B C B A
The following table shows what is fetched from cursor C1, doing a brute force search
of the primary key b-tree that scans records from left to right starting from the record
with value 1. Given the specified value of SKIPGENERATED, ignore the deadlocks
caused by this fetching. Assume that fetching of each line of the table is independent
of every other.
Assume that run A has committed, but runs B and C are still uncommitted. * indicates
a record that is committed. The fact that run A has committed, does not change
anything with its own selects.
1 2 3 4 5 6 7
* B * B C B *
9.15.2. Example
The following example directs RDMS to use a previously collected set of statistics:
SET STATISTICS ON
Statistics On or Off?
Statistics use is on or off based on the value of the UREP configuration attribute
RDMS-SET-STATISTICS-DEFAULT. If that value is OFF, RDMS does not use statistics
unless you execute a SET STATISTICS ON statement.
When statistics is turned on, RDMS uses the most recently collected set of statistics
to optimize access paths (the frequency of collection is determined by the database
administrator).
When statistics is turned off, RDMS determines access paths by using a general set of
assumptions.
Suggested Use
The use of statistics on a query specification that refers to some tables for which
statistics were gathered and some for which statistics were not gathered can result in
a poorly chosen access path.
If you have not gathered statistics, use SET STATISTICS OFF. If you use SET
STATISTICS ON, RDMS must spend time looking up the statistics.
Obtaining Statistics
Statistics on table contents are gathered by the RUN STATISTICS statement of the
RDMUTL processor. For more information about the RDMUTL processor, see the
Relational Database Server for ClearPath OS 2200 Administration Guide.
Scope
When used in the interpreter interface or dynamic ESQL, the SET STATISTICS
statement turns statistics use on or off for interpreter interface or dynamic ESQL
statements that are executed after the SET STATISTICS statement, until the thread is
ended or until another SET STATISTICS statement is executed, whichever occurs first.
When used in static ESQL, the SET STATISTICS statement turns statistics use on or off
for static ESQL statements that follow it in the source code but that precede any other
static ESQL SET STATISTICS statements in the source code.
The access path of a cursor is determined only when it is declared, not when it is
opened or fetched. This means that the SET STATISTICS statement, when used before
a DECLARE statement, affects all further use of that cursor, even if the use of
statistics is changed before the cursor is opened or fetched.
In ESQL, the access path of a statically declared cursor is determined during program
compilation, which means that interpreter or dynamic use of SET STATISTICS during
program execution has no effect on a static ESQL cursor.
This section contains reference information about the following SQL statements:
• UNLOAD (10.1)
• UNLOCK (10.2)
• UPDATE ALL (10.3)
• UPDATE Positioned (10.4)
• UPDATE Searched (10.5)
• UPDATE SYNCHRONIZE (10.6)
• UPDATE VALUES (10.7)
• USE DEFAULT (10.8)
• WHENEVER (10.9)
10.1. UNLOAD
Use the UNLOAD statement to dump selected rows into a system data format (SDF)
file.
where:
SDF
directs RDMS to create a file with SDF images and SDF control words. This is the
default. The SDF file type may be generated USING SDFO or USING IO.
PCIOS
directs RDMS to create a file with PCIOS images and PCIOS control words. The
PCIOS file type may be generated USING IO.
file-name
is an existing Exec mass storage or tape file name. (Since certain characters, like
the hyphen, are allowed in a file name but not in an RDMS name, enclose the file
name in quotation marks.) The file name should not be more than 30 characters. If
the file name is longer than 30 characters, attach a USE name (@USE) to the file
before executing this statement.
If the file is a tape file, you must use the USING SDFO clause.
file-name2
is an Exec large program file. (The same naming rules apply as for file-name
except that tape files are not allowed, no file cycle is allowed, and the implicit file
cycle must be 1.) RDMS stores BLOB data as omnibus elements in this file. This is
true regardless of the size of the BLOB or whether the BLOB is stored in the
record or in an RDMS LOB storage-area. A large program file has a limit of 26,146
elements. When performing an UNLOAD of a filename with the maximum of 12
characters, you must catalog the filename with 0 to 7 characters of your choice
and with the last 5 characters 00001.
qualifier*0-to-7-character-file-name00001.
00001
A00001
OUTBLOB00001
ABCDEFG00001
When the BLOB data requires more than one program file, RDMS looks for a file
with the same name, ending with 00002, then 00003, and so on, up to a limit of
64000, the maximum number of files that can be cataloged in a system. You can
catalog as many files as are required to store the BLOB data.
RDMS first tries to @ASG the file. If it does not exist, RDMS then catalogs the file
using the maximum size of a large program file with no initial reserve. If you want
to set initial reserve, you must catalog the file yourself. When cataloging a file, you
must catalog the file using positions instead of tracks.
To calculate the number of files required to unload BLOB data, use the following
formula:
If the result of the division has any fractional part, round the value up to the next
whole number. The end result is the number of files required to store the BLOB
values for the table.
SDFO
directs RDMS to use the SLIB routine SDFO to write the images to the file. SDFO
can only generate an SDF file type. You must use this clause for a tape file.
IO
directs RDMS to use ER IO$ to write images to the file. This is the default. IO can
generate either SDF or PCIOS file types.
cursor-name
is the name of a declared cursor (see 7.4).
query-expression
is a query that can include query specifications, the set operators UNION and
UNION ALL, and query terms, in the form
where:
query-term
is a separate query specification, or a subexpression in parentheses, of the
query expression in the form
{ query-specification │ (query-expression) }
UNION [ALL]
lets you derive a result table by combining two other result tables. The result
of a UNION operation is the set of all rows in either tables with duplicate rows
eliminated. Two rows are duplicates if each value in the first is equal to the
corresponding value in the second. Two null values are considered equal. The
result of a UNION ALL operation contains all rows from both tables.
sort-specification-list
is a list of column-specifications or ordinal numbers (see 7.4).
EXTERNAL
(default) directs RDMS to convert retrieved items into ASCII display format. RDMS
places the data items of each column in the file according to how you specify
them in the position-and-null list.
External files are suitable for transfer to other systems. RDMS tables can be
loaded from EXTERNAL format files; however, the INTERNAL format is more
efficient.
position-and-null-list
specifies how to format the output file. A position-and-null statement specifies
the range of print columns into which RDMS places a data value in an SDF output
file and also explains how to represent nulls in that file. The list is a sequence of
positions-and-null specifications separated by commas.
where:
Be careful not to overlap the item position of one data item with that of
another. You must allocate enough CHARACTER columns to accommodate
the longest possible value of the data item. For example, if you defined a
column to be 40 characters in the CREATE TABLE statement, you must
allocate at least 40 characters for it in the item position. If you do not
specify end-column, the end column is determined by the length of the
data item (plus 1 for the decimal point if the item is a decimal) as defined
in 6.10.
NULL IS string-literal
is the character string to place in the output file whenever nulls are
encountered in data columns. If omitted, blanks are inserted if nulls are
encountered.
If the NULL IS clause is for a BLOB column, the string-literal to place in the
output file must not start with a number.
List the item positions in the same order in which the columns are specified in the
SELECT clause of the UNLOAD or DECLARE CURSOR statement.
INTERNAL
directs RDMS to format values in the file in a way that is internal to RDMS. The
section on the RDMUTL processor in the Relational Database Server for
ClearPath OS 2200 Administration Guide further describes this format.
INTERNAL format files can be used only as input to the RDMUTL LOAD statement.
MAPPER
directs RDMS to use the length of each data item to determine its CHARACTER
column range and to prefix each data item's value with a tab character. This makes
the output file suitable for input to the MAPPER RETRIEVE function (with the P
option).
TAB
directs RDMS to prefix each data item value with a tab character. The TAB
keyword is synonymous with MAPPER.
COMMA
directs RDMS to separate data item values with commas.
PIPE
directs RDMS to separate data item values with the pipe ( | ) character (vertical
bar).
WITHOUT DESCRIPTION
(default) directs RDMS not to place a description of the data into the output file.
CSV
comma-separated values; directs RDMS to separate data item values with
commas, removing any unnecessary leading and trailing spaces. Data item values
are delimited by double quotes if needed. CSV format only works with USING IO
(the default). If using PCIOS as the file type, up to three extra spaces may be
added following the last data item value of each record. If WITH DESCRIPTION is
specified, the column position of the data item values are the maximum values.
10.1.2. Examples
Example 1
The following example does not specify a format. It unloads all columns from table
S1.CUSTOMERS to file CUSTOMERS2. RDMS uses the EXTERNAL format for the files
because the example does not specify a format.
>DESCRIPTION<
1 C4 1:4 S1.CUSTOMERS:PRODUCTION.CNO
2 C28 6:33 S1.CUSTOMERS:PRODUCTION.CNAME
3 D12.0 35:46 S1.CUSTOMERS:PRODUCTION.MAXPRICE
4 C40 48:87 S1.CUSTOMERS:PRODUCTION.DESIREDLOC
>END DESCRIPTION<
C101 Thompson 150000 Woodbury
C102 Owen 70000 New London
C103 Johnson 90000 Woodbury
C104 Jones 100000
C105 Smith 120000 Westchester
Customer C104 has no desired location; therefore, column DESIREDLOC is null. Since
the representation for nulls is not specified, all spaces is used by default.
Example 2
This example uses INTERNAL format with description:
>DESCRIPTION<
1 C4 1:4 S1.HOUSES:PRODUCTION.HNO
2 C28 5:32 S1.HOUSES:PRODUCTION.LOCATION
3 D14.2 33:46 S1.HOUSES:PRODUCTION.PRICE
0 C3 47:49 NULL INDICATOR BYTES
>END DESCRIPTION<
H101Woodbury +0000013000000~~~
H102Woodbury +0000004000000~~~
H103Westchester +0000009000000~~~
H104 +0000008500000~N~
H105Turtle Creek +0000011000000~~~
The values in the price columns do not contain a decimal point because RDMS does
not explicitly format decimal points in INTERNAL format. In addition, a plus sign and
leading zeros are explicit in INTERNAL format.
The characters in columns 47 to 49 of the file are null indicator bytes. The location
column for house H104 contains a null.
Example 3
This example selects columns MAXPRICE, CNAME, and DESIREDLOC from table
CUSTOMERS in the illustrated format:
>DESCRIPTION<
1 D12.0 4:15 S1.CUSTOMERS:PRODUCTION.MAXPRICE
2 C28 18:45 S1.CUSTOMERS:PRODUCTION.CNAME
3 C40 49:88 S1.CUSTOMERS:PRODUCTION.DESIREDLOC
>END DESCRIPTION<
150000 Thompson Woodbury
70000 Owen New London
90000 Johnson Woodbury
100000 Jones XXXXXXXX
120000 Smith Westchester
Customer Jones has no desired location; therefore, column DESIREDLOC is null. The
null is represented by XXXXXXXX, as specified in the UNLOAD statement.
Example 4
This example unloads a join of tables HOUSES and CUSTOMERS. It lists all houses for
each customer where the price of the house is not more than the customer’s
maximum price and the house itself is located in the customer's desired location.
Since the bank currently requires a minimum down payment of 6.85 percent, this
example also includes the minimum down payment to purchase each house. To
unload this information into a file, enter the following DECLARE CURSOR and UNLOAD
statements:
>DESCRIPTION<
1 C28 1:28 Customer Name
2 C4 30:33 House #
3 C28 35:62 RDMS.HOUSES:PRODUCTION.LOCATION
4 D15.2 64:78 RDMS.HOUSES:PRODUCTION.PRICE
5 D20.6 80:99 Min Down Pymt
>END DESCRIPTION<
Johnson H102 Woodbury 40000.00
2740.000000
Smith H103 Westchester 90000.00
6165.000000
Thompson H102 Woodbury 40000.00
2740.000000
Thompson H101 Woodbury 130000.00
8905.000000
This example also illustrates how a title name appears in the description portion of the
output.
Example 5
This example contains an additional BLOB column ‘picture’ in table HOUSES. The
UNLOAD statement selects HNO, LOCATION, PRICE, and PICTURE from table
HOUSES. See the Relational Database Server for ClearPath OS 2200 Administration
Guide for the content of an SDF file internal lob-id and an SDF file external lob-id.
>DESCRIPTION<
1 C4 3:6 S1.HOUSES:PRODUCTION.HNO
2 C28 8:35 S1.HOUSES:PRODUCTION.LOCATION
3 D14.2 37:50 S1.HOUSES:PRODUCTION.PRICE
4 L35M 52:75 S1.HOUSES:PRODUCTION.PICTURE
>END DESCRIPTION<
H101 Woodbury 130000.00 200001 0021
H102 Woodbury 40000.00 200001 0022
H103 Westchester 90000.00 200001 0023
H104 Parkway Heights 85000.00 200001 0024
H105 Turtle Creek 110000.00 200001 0025
3 6 8 35 37 50 52 75
H101 Woodbury 130000.00 200001 0021 (Ext. lob-id)
H102 Woodbury 40000.00 200001 0022 (Ext. lob-id)
H103 Westchester 90000.00 200001 0023 (Ext. lob-id)
H104 Parkway Heights 85000.00 200001 0024 (Ext. lob-id)
H105 Turtle Creek 110000.00 200001 0025 (Ext. lob-id)
UNLOAD TO FILE "customers6", "blobb00001"
SELECT hno, location, price, picture
FROM s1.houses
FORMAT INTERNAL
WITH DESCRIPTION
>DESCRIPTION<
1 C4 1:4 S1.HOUSES:PRODUCTION.HNO
2 C28 5:32 S1.HOUSES:PRODUCTION.LOCATION
3 D14.2 33:46 S1.HOUSES:PRODUCTION.PRICE
4 L35M 47:70 S1.HOUSES:PRODUCTION.PICTURE
>END DESCRIPTION<
H101Woodbury +0000013000000100001~
H102Woodbury +0000004000000100001~
H103Westchester +0000009000000100001~
H104Parkway Heights +0000008500000100001~
H105Turtle Creek +0000011000000100001~
1 4 5 32 33 46 47 70
H101 Woodbury +0000013000000 100001~ (Int. lob-id)
H102 Woodbury +0000004000000 100001~ (Int. lob-id)
H103 Westchester +0000009000000 100001~ (Int. lob-id)
H104 Parkway +0000008500000 100001~ (Int. lob-id)
Heights
H105 Turtle Creek +0000011000000 100001~ (Int. lob-id)
Example 6
This example selects columns MAXPRICE, CNAME, and DESIREDLOC from table
150000,Thompson,Woodbury
70000,Owen,New London
90000,Johnson,Woodbury
100000,Jones,
120000,Smith,Westchester
Customer Jones has no desired location; therefore, DESIREDLOC is null. For CSV
format, no characters are printed for a null column.
Cursors
For ESQL UNLOAD statements, the cursor must already be opened either with an
OPEN statement or, for a cursor declared through the interpreter interface, opened
implicitly with a preceding FETCH statement through the interpreter interface.
If you are unloading data from a cursor declared through ESQL, you must first open
the cursor. If the cursor is positioned after its last row, no rows are unloaded.
If the cursor was declared through the interpreter interface and placeholders are
present in the cursor declaration, it must be opened. If the cursor is positioned after
its last row, all rows are unloaded.
Regardless of how the cursor was declared, if it is positioned at or before the last
row, RDMS writes all rows following the current row to the output file. For example, if
you declare a cursor that has more than two rows and then execute two FETCH NEXT
statements before executing an UNLOAD statement, the file includes all but the first
two rows of the cursor.
Query Expressions
If you have a query expression in the UNLOAD statement, RDMS copies all selected
rows to the output file. The query expression can include up to 14 base tables or
global temporary tables. If a base table or global temporary table is specified more
than once, each specification counts towards the maximum of 14. If a view is specified
in the query expression, it does not count towards this limit; however, each of its
underlying base or global temporary tables does count.
If the data image is greater than 8,188 characters in length, RDMS generates
continuation images. If the unload file type is PCIOS, RDMS generates PCIOS
continuation images, signaled by the segmentation flag in the PCIOS image control
word. If the unload file type is SDF, RDMS generates continuation control records
(051). See the Data Structures Programming Reference Manual for more information
about system data format. The OS 2200 editors do not handle continuation images.
When reading an unload file with a processor or program, see the applicable reference
manual to find how long images are handled. For example, to read an unload file from
a COBOL program, it is necessary to specify the device type DISC in the FILE
CONTROL paragraph to avoid truncation of long images.
Performance
When unloading many rows, you should lock the tables being loaded in PROTECTED
RETRIEVAL, EXCLUSIVE RETRIEVAL or EXCLUSIVE UPDATE mode (see 9.3).
Otherwise, RDMS locks each row or page you unload, significantly slowing execution
of the UNLOAD statement.
Including the USING IO clause on the UNLOAD statement improves the performance
of the UNLOAD command up to 40 percent, depending on the length of the RDMS
records. With longer records, you will see more improvement in performance.
Descriptions
The LOAD statement of the RDMUTL processor ignores the description.
Auxiliary Information
The number of rows unloaded is returned to the program through the auxiliary
information parameter or the ESQL AUX-INFO variable.
EXTERNAL Clause
All information in the EXTERNAL clause position-and-null list is optional. The following
syntax is acceptable:
This is a list of four items, with no formatting information for the second or fourth
items. This list can be used when the select list contains four items, as there must be
one position-and-null statement for each item in the select list.
If the select and external lists do not match, an error status is returned. The above
FORMAT clause directs RDMS to place an asterisk ( * ) into the output file if it finds a
null in the first data column. All other columns either have no nulls or RDMS uses the
default representation (blanks). All values are placed into the output file according to
the table definition except the third value, which is placed in print columns 41 to 43.
If you want to control the format of even just one data column, you must provide a
position-and-null statement for each column selected.
No Finds
The UNLOAD statement never returns a 6001 no-find error status or an SQLCODE
of +100. If no records satisfy the query specification or remain in the cursor, RDMS
returns an OK status of 0000 or an SQLCODE of zero, and the auxiliary information
variable is set to zero.
INTERNAL Format
When you use FORMAT INTERNAL, RDMS adds information about nulls at the end of
each line in the file. One character is added for each column that allows nulls. These
additional print columns are arranged in the same order as the columns in the select
list that allow nulls.
If a data item in a row is null, its corresponding null indicator character is N in the
row’s line in the file.
If the data item is not null, the null indicator character is a tilde ( ~ ).
The LOAD statement uses these bytes to determine whether any data values are null.
See the Relational Database Server for ClearPath OS 2200 Administration Guide.
The following example illustrates the first line of the output file with description:
>DESCRIPTION
>END DESCRIPTION
Descriptions of each data item appear between DESCRIPTION and END DESCRIPTION.
Each column description fits on one line.
When you specify FORMAT MAPPER, RDMS places the lines of data in the data file in
MAPPER tab type lines. This means that RDMS separates each data item with a tab
character.
If you specify WITH DESCRIPTION in addition to FORMAT MAPPER, RDMS places the
description lines in the file as MAPPER comment lines. This means that each line of
description text starts with a period in column 1.
The data files created by RDMS are not true MAPPER format files as used in a
MAPPER report. This means that you should place an N in the MAPPER FORMAT field
on the RET P function request screen when loading the file into a MAPPER report.
In addition, place a Y in the HEADERS field on the RET P function request screen;
RDMS does not place a header in the data field. By placing a Y in this field, you are
directing the MAPPER system to insert the standard header for the type of report
being loaded.
The resulting file is as follows, where number signs ( # ) indicate the location of tab
characters:
Note: If a column with data type BLOB is projected, RDMS issues an error. You
cannot use the UNLOAD MAPPER command for tables with BLOB columns.
file-name2
Use of file-name2 is optional. RDMS actions are as follows.
Note: If you want to unload to the same program file with two or more UNLOAD
commands, you must perform an End Thread after the previous UNLOAD is done,
then a Begin Thread before doing another UNLOAD to the same program file. This is
because UDS Control keeps the file assigned until the End Thread, and does not
allow the Exec to reassign the program file within the same thread after the
program file is freed.
Refer to PLE #17384937 if you want to unload the data from a table without unloading
the BLOB values.
Column number
The ordinal number of the column as found in the SELECT clause of the
UNLOAD or DECLARE CURSOR statement. It is an integer in CHARACTER
columns 1 to 4, left-justified, and space-filled.
Column type
A single character in column 6 that indicates the type of data in the column:
A DATE
B NUMERIC
C CHARACTER
D DECIMAL
F FLOAT
I INTEGER
L BLOB
M TIMESTAMP
N NATIONAL CHARACTER
P DOUBLE PRECISION
R REAL
S SMALLINT
T TIME
If the format is INTERNAL for datetime data types (DATE, TIME, and
TIMESTAMP), refer to Table 2-10.
If the format is EXTERNAL or MAPPER for datetime data types, see 2.7.3.
If the format is INTERNAL, the size of a DECIMAL column is the same as the
size specified in the CREATE TABLE statement. Similarly, the scale is the same
scale specified in the CREATE TABLE statement.
For a BLOB column, the integer value must be between 1 and 4096M. If the
number is larger than 5 digits, it is rounded up to either K (1,024 bytes) or M
(1,048,576 bytes). Any number between 1 to 99999 is specified as it is. Any
number between 100,000 to 10,238,976 is rounded up as 98K to 9999K. Any
number between 10,238,977 to 4,294,967,296 is rounded up as 10M to 4096M.
Column name
The fully qualified name of the column in the form
qualifier-name.table-name:version-name.column-name
This begins in column 23. The column name does not appear in all cases. In
general, if a name can be deduced from the DECLARE CURSOR statement or
the SELECT clause in the UNLOAD statement (from a UNION operation, for
example), it is included in the description.
On the other hand, if a statement such as the following is used, no name can
be deduced for the single column selected:
In such a case, the words “result of arithmetic expression” appear, rather than
the column name.
If INTERNAL format is used for columns allowing nulls, the last description line in this
item reads “null indicator bytes.”
10.2. UNLOCK
Use the UNLOCK statement to release the locking protocol for one or more tables.
10.2.2. Example
The following example releases any explicit locks on tables HOUSES and
CUSTOMERS:
UNLOCK houses,customers
Restrictions
The UNLOCK statement has the following restrictions:
• If the thread has an active cursor accessing a table, RDMS rejects the UNLOCK
statement.
• RDMS immediately releases any retrieval lock (RETRIEVAL, SHARED RETRIEVAL,
PROTECTED RETRIEVAL, or EXCLUSIVE RETRIEVAL).
• The UNLOCK statement releases only explicit table level locks created by the
LOCK statement. Row level locks in place when you execute the UNLOCK
statement are not affected.
The following example releases any explicit locks on tables HOUSES and
CUSTOMERS, but avoids any confusion if RDMS encounters an error while executing
either UNLOCK statement:
UNLOCK houses
UNLOCK customers
XTC
If the application group is configured for Extended Transaction Capacity (XTC), the
UNLOCK statement affects the entire storage area in which the table to be unlocked
resides. If one table in a storage area is unlocked, all other tables in the same storage
area (if any exist) remain locked until they are unlocked individually.
where:
table-specification
is a table name as defined in 2.2.2.
change-specification-list
is a list of column names and the values for each data item in a column. The list is
one or more entries in the form
[ ( ] column-name=value-specification
[ ,column-name=value-specification ] ...[ ) ]
In place of a value (for example, 1, NULL, ‘a’) in the value-specification you can
now specify the DEFAULT keyword. If a value of DEFAULT is specified for a
column, it works as follows:
embedded-variable-specification-list
is a list of variable pairs (see 2.10) into which the values of the updated columns
are to be placed. The number of variables in the list must equal the number of
columns being updated.
If you update more than one row on the UPDATE statement, the embedded
variables contain the values of the columns in the last row updated.
10.3.2. Example
The following example changes the price of all houses in table HOUSES to $150,000:
UPDATE houses
CHANGE ALL ROWS price = 150000
As a result, all rows in table HOUSES have a value of 150000 in column PRICE.
Locking, Committing
RDMS locks updated rows so that other threads cannot access them until these rows
are committed to the database.
When you update the primary key of more than one row at a time, RDMS first deletes
all affected rows and then reinserts them.
Unique Constraints
When you update any columns defined as a unique constraint and the update results
in duplicate values, RDMS returns an error and rolls back any updates. For more
information on unique constraints, see 6.11.
When you update the columns of a foreign key for a child table (as defined by a
foreign key constraint), all new values being assigned to the foreign key columns must
exist as values in the referenced columns (that is, the columns of either the primary
key or a unique constraint) of the parent table.
If a violation is encountered before any updates actually occur, RDMS returns an error
but no rollback occurs. If a violation is encountered during the update process, RDMS
returns an error and rolls back any updates.
For a self-referencing foreign key constraint (that is, the same table is both the parent
and child), any check for violations is deferred until after the update. A rollback always
occurs for a self-referencing foreign key violation.
Check Constraints
If the column specified in the UPDATE statement is bound to a column or table check
constraint and the new value for the column violates the check constraint, RDMS
returns an error and rolls back any updates.
Auxiliary Information
RDMS returns the number of rows updated through the auxiliary information variable.
For more information, see the reference manual for the programming language you
are using.
10.4.1. Syntax
SQL 92 Syntax (Entry Level)
UPDATE table-specification
SET change-specification-list
UPDATE table-specification
SET change-specification-list
UPDATE table-specification
where:
table-specification
is a table name as defined in 2.2.2.
change-specification-list
is a list of column names and the values for each data item in a column. The list is
one or more entries in the form
column-name=value-specification
[ ,column-name=value-specification ] ...
The list can be enclosed in parentheses in RDMS extended syntax but not in
standard SQL syntax.
cursor-name
is the name of the cursor with the current row being updated.
To reference the cursor in an UPDATE statement, you must follow these rules:
• If the FOR UPDATE OF clause is used by the cursor definition, only those
columns listed by the cursor can be listed in the UPDATE statement change
specification.
• The table specification in the UPDATE statement must be the same as the
table specification in the cursor's FROM clause.
• A FETCH statement executed before the UPDATE statement must
successfully fetch a row from the cursor specified in the UPDATE statement.
If FETCH NEXT n is used on the cursor, positional UPDATE statements are not
allowed and are rejected.
embedded-variable-specification-list
is a list of variable pairs (see 2.10) into which the values of the updated columns
are to be placed. The number of variables in the list must equal the number of
columns being updated.
If you update more than one row on the UPDATE statement, the embedded
variables contain the values of the columns in the last row updated.
10.4.2. Example
The following example illustrates a positional cursor update:
The FETCH FIRST statement returns data on house H101, the FETCH NEXT statement
returns data on house H102, and the UPDATE statement changes the price of house
H102 to $35,000.
Locking, Committing
RDMS locks updated rows so that other threads cannot access them until these rows
are committed to the database.
• First, fetch all the cursor records into your program and then issue an UPDATE
Searched statement for each record fetched.
• Perform an UNLOAD of all the cursor records and read the resulting file in your
program; issue an UPDATE Searched statement for each record read.
• Use the INSERT . . . SELECT statement to insert the records selected by the cursor
WHERE clause into a working table that you place in a storage area with AUDITED
FALSE and RECOVERED FALSE and that you lock in EXCLUSIVE UPDATE mode.
Declare a cursor to fetch records from this working table. For each record fetched,
issue an UPDATE Searched statement against the original table.
• If you have a UNIQUE constraint on the table and are not updating UNIQUE
columns, specify predicates against the leading columns of the UNIQUE constraint
in the WHERE clause so that the UNIQUE constraint is selected as the cursor
access path. Update of primary key columns WHERE CURRENT OF CURSOR using
a UNIQUE constraint as its access path does not cause records to be fetched
twice, unless UNIQUE columns are also updated.
Note: The same problem can occur if you fetch and update records from a cursor
one at a time even if the update is performed using the UPDATE Searched or
UPDATE VALUES statement.
When you update the primary key, RDMS first deletes the row and then reinserts it
with its new primary key value.
Unique Constraints
When you update any columns defined as a unique constraint and the update results
in duplicate values, RDMS returns an error and rolls back any updates. For more
information on unique constraints, see 6.11.
When you update the columns of a foreign key for a child table (as defined by a
foreign key constraint), all new values being assigned to the foreign key columns must
exist as values in the referenced columns (that is, the columns of either the primary
key or a unique constraint) of the parent table.
If a violation is encountered before any updates actually occur, RDMS returns an error
but no rollback occurs. If a violation is encountered during the update process, RDMS
returns an error and rolls back any updates.
For a self-referencing foreign key constraint (that is, the same table is both the parent
and child), any check for violations is deferred until after the update. A rollback always
occurs for a self-referencing foreign key violation. If a violation is encountered during
the update process, RDMS returns an error and rolls back any updates.
Check Constraints
If the column specified in the UPDATE statement is bound to a column or table check
constraint and the new value for the column violates the check constraint, RDMS
returns an error and rolls back any updates.
Auxiliary Information
RDMS returns the number of rows updated through the auxiliary information variable.
For more information, see the reference manual for the programming language you
are using.
In routines, the RDMSAUXINFO system variable can be used to obtain this information.
See 4.9.1.
The cursor must be opened using the OPEN statement and positioned on a row by a
FETCH statement prior to the execution of the UPDATE statement.
10.5.1. Syntax
SQL 92 Syntax (Entry Level)
UPDATE table-specification
SET change-specification-list
[ WHERE Boolean-expression ]
UPDATE table-specification
[ WHERE Boolean-expression ]
UPDATE table-specification
SET change-specification-list
[ WHERE Boolean-expression ]
where:
table-specification
is a table name as defined in 2.2.2.
change-specification-list
is a list of column names and the values for each data item in a column. The
list is one or more entries in the form
column-name=value-specification
[ ,column-name=value-specification ]...
The list can be enclosed in parentheses in RDMS extended syntax but not in
standard SQL syntax. For a description of value-specification, see 10.3.
Boolean-expression
specifies the rows to be updated. If omitted, all rows are updated. For more
information on Boolean expressions, see 2.4.2.
embedded-variable-specification-list
is a list of variable pairs (see 2.10) into which the values of the updated
columns are to be placed. The number of variables in the list must equal the
number of columns being updated.
If you update more than one row on the UPDATE statement, the embedded
variables contain the values of the columns in the last row updated.
10.5.2. Examples
The following example changes the asking price for house number H101 in table
HOUSES to $150,000:
UPDATE houses
SET price = 150000
WHERE hno = 'H101'
The following example illustrates how to use one UPDATE statement to change the
asking price of two houses:
UPDATE houses
SET price = 150000
WHERE hno = 'H101' OR hno = 'H102'
The following example illustrates how to update the price of a house by an inflation
factor of 3 percent. It also uses an embedded variable specification to return the new
price into the embedded variable NEWPRICE. This eliminates the need to perform a
separate retrieval operation to find the updated value.
Locking, Committing
RDMS locks updated rows so that other threads cannot access them until these rows
are committed to the database.
When you update the primary key of more than one row at a time, RDMS first deletes
all affected rows and then reinserts them.
Unique Constraints
When you update any columns defined as a unique constraint and the update results
in duplicate values, RDMS returns an error and rolls back any updates. For more
information on unique constraints, see 6.11.
When you update the columns of a foreign key for a child table (as defined by a
foreign key constraint), all new values being assigned to the foreign key columns must
exist as values in the referenced columns (that is, the columns of either the primary
key or a unique constraint) of the parent table.
If a violation is encountered before any updates actually occur, RDMS returns an error
but no rollback occurs. If a violation is encountered during the update process, RDMS
returns an error and rolls back any updates.
For a self-referencing foreign key constraint (that is, the same table is both the parent
and child), any check for violations is deferred until after the update. A rollback always
occurs for a self-referencing foreign key violation.
Check Constraints
If the column specified in the UPDATE statement is bound to a column or table check
constraint and the new value for the column violates the check constraint, RDMS
returns an error and rolls back any updates.
Auxiliary Information
RDMS returns the number of rows updated through the auxiliary information variable.
For more information, see the reference manual for the programming language you
are using.
In routines, the RDMSAUXINFO system variable can be used to obtain this information
(see 4.9.1).
WHERE Boolean-expression
where:
table-specification
is a table name as defined in 2.2.2.
value-list
is a list that can contain any combination of
• String literals
• Numeric constants
• Datetime literals
• CAST functions
• Variable specifications
• The keywords NULL or USER
• The datetime functions CURRENT_DATE, CURRENT_TIME, or
CURRENT_TIMESTAMP
Arithmetic expressions are not allowed. Use commas to separate the values.
You must specify values for every column in the table. In addition, these values
must be listed in the same sequence in which the columns are defined in the
CREATE TABLE statement.
Boolean-expression
specifies the row to be updated. For more information on Boolean expressions,
see 2.4.2.
embedded-variable-specification-list
is a list of variable pairs (see 2.9) into which the values of the updated columns are
to be placed. The number of variables in the list must equal the number of
columns being updated.
10.6.2. Examples
Example 1
The following example calls UPDATE SYNCHRONIZE twice, with synchronization
turned on, for house number H106 in the HOUSES sample table. Assume that house
H106 does not exist for the first call to UPDATE SYNCHRONIZE, and that then the
house is sold and its row of data is obsolete and a new listing needs to be added. The
same HNO value (H106) can be retained and new values for the other columns
inserted.
The HNO column is the primary key. You are changing only the last three columns, but
you must include a data item for every column in the table. You must place the data
items in the same order in which the columns were originally defined.
UPDATE houses
SYNCHRONIZE VALUES ('H106', 'Big Town', 400000, '3000 sq ft overlooking
golf course')
WHERE hno = 'H106'
UPDATE houses
SYNCHRONIZE VALUES ('H106', 'Suburb', 80000, 'handyperson special')
WHERE hno = 'H106'
Example 2
The ESQL example that follows shows how the UPDATE SYNCHRONIZE statement
can be used in a C program. The example also demonstrates the use of indicator
variables.
#include <rsa.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <rsa$clib>
EXEC SQL BEGIN DECLARE SECTION;
char v_hno[5];
int ind_var_hno = 0;
char v_location[80];
int ind_var_location = 0;
int v_price = 400000;
int ind_var_price = 0;
char v_description[40];
int ind_var_description = 0;
EXEC SQL END DECLARE SECTION;
main(void)
{
/* This update will insert a new record into the houses table. */
printf("Insert the new record into the houses table using update with synchronize. \n");
/* This will update the record with HNO equal to H106 in the houses table. */
ind_var_hno = 0;
ind_var_location = 1; /* setting the indicator variable to 1 will not update this column */
ind_var_price = 0; /* the value in the PRICE column will be updated */
ind_var_description = -1; /* the value in DESCRIPTION will be set to null */
strcpy(v_location, “Suburb”);
v_price = 80000;
strcpy(v_description, “handyperson special”);
printf("Update the values in the houses table using UPDATE SYNCHRONIZE . \n");
EXEC SQL
END THREAD TERMINATE;
printf("end thread terminate\n");
return(0);
Locking, Committing
RDMS locks the updated row so that other threads cannot access it until the row is
committed to the database. UPDATE SYNCHRONIZE immediately XU locks the page
that contains the record to be updated, or where the record will be inserted. This
reduces the possibility of deadlocks, in comparison to using the UPDATE VALUES,
UPDATE SEARCHED, or INSERT statements, by eliminating lock upgrades. It also
improves performance in the XTC environment by eliminating at least one trip to the
RLP. If you have deadlocks caused by lock upgrades or performance issues caused by
the number of trips to the RLP, it could be beneficial to change your UPDATE
statements to UPDATE SYNCHRONIZE statements.
Unique Constraints
When you update any column defined as a unique constraint and the update results in
duplicate values, RDMS returns an error and rolls back any updates. For more
information on unique constraints, see 6.11.
When you update the columns of a foreign key for a child table (as defined by a
foreign key constraint), all new values being assigned to the foreign key columns must
exist as values in the referenced columns (that is, the columns of either the primary
key or a unique constraint) of the parent table.
If a violation is encountered before any updates actually occur, RDMS returns an error
but no rollback occurs. If a violation is encountered during the update process, RDMS
returns an error and rolls back any updates.
For a self-referencing foreign key constraint (that is, the same table is both the parent
and child), any check for violations is deferred until after the update. A rollback always
occurs for a self-referencing foreign key violation.
Check Constraints
If the column specified in the UPDATE statement is bound to a column or table check
constraint and the new value for the column violates the check constraint, RDMS
returns an error and rolls back any updates. The Boolean expression cannot refer to a
subquery that contains the table being updated in its FROM clause.
Auxiliary Information
RDMS returns 1, the number of rows updated, through the auxiliary information
variable. For more information, see the reference manual for the programming
language you are using.
WHERE Boolean-expression
where:
table-specification
is a table name as defined in 2.2.2.
value-list
is a list of any combination of string literals, numeric constants, datetime literals,
CAST functions, variable specifications, the keywords NULL and USER, or the
datetime functions CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP.
Arithmetic expressions are not allowed. Use commas to separate the values.
You must specify values for every column in the table. In addition, these values
must be listed in the same sequence in which the columns are defined in the
CREATE TABLE statement.
Boolean-expression
specifies the rows to be updated. For more information on Boolean expressions,
see 2.4.2.
embedded-variable-specification-list
is a list of variable pairs (see 2.10) into which the values of the updated columns
are to be placed. The number of variables in the list must equal the number of
columns being updated.
If you update more than one row on the UPDATE statement, the embedded
variables contain the values of the columns in the last row updated.
10.7.2. Example
The following example updates values for house number H101 in table HOUSES.
Assume that house H101 is sold and that its row of data is obsolete and a new listing
needs to be added. The same HNO value (H101) can be retained, and new values for
the other columns inserted.
The HNO column is the primary key. You are changing only the last three columns, but
you must include a data item for every column in the table. You must place the data
items in the same order in which the columns were originally defined.
UPDATE houses
CHANGE VALUES ('H101','Camden',40000,'Cottage')
WHERE hno = 'H101'
Locking, Committing
RDMS locks updated rows so that other threads cannot access them until these rows
are committed to the database.
When you update the primary key of more than one row at a time, RDMS first deletes
all affected rows and then reinserts them.
Unique Constraints
When you update any columns defined as a unique constraint and the update results
in duplicate values, RDMS returns an error and rolls back any updates. For more
information on unique constraints, see 6.11.
When you update the columns of a foreign key for a child table (as defined by a
foreign key constraint), all new values being assigned to the foreign key columns must
exist as values in the referenced columns (that is, the columns of either the primary
key or a unique constraint) of the parent table. If a violation is encountered during the
update process, RDMS returns an error and rolls back any updates.
For a self-referencing foreign key constraint (that is, the same table is both the parent
and child), any check for violations is deferred until after the update. In any case, a
rollback always occurs with a foreign key violation. For more information about foreign
keys, see 6.11.
Check Constraints
If the column specified in the UPDATE statement is bound to a column or table check
constraint and the new value for the column violates the check constraint, RDMS
returns an error and rolls back any updates.
Auxiliary Information
RDMS returns the number of rows updated through the auxiliary information variable.
For more information, see the reference manual for the programming language you
are using.
Performance
When the primary key does not need to be changed (as the example illustrates), it is
more efficient to use the UPDATE Searched statement (see 10.5).
where:
schema-name
is the schema name. The keywords QUALIFIER and SCHEMA are synonymous.
The terms schema-name and qualifier-name are used synonymously in RDMS.
See 2.2.2 for information on using the default schema name.
placeholder
is a placeholder for a host program variable that contains a name. Placeholders are
allowed only through the interpreter interface.
version-name
is the version name.
10.8.2. Examples
Example 1
The following example sets the default schema name to HOUSE_SCHEMA:
Example 2
In the following example, the default schema name is the value of the application
program variable associated with the placeholder variable, $P1:
Example 3
The following example sets the default version name to TUESDAY:
Example 4
When a cursor refers to a table without explicitly specifying a qualifier or version
(see 6.1 and 7.4), RDMS uses the default qualifier name when you declare the cursor
and the default version when you open the cursor. If an OPEN statement is not
required (see 9.4.3), RDMS implicitly opens the cursor when you first fetch it.
active_version Function
The active_version function returns the current default version value.
Scope
A USE DEFAULT statement that is executed at run time (through either the interpreter
interface or dynamic ESQL) establishes a default qualifier or version name for all
interpreter interface and dynamic ESQL statements that execute after it, until another
run-time USE DEFAULT statement is executed.
A static ESQL USE DEFAULT statement establishes a default qualifier or version name
for all static ESQL statements that textually follow it in the source code until the next
static ESQL USE DEFAULT statement.
For example, assume a portion of a UCS COBOL program looks like this:
The first DELETE statement deletes rows from table STAY.X; the second DELETE
statement affects table TRANS.X.
Neither interactive nor dynamic embedded USE DEFAULT VERSION statements affect
the execution of static ESQL statements. To dynamically specify the version used by a
static ESQL statement, pass the version as a parameter to the static ESQL statement.
See 2.2.2 for more information.
Placeholders
A qualifier or version name contained in a placeholder is subject to the rules for
delimited identifiers (see 2.2.1). In particular, lowercase letters are not equivalent to
uppercase characters.
The default qualifier and version name remain in effect for the life of a thread, or until
you establish new default names.
The system configuration determines the thread default qualifier name for all tables
unless you establish a new default qualifier name.
The thread default version name for all tables is PRODUCTION unless you establish a
new default version name.
As with the qualifier name, RDMS uses the default version name when you omit the
version name on a table specification.
• Section 4
• 8.8 (FUNCTION)
• 9.6 (PROCEDURE)
10.9. WHENEVER
Use the WHENEVER statement to direct a UCS COBOL or UCS C program of the action
to take if RDMS encounters an error while executing an SQL statement.
where:
SQLERROR
refers to an abnormal error status (negative value in SQLCODE).
NOT FOUND
refers to the SQLCODE no-find status of +100 on a retrieval statement
(see C.3).
CONTINUE
directs the program to execute the program statement following the ESQL
statement that generates the condition specified in this WHENEVER
statement.
GOTO or GO TO
directs the program to jump to the paragraph or label named if the ESQL
statement encounters the condition specified in this WHENEVER statement.
paragraph-name
is the name of a paragraph or label in the program.
10.9.2. Examples
The following example has the UCS COBOL program proceed without breaking its
normal flow of control if an ESQL statement encounters an error:
Scope
A WHENEVER statement with either SQLERROR or NOT FOUND affects all ESQL
statements that textually come after it and before the next WHENEVER statement
with the same condition in the source code.
Code Suggestion
To avoid looping if an ESQL error occurs, place a WHENEVER statement in the
error-handling code.
Keywords (called tokens in standard SQL) include reserved and nonreserved words.
Table A–1 lists reserved words and Table A–2 lists nonreserved words.
A keyword has a special meaning to RDMS. You cannot use RDMS reserved words as
names for identifiers managed by RDMS (for example, for tables and columns).
Avoid using SQL89, SQL92, and SQL99 reserved words as identifiers, because they
may become unavailable as new features are added to RDMS.
COLUMN, COLUMNS
INT, INTEGER
NULL, NULLS
QUALIFIER, SCHEMA
BOTH BOTH
BREADTH
BY BY BY
CALL CALL
CASCADE CASCADE CASCADE
CASCADED CASCADED
CASE CASE
CAST CAST
CATALOG CATALOG
CHAR CHAR CHAR
CHARACTER CHARACTER CHARACTER
CHAR_LENGTH
CHARACTER_
LENGTH
CHECK CHECK CHECK CHECK
CLASS
CLOB
CLOSE CLOSE CLOSE
COALESCE
COBOL COBOL
COLLATE COLLATE COLLATE
COLLATION COLLATION
COLUMN COLUMN COLUMN
COLUMNS
COMMIT COMMIT COMMIT
COMPLETION
CONNECT CONNECT
CONNECTION CONNECTION
CONSTRAINT CONSTRAINT CONSTRAINT
CONSTRAINTS CONSTRAINTS
CONSTRUCTOR
CONTINUE CONTINUE CONTINUE CONTINUE
CONVERT
CORRESPONDING CORRESPONDING
COUNT COUNT COUNT
CREATE CREATE CREATE CREATE
CROSS CROSS
CUBE
CURRENT CURRENT CURRENT CURRENT
CURRENT_DATE CURRENT_DATE CURRENT_DATE
CURRENT_PATH
CURRENT_ROLE
CURRENT_TIME CURRENT_TIME CURRENT_TIME
CURRENT_ CURRENT_ CURRENT_
TIMESTAMP TIMESTAMP TIMESTAMP
CURRENT_USER CURRENT_USER
CURSOR CURSOR CURSOR CURSOR
CYCLE
DATA DATA
DATE DATE DATE
DAY DAY
DEALLOCATE DEALLOCATE
DEC DEC DEC
DECIMAL DECIMAL DECIMAL
DECLARE DECLARE DECLARE
DEFAULT DEFAULT DEFAULT DEFAULT
DEFERRABLE DEFERRABLE
DEFERRED DEFERRED
DELETE DELETE DELETE
DEPTH
DEREF
DESC DESC DESC
DESCRIBE DESCRIBE
DESCRIPTOR DESCRIPTOR
DESTROY
DESTRUCTOR
DETERMINISTIC
DIAGNOSTICS DIAGNOSTIC
DICTIONARY
DISCONNECT DISCONNECT
DISTINCT DISTINCT DISTINCT DISTINCT
DO
DOMAIN DOMAIN
DOUBLE DOUBLE DOUBLE DOUBLE
DROP DROP DROP
DYNAMIC
EACH
ELSE ELSE ELSE
ELSEIF
END END END END
ENDÄEXEC ENDÄEXEC
END IF
END WHILE
EQUALS
ESCAPE ESCAPE ESCAPE ESCAPE
EVERY
EXCEPT EXCEPT EXCEPT
EXCEPTION EXCEPTION
EXEC EXEC EXEC EXEC
EXECUTE EXECUTE
EXISTS EXISTS EXISTS
EXIT
EXPLAIN
EXTERNAL EXTERNAL
EXTRACT
FALSE FALSE
INITIALLY INITIALLY
INNER INNER
INOUT INOUT
INPUT INPUT
INSENSITIVE
INSERT INSERT INSERT
INT INT INT INT
INTEGER INTEGER INTEGER INTEGER
INTERSECT INTERSECT INTERSECT
INTERVAL INTERVAL
INTO INTO INTO INTO
IPF
IS IS IS IS
ISOLATION ISOLATION
ITERATE
JOIN JOIN
KEY KEY KEY KEY
LARGE
LAST LAST LAST
LATERAL
LEADING LEADING
LEFT LEFT
LESS
LEVEL LEVEL
LIKE LIKE LIKE LIKE
LIMIT
LOCAL LOCAL
LOCALTIME
LOCALTIMESTAMP
LOCATOR
LOWER
MATCH MATCH
REF
REFERENCES REFERENCES REFERENCES REFERENCES
REFERENCING
REFERS
RELATIVE RELATIVE RELATIVE
RENAME
RESTRICT RESTRICT RESTRICT
RESULT
RETURN RETURN
RETURNS RETURNS
REVOKE REVOKE
RIGHT RIGHT
ROLE
ROLLBACK ROLLBACK ROLLBACK
ROLLUP
ROUTINE
ROW
ROWS ROWS ROWS
SAVEPOINT
SCHEMA SCHEMA SCHEMA SCHEMA
SCOPE
SCROLL SCROLL SCROLL
SEARCH
SECOND SECOND
SECTION SECTION SECTION SECTION
SELECT SELECT SELECT SELECT
SEQUENCE
SESSION SESSION
SESSION_USER SESSION_USER
SET SET SET SET
SETS
SIZE SIZE
TO TO TO
TRAILING TRAILING
TRANSACTION TRANSACTION TRANSACTION
TRANSLATE
TRANSLATION TRANSLATION
TREAT
TRIGGER TRIGGER
TRIM
TRUE TRUE
UNDER
UNION UNION UNION UNION
UNIQUE UNIQUE UNIQUE UNIQUE
UNKNOWN UNKNOWN
UNNEST
UNOWNED
UPDATE UPDATE UPDATE
UPPER
USAGE USAGE
USER USER USER USER
USING USING USING
VALUE VALUE
VALUES VALUES VALUES
VARIABLE
VARYING VARYING
VIEW VIEW VIEW VIEW
VIEWS
WHEN WHEN
WHENEVER WHENEVER WHENEVER WHENEVER
WHERE WHERE WHERE WHERE
WHILE
WITH WITH WITH WITH
WITHOUT WITHOUT
This appendix discusses error messages returned by RDMS. It explains how to obtain
a list of current error messages from the release tape, categorizes the messages, and
suggests methods for correcting errors.
RSAC-MSG
MCON-RDM
RDMS-UPMSPEC
1. Check for the 6001 status if you use the FETCH or SELECT statement. The status is
not really an error, but means rather that no data (or no further data) is available to
retrieve.
2. Check to see whether the status is not in the 6000 to 6999 or 8000 to 8999 range.
Errors outside these ranges are RDMS errors, which usually mean that something
is wrong with the syntax, the parameters you are passing to RDMS, or the manner
in which you are passing the parameters. A program can print the status, auxiliary
information variable, and error messages (with the GETERROR statement). You
may then want to terminate the program and debug it.
3. You must handle errors in the 6000 to 6999 or 8000 to 8999 range. These
statuses represent errors detected by RDMS, the Data Definition Facility (DDF), or
some other component of UDS. When one of these statuses is returned, you can
check the rollback status in the auxiliary information variable and retrieve error
message text with the GETERROR statement.
IPF SQL users see error messages automatically. In IPF SQL, you can obtain more
information about an error message (if more information exists) by entering a question
mark (?) immediately after receiving the error message.
Error messages returned by other UDS components (and some error messages by
RDMS) have the following form:
where:
xx
is the application group number in columns 5 and 6.
ccc
is the abbreviation for the UDS component in columns 8 to 10:
yy
is the message category in columns 13 and 14:
zzzzz or ZZZZ
is the message number in columns 16 to 20, or 8 to 11, depending on the form of
the message.
Several messages may be returned at one time. The first message is usually the most
significant.
The two types of rollbacks are thread rollbacks and command rollbacks:
• Thread rollbacks cause the current step to end and all changes made during the
step to be discarded. All step-duration locks are released and all cursors are
closed.
• Command rollbacks discard changes made from the beginning of the statement to
the point where the error was detected, but do not release locks or close cursors.
A command rollback can occur only when COMMANDLOOKS recovery is used.
Whether a thread rollback occurs as the result of an RDMS error depends on several
factors:
• Message category
All rollback category errors (numbered 50000 to 69999) always cause a thread
rollback. IN and EX errors (numbered 0 to 49999) may or may not cause a thread
rollback, depending on other factors.
• Recovery option
Since command level recovery is available only when you specify the
COMMANDLOOKS recovery option, RDMS converts command rollbacks into
thread rollbacks for many errors when you specify QUICKLOOKS, DEFERRED, or
NONE as the recovery option.
• Error situation
In certain cases, one type of error may or may not cause a thread rollback,
depending on the situation in which the error was detected. For example, some
errors cause a thread rollback when detected during an update statement; they do
not, however, cause a rollback if detected during an insert statement.
• Status returned by RDMS
RDMS returns a status to the user program in the range 6000 to 6012 when an
error is detected. Certain statuses are associated with certain types of rollbacks.
For example, 6000 and 6002 do not accompany thread rollback; 6007 may or may
not accompany a thread rollback; and 6010 always accompanies a thread rollback.
Since certain error messages do not always accompany a rollback, you should
always check for the rollback status in the auxiliary information variable. This
variable returns one of three values:
0 The statement executed normally, and no rollback occurred.
1 The statement was not executed, and the thread was not rolled back.
2 The statement was not executed, and a thread rollback occurred.
Note: For more information about an error status marked with an asterisk ( * ), see
the Relational Database Server for ClearPath OS 2200 Administration Guide.
Status Meaning
Status Meaning
6019 * An attempt was made to access a record in a primary key or secondary index
partition which is detached. The thread has been rolled back.
6020 * An attempt was made to retrieve, insert, update, or delete a record in a
primary key or secondary index partition which is hidden. Records in a hidden
partition are invisible to SQL commands. The thread has been rolled back.
6021 * An attempt was made to insert or move a record so that it is not within the
range of any partition. The thread has been rolled back.
6022 The called stored procedure returned dynamic result sets (see 4.7). AUXINFO
contains the number of result sets returned.
6023 The called stored procedure attempted to return more result sets than the
value of max-result-sets specified by the DYNAMIC RESULT SETS clause.
The number of result sets was limited to the specified value of
max-result-sets.
6024 Internal error in the interface between JDBC and RDMS. The size of the PCA
is too small. Please resubmit the request with a larger area. AUXINFO
contains the required size. The command was executed.
6025 Internal error in the interface between JDBC and RDMS. The section passed
to RDMS is out of date because it references a table whose definition has
been altered since the section was optimized. The command was not
executed.
6026 Internal error in the interface between JDBC and RDMS. The PCA is not large
enough to contain the section. The command was not executed. AUXINFO
contains the required size.
6027 Internal error in the interface between JDBC and RDMS. The statement
executed but was re-optimized. The description of the cursor is different
from that returned when the cursor was originally optimized. The previous
description should be discarded.
6028 Internal error in the interface between JDBC and RDMS. There is no PCA
available for this command. RDMS needs a PCA for the compiled section. The
command was not executed.
6029 Internal error in the interface between JDBC and RDMS. The OPEN CURSOR
failed because the size, or precision, of a program variable passed on the
OPEN is not compatible with the size, or precision, of that program variable
value passed on DECLARE CURSOR.
1. Check for locking conflict status 6004 if you locked tables using the ON CONFLICT
RETURN specification. If this is not the case, 6004 should never occur and can be
grouped with the other error statuses. Status 6004 means that RDMS returned
control to you instead of queuing. The action the program should take depends on
the reason for inhibiting queuing; you may wish to go on to the next operation and
try again later.
Unless you are using COMMANDLOOKS recovery or read-only mode, the thread
was probably rolled back, in which case you must repeat any UPDATE, DELETE,
INSERT or OPEN statement in the step rolled back.
2. Check for deadlock status 6010. If more than one thread is attempting to access a
table at the same time, a deadlock is probable and the program should handle it.
One way to handle it is to wait one second and then repeat all the DELETE,
UPDATE, INSERT, and OPEN statements in the step rolled back by the deadlock.
If another deadlock occurs while repeating these statements, repeat the process
up to a determined reasonable limit to prevent infinite looping. If this is occurring
in several threads simultaneously, you may want to choose the wait time
randomly to reduce looping.
3. Handle all other error statuses in the same way. Use the GETERROR statement to
retrieve the error text. The program should print the message to inform the user
of the error situation. If the AUX-INFO variable indicates that a thread rollback
occurred, you may want to repeat the UPDATE, DELETE, and OPEN statements
before continuing or stopping the program.
Based on your experience with various errors, you may want to handle certain
errors in special ways. This requires that the program examine the text of the
message to extract the error number in columns 15 to 19 of the message and the
component (for example, RDM) in columns 7 to 9. Unisys reserves the right to
change, delete, add, or renumber errors in future releases.
B.5. SQLSTATE
Using the SQLSTATE variable is the preferred SQL 92 standard method for checking
the successful completion of an SQL statement. SQLCODE, however, is still supported
by the standard and by RDMS (see C.3, “Using SQLCODE in an ESQL Program”).
• If the error caused the transaction to roll back, an SQLSTATE value of class 40 is
returned regardless of any other possible SQLSTATE mapping.
• If the particular condition (such as “no data”) is defined by SQL 92, RDMS returns
the SQL 92 SQLSTATE value.
• If the particular condition (such as “base table not found”) is defined by ODBC,
RDMS returns the ODBC SQLSTATE value.
• If neither of the preceding two conditions is true, RDMS defines an SQLSTATE
value that consists of the character U followed by the RDMS error status, and
returns it. (Error status 6013 has an associated SQLSTATE value of U6013, for
example.) For information about RDMS error message groups, see B.2; for a
description of RDMS error statuses, see B.3.3.
The following table illustrates the mapping between the RDMS error status,
SQLCODE, and SQLSTATE.
SQLSTATE Error
SQLSTATE Error
APP 3 RDM IN 6000 The following RDM messages were encountered while compiling
routine, HOUSE_SCHEMA.RSA1080 :
APP 3 RDM IN 7010 *ERROR 1080: This command is not allowed within a stored
procedure, function, or trigger :
The technique for this kind of source formatting varies with the programming
language used to interface with RDMS.
This appendix discusses tools and methods for handling ESQL errors during program
execution.
You can use these tools alone or in combination. For example, a program can use all of
the tools or just SQLSTATE, GETERROR, and AUX-INFO.
Error handling is not warranted for static ESQL statements that are processed entirely
during program compilation. These statements include the following:
fetch-para.
EXEC SQL WHENEVER NOT FOUND GO TO fetch-exit END-EXEC.
(do fetch)
GO TO fetch-para.
fetch-exit.
EXIT.
The value in SQLCODE after an SQL statement is executed indicates the completion
status of that SQL statement.
In some cases, this simplifies the migration to ESQL. To migrate an existing interpreter
interface program to ESQL without using SQLCODE, perform the following steps:
1. Replace the declaration of the variables passed as the second and third
parameters in the ENTER MASM ‘ACOB$RDMR’ statements with the following:
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 RDMCA.
02 ERROR-STATUS PIC 9(4)
02 AUX-INFO PIC S9(9) BINARY.
EXEC SQL END DECLARE SECTION END-EXEC.
The variables within the RDMCA must appear within the DECLARE section and be
spelled ERROR-STATUS and AUX-INFO.
2. Modify the program to use RDMCA.ERROR-STATUS and RDMCA.AUX-INFO.
3. Change the ENTER MASM syntax in the program to ESQL syntax.
• Replace existing tests of ERROR-CODE, the error status variable used by the
program, with the WHENEVER statement where possible:
ᔭ “IF ERROR-CODE <> OK” can sometimes be replaced with “WHENEVER
SQLERROR GO TO <label>”.
ᔭ “IF ERROR-CODE = ‘6001’” (a not-found condition) can sometimes be replaced
with “WHENEVER NOT FOUND GO TO <label>”.
• Replace remaining comparisons of ERROR-CODE to zero with a comparison of
SQLCODE to zero.
• Replace remaining comparisons of ERROR-CODE to ‘6001’ with a comparison of
SQLCODE to +100.
• Replace remaining comparisons of ERROR-CODE to anything other than ‘6001’ (for
example, ‘nnnn’) with a comparison of SQLCODE to -nnnn.
Examples
The following are valid examples of the GETERROR statement:
All of these examples are acceptable syntax and retrieve text for ESQL, or for SQL
statements that are not embedded.
Note that the second and third examples do not have the embedded prefix and suffix,
and that the third example does not have the colon prefix for embedded variables.
The embedded prefix and suffix are optional on the GETERROR statement. The colon
prefix is also optional on embedded variables.
SQLCODE, ERROR-STATUS, and AUX-INFO are not changed on the GETERROR call.
Note: If an error occurs in the execution of an ESQL statement, you must execute
the GETERROR statement through ESQL also. Similarly, you must execute the
GETERROR statement following an erring interpreter interface SQL statement
through the interpreter interface.
By declaring RDMCA in the embedded declarative section of the DATA DIVISION, you
have access to the 4-digit RSA error status and auxiliary information. This includes the
rollback status and the number of records affected by an UPDATE, DELETE, INSERT, or
REVOKE statement.
For more information on declaring and using the RDMCA variables, see the COBOL
Compiler Programming Reference Manual Volume 2.
This appendix explains how to use SQL statements from an ASCII COBOL program. It
discusses only the interpreter interface. ESQL is not available from ASCII COBOL
programs.
where:
sql-statement
is a literal or program variable containing an SQL statement.
error-status
is a PIC XXXX (or 9999 DISPLAY) item that, upon completion of the
ENTER MASM statement, contains the error status of that SQL statement. A
value of ‘0000’ means that the statement has no errors. Use a variable name
such as ERRSTAT to hold the error status value. For more information, see
Table D–1.
auxiliary-information
is a multipurpose 1-word numeric item that, upon completion of the ENTER
MASM statement, contains useful information about error-status. You must
declare this variable as S1(36) or S9(10) USAGE COMP. For more information,
see Table D–1.
ERROR-
STATUS Contents of AUXILIARY-INFORMATION
* If the SET AUXINFO statement was not used, or SET AUXINFO RECORD COUNT
was used, then the contents for the auxiliary-information parameter will display
as indicated.
For SET AUXINFO PAGE COUNT, the first half of aux-info gives the count of
modified pages; the second half gives the count of modified rows.
where:
ERRSTAT
is the program variable that receives the error status messages from RDMS.
AUXINF
is the program variable that contains any auxiliary information about the
statement.
Note: The variables ERRSTAT and AUXINF are program variables defined in the
application program.
Alphanumeric edited and USAGE DISPLAY-1 (Fieldata) characters are not supported.
RDMS does not allow the following application program variable arguments:
• Numeric edited
• Alphanumeric edited
• USAGE DISPLAY-1 (Fieldata characters)
• Any attempt to store into a constant
If the application program variable argument is an unsigned numeric item, RDMS strips
any sign before storing a value into the application program variable argument.
You can store any data type into an alphanumeric program variable argument. RDMS
also stores numeric items as a string with a decimal point inserted at the proper
position. You can store only numeric values in numeric program variable arguments.
RDMS converts the different numeric data types as needed.
You can take one of the following two steps to obtain the information you need. Both
require reexecuting the program.
CBEP$$RSA
RDMR-ACOBDAT
Find these elements in the first of the two RDMS product files for a particular
application group. For the default application group, this file is SYS$LIB$*RSA. Ask the
database administrator for the name of the file in any other application groups.
Example
This example illustrates how to collect an ASCII COBOL program that has SQL
statements:
@MAP,I ,USER.PROGRAM/ABS
LIB COBOL*LIBRARY.
IN USER.PROGRAM/REL
IN SYS$LIB$*RSA.CBEP$$RSA
IN SYS$LIB$*RSA.RDMR-ACOBDAT
END
If the ASCII COBOL program also calls DMS or SFS, other steps are necessary. For
details, see the Universal Data System Configuration Guide.
Since RDMS uses the full 262K address window, UDS Control must transfer some of
the program's data to and from the UDS address space. The following data must be
transferred:
This data must reside between 024000 (10K) and 0615000 (203K).
None of the program data banks should overlap the RSA basic mode common bank,
C$RDMRPLB4.
This bank resides between locations 01000 and 037777. If the program banks start
below 040000, an overlap may occur and the results are unpredictable. You may get
incorrect results, irrelevant error statuses, hangups, loops, or contingencies. RDMS
returns statement statuses to programs through a parameter in the program data
bank. An overlap may therefore make it impossible for RDMS to report any error
condition.
CALL 'RSA$INIT'.
• AUX-INFO
This variable receives the column position if RDMS detects an error. It also
receives information if an UPDATE, DELETE, REVOKE, INSERT, or LOCATE
statement is issued. None of these statements are in this program.
• ERROR-STATUS
This is the variable into which RDMS places the status of each statement. It must
be four ASCII characters.
• The following four variables correspond to the placeholder variables in the FETCH
statement. Each variable receives the value of the corresponding data column in
the fetched row. Variables must have data types compatible with their associated
column data types.
Hno
Locus
Price
Desc
The choice of names is unimportant. However, you must have COBOL program
variables for the error status, the error column, and the fetched values of each
column.
Since the BEGIN THREAD statement does not use the UDSMESSAGES option,
each call to ACOB$RDMR is followed by a check of the error status.
IDENTIFICATION DIVISION.
PROGRAM-ID. list-houses.
AUTHOR. DAA
DATE-WRITTEN. 1998 August 11
DATE-COMPILED.
*
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. UNIVAC-1100.
OBJECT-COMPUTER. UNIVAC-1100.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 aux-info PIC S9(10) USAGE COMP.
01 aux-inf redefines aux-info.
02 aux-page-count PIC S9(5)USAGE COMP.
02 aux-record-count PIC S9(5)USAGE COMP.
01 error-status PIC 9999.
01 result.
10 FILLER OCCURS 4.
15 error-line PIC X(132).
01 i PIC 9999.
01 err-end-flag PIC 9999.
01 hno PIC X(4).
01 locus PIC X(28).
01 price PIC S9(10) SIGN LEADING SEPARATE.
01 desc PIC X(40).
01 label-line.
04 FILLER PIC X(4) VALUE IS 'Hno'.
04 FILLER PIC X(1) VALUE IS ' '.
04 FILLER PIC X(28) VALUE IS 'Location'.
04 FILLER PIC X(1) VALUE IS ' '.
04 FILLER PIC X(10) VALUE IS 'Price'.
04 FILLER PIC X(1) VALUE IS ' '.
04 FILLER PIC X(40) VALUE IS 'Description'.
*
PROCEDURE DIVISION.
*
main-control SECTION.
*
go-to-it.
*
D.7.3. Output
After compilation, collection, and execution, this example COBOL program provides
the following output:
This appendix explains how to use SQL statements from an ASCII FORTRAN program.
It discusses only the interpreter interface. ESQL is not available from ASCII FORTRAN
programs.
where:
F$RDMR
is the entry point into RDMS for ASCII FORTRAN.
sql-statement
is a CHARACTER item, a string or program variable containing a statement.
error-status
is a CHARACTER*4 item that, when it exits the CALL command, contains the
status of the statement. The value '0000' means that the statement did not
terminate in or cause an error. For more information, see Table E–1.
auxiliary-information
is a multipurpose INTEGER item that, when it exits the CALL command, contains
useful information, depending on the value of error-status or the type of
statement. For more information, see Table E–1.
program-variable-1,...,n
are application program variable names. Each application program variable is
associated with a placeholder variable ($P1, $P2, and so forth) in the statement.
You must declare at least one program variable in the program.
* If the SET AUXINFO statement was not used, or SET AUXINFO RECORD COUNT
was used, then the contents for the auxiliary-information parameter will display
as indicated.
For SET AUXINFO PAGE COUNT, the first half of aux-info will give the count of
modified pages; the second half will give the count of modified rows.
ERROR is the variable that contains the error status. AUXINF is the application program
variable that contains additional information about the SQL statement.
RDMS treats LOGICAL program variable arguments as if they were type INTEGER.
Program labels and subprograms are not valid program variable arguments.
Constants are not allowed as program variable arguments that are to receive data
from RDMS.
You can compile subprograms that do not call F$RDMR to ignore type checking for
arguments.
The F$RDMR procedure has no fixed number of parameters. This violates FORTRAN
conventions, and the compiler may issue warning messages as a consequence.
These warnings can be safely ignored.
F$RDMR does not accept banked data. The program aborts when you pass banked
data to F$RDMR.
You can take one of the following two actions to obtain the information you need.
Both require re-executing the program.
CBEP$$RSA
RDMR-ACOBDAT
Find these elements in the first of the two RDMS product files for a particular
application group. For the default application group, this file is SYS$LIB$*RSA. Ask the
database administrator for the name of the file in any other application groups.
Example
This example illustrates how to collect an ASCII FORTRAN program that contains SQL
statements:
@MAP,I ,USER.PROGRAM/ABS
LIB FORTRAN*LIB.
IN USER.PROGRAM/REL
IN SYS$LIB$*RSA.CBEP$$RSA
IN SYS$LIB$*RSA.RDMR-ACOBDAT
END
Because RDMS uses the full 262K address window, UDS Control must transfer some
of the program’s data to and from the UDS address space. The following data must be
transferred:
This data must reside between 024000 (10K) and 0615000 (203K).
None of the program data banks should overlap the RSA common bank,
C$RDMRPLB4.
This bank resides between locations 01000 and 037777. If the program banks start
below 040000, an overlap may occur and the results are unpredictable. You may get
incorrect results, irrelevant error statuses, hangups, loops, or contingencies. RDMS
returns the status of statements to programs through a parameter in the program
data bank. An overlap may therefore make it impossible for RDMS to report any error
condition.
CALL RSA$IN
• auxinf
This variable receives the column position if RDMS detects an error. It also
receives information if an UPDATE, DELETE, or REVOKE statement is issued. None
of these statements are in this program.
• errcod
This is the variable into which RDMS places the status of each statement. It must
be four ASCII characters.
• The following four variables correspond to the placeholder variables in the FETCH
statement. Each variable receives the value of the corresponding data column in
the fetched row. Variables must have data types compatible with their associated
column data types.
cno
cname
maxpri
desloc
The choice of names is unimportant. However, you must have FORTRAN program
variables for the error status, the error column, and the fetched values of each
column.
Since the BEGIN THREAD statement does not use the UDSMESSAGES option,
each call to F$RDMR is followed by a call to a subroutine to check the error status
in errcod. This subroutine is passed to the error column, error status, the expected
status (if it is not 0000), and two return points, one to receive control if an
unexpected error is encountered, the other if the error status is expected.
• Since the error checking subroutine, errchk, calls F$RDMR (to perform GETERROR
statements), it declares the following variables. (To avoid truncated error message
lines, each of these variables must be able to hold up to 80 characters.)
C
C
C
C Main program to dump the relations CUSTOMERS
C ******************************************
C
C
C
INTEGER auxinf, auxpgs, auxrec
CHARACTER*4 errcod
CHARACTER*4 cno @ The first column (CNO)
CHARACTER*28 cname @ The second (CNAME)
REAL maxpri @ The third (Maxprice)
CHARACTER*40 desloc @ The fourth (DesiredLoc)
C
C
C Connect to UDS and submit a USE command
C
C
CALL F$RDMR('BEGIN THREAD FOR APPLICATION udssrc READ;',
$ errcod,auxinf)
CALL errchk(errcod,auxinf,' ',*90,*90)
CALL F$RDMR(’SET AUXINFO PAGE COUNT;’,errcod, auxinf)
CALL F$RDMR('USE DEFAULT QUALIFIER realty;',
$ errcod,auxinf)
CALL errchk(errcod,auxinf,' ',*90,*90)
CALL F$RDMR(’UPDATE houses SET price=150000 WHERE hno=$P1;’,errcod,auxinf,p1)
auxpgs=BITS(auxinf,1,18)
auxrec=BITS(auxinf,19,18)
CALL errchk(errcod,auxinf,' ',*90,*90)
C
C
C Dump the relation
C
C
C
C Define the cursor
C
C
CALL F$RDMR('DEFINE CURSOR dmprel SELECT * FROM customers ;',
$ errcod, auxinf)
CALL errchk(errcod,auxinf,' ',*90,*90)
C
C
C Open the relation
C
C
CALL F$RDMR('OPEN CURSOR dmprel;', errcod, auxinf)
CALL errchk(errcod,auxinf,' ',*90,*90)
C
C
C Loop to read and print the rows
C
C
10 CONTINUE
CALL F$RDMR('FETCH NEXT dmprel INTO $p1,$p2,$p3,$p4;',
$ errcod, auxinf, cno, cname, maxpri, desloc)
CALL errchk(errcod,auxinf,'6001',*90,*20)
PRINT '(1X,A,1X,A,F12.2,1X,A)', cno, cname, maxpri, desloc
GO TO 10
C
C
C End of relation found
C
C
20 CONTINUE
PRINT '(17H0End of relation)'
CALL F$RDMR('END THREAD;', errcod, auxinf)
CALL errchk(errcod, auxinf, ' ', *90, *90)
PRINT '(23H0Normal end of program.)'
STOP
90 CONTINUE
PRINT '(39H0***** Error status terminated program.)'
STOP
END
C
C
C
C Subroutine to check the status returned by RDMS
C **********************************************
C
C
SUBROUTINE errchk(errcod, auxinf, accept, *, *)
C
CHARACTER*4 accept @ Acceptable status for RETURN 2
INTEGER colloc,auxinf
CHARACTER*4 errcod,errloc
CHARACTER*132 p1,p2,p3,p4
IF (errcod.EQ.'0000') RETURN
IF (errcod.EQ.accept) RETURN 2
PRINT '(31H0***** Unexpected error status ,A,11H at column
* ,I3)',
* errcod, auxinf
CALL F$RDMR('GETERROR INTO $p1,$p2,$p3,$p4;',
* errloc, colloc, p1, p2, p3, p4)
IF (errloc .NE. '0000') THEN
PRINT '(20H ***** Error status ,A,14H from GETERROR)',
* errloc
ELSE
CALL prres
END IF
RETURN 1
C
C
C Internal subroutine to print the result of a GETERROR statement
C
C
SUBROUTINE prres
IF (p1 .NE. ' ') PRINT '(1X,A)', p1
IF (p2 .NE. ' ') PRINT '(1X,A)', p2
IF (p3 .NE. ' ') PRINT '(1X,A)', p3
IF (p4 .NE. ' ') PRINT '(1X,A)', p4
RETURN
END
E.8.3. Output
After compilation, collection, and execution, this example FORTRAN program provides
the following output:
This appendix describes some restrictions when using RDMS from an HVTIP
environment.
In the HVTIP run-time environment, only the main program D-bank space remains
intact during the program’s entire execution. Space is allocated to subprograms when
they are called; it is deallocated when they return to their callers. Unpredictable results
can occur if the program includes calls to RDMS in different compilation units (where
each unit contains a copy of the RDMS D-bank space element RDMR-ACOBDAT,
which is collected with it), unless you take the precautions described in this appendix.
The following items require carryover of information in the RDMS D-bank area
between calls to RDMS:
• GETERROR statement
The GETERROR statement requires the last statement status, relational data
management communication area (RDMCA), and possibly various GETERROR
counters to be in place.
• GET DESCRIPTION statement
The data description packet must be available (from the DECLARE CURSOR
statement), and only one column description is available per call. Various counters
are retained between calls. If the GET DESCRIPTION statement is executed in the
same program module in which the DECLARE CURSOR statement appears, you
should have no problem.
• FETCH NEXT statement shortcut
To take advantage of the performance shortcut on FETCH statements, RDMS
must be able to retain information between FETCH statements. If FETCH NEXT
statements execute within a single program module, there should be no problem.
• DEBUG statement
DEBUG flags are set in the RSA work area. Debugging takes place only within the
program module in which the DEBUG statement is executed.
Note: If you are programming in C, use the rsa function to call RDMS. The C
function for passing parameters is rsa_param.
This appendix explains how to use the RSA$PARAM subroutine to pass the maximum
number of parameters and indicators plus the three required parameters (statement
string, error status, and auxiliary information) to RDMS from a host language on an
ENTER MASM call.
All host languages have a limit on how many parameters can be passed on an
interpreter interface call. Use the RSA$PARAM subroutine to pass the maximum
number of parameters and indicators plus the three required parameters (command
string, error status, and auxiliary information).
Call RSA$PARAM to build a list of parameters, and then call it again as many times as
necessary to pass variables before calling ACOB$RDMR (or F$RDMR, as appropriate).
You must pass the command string, error status variable, and auxiliary information
variable when you call ACOB$RDMR. If fewer than the maximum number of variables
remain to pass to RDMS for this statement, you can pass them when you call
ACOB$RDMR.
Example 1
In the following example, suppose you need to insert a row into a 90-column table
named BIG_TABLE:
You cannot “reuse” parameters passed in this way. For each SQL statement of more
than the maximum number of placeholders, you must use a separate set of
RSA$PARAM calls, as illustrated in the following example:
C programs that use the interpreter interface may also need to pass more parameters
for one SQL statement than the UCS C compiler allows. These programs may call
function rsa_param in the same manner as a COBOL program calls RSA$PARAM.
Example 2
Suppose a cursor named cur_sor is declared, joining a 15-column table with a
30-column table. The following example illustrates the retrieval of one row from the
resulting 450-column cursor.
A work area with an initial default allocation of about 14,000 words is provided for UCS
programs (interpreted, module, and embedded SQL) that access RDMS databases. As
more space is needed, the system acquires it dynamically.
1. To determine the size of the work area, enter a DEBUG DUMP SIZES command
immediately after the program's END THREAD command.
C #include <rsa.h>
...
rsa("DEBUG DUMP SIZES;",error_code,&aux_info);
COBOL ...
(embedded) EXEC SQL EXECUTE IMMEDIATE 'DEBUG DUMP SIZES '
END-EXEC. ....
COBOL ...
(interpreted) ENTER MASM 'ACOB$RDMR' USING
'DEBUG DUMP SIZES;' ERROR-STATUS AUX-INFO. ...
FORTRAN ...
CALL f$rdmr('DEBUG DUMP SIZES;' ,ERRM,AUXM) ...
2. Execute the program and check the output of the DEBUG DUMP SIZES command,
which appears in the following format:
3. Include a call to the RSA$INIT subroutine in the program that allocates the space
desired for the RDMS work area by setting the work area size parameter. This call
must precede the first RDMS command in the program and should be the only call
to RSA$INIT. Remove the DEBUG DUMP SIZES command from the program.
The following table illustrates the syntax for RSA$INIT for the available UCS
languages. The size of the work area is a 36-bit binary integer.
C #include <rsa.h>
int work_area_size;
...
work_area_size = 20000;
rsa_init(&work_area_size);
COBOL work-area-size PIC 1(36) Usage Binary-1 .
...
MOVE 20000 to work-area-size.
call "rsa$init" using work-area-size.
FORTRAN INTEGER work_area_size
...
work_area_size = 20000
call rsa$init(work_area_size) .
You can avoid this problem by calling the RSA$FREE subroutine after issuing an END
THREAD statement.
C #include <rsa.h>
...
rsa$free();
...
COBOL ...
call "rsa$free"
....
FORTRAN ...
call rsa$free() .
...
HVTIP users cannot use the TIPMALLOC option, but can get more banks using valtab
settings and making LINK changes. The default bank is URTS$TABLES.
An RDMS table can contain 510 columns. The primary key column cannot be a BLOB;
therefore, 509 columns in a table may be BLOB columns. The data for each BLOB
column may be stored in a different set of storage areas. Each set of storage areas
may contain up to 511 storage areas. The data inserted into BLOB storage areas can be
audited and recovered.
BLOBs are generically referred to as large objects. The terms BLOB and LOB are used
interchangeably throughout the RDMS documentation.
BLOB data is stored in the RDMS database as a structure (or, in COBOL terms, as a
record). The structure of the data is set by the structure of the host language variable
declared with the BLOB data type. See the following for more information:
Note: Use of BLOB data is not supported for the IPF SQL interface.
• The LOB storage areas are identified by the DATA-FORMAT value of RSM-LOB.
• LOB storage areas may be based on EXEC or TIP files and can be large files. Each
file can be as large as 120 gigabytes.
• The default page size is 112 (words), and using that page size is encouraged for
optimal use of the storage space. If you are auditing BLOB data (storage area
attribute LOB-AUDITED is TRUE), 112 may not be the optimal page size. Because
auditing is on a page basis, using a small page size such as 112 results in the
processing of more audit looks than would be required for a larger page size. The
optimal size depends on your system configuration, however.
For more detailed information on how BLOB data is arranged in the storage area,
see the Relational Database Server for ClearPath OS 2200 Administration Guide.
An in-record BLOB is excellent for storing short binary data such as encrypted credit
card numbers. This provides better performance than when the BLOB is stored in a
LOB storage area. Using a BLOB is the only way to insert binary data from a JAVA
program.
where:
hno
identifies the property uniquely.
location
describes where the property is located.
price
is the asking price.
description
is a short description of the property.
detail_description
is a long textual description of the property. Since this description may exceed the
7000-byte limit of the CHAR data type, it is stored in a BLOB instead.
house_photo
is a GIF or JPEG photo of the property.
inspection_disclosure
contains a formatted inspection disclosure created by a word processing program.
Note: Each BLOB column has its own storage area or areas, up to 511 storage areas
per column. If you include more than one storage area, the names must be enclosed
in parentheses and separated by commas
• When you fetch data from a column into your application program, you will need
to allocate a buffer big enough to hold the data. If you know that the data is limited
to, say, 50K bytes, you can allocate just the right amount of memory.
• When a LOB value is stored in a table, the table entry is actually a descriptor, or
LOB-id, that points to the LOB value in a RSM-LOB storage area corresponding to
the column. The length of the LOB-id is 24 bytes. In any given table, the total size
of all the column data, including the LOB-ids for each BLOB column, cannot exceed
7168 bytes. In order to store 259 BLOB columns plus a short (CHAR(4), INTEGER,
or SHORT) primary key, the page size for the storage area containing the table
data (in our example it is s1.data_area1) must be 7168. The page size for the
storage area is calculated in words with 4 bytes per word.
• When RDMS allocates space in the storage area for a BLOB value, it allocates the
declared size number of bytes. So if the value being inserted into the column is
40,000 bytes long and the column is declared to be 50K bytes long (51,200 bytes),
RDMS allocates 51,200 bytes of storage space in the storage area. The extra
space is inaccessible for any other use.
Example 1
A BLOB column is declared as inspection_disclosure: blob(50K) and the page size is
224 words. The minimum file size calculation is as follows:
• ((50*1024)+3)/4 = 12,800 words per BLOB value, where K = 1024 times 50. Add 3
and divide by 4, and drop any fractional part of the result to change bytes into
whole words.
• 12,800 / 224 = 57.5 pages per BLOB value. RDMS rounds up to a whole number of
pages, so there are 58 pages per BLOB value.
• 58 * 224 = 12,992 words per page-granularity BLOB value.
• 12,992 / 1792 = 7.25 tracks per BLOB value. RDMS rounds up to a whole number
of tracks, so there are 8 tracks per BLOB value.
• Eight tracks * 8 BLOB values minimum = 64 tracks, which is the minimum size for
the file.
• Add 1 track for the file control information, so the minimum file size is 65 tracks.
• Set the maximum-pages attribute for the storage area to 65*1792/224 = 520
pages.
Example 2
A BLOB column is declared as inspection_disclosure: blob(500M) and the page size is
224 words. The minimum file size calculation is as follows:
Example 3
A BLOB column is declared as inspection_disclosure: blob(2G) and the page size is
224 words. The minimum file size calculation is as follows:
Example 1
A BLOB column is declared as inspection_disclosure: blob(50K) and the page size is
224 words. The calculation is as follows:
• From the calculations in the preceding examples, each BLOB takes 58 pages or
12,992 words.
• 262,143 * 1792 = 469,760,256 words.
• 469,760,256 minus 448 words for the file control information = 469,759,808 words
for BLOB data.
Example 2
A BLOB column is declared as inspection_disclosure: blob(500M) and the page size is
224 words. The calculation is as follows:
Example 3
A BLOB column is declared as inspection_disclosure: blob(2G) and the page size is
224 words. Because the minimum file size exceeds 262,143 tracks, this size file cannot
be used. You must use a large file to store BLOB values of this size.
As an example, suppose you have 40,000 house_photo images to insert into the
house table, and each photo is between 40,000 and 45,000 bytes. The column size is
set in the table definition to 50K bytes (51,200 bytes), so RDMS allocates 51,200 bytes
of the storage area for each house_photo value inserted.
The following table illustrates the amount of space in the file that becomes
inaccessible, based on page size.
Pages
per Inaccessible
Page BLOB Inaccessible Space per Space for 40,000
Column Size Value Value in Words Values in Words
Smaller page sizes generally give the best storage area usage, with no impact on
performance.
This can happen even on the first INSERT. The reason is that RDMS tries to spread the
BLOB values out across the file. This is to support multithread access to the BLOB
storage area. RDMS divides the storage area into eight pieces, with page allocation
controlled independently for each piece. When inserting a BLOB value into the file,
RDMS randomly chooses one of the eight pieces from which to allocate pages to
store the BLOB value. So even though it may be the first BLOB value to be inserted
into the database, RDMS may choose the eighth piece, whose page numbers are
beyond the end of the file.
To avoid this error, ensure that the MAXIMUM-PAGES value times the PAGE-SIZE
value is smaller than the maximum size of the file.
• You must have the storage area attribute AUDITED set to true. AUDITED is true by
default if RECOVERED is true.
• You must also have LOB-AUDITED set to true. This is false by default.
See the Repository for ClearPath OS 2200 Programming Reference Manual for more
details about storage area attributes.
Note: Auditing BLOB data when BLOBs are very large or numerous can
significantly increase audit volume and affect system performance. Also, because
each page within a BLOB is audited separately, you should avoid small page sizes if
BLOB data is audited.
If you use IRU to dump your BLOB areas, you should be aware that you may get many
messages from IRU indicating that I/O errors have occurred, because RSM-LOB areas
can contain unallocated areas of mass storage. If you want to avoid these messages
and increase the speed of the dump and reload, you should preallocate the entire file
using the IRU ALLOCATE command, or preallocate a large initial reserve when you
create the file.
If you do not audit BLOB data, you must manually back up and recover the BLOB
storage areas. For best results, use IRU to dump and reload the storage area as
needed. When you reload a BLOB storage area, you cannot recover the file after
reload, because there are no LOB page records on the audit trail for IRU to apply
(when LOB-AUDITED is false). For this reason, avoid dynamic dumps. At the same time
that you dump the BLOB storage area, dump the associated data storage area, to have
a consistent recovery point. When you restore a BLOB storage area from a dump,
you should also restore all associated storage areas to dumps from the same time.
BLOB variables in a C program are actually structured data. When you declare a
variable with the data type BLOB, the UCS C compiler generates a structure to
describe the BLOB data item.
The declaration format is similar to other C variables, but with the SQL TYPE clause:
The UCS C compiler generates the following structure. Note that the name you give is
used as a prefix for each of the three parts of the structure:
large-object-length
is the maximum length for the BLOB variable, in bytes. The value can be in the
range 1 to approximately 4 gigabytes. See Table I–1 for more information.
If you use the K or M suffix in the declaration, they must be uppercase letters.
For the s1.houses table in this example, the following declarations could be made:
You can initialize BLOB variables using C structure initialization syntax. For example
The UCS C compiler allocates automatic variables in a small bank and allocates static
variables in a small or large bank, depending on the size of the static data items.
The UCS Runtime System allocates a very large bank when you call the UCS C
memory management functions such as malloc( ) for a single storage request in
excess of 16,777,216 words (67,108,864 bytes).
The UCS C compiler generates code to access data references using a 24-bit index
register. The compiler-generated code is limited to addressing a single object (array or
structure) up to 16,777,216 words in size. A UCS C pointer is limited to addressing up
to 16,777,216 words. If you use pointer arithmetic or array indexing to access a word in
a very large bank that exceeds an address of 16,777,216 words, the data reference
wraps back to zero, the beginning of the bank. There are no diagnostics issued if you
attempt to access a word in a very large bank beyond the limit. It is your responsibility
to avoid using a C pointer or array index that exceeds the limit.
Table I–1 summarizes the kinds of data access available based on the size of the BLOB
variable. Yes indicates that you can use the technique for the given size of BLOB
variable. No indicates that you cannot.
4. The low-level I/O functions fio( ) and fiow( ) are limited to reading and writing a
maximum of 128 tracks or 917,504 bytes per function call.
detail_description.detail_description_data[45] = 'B';
v_house_photo.v_house_photo_data
[v_house_photo.v_house_photo_length] = '\n';
strcpy(v_detail_description.v_detail_description_data ,
"charming two story home in the prestigious Powderhorn neighborhood");
When you put data into a BLOB variable, before calling RDMS to insert the value into
the database you must set the length of the value in the xx_length area of the
generated BLOB variable structure.
strcpy(v_detail_description.v_detail_description_data ,
"charming two story home in the prestigious Powderhorn neighborhood");
v_detail_description.v_detail_description_length =
strlen(v_detail_description. v_detail_description_data);
The strcpy( ) function copies the string including the null terminator. The strlen( )
function returns the length of the string not including the null terminator. If you require
the null terminator as significant data in your BLOB, you must add one to the result of
strlen( ) (the null character has already been added by the strcpy( ) function):
v_detail_description.v_detail_description_length ++;
For automatic and static BLOB variables, the UCS C compiler always creates the
generated BLOB structure as whole words, that is, a whole multiple of 4 bytes. For
example, you could use the following declaration:
However, the computer allocates 8 bytes for the v_example_blob_data. When RDMS
copies data to and from the generated structure, it likewise copies whole words. In
this case, v_example_blob could be used on an RDMS INSERT statement:
strcpy(v_example_blob.v_example_blob_data, "nodata");
v_example_blob.v_example_blob_length = 6;
EXEC SQL INSERT INTO s1.houses (hno, house_photo)
VALUES (:v_hno, :v_example_blob) ;
As a result, up to 3 bytes of indeterminate data are written from the BLOB variable to
the database on an INSERT statement and are written from the database to the BLOB
variable on a FETCH statement. The xx_length field contains the true length of the
value, in bytes.
For example, suppose you want to acquire space for a BLOB value whose maximum
size is 20,000 bytes and fetch a value into it:
#define blob_header_size 8
bytes_to_read = 20000;
v_inspection_disclosure = malloc(bytes_to_read + blob_header_size);
v_inspection_disclosure-> v_inspection_disclosure_length =
bytes_to_read;
EXEC SQL
DECLARE curs1 CURSOR FOR SELECT hno, inspection_disclosure FROM
s1.houses;
EXEC SQL OPEN CURSOR curs1;
EXEC SQL FETCH NEXT curs1 INTO :v_hno, :v_inspection_disclosure ;
BLOB variables in a COBOL program are actually a record rather than a primitive data
item. When you declare a variable with the data type BLOB, the UCS COBOL compiler
generates a record to describe the BLOB data item.
The declaration format is similar to other COBOL variables, but with a new SQL TYPE
clause:
01 v-house-photo.
02 v-house-photo-reserved PIC S9(9) USAGE IS BINARY.
02 v-house-photo-length PIC S9(9) USAGE IS BINARY.
02 v-house-photo-data PIC X(large-object-length).
large-object-length
is the maximum length for the BLOB variable, in bytes. The value can be in the
range 1 to 67,108,852. The maximum length can be specified as a simple integer
representing the number of bytes or as an integer followed by one of the
following suffixes:
K Kilobytes (210 or 1,024 bytes)
M Megabytes (220 or 1,048,576 bytes)
For the house schema in our example, the following declarations could be made:
Table I–2 summarizes the kinds of data access available based on the size of the
BLOB variable. Yes indicates that you can use the technique for the given size of BLOB
variable. No indicates that you cannot.
For more information on the capabilities described in the preceding table, see either
When you put data into a BLOB variable, before calling RDMS to insert the value into
the database you must set the length of the value in your name-length area of the
generated BLOB variable structure.
The UCS COBOL compiler always creates the generated BLOB record as whole
words, that is, a multiple of 4 bytes. For example, if you use the following
declaration:
01 v-example-blob.
02 v-example-blob-reserved PIC S9(9) USAGE IS BINARY.
02 PIC S9(9) USAGE IS BINARY.
02 v-example-blob-data PIC X(6).
Since v-example-blob is an 01 level item, UCS COBOL allocates 8 bytes for the
v-example-blob-data to make the record occupy a whole number of words. When
RDMS copies data to and from the generated record, it likewise copies whole words.
In this case, v-example-blob could be used on an RDMS INSERT statement:
As a result, up to 3 bytes of indeterminate data are written from the BLOB variable to
the database on an INSERT statement and are written from the database to the BLOB
variable on a FETCH statement.
The following are the differences between the embedded SQL and interactive SQL
versions of the program. (See I.11 for the interactive SQL version.)
Example Code
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <sysutil.h>
5 #include <rsa.h>
6 #define NO_FIND_STATUS 6001
7 #define NO_DATA_STATUS "02000"
8 #define OK_STATUS "00000"
9 #define TRUNC_WARN "01004"
10 #define blob_header_size 8
11
12 int size_needed_in_bytes;
13 rsa_error_code_type error_code;
14 int aux_info = 0;
15 char SQLSTATE[6];
16
17 EXEC SQL BEGIN DECLARE SECTION;
18 char v_hno[5];
19 char v_location[80];
20 int v_price;
21 char v_description[40];
22 SQL TYPE IS BLOB (50K) v_detail_description;
23 SQL TYPE IS BLOB (30000) v_house_photo = { 0, 1, 700};
24 /* initialize with end of file sentinel */
25 SQL TYPE IS BLOB (500K) *v_disclosure;
26
27 char d_hno[5];
28 char d_location[80];
29 int d_price;
30 char d_description[40];
31 SQL TYPE IS BLOB (40K) d_detail_description;
32 SQL TYPE IS BLOB (30000) d_house_photo;
33 SQL TYPE IS BLOB (500K) *d_disclosure;
34
35 int indicator1, indicator2, indicator3, indicator4;
36 int indicator5, indicator6, indicator7;
37 EXEC SQL END DECLARE SECTION;
38
39
40 main()
41 {
42 EXEC SQL WHENEVER SQLERROR goto:a_bad_end;
43
44 EXEC SQL
45 BEGIN THREAD FOR app014 UPDATE UDSMSG;
46
47 /* use malloc to get the maximum amount of space for the
48 inspection_disclosure and add 8 bytes for the BLOB header information.
49 */
50
51 size_needed_in_bytes = sizeof(v_disclosure -> v_disclosure_data);
52 v_disclosure = malloc(size_needed_in_bytes + blob_header_size);
53 v_disclosure -> v_disclosure_length = size_needed_in_bytes;
54
55
56 /* Assume that at this point we get the names of the files containing
57 the detail description, house photo, and inspection disclosure and
58 perform the I/O to read data into the variables v_detail_description,
59 v_house_photo, and v_disclosure. See the C Compiler Programming
60 Reference Manual Volume 2: Compiler and System Interface for an
61 example of Input and Output of BLOBs.
62
63 Also, assume that we get the values for hno, location, price, and
64 description from the user.
65
66 This example uses strcpy in place of the I/O to illustrate the
67 specific RDMS issues.
68 */
69
70 strcpy(v_hno, "H907");
71 strcpy(v_location, "123 Main Street Minneapolis");
72 v_price = 120000;
73 strcpy(v_description, "older home 4BR 2BA FP AC");
74
75 /* fill in detail description; set the length to the actual length,
76 in bytes. Note that the trailing NULL character in the string is
77 not included in the length. In this instance, the NULL is not
78 a significant character.
79 */
80
81 strcpy(v_detail_description.v_detail_description_data ,
82 "charming two story home in the prestigious Powderhorn neighborhood");
83 v_detail_description.v_detail_description_length = 66;
84 v_detail_description.v_detail_description_reserved = 0;
85
86 /* assume there is no house photo */
87
88 strcpy(v_disclosure -> v_disclosure_data , "no work orders required");
Output
Executing this program produces the following output:
@XQT file.example
hno: H907
location: 123 Main Street Minneapolis
price: 120000
description: older home 4BR 2BA FP AC
detail description:
charming two story home in the prestigious Powderhorn neighborhood
house_photo: no house photo available
inspection disclosure: no work orders required
inspection disclosure length from indicator: 1048576
These are differences to note between the interactive SQL and embedded SQL
versions of the program (see I.10 for the embedded SQL version of the program).
Example Code
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <sysutil.h>
5 #include <rsa.h>
6 #define NO_FIND_STATUS 6001
7 #define NO_DATA_STATUS "02000"
8 #define OK_STATUS "00000"
9 #define TRUNC_WARN "01004"
10 #define blob_header_size 8
11
12 int size_needed_in_bytes;
13 rsa_error_code_type error_code;
14 int aux_info = 0;
15 char SQLSTATE[6];
16
17 EXEC SQL BEGIN DECLARE SECTION;
18 char v_hno[5];
19 char v_location[80];
20 int v_price;
21 char v_description[40];
126
127
128 /* Now, fetch the records back again */
129
130 /* Since the variable d_disclosure is a pointer to BLOB, we malloc
131 the space and then must tell RDMS how big the size is by setting
132 d_disclosure_length
133 */
134
135 1 d_disclosure = malloc(size_needed_in_bytes + blob_header_size);
136 1 d_disclosure -> d_disclosure_length = size_needed_in_bytes;
137 1 d_disclosure -> d_disclosure_reserved = 0;
138
139 1 rsa("DECLARE curs301 CURSOR FOR SELECT * FROM s1.house;",
140 error_code, &aux_info);
141 1 if (atoi(error_code)) {
142 2 printf("Error on COMMIT THREAD\n");
143 2 goto a_bad_thing;
144 }
145
146 1 rsa("OPEN CURSOR curs301;", error_code, &aux_info);
147 1 if (atoi(error_code)) {
148 2 printf("Error on OPEN CURSOR\n");
149 2 goto a_bad_thing;
150 }
151
152 /* NOTE: In the list of arguments for the rsa call, the variable
153 d_disclosure is passed by value, not by reference. This is because
154 the variable is declared as a 'pointer to blob'.
155 */
156
157 1 rsa("FETCH FIRST curs301 INTO $p1 $p2, $p3 $p4, $p5 $p6, \
158 $p7 $p8, $p9 $p10, $p11 $p12, $p13 $p14;",
159 error_code, &aux_info, &d_hno, &indicator1, &d_location, &indicator2,
160 &d_price, &indicator3, &d_description, &indicator4,
161 &d_detail_description, &indicator5, &d_house_photo, &indicator6,
162 d_disclosure, &indicator7);
163 1 if (atoi(error_code)) {
164 2 printf("Error on FETCH 1\n");
165 2 goto a_bad_thing;
166 }
167
168 /* Assume that at this point we write the three BLOB values to files for
169 transport to a display device.
170
171 This example uses printf to illustrate the specific RDMS issues
172 */
173
174
175
176 /* Since the trailing NUL character is not part of the actual data values,
177 insert one now to be able to display the values.
178 */
179
180 d_detail_description.d_detail_description_data
181 1 [d_detail_description.d_detail_description_length]= '\0';
182 d_house_photo.d_house_photo_data
183 1 [d_house_photo.d_house_photo_length]= '\0';
184 d_disclosure -> d_disclosure_data
185 1 [d_disclosure -> d_disclosure_length]= '\0';
186
187
188 1 printf("hno: %s\n", &d_hno);
189 1 printf("location: %s\n", &d_location);
190 1 printf("price: %i\n", d_price);
191 1 printf("description: %s\n", &d_description);
192 1 printf("detail description: \n %s\n",
193 &d_detail_description.d_detail_description_data);
194 1 printf("house_photo: %s\n", &d_house_photo.d_house_photo_data);
195 1 printf("inspection disclosure: %s\n",
196 &d_disclosure -> d_disclosure_data);
197
198
199 /* Suppose the variable to hold the inspection disclosure is too small
200 to hold the value being fetched. RDMS returns a truncation warning
201 and puts the column length into the corresponding indicator variable.
202 Note that it is the column's declared length, not the length of the
203 value being fetched.
204
205 NOTE: In the list of arguments for the rsa call, the variable
206 d_disclosure is passed by value, not by reference. This is because
207 the variable is declared as a 'pointer to blob'.
208
209 */
210
211 1 d_disclosure -> d_disclosure_length = 20;
212 1 rsa("FETCH FIRST curs301 INTO $p1 $p2, $p3 $p4, $p5 $p6, \
213 $p7 $p8, $p9 $p10, $p11 $p12, $p13 $p14;",
214 error_code, &aux_info, &d_hno, &indicator1, &d_location, &indicator2,
215 &d_price, &indicator3, &d_description, &indicator4,
216 &d_detail_description, &indicator5, &d_house_photo, &indicator6,
217 d_disclosure, &indicator7);
218 1 if (atoi(error_code)) {
219 2 printf("Error on FETCH 2\n");
220 2 goto a_bad_thing;
221 }
222
223 1 printf("inspection disclosure length from indicator: %i\n", indicator7);
224
225 1 rsa("CLOSE curs301;", error_code, &aux_info);
226 1 if (atoi(error_code)) {
227 2 printf("Error on CLOSE\n");
228 2 goto a_bad_thing;
229 }
230
231 1 rsa("END THREAD TERMINATE;", error_code, &aux_info);
232 1 if (atoi(error_code)) {
233 2 printf("Error on END THREAD\n");
234 2 goto a_bad_thing;
235 }
236 1 return 0;
237
238 a_bad_thing:
239 1 handle_sqlerror();
240 1 rsa("END THREAD TERMINATE;", error_code, &aux_info);
241 1 if (atoi(error_code)) {
242 2 printf("Error on END THREAD\n");
243 2 goto a_bad_thing;
244 }
245 1 return 1;
246 }
247
248
249 void handle_sqlerror(void)
250 {
251 1 printf("PROGRAM TERMINATED IN ERROR *error_code = %s, *aux_info = %d\n",
252 error_code, aux_info);
253 1 return;
254 }
Output
Executing this program produces the following output:
@XQT OBJ$.do-house2zm
hno: H907
location: 123 Main Street Minneapolis
price: 120000
description: older home 4BR 2BA FP AC
detail description:
charming two story home in the prestigious Powderhorn neighborhood
house_photo: no house photo available
inspection disclosure: no work orders required
inspection disclosure length from indicator: 1048576
These are differences to note between the embedded SQL and interactive SQL
versions of the program (see I.13 for the interactive SQL version of the program).
Passing an SQL EXEC SQL SQL- ENTER MASM 'ACOB$RDMR' USING "SQL-
statement to statement statement", error_status, aux_info.
RDMS END-EXEC.
Detecting Use the WHENEVER Check error-status directly, as in the example.
errors clause.
Example Code
1 IDENTIFICATION DIVISION.
2 PROGRAM-ID. cobol-example.
3 AUTHOR. RDMS.
4 DATE-WRITTEN. 2000 Oct 31.
5 ENVIRONMENT DIVISION.
6 CONFIGURATION SECTION.
7 SOURCE-COMPUTER. UNISYS-2200-5600.
8 OBJECT-COMPUTER. UNISYS-2200-5600.
9 SPECIAL-NAMES.
10 PRINTER IS PRINTER.
11
12 DATA DIVISION.
13
14 WORKING-STORAGE SECTION.
15
16 EXEC SQL BEGIN DECLARE SECTION END-EXEC.
17
18 01 v-hno PIC X(4).
19 01 v-location PIC X(28).
20 01 v-price PIC 9(10) BINARY.
21 01 v-description PIC X(40).
22 01 v-detail-description SQL TYPE IS BLOB(20K).
23 01 v-house-photo SQL TYPE IS BLOB(30000).
24 01 v-disclosure SQL TYPE IS BLOB(500K).
25
26 01 d-hno PIC X(4).
27 01 d-location PIC X(28).
28 01 d-price PIC 9(10) BINARY.
29 01 d-description PIC X(40).
30 01 d-detail-description SQL TYPE IS BLOB(20K).
83 01 print-line5a.
84 05 filler PIC X(4).
85 05 detail-description-value PIC X(72).
86
87 01 print-line6.
88 05 label11 PIC X(12).
89 05 indicator6-value PIC +9(7).
90 05 label12 PIC X(16).
91 05 house-photo-value PIC X(40).
92
93 01 print-line7.
94 05 label13 PIC X(12).
95 05 indicator7-value PIC +9(7).
96 05 label14 PIC X(16).
97 05 disclosure-value PIC X(40).
98 *
99 *
100 PROCEDURE DIVISION.
101 Start-test.
102
103 init-rsa.
104 CALL 'RSA$INIT' USING WORK-AREA-SIZE.
105 EXEC SQL
106 WHENEVER SQLERROR GO TO :RDMS-ERROR-PARA
107 END-EXEC.
108
109 init-print-lines.
110 MOVE SPACES TO print-line1.
111 MOVE SPACES TO print-line2.
112 MOVE SPACES TO print-line3.
113 MOVE SPACES TO print-line4.
114 MOVE SPACES TO print-line5.
115 MOVE SPACES TO print-line5a.
116 MOVE SPACES TO print-line6.
117 MOVE SPACES TO print-line7.
118 MOVE 'indicator1: ' TO label1.
119 MOVE 'indicator2: ' TO label3.
120 MOVE 'indicator3: ' TO label5.
121 MOVE 'indicator4: ' TO label7.
122 MOVE 'indicator5: ' TO label9.
123 MOVE 'indicator6: ' TO label11.
124 MOVE 'indicator7: ' TO label13.
125 MOVE ' house number: ' TO label2.
126 MOVE ' location: ' TO label4.
127 MOVE ' price: ' TO label6.
128 MOVE ' description: ' TO label8.
129 MOVE ' detail description: ' TO label10.
130 MOVE ' house-photo: ' TO label12.
131 MOVE ' disclosure: ' TO label14.
132
133
134 do-the-work.
135 *
136 * Assume that at this point we get the names of the files containing
137 * the detail description, house photo, and inspection disclosure and
138 * perform the I/O to read the data into the variables v-detail-
description
139 * v-house-photo, and v-disclosure. See the COBOL Compiler Programming
140 * Reference Manual Volume 2: Compiler and System Interface for an
141 * example of Input and Output of BLOBs.
142 *
143 * Also, assume that we get the values for hno, location, price, and
144 * description from the user.
145 *
146 * This example uses MOVE in place of the I/O to illustrate the
147 * specific RDMS issues.
148 *
149 MOVE 'H907' TO v-hno.
150 MOVE '123 Main Street Minneapolis, MN' TO v-location.
151 MOVE 120000 to v-price.
152 MOVE 'older home 4BR 2BA FP AC' to v-description.
153 *
154 * fill in detail description; set the length to the actual length,
155 * in bytes. Note that trailing spaces in the string are
156 * not included in the length. In this instance, the trailing spaces
157 * are not significant characters.
158 *
159 STRING
160 'charming two story home in the prestigious '
161 DELIMITED SIZE,
162 'Powderhorn neighborhood'
163 DELIMITED SIZE
164 INTO v-detail-description-data.
165 MOVE 66 TO v-detail-description-length.
166 *
167 * assume there is no house photo
168 *
169 MOVE 'no work orders required' TO v-disclosure-data.
170 MOVE 23 TO v-disclosure-length.
171 *
172 * There are several ways to tell RDMS that the house_photo column will
173 * have a NULL value -- and thereby trigger the insertion of the
174 * default value from the table definition:
175 * - set the corresponding indicator to -1
176 * - set v-house-photo-length to 0
177 * - include the keyword NULL in place of the variable :v-house-photo
178 *
179 MOVE 0 TO v-house-photo-length.
180
181 EXEC SQL
182 INSERT INTO s1.house
183 VALUES (:v-hno, :v-location, :v-price, :v-description,
184 :v-detail-description, :v-house-photo,
185 :v-disclosure)
186 END-EXEC.
187
188 EXEC SQL
189 COMMIT THREAD
190 END-EXEC.
191
192 *
193 * Now, fetch the records back again
194 *
195 EXEC SQL
196 DECLARE curs301 CURSOR
197 FOR SELECT * FROM s1.house
198 END-EXEC.
199
200 EXEC SQL
201 OPEN CURSOR curs301
202 END-EXEC.
203 *
204 * Clear the BLOB destination variables
205 *
206 MOVE SPACES TO d-detail-description.
207 MOVE SPACES TO d-house-photo.
208 MOVE SPACES TO d-disclosure.
209
210 EXEC SQL
211 FETCH FIRST curs301 INTO :d-hno :indicator1,
212 :d-location :indicator2, :d-price :indicator3,
213 :d-description :indicator4,
214 :d-detail-description :indicator5,
215 :d-house-photo :indicator6,
216 :d-disclosure :indicator7
217 END-EXEC.
218 *
219 * Assume that at this point we write the three BLOB values to files
for
220 * transport to a display device.
221 *
222 * This example uses DISPLAY to illustrate the specific RDMS issues
223 *
224 MOVE indicator1 TO indicator1-value.
225 MOVE indicator2 TO indicator2-value.
226 MOVE indicator3 TO indicator3-value.
227 MOVE indicator4 TO indicator4-value.
228 MOVE indicator5 TO indicator5-value.
229 MOVE indicator6 TO indicator6-value.
230 MOVE indicator7 TO indicator7-value.
231
232 MOVE SPACES TO hno-value.
233 IF indicator1 IS >= ZERO
234 MOVE d-hno TO hno-value.
235 MOVE SPACES TO location-value.
236 IF indicator2 IS >= ZERO
289 END-EXEC.
290
291
292 PERFORM END-THREAD-TO-UDS.
293 PERFORM TERMINATION-PARA.
294 *
295 * other procedure paragraphs
296 *
297
298
299 END-THREAD-TO-UDS.
300 END THREAD.
301
302 TERMINATION-PARA.
303 DISPLAY 'END UCOB example'
304 UPON PRINTER.
305 STOP RUN.
306
307 RDMS-ERROR-PARA.
308 EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC.
309 DISPLAY '*** SQLSTATE = ' SQLSTATE UPON PRINTER.
Output
Executing this program produces the following output:
@XQT OBJ$.EXAMPLE-UCOB
indicator1: +0000000 house number: H907
indicator2: +0000000 location: 123 Main Street Minneapolis,
indicator3: +0000000 price: $120,000.00
indicator4: +0000000 description: older home 4BR 2BA FP AC
indicator5: +0000000 detail description:
charming two story home in the prestigious Powderhorn neighborhood
indicator6: +0000000 house-photo: no house photo available
indicator7: +0000000 disclosure: no work orders required
inspection disclosure length from indicator:
+1048576
END UCOB example
These are differences to note between the embedded SQL and interactive SQL
versions of the program (see I.12 for the embedded SQL version of the program).
Passing an SQL EXEC SQL SQL-statement ENTER MASM 'ACOB$RDMR' USING "SQL-
statement to END-EXEC. statement", error_status, aux_info.
RDMS
Detecting Use the WHENEVER Check error-status directly, as in the example.
errors clause.
Example Code
1 1 IDENTIFICATION DIVISION.
2 PROGRAM-ID. cobol-example.
3 AUTHOR. RDMS.
4 DATE-WRITTEN. 2003 Oct 29.
5 ENVIRONMENT DIVISION.
6 CONFIGURATION SECTION.
7 SOURCE-COMPUTER. UNISYS-2200-5600.
8 OBJECT-COMPUTER. UNISYS-2200-5600.
9 SPECIAL-NAMES.
10 PRINTER IS PRINTER.
11
12 DATA DIVISION.
13
14 WORKING-STORAGE SECTION.
15
16 EXEC SQL BEGIN DECLARE SECTION END-EXEC.
17
18 01 v-hno PIC X(4).
19 01 v-location PIC X(28).
20 01 v-price PIC 9(10) BINARY.
21 01 v-description PIC X(40).
22 01 v-detail-description SQL TYPE IS BLOB(20K).
23 01 v-house-photo SQL TYPE IS BLOB(30000).
24 01 v-disclosure SQL TYPE IS BLOB(500K).
25
26 01 d-hno PIC X(4).
27 01 d-location PIC X(28).
28 01 d-price PIC 9(10) BINARY.
29 01 d-description PIC X(40).
30 01 d-detail-description SQL TYPE IS BLOB(20K).
84 01 print-line5a.
85 05 filler PIC X(4).
86 05 detail-description-value PIC X(72).
87
88 01 print-line6.
89 05 label11 PIC X(12).
90 05 indicator6-value PIC +9(7).
91 05 label12 PIC X(16).
92 05 house-photo-value PIC X(40).
93
94 01 print-line7.
95 05 label13 PIC X(12).
96 05 indicator7-value PIC +9(7).
97 05 label14 PIC X(16).
98 05 disclosure-value PIC X(40).
99 *
100 *
101 1 PROCEDURE DIVISION.
102 1 Start-test.
103
104 1 init-rsa.
105 1 EXEC SQL
106 WHENEVER SQLERROR GO TO RDMS-ERROR-PARA
107 END-EXEC.
108
109 1 init-print-lines.
110 1 MOVE SPACES TO print-line1.
111 1 MOVE SPACES TO print-line2.
112 1 MOVE SPACES TO print-line3.
113 1 MOVE SPACES TO print-line4.
114 1 MOVE SPACES TO print-line5.
115 1 MOVE SPACES TO print-line5a.
116 1 MOVE SPACES TO print-line6.
117 1 MOVE SPACES TO print-line7.
118 1 MOVE 'indicator1: ' TO label1.
119 1 MOVE 'indicator2: ' TO label3.
120 1 MOVE 'indicator3: ' TO label5.
121 1 MOVE 'indicator4: ' TO label7.
122 1 MOVE 'indicator5: ' TO label9.
123 1 MOVE 'indicator6: ' TO label11.
124 1 MOVE 'indicator7: ' TO label13.
125 1 MOVE ' house number: ' TO label2.
126 1 MOVE ' location: ' TO label4.
127 1 MOVE ' price: ' TO label6.
128 1 MOVE ' description: ' TO label8.
129 1 MOVE ' detail description: ' TO label10.
130 1 MOVE ' house-photo: ' TO label12.
131 1 MOVE ' disclosure: ' TO label14.
132
133
134 1 do-the-work.
135 *
136 * Assume that at this point we get the names of the files containing
137 * the detail description, house photo, and inspection disclosure and
138 * perform I/O to read the data into the variables v-detail-description
139 * v-house-photo, and v-disclosure. See the COBOL Compiler Programming
140 * Reference Manual Volume 2: Compiler and System Interface for an
141 * example of Input and Output of BLOBs.
142 *
143 * Also, assume that we get the values for hno, location, price, and
144 * description from the user.
145 *
146 * This example uses MOVE in place of the I/O to illustrate the
147 * specific RDMS issues.
148 *
149 1 MOVE 'H907' TO v-hno.
150 1 MOVE '123 Main Street Minneapolis, MN' TO v-location.
151 1 MOVE 120000 to v-price.
152 1 MOVE 'older home 4BR 2BA FP AC' to v-description.
153 *
154 * fill in detail description; set the length to the actual length,
155 * in bytes. Note that trailing spaces in the string are
156 * not included in the length. In this instance, the trailing spaces
157 * are not significant characters.
158 *
159 1 STRING
160 'charming two story home in the prestigious '
161 DELIMITED SIZE,
162 'Powderhorn neighborhood'
163 DELIMITED SIZE
164 INTO v-detail-description-data.
165 1 MOVE 66 TO v-detail-description-length.
166 *
167 * assume there is no house photo
168 *
169 1 MOVE 'no work orders required' TO v-disclosure-data.
170 1 MOVE 23 TO v-disclosure-length.
171 *
172 * There are several ways to tell RDMS that the house_photo column will
173 * have a NULL value -- and thereby trigger the insertion of the
174 * default value from the table definition:
175 * - set the corresponding indicator to -1
176 * - set v-house-photo-length to 0
177 * - include the keyword NULL in place of the variable :v-house-photo
178 *
179 1 MOVE 0 TO v-house-photo-length.
180 *
181 * do the begin thread statement
182 *
183 1 MOVE SPACES TO COMMAND-AREA.
184 1 MOVE 'BEGIN THREAD FOR app014 UPDATE UDSMSG;' TO CM-LINE(1).
185 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
186 ERROR-STATUS, AUX-INFO.
187 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
344 1 DISPLAY
345 'inspection disclosure length from indicator:'
346 UPON PRINTER.
347 1 DISPLAY indicator7 UPON PRINTER.
348 *
349 * close the cursor
350 *
351
352 1 MOVE SPACES TO COMMAND-AREA.
353 1 MOVE 'CLOSE curs301; ' TO CM-LINE(1).
354
355 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
356 ERROR-STATUS, AUX-INFO.
357 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
358 1 DISPLAY 'Error on CLOSE CURSOR' UPON PRINTER
359 1 PERFORM RDMS-ERROR-PARA
360 END-IF.
361
362
363 1 PERFORM END-THREAD-TO-UDS.
364 1 PERFORM TERMINATION-PARA.
365 *
366 * other procedure paragraphs
367 *
368
369
370 1 END-THREAD-TO-UDS.
371 1 MOVE SPACES TO COMMAND-AREA.
372 1 MOVE 'END THREAD TERMINATE; ' TO CM-LINE(1).
373
374 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
375 ERROR-STATUS, AUX-INFO.
376 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
377 1 DISPLAY 'Error on END THREAD' UPON PRINTER
378 1 PERFORM RDMS-ERROR-PARA
379 END-IF.
380
381 1 TERMINATION-PARA.
382 1 DISPLAY 'END UCOB example'
383 UPON PRINTER.
384 1 STOP RUN.
385
386 1 RDMS-ERROR-PARA.
387 1 EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC.
388 1 DISPLAY '*** RDMCA AUX-INFO = ' AUX-INFO UPON PRINTER.
389 1 DISPLAY '*** ERROR STATUS = ' ERROR-STATUS UPON PRINTER.
Output
Executing this program produces the following output:
@XQT OBJ$.EX-UCOB2
indicator1: +0000000 house number: H907
indicator2: +0000000 location: 123 Main Street Minneapolis,
indicator3: +0000000 price: $120,000.00
indicator4: +0000000 description: older home 4BR 2BA FP AC
indicator5: +0000000 detail description:
charming two story home in the prestigious Powderhorn neighborhood
indicator6: +0000000 house-photo: no house photo available
indicator7: +0000000 disclosure: no work orders required
inspection disclosure length from indicator:
+1048576
END UCOB example
*78308160-027*
All rights reserved.
7830 8160–027