Informix Guide To SQL
Informix Guide To SQL
Tutorial
ii
Preface
This book is a tutorial on the Structured Query Language (SQL) as it is
implemented by Informix products. The Informix Guide to SQL: Tutorial and
its companion volumes, the Informix Guide to SQL: Reference and the Informix
Guide to SQL: Syntax, tell you how to create, manage, and use relational
databases with Informix software tools.
Examples in this manual represent a number of Informix products and
operating systems at different release levels.
You must have the following Informix software:
• An INFORMIX-OnLine Dynamic Server database server or an
INFORMIX-SE database server
The database server either must be installed on your machine or on
another machine to which your machine is connected over a network.
• Either an Informix application development tool, such as INFORMIX-4GL;
or an SQL application programming interface (API), such as
INFORMIX-ESQL/C; or the DB-Access database access utility, which is
shipped as part of your database server.
The application development tool, SQL API, or DB-Access enables you to
compose queries, send them to the database server, and view the results
that the database server returns. You can use DB-Access to try out all the
SQL statements described in this guide.
Preface iii
Summary of Chapters
The Informix Guide to SQL: Tutorial includes the following chapters:
• This Preface provides general information about the book and lists
additional reference materials that can help you understand relational
database management.
• The Introduction tells how SQL fits into the Informix family of products
and books, explains how to use this book, introduces the demonstration
database from which the product examples are drawn, and lists the new
features for Version 6.0 of Informix database server products.
Part I – “Using Basic SQL.” This part contains introductory chapters on how
to use SQL. Read these chapters first if you are new to databases and SQL.
• Chapter 1, “Introducing Database Features and SQL,” contains an
overview of database terminology and defines some important terms and
ideas that are used throughout the book.
• Chapter 2, “Composing Simple SELECT Statements,” begins the
exploration of making simple queries to retrieve and display database
data.
• Chapter 3, “Composing Advanced SELECT Statements,” discusses
making advanced queries to retrieve and display database data.
• Chapter 4, “Modifying Data,” describes the statements you use to insert,
delete, or update data, and introduces the concepts of database privileges,
maintaining data integrity, and archiving data.
• Chapter 5, “Programming with SQL,” discusses calling the database
server, retrieving rows, and embedding data.
• Chapter 6, “Modifying Data Through SQL Programs,” provides an
in-depth look at INSERT, DELETE, and UPDATE statements and using
these statements in SQL programs.
• Chapter 7, “Programming for a Multiuser Environment,” provides a
complete discussion on concurrency, isolation levels, and locking.
Part II – “Designing and Managing Databases.” This part contains overview
chapters about designing and managing databases. Read these chapters to
understand the entity-relationship data model for databases and how to
create and tune a database.
• Chapter 8, “Building Your Data Model,” describes the components of a
data model and provides a step-by-step procedure for building one.
• Chapter 9, “Implementing Your Data Model,” tells you how to define
database data types and create a database.
iv Preface
• Chapter 10, “Tuning Your Data Model,” discusses many of the details that
help you set up an efficient database model, including disk storage, cal-
culating table sizes, managing indexes, and maximizing concurrency.
• Chapter 11, “Granting and Limiting Access to Your Database,” details
how you can ensure data security by granting privileges and using stored
procedures and views.
• Chapter 12, “Understanding Informix Networking,” discusses networks
and how you can best set up a database to work over a network.
Part III – “Using Advanced SQL.” This part contains advanced SQL chapters,
such as how to optimize your queries, how to create and use stored proce-
dures, and how to create and use triggers. Read these chapters if you need
better performance in your database.
• Chapter 13, “Optimizing Your Queries,” defines techniques to refine and
optimize your queries, introduces and explains the query Optimizer, and
discusses the time costs of various operations.
• Chapter 14, “Creating and Using Stored Procedures,” describes how to
create and use stored procedures.
• Chapter 15, “Creating and Using Triggers,” describes how to create and
use triggers.
Preface v
Related Reading
If you want additional technical information on database management,
consult the following texts by C. J. Date:
• An Introduction to Database Systems, Volume I (Addison-Wesley Publishing,
1990)
• An Introduction to Database Systems, Volume II (Addison-Wesley
Publishing, 1983)
This guide assumes that you are familiar with your computer operating sys-
tem. If you have limited UNIX system experience, you might want to look at
your operating system manual or a good introductory text before you read
this tutorial.
The following list contains some suggested texts about UNIX systems:
• A Practical Guide to the UNIX System, Second Edition, by M. Sobell
(Benjamin/Cummings Publishing, 1989)
• A Practical Guide to UNIX System V by M. Sobell (Benjamin/Cummings
Publishing, 1985)
• Introducing the UNIX System by H. McGilton and R. Morgan (McGraw-Hill
Book Company, 1983)
• UNIX for People by P. Birns, P. Brown, and J. Muster (Prentice-Hall, 1985)
If you are interested in learning more about SQL, consider the following text:
• Using SQL by J. Groff and P. Weinberg (Osborne McGraw-Hill, 1990)
vi Preface
Table of
Contents
Table of Contents
Introduction
Informix Products That Use SQL 3
Products Included in This Manual 3
Other Useful Documentation 4
How to Use This Manual 5
Typographical Conventions 5
Example Code Conventions 5
Useful On-Line Files 6
ASCII and PostScript Error Message Files 7
The Demonstration Database 7
Creating the Demonstration Database 8
New Features in Informix Version 6.0 Products
That Use SQL 9
Table of Contents ix
Retrieving Single Rows 5-13
Data Type Conversion 5-14
Dealing with Null Data 5-15
Dealing with Errors 5-16
Retrieving Multiple Rows 5-19
Declaring a Cursor 5-20
Opening a Cursor 5-20
Fetching Rows 5-21
Cursor Input Modes 5-23
The Active Set of a Cursor 5-24
Using a Cursor: A Parts Explosion 5-26
Dynamic SQL 5-28
Preparing a Statement 5-29
Executing Prepared SQL 5-31
Dynamic Host Variables 5-33
Freeing Prepared Statements 5-33
Quick Execution 5-34
Embedding Data Definition Statements 5-34
Embedding Grant and Revoke Privileges 5-34
Summary 5-37
x Table of Contents
Lock Scope 7-6
The Duration of a Lock 7-8
Locks While Modifying 7-9
Setting the Isolation Level 7-9
Dirty Read Isolation 7-10
Committed Read Isolation 7-10
Cursor Stability Isolation 7-11
Repeatable Read Isolation 7-12
Setting the Lock Mode 7-13
Waiting for Locks 7-13
Not Waiting for Locks 7-14
Waiting a Limited Time 7-14
Handling a Deadlock 7-14
Handling External Deadlock 7-15
Simple Concurrency 7-15
Locking with Other Database Servers 7-16
Isolation While Reading 7-17
Locking Updated Rows 7-17
Hold Cursors 7-18
Summary 7-19
Table of Contents xi
Creating the Database 9-20
Using CREATE DATABASE 9-21
Using CREATE TABLE 9-24
Using Command Scripts 9-26
Populating the Tables 9-27
Summary 9-29
Table of Contents xv
Using Triggered Actions 15-7
Using BEFORE and AFTER Triggered Actions 15-7
Using FOR EACH ROW Triggered Actions 15-8
Using Stored Procedures as Triggered Actions 15-10
Tracing Triggered Actions 15-12
Generating Error Messages 15-14
Applying a Fixed Error Message 15-15
Generating a Variable Error Message 15-16
Summary 15-17
Index
Introduction
Informix Products That Use SQL 3
Products Included in This Manual 3
Other Useful Documentation 4
How to Use This Manual 5
Typographical Conventions 5
Example Code Conventions 5
Useful On-Line Files 6
ASCII and PostScript Error Message Files 7
The Demonstration Database 7
Creating the Demonstration Database 8
Compliance with Industry Standards 9
New Features in Informix Version 6.0 Products
That Use SQL 10
2 Introduction
Structured Query Language (SQL) is an English-like language that you can
use when creating, managing, and using relational databases. The SQL
provided with Informix products is an enhanced version of the industry-
standard query language developed by International Business Machines
Corporation (IBM).
Introduction 3
Other Useful Documentation
In addition, some examples in this manual are built using Informix products
at earlier release levels.
4 Introduction
How to Use This Manual
Typographical Conventions
Informix product manuals use a standard set of conventions to introduce
new terms, illustrate screen displays, describe command syntax, and so forth.
The following typographical conventions are used throughout this manual:
italics New terms, emphasized words, and variables are printed in
italics.
boldface Database names, table names, column names, filenames,
utilities, and other similar terms are printed in boldface.
computer Information that the product displays and information that
you enter are printed in a computer typeface.
KEYWORD All keywords appear in uppercase letters.
This symbol indicates a warning. Warnings provide critical
! information that, if ignored, could cause harm to your
database.
Additionally, when you are instructed to “enter” or “execute” text,
immediately press RETURN after the entry. When you are instructed to “type”
the text or “press” a key, no RETURN is required.
Introduction 5
Useful On-Line Files
CONNECT TO stores6
.
.
.
DELETE FROM customer
WHERE customer_num = 121
.
.
.
COMMIT WORK
DISCONNECT CURRENT
6 Introduction
ASCII and PostScript Error Message Files
A number of Informix products also provide on-line Help files that walk you
through each menu option. To invoke the Help feature, simply press CTRL-W
wherever you are in your Informix product.
Introduction 7
The Demonstration Database
• You can use letters, characters, and underscores (_) for the rest of the
name.
• DB-Access makes no distinction between uppercase and lowercase
letters.
• The database name should be unique.
When you run dbaccessdemo6, you are, as the creator of the database, the
owner and Database Administrator (DBA) of that database.
If you installed your Informix database server according to the installation
instructions, the files that make up the demonstration database are protected
so you cannot make any changes to the original database.
You can run the dbaccessdemo6 script again whenever you want to work
with a fresh demonstration database. The script prompts you when the cre-
ation of the database is complete, and asks if you would like to copy the sam-
ple command files to the current directory. Enter “N” if you have made
changes to the sample files and do not want them replaced with the original
versions. Enter “Y” if you want to copy over the sample command files.
8 Introduction
New Features in Informix Version 6.0 Products That Use SQL
4. Create the demonstration database and copy over the sample command
files by entering the following command:
To create the database without logging enter:
dbaccessdemo6 dbname
Introduction 9
New Features in Informix Version 6.0 Products That Use SQL
This section highlights the major new features implemented in Version 6.0 of
Informix products that use SQL.
• Native Language Support
Native Language Support (NLS) makes Informix Version 6.0 products
adaptable to various European cultural and language environments
without requiring changes to the application source code.
When appropriate environment variables are set to activate NLS and
specify a locale, Informix products can properly collate strings that con-
tain foreign characters, accept money and decimal input, and print dates
and times in the format required by the locale where the software is run.
The user can
o Create or access database information in any language available on
the system by changing a few environment variables
o Name user-defined objects such as databases, tables, columns, views,
cursors, and files using a foreign character set
o Use the new NCHAR and NVARCHAR data types in place of CHAR and
VARCHAR, respectively, for storing national characters
In addition, by installing one or more language supplements with an
Informix product, the user can view error and warning messages in the
language of the locale.
• Enhanced Database Connections
You can now use three new statements, CONNECT TO, DISCONNECT, and
SET CONNECTION to provide a connection-oriented association between
client and server processes in a networked or a non-networked environ-
ment. These three statements are compliant with X/Open and ANSI/ISO
specifications. Applications with embedded SQL can use these statements
for more uniform and portable syntax when accessing local or remote
data.
• Cascading Deletes
Support for cascading deletes is provided in INFORMIX-OnLine
Dynamic Server as an enhancement to referential integrity. Previously,
when you attempted to delete a row from a parent table without deleting
rows from associated child tables first, the delete was disallowed. Now
you can specify the ON DELETE CASCADE option on either the CREATE
TABLE or ALTER TABLE statements or on DB-Access menus to allow
deletes from a parent table to cause deletes on child tables.
10 Introduction
New Features in Informix Version 6.0 Products That Use SQL
Introduction 11
New Features in Informix Version 6.0 Products That Use SQL
o INFORMIXSERVER
o INFORMIXSHMBASE
o INFORMIXSTACKSIZE
o LANG
o LC_COLLATE
o LC_CTYPE
o LC_MONETARY
o LC_NUMERIC
o LC_TIME
• New Data Distribution Features
You can use the UPDATE STATISTICS statement to create data
distributions for each table. The database server uses these data distribu-
tions to improve the choice of execution paths for SELECT statements. The
new data-distribution feature affects application development in the
following three ways:
o The syntax for the UPDATE STATISTICS statement has been expanded.
o A new environment variable, DBUPSPACE, sets the upper limit of disk
space that you want to use when columns are sorted.
o You can use the dbschema utility to print distribution information.
• Introduction of Environment-Configuration Files
The following environment-configuration files can contain default values
of environment variables:
o $INFORMIXDIR/etc/informix.rc
o ~/.informix
These optional files allow the administrator or the user to set
environment variables in much the same way a .login or .profile file is
used, so that the variables do not need to be set at each session.
12 Introduction
Section I: Using Basic SQL
Chapter
1
Introducing
Database Features
and SQL
Chapter Overview 3
Databases: What and Why? 3
The Data Model 3
Storing Data 6
Querying Data 6
Modifying Data 8
Concurrent Use and Security 8
Centralized Management 9
Group and Private Databases 10
Essential Databases 10
Important Database Terms 11
The Relational Model 11
Tables 11
Columns 12
Rows 12
Tables, Rows, and Columns 12
Operations on Tables 13
Structured Query Language 14
Standard SQL 14
Informix SQL and ANSI SQL 15
ANSI-Compliant Databases 15
NLS Databases 16
The Database Software 16
The Applications 16
The Database Server 16
Interactive SQL 17
Reports and Forms 17
General Programming 17
Applications and Database Servers 18
Summary 18
ORDERS
order
1003
05/22/93
order
1001
05/20/93 customer
Anthony Higgins
item order
tennis 1011
racquet order 06/18/93
$19.80 1013
06/22/93
item
2 item
volleyball 1 case
nets tennis
ball
Storing Data
Another difference between a database and a file is that the organization of
the database is stored with the database.
A file may have a complex inner structure, but the definition of that structure
is not within the file; it is in the programs that create or use the file. For exam-
ple, a document file as stored by a word-processing program may contain
very detailed structures describing the format of the document. However,
only the word-processing program can decipher the contents of the file
because the structure is defined within the program, not within the file.
A data model, however, is contained in the database it describes. It travels
with the database and is available to any program that uses the database. The
model defines not only the names of the data items but also their data types,
so a program can adapt itself to the database. For example, a program can
find out that, in the current database, a price item is a decimal number with
eight digits, two to the right of the decimal point; then it can allocate storage
for a number of that type. How programs work with databases is the subject
of Chapter 5, “Programming with SQL,” and Chapter 6, “Modifying Data
Through SQL Programs.”
Querying Data
Another difference between a database and a file is the way you can
interrogate them. You can search a file sequentially, looking for particular val-
ues at particular physical locations in each line or record. That is, you might
ask a file, “What records have numbers under 20 in the fifth field?” Figure 1-2
illustrates this type of search.
ORDERS
In contrast, when you query a database you use the terms defined by its
model. To a database, you can pose questions such as, “What orders have been
placed for products made by the Shimara Corporation, by customers in New
Jersey, with ship dates in the third quarter?” Figure 1-3 illustrates this type of
query.
In other words, when you interrogate data stored in a file, you must state
your question in terms of the physical layout of the file. When you query a
database, you can ignore the arcane details of computer storage and state
your query in terms that reflect the real world—at least, to the extent that the
data model reflects the real world.
In this manual, Chapters 2 and 3 discuss the language you use for making
queries. Chapters 8 through 11 discuss designing an accurate, robust data
model for other users to query.
order
1016 state
order manufacturer 06/29/93 New Jersey
1019 Shimara
customer
07/16/93
Cathy
O’Brian
customer
Bob
order
Shorter
1023
07/24/93
Modifying Data
The model also makes it possible to modify the contents of the database with
less chance for error. You can query the database with commands such as
“Find every stock item with a manufacturer of Presta or Schraeder, and increase
its price by 13 percent.” You state changes in terms that reflect the meaning of
the data. You do not have to waste time and effort thinking about details of
fields within records in a file, so the chances for error are less.
The statements you use to modify stored data are covered in Chapter 5, “Pro-
gramming with SQL.”
Centralized Management
Databases that are used by many people are highly valuable and must be
protected as important business assets. This creates two significant problems:
protecting data and maintaining performance. The INFORMIX-OnLine
Dynamic Server database server allows you to centralize these tasks.
Databases must be guarded against loss or damage. The hazards are many:
failures in software and hardware, and the risks of fire, flood, and other nat-
ural disasters. Losing an important database creates a huge potential for
damage. The damage could include not only the expense and difficulty of re-
creating the lost data but also the loss of productive time by the database
users as well as the loss of business and good will while users cannot work.
A plan for regular archiving of critical databases can help avoid or mitigate
these potential disasters.
A large database used by many people must be maintained and tuned.
Someone must monitor its use of system resources, chart its growth, antici-
pate bottlenecks, and plan for expansion. Users will report problems in the
application programs; someone must diagnose these and correct them. If
rapid response is important, someone must study and analyze the
performance of the system and find the causes of slow responses.
Essential Databases
The INFORMIX-OnLine Dynamic Server database server is designed to man-
age large databases with requirements for high reliability, high availability,
and high performance. Although it supports private and group databases
very well, it is at its best managing the databases that are essential for your
organization to carry out its work.
INFORMIX-OnLine Dynamic Server gives you the ability to make archival
copies while the databases are in use. It also allows incremental archiving
(archiving only modified data), an important feature when making a com-
plete copy could take many reels of tape.
INFORMIX-OnLine Dynamic Server has an interactive monitor program by
which its operator (or any user) can monitor the activities within the database
server to see when bottlenecks are developing. It also comes with utility pro-
grams to analyze its use of disk storage. In addition, OnLine provides the
sysmaster tables that contain information about an entire OnLine database
server, which might manage many databases. For more information about
the sysmaster tables, see the INFORMIX-OnLine Dynamic Server Administra-
tor’s Guide.
Tables
A database is a collection of information grouped into one or more tables. A
table is an array of data items organized into rows and columns. A demon-
stration database is distributed with every Informix product. A partial table
from the demonstration database is shown in Figure 1-4.
stock Table
Figure 1-4 The stock table from the demonstration database distributed with all Informix
products
A table represents all that is known about one entity, one type of thing that
the database describes. The example table, stock, represents all that is known
about the merchandise that is stocked by a sporting-goods store. Other tables
in the demonstration database represent such entities as customer and
orders.
A database can be thought of as a collection of tables. To create a database is
to create a set of tables. The right to query or modify tables can be controlled
on a table-by-table basis, so that some users can view or modify some tables
and not others.
Columns
Each column of a table stands for one attribute, which is one characteristic,
feature, or fact that is true of the subject of the table. The stock table has col-
umns for the following facts about items of merchandise: stock numbers,
manufacturer codes, descriptions, prices, and units of measure.
Rows
Each row of a table stands for one instance of the subject of the table, which is,
one particular example of that entity. Each row of the stock table stands for
one item of merchandise that is sold by the sporting-goods store.
Operations on Tables
Because a database is really a collection of tables, database operations are
operations on tables. The relational model supports three fundamental oper-
ations, two of which are illustrated in Figure 1-5. (All three operations are
defined in more detail, with many examples, in Chapter 2, “Composing Sim-
ple SELECT Statements,” and Chapter 3, “Composing Advanced SELECT
Statements.”)
To select from a table is to choose certain rows, leaving others aside. One
selection that could be made on the stock table is “select all rows in which the
manufacturer code is HRO and the unit price is between 100.00 and 200.00.”
To project from a table is to choose certain columns, leaving others aside. One
projection that can be made from the stock table is “show me the stock_num,
unit_descr, and unit_price columns only.”
A table contains information about only one entity; when you want informa-
tion about multiple entities, you must join their tables. You can join tables in
many ways. (The join operation is the subject of Chapter 3, “Composing
Advanced SELECT Statements.”)
stock Table
P R O J E C T I O N
All the SQL statements are specified in detail in the Informix Guide to SQL:
Syntax. Most of the statements are used infrequently—when setting up or
tuning a database. People generally use three or four statements to query or
update databases.
One statement, SELECT, is in almost constant use. It is the only statement that
you can use to retrieve data from the database. It is also the most complicated
statement, and the next two chapters of this book are devoted to exploring its
many uses.
Standard SQL
SQL and the relational model were invented and developed at IBM in the
early and middle 1970s. Once IBM proved that it was possible to implement
practical relational databases and that SQL was a usable language for manip-
ulating them, other vendors began to provide similar products for non-IBM
computers.
For reasons of performance or competitive advantage, or to take advantage
of local hardware or software features, each of these SQL implementations
differed in small ways from each other and from the IBM version of the lan-
guage. To ensure that the differences remained small, a standards committee
was formed in the early 1980s.
This resolution is fair but makes the SQL documentation more complicated.
Wherever a difference exists between Informix and ANSI SQL, the Informix
Guide to SQL: Syntax describes both versions. Because you probably intend to
use only one version, you will have to ignore the version you do not need.
ANSI-Compliant Databases
You can designate a database as ANSI-compliant by using the MODE ANSI
keywords when you create it. Within such a database, certain characteristics
of the ANSI standard apply. For example, all actions that modify data auto-
matically take place within a transaction, which means that the changes are
made in their entirety or not at all. Differences in the behavior of ANSI-
compliant databases are noted where appropriate in the Informix Guide to
SQL: Syntax.
NLS Databases
The Version 6.0 Informix database servers provide Native Language Support
(NLS). This allows you to work in various European or Latin American lan-
guages other than English and conform to the customs of a specific locale
(various money and date formats, foreign characters in data or identifier
names, different collation order, and so on). You can activate the NLS func-
tionality by setting the DBNLS environment variable as well as other
NLS-specific environment variables.
Chapter 4 of the Informix Guide to SQL: Reference describes how to set the NLS
environment variables. For additional information on NLS databases, see
Chapter 1 in the Informix Guide to SQL: Reference.
The Applications
A database application, or simply application, is a program that uses the
database. It does so by calling on the database server. At its simplest, the
application sends SQL commands to the database server, and the database
server sends rows of data back to the application. Then the application
displays the rows to you, its user.
Alternatively, you command the application to add new data to the database.
It incorporates the new data as part of an SQL command to insert a row and
passes this command to the database server for execution.
Several types of applications exist. Some allow you to access the database
interactively using SQL; others present the stored data in different forms
related to its use.
Interactive SQL
To carry out the examples in this book, and to experiment with SQL and
database design for yourself, you need a program that lets you execute SQL
statements interactively. DB-Access and INFORMIX-SQL are two such pro-
grams. They assist you in composing SQL statements; then they pass your
SQL to the database server for execution and display the results to you.
General Programming
You can write programs that incorporate SQL statements and exchange data
with the database server. That is, you can write a program to retrieve data
from the database and format it however you choose. You also can write pro-
grams that take data from any source in any format, prepare it, and insert it
into the database.
You also can write programs called stored procedures to work with database
data and objects. The stored procedures that you write are stored directly in
a database within tables. You can then execute a stored procedure from
DB-Access or an SQL API.
1. An application that interacts with the user, prepares and formats data,
and sets up SQL statements.
2. A database server that manages the database and interprets the SQL.
All the applications converge on the database server, and only the database
server manipulates the database files on disk.
Summary
A database contains a collection of related information but differs in a
fundamental way from other methods of storing data. The database contains
not only the data but also a data model that defines each data item and
specifies its meaning with respect to the other items and to the real world.
A database can be used and even modified by several computer users
working concurrently. Different users can be given different views of the con-
tents of a database, and their access to those contents can be restricted in
several ways.
Composing Simple
SELECT Statements
2
Chapter Overview 3
Introducing the SELECT Statement 4
Some Basic Concepts 4
Privileges 5
Relational Operations 5
Selection and Projection 5
Joining 8
The Forms of SELECT 10
Special Data Types 11
Single-Table SELECT Statements 11
Selecting All Columns and Rows 12
Using the Asterisk 12
Reordering the Columns 13
Sorting the Rows 13
Selecting Specific Columns 18
ORDER BY and Native Language Support 25
Selecting Substrings 27
Using the WHERE Clause 28
Creating a Comparison Condition 29
Using Variable Text Searches 37
Using Exact Text Comparisons 37
Using a Single-Character Wildcard 38
MATCHES and Native Language Support 42
Comparing for Special Characters 43
Expressions and Derived Values 46
Arithmetic Expressions 46
Sorting on Derived Columns 52
Using Functions in SELECT Statements 53
Aggregate Functions 53
Time Functions 56
Other Functions and Keywords 63
Using Stored Procedures in SELECT Statements 67
Multiple-Table SELECT Statements 69
Creating a Cartesian Product 69
Creating a Join 71
Equi-Join 71
Natural Join 75
Multiple-Table Join 77
Some Query Shortcuts 79
Using Aliases 79
The INTO TEMP Clause 83
Summary 84
Privileges
Before you can query on data, you must have the Connect privilege to the
database and the Select privilege to the tables in it. These privileges normally
are granted to all users as a matter of course. Database access privileges are
discussed in Chapter 11, “Granting and Limiting Access to Your Database,”
of this manual and in the GRANT and REVOKE statements in Chapter 1 of the
Informix Guide to SQL: Syntax.
Relational Operations
A relational operation involves manipulating one or more tables, or relations, to
result in another table. The three kinds of relational operation are selection,
projection, and join. This chapter includes examples of selection, projection,
and simple joining.
Query 2-1
Query Result 2-1 contains the same number of columns as the customer table,
but only a subset of its rows. Because the data in the selected columns does
not fit on one line of the DB-Access or INFORMIX-SQL Interactive Schema
Editor (ISED) screen, the data is displayed vertically instead of horizontally.
customer_num 119
fname Bob
lname Shorter
company The Triathletes Club
address1 2405 Kings Highway
address2
city Cherry Hill
state NJ
zipcode 08002
phone 609-663-6079
customer_num 122
fname Cathy
lname O’Brian
company The Sporting Life
address1 543 Nassau Street
address2
city Princeton
state NJ
zipcode 08540
phone 609-342-0054
Query 2-2
Query Result 2-2 contains the same number of rows as the customer table,
but it projects only a subset of the table’s columns:
Bartlesville OK 74006
Blue Island NY 60406
Brighton MA 02135
Cherry Hill NJ 08002
Denver CO 80219
Jacksonville FL 32256
Los Altos CA 94022
Menlo Park CA 94025
Mountain View CA 94040
Mountain View CA 94063
Oakland CA 94609
Palo Alto CA 94303
Palo Alto CA 94304
Phoenix AZ 85008
Phoenix AZ 85016
Princeton NJ 08540
Redwood City CA 94026
Redwood City CA 94062
Redwood City CA 94063
San Francisco CA 94117
Sunnyvale CA 94085
Sunnyvale CA 94086
Wilmington DE 19898
The most common kind of SELECT statement uses both selection and
projection. A query of this kind, shown in Query 2-3, returns some of the
rows and some of the columns in a table:
Query 2-3
Query Result 2-3 contains a subset of the rows and a subset of the columns in
the customer table:
Joining
A join occurs when two or more tables are connected by one or more columns
in common, creating a new table of results. Query 2-4 uses a subset of the
items and stock tables to illustrate the concept of a join, as shown in Figure
2-1.
1 1002 4 football
Query 2-4
Query Result 2-4 is composed of specified rows and columns from both the
customer and state tables:
Query 2-5a
Query 2-5b uses the wildcard * (asterisk), which is shorthand for the select list.
The * represents the names of all the columns in the table. You can use the *
when you want all the columns, in their defined order.
Query 2-5b
Query 2-5a and Query 2-5b are equivalent and display the same results; that
is, a list of every column and row in the manufact table. Query Result 2-5
shows the results as they would appear on a DB-Access or INFORMIX-SQL
Interactive Schema Editor (ISED) screen.
SMT Smith 3
ANZ Anza 5
NRG Norge 7
HSK Husky 5
HRO Hero 4
SHM Shimara 30
KAR Karsten 21
NKL Nikolus 8
PRC ProCycle 9
Query 2-6
Query Result 2-6 includes the same columns as the previous one, but because
the columns are specified in a different order, the display is also different:
Smith SMT 3
Anza ANZ 5
Norge NRG 7
Husky HSK 5
Hero HRO 4
Shimara SHM 30
Karsten KAR 21
Nikolus NKL 8
ProCycle PRC 9
Query 2-7a
Query 2-7b
Query 2-7a and Query 2-7b produce the same display. Query Result 2-7
shows a list of every column and row in the manufact table, in order of
lead_time:
SMT Smith 3
HRO Hero 4
HSK Husky 5
ANZ Anza 5
NRG Norge 7
NKL Nikolus 8
PRC ProCycle 9
KAR Karsten 21
SHM Shimara 30
Ascending Order
The retrieved data is sorted and displayed, by default, in ascending order.
Ascending order is uppercase A to lowercase z for CHARACTER data types,
and lowest to highest value for numeric data types. DATE and DATETIME
type data are sorted from earliest to latest, and INTERVAL data is ordered
from shortest to longest span of time.
Descending Order
Descending order is the opposite of ascending order, from lowercase z to
uppercase A for character types and highest to lowest for numeric data types.
DATE and DATETIME data are sorted from latest to earliest, and INTERVAL
data is ordered from longest to shortest span of time. Query 2-8 shows an
example of descending order:
Query 2-8
The keyword DESC following a column name causes the retrieved data to be
sorted in descending order, as shown in Query Result 2-8:
SHM Shimara 30
KAR Karsten 21
PRC ProCycle 9
NKL Nikolus 8
NRG Norge 7
HSK Husky 5
ANZ Anza 5
HRO Hero 4
SMT Smith 3
You can specify any column (except TEXT or BYTE) in the ORDER BY clause,
and the database server sorts the data based on the values in that column.
Query 2-9
Query 2-10 shows the reversed order of the columns in the ORDER BY clause:
Query 2-10
In Query Result 2-10, the data appears in ascending order of unit_price and,
where two or more rows have the same unit_price (for example, $20.00,
$48.00, $312.00), the manu_code is in alphabetical order:
The order of the columns in the ORDER BY clause is important, and so is the
position of the DESC keyword. Although the statements in Query 2-11 con-
tain the same components in the ORDER BY clause, each produces a different
result (not shown):
Query 2-11
Query 2-12
Query Result 2-12 shows how the statement simply selects all data in the
customer_num column in the orders table and lists the customer numbers on
all the orders, including duplicates:
customer_num
101
104
104
104
104
106
106
110
110
111
112
115
116
117
117
119
120
121
122
123
124
126
127
The output includes several duplicates because some customers have placed
more than one order. Sometimes you want to see duplicate rows in a projec-
tion. At other times, you want to see only the distinct values, not how often
each value appears.
You can cause duplicate rows to be suppressed by including the keyword
DISTINCT or its synonym UNIQUE at the start of the select list, as shown in
Query 2-13:
Query 2-13
Query 2-13 limits the display to show each customer number in the orders
table only once, producing a more readable list, as shown in Query Result
2-13:
customer_num
101
104
106
110
111
112
115
116
117
119
120
121
122
123
124
126
127
Suppose you are handling a customer call, and you want to locate purchase
order number DM354331. You decide to list all the purchase order numbers in
the orders table, using a statement such as the one in Query 2-14:
Query 2-14
Query Result 2-14 shows how the statement retrieves data in the po_num
column in the orders table:
po_num
B77836
9270
B77890
8006
2865
Q13557
278693
LZ230
4745
429Q
B77897
278701
B77930
8052
MA003
PC6782
DM354331
S22942
Z55709
W2286
C3288
W9925
KF2961
However, the list is not in a very useful order. You can add an ORDER BY
clause to sort the column data in ascending order and make it easier to find
that particular po_num, as shown in Query 2-15:
Query 2-15
po_num
278693
278701
2865
429Q
4745
8006
8052
9270
B77836
B77890
B77897
B77930
C3288
DM354331
KF2961
LZ230
MA003
PC6782
Q13557
S22942
W2286
W9925
Z55709
To select multiple columns from a table, list them in the select list in the
SELECT clause. Query 2-16 shows the order in which the columns are selected
is the order in which they are produced, from left to right:
Query 2-16
As shown in “Sorting on Multiple Columns” on page 2-15, you can use the
ORDER BY clause to sort the data in ascending or descending order and
perform nested sorts. Query Result 2-16 shows descending order:
When you use SELECT and ORDER BY on several columns in a table, you
might find it helpful to use integers to refer to the position of the columns in
the ORDER BY clause.The statements in Query 2-17 retrieve and display the
same data, shown in Query Result 2-17.
Query 2-17
You can include the DESC keyword in the ORDER BY clause when you assign
integers to column names, as shown in Query 2-18:
Query 2-18
SELECT numéro,nom,prénom
FROM abonnés
ORDER BY nom;
Query 2-19
The collation order for the results of this query may vary, depending on
whether NLS is activated and the settings for the LANG and LC_COLLATE
environment variables, as well as how uppercase versus lowercase letters are
handled by the particular system. Query Result 2-19a and Query Result 2-19b
show two sample sets of output:
Query Result 2-19a follows the standard ASCII sorting order, which ranks
capital letters before lowercase letters and moves the names that start with a
capitalized foreign character (Ålesund, Étaix, Ötker, and Øverst) to the end
of the list.
Query Result 2-19b indicates that with the appropriate NLS environment
variable settings, names starting with foreign characters (Ålesund, Étaix,
Ötker, and Øverst) are collated differently than they are in the standard ASCII
order so they are integrated in the list. It does not distinguish between
uppercase and lowercase letters.
Selecting Substrings
You can select part of the value of a CHARACTER column by including a
substring in the select list. Suppose your marketing department is planning a
mailing to your customers and wants a rough idea of their geographical
distribution based on zip codes. You could write a query similar to Query
2-20:
Query 2-20
Query 2-20 uses a substring to select the first three characters of the zipcode
column (which identify the state) and the full customer_num, and lists them
in ascending order by zip code, as shown in Query Result 2-20:
zipcode customer_num
021 125
080 119
085 122
198 121
322 123
604 127
740 124
802 126
850 128
850 120
940 105
940 112
940 113
940 115
940 104
940 116
940 110
940 114
940 106
940 108
940 117
940 111
940 101
940 109
941 102
943 103
943 107
946 118
The set of rows returned by a SELECT statement is the active set for that
statement. A singleton SELECT statement returns a single row. In
INFORMIX-4GL or an SQL API, the retrieval of multiple rows requires the use
of a cursor. See Chapter 5, “Programming with SQL,” and Chapter 6,
“Modifying Data Through SQL Programs.”
Operator Operation
= equals
!= or <> does not equal
> greater than
>= greater than or equal to
< less than
<= less than or equal to
For CHAR expressions, “greater than” means after in ASCII collating order,
where lowercase letters are after uppercase letters, and both are after numer-
als. See the ASCII Character Set chart in Chapter 1 of the Informix Guide to
SQL: Syntax. For DATE and DATETIME expressions, “greater than” means
later in time, and for INTERVAL expressions, it means of longer duration. You
cannot use TEXT or BYTE columns in string expressions, except when you test
for null values.
You can use the preceding keywords and operators in a WHERE clause to
create comparison condition queries that perform the following actions:
• Include values
• Exclude values
• Find a range of values
Including Rows
Use the relational operator = to include rows in a WHERE clause, as shown in
Query 2-21:
Query 2-21
Query 2-21 returns the set of rows shown in Query Result 2-21:
Excluding Rows
Use the relational operators != or <> to exclude rows in a WHERE clause.
Query 2-22 assumes that you are selecting from an ANSI-compliant database;
the statements specify the owner or login name of the creator of the customer
table. This qualifier is not required when the creator of the table is the current
Query 2-22
Specifying Rows
Query 2-23 shows two ways to specify rows in a WHERE clause:
Query 2-23
Each statement in Query 2-23 specifies a range for catalog_num from 10005
through 10008, inclusive. The first statement uses keywords, and the second
uses relational operators to retrieve the rows shown in Query Result 2-23:
catalog_num 10005
stock_num 3
manu_code HSK
cat_advert High-Technology Design Expands the Sweet Spot
catalog_num 10006
stock_num 3
manu_code SHM
cat_advert Durable Aluminum for High School and Collegia
te Athletes
catalog_num 10007
stock_num 4
manu_code HSK
cat_advert Quality Pigskin with Joe Namath Signature
catalog_num 10008
stock_num 4
manu_code HRO
cat_advert Highest Quality Football for High School
and Collegiate Competitions
Note that although the catalog table includes a column with the BYTE data
type, that column is not included in this SELECT statement because the out-
put would show only the words <BYTE value> by the column name. You
can display TEXT and BYTE values by using the PROGRAM attribute when
using forms in INFORMIX-SQL or INFORMIX-4GL or by writing a 4GL or an
SQL API to do so.
Query 2-24
Query 2-25
Each statement in Query 2-25 retrieves rows that include the subset of AZ or
NJ in the state column of the Aleta.customer table, as shown in Query Result
2-25:
Note that you cannot test a TEXT or BYTE column with the IN keyword.
In Query 2-26, an example of a query on an ANSI-compliant database, no
quotation marks exist around the table owner name. Whereas the two state-
ments in Query 2-25 searched the Aleta.customer table, Query 2-26 searches
the table ALETA.customer, which is a different table, due to how ANSI-
compliant databases look at owner names.
Query 2-26
In Query 2-26, by adding the keyword NOT IN, the subset changes to exclude
the subsets AZ and NJ in the state column. Query Result 2-26 shows the
results in order of state:
Query 2-27
Query 2-28
Query 2-28 returns all rows that have a null paid_date and the ones that do
not also have a null ship_date, as shown in Query Result 2-28:
Symbol Meaning
LIKE
% evaluates to zero or more characters
_ evaluates to a single character
\ escapes special significance of next character
MATCHES
* evaluates to zero or more characters
? evaluates to a single character (except null)
[] evaluates to single character or range of values
\ escapes special significance of next character
Each statement in Query 2-29 retrieves all the rows that have the single word
helmet in the description column:
Query 2-29
Query 2-30
Each statement in Query 2-30 retrieves only those rows for which the middle
letter of the manu_code is R, as shown in Query Result 2-30:
The comparison '_R_' (for LIKE) or '?R?' (for MATCHES) specifies, from left
to right, the following items:
• Any single character
• The letter R
• Any single character
Query 2-31
Query 2-32
Query 2-33
The statement retrieves only the rows found in Query Result 2-33:
When you select from a large table and use an initial wildcard in the
comparison string (such as '%cycle'), the query often takes longer to execute.
This is because indexes cannot be used, so every row is searched.
SELECT numéro,nom,prénom
FROM abonnés
WHERE nom MATCHES '[E-P]*'
ORDER BY nom;
Query 2-34
The output in Query Result 2-34a and Query Result 2-34b show different
rows selected for the MATCHES range by the same query, based on different
NLS environment variable settings:
In Query Result 2-34a, the rows for Étaix, Ötker, and Øverst are not selected
and listed because, with standard ASCII ordering, the accented first letter of
each name is not in the E-P MATCHES range for the nom column.
In Query Result 2-34b, the rows for Étaix, Ötker, and Øverst are included in
the list because, with the appropriate NLS environment variable settings, the
accented first letter of each name is in the E-P MATCHES range for the nom
column.
Query 2-35
can search for occurrences of a percent sign (%) in the res_descr column with
the LIKE wildcard %. The query retrieves the row shown in Query Result 2-35:
customer_num 116
call_dtime 1992-12-21 11:24
user_id mannyn
call_code I
call_descr Second complaint from this customer! Received
two cases right-handed outfielder gloves
(1 HRO) instead of one case lefties.
res_dtime 1992-12-27 08:19
res_descr Memo to shipping (Ava Brown) to send case of
left-handed gloves, pick up wrong case; memo
to billing requesting 5% discount to placate
customer due to second offense and lateness
of resolution because of holiday
Query 2-36
The subscript [1,4] causes Query 2-36 to retrieve all rows in which the first
four letters of the cat_advert column are High, as shown in Query Result
2-36:
catalog_num 10004
stock_num 2
manu_code HRO
cat_advert Highest Quality Ball Available, from
Hand-Stitching to the Robinson Signature
cat_descr
Jackie Robinson signature ball. Highest professional quality, used by
National League.
catalog_num 10005
stock_num 3
manu_code HSK
cat_advert High-Technology Design Expands the Sweet Spot
cat_descr
Pro-style wood. Available in sizes: 31, 32, 33, 34, 35.
catalog_num 10008
stock_num 4
manu_code HRO
cat_advert Highest Quality Football for High School and
Collegiate Competitions
cat_descr
NFL-style, pigskin.
catalog_num 10012
stock_num 6
manu_code SMT
cat_advert High-Visibility Tennis, Day or Night
cat_descr
Soft yellow color for easy visibility in sunlight or
artificial light.
catalog_num 10043
stock_num 202
manu_code KAR
cat_advert High-Quality Woods Appropriate for High School
Competitions or Serious Amateurs
cat_descr
Full set of woods designed for precision control and
power performance.
catalog_num 10045
stock_num 204
manu_code KAR
cat_advert High-Quality Beginning Set of Irons
Appropriate for High School Competitions
cat_descr
Ideally balanced for optimum control. Nylon covered shaft.
catalog_num 10068
stock_num 310
manu_code ANZ
cat_advert High-Quality Kickboard
cat_descr
White. Standard size.
Arithmetic Expressions
An arithmetic expression contains at least one of the arithmetic operators listed
in Figure 2-4 and produces a number. You cannot use TEXT or BYTE columns
in arithmetic expressions.
Operator Operation
+ addition
- subtraction
* multiplication
/ division
Query 2-37
Query 2-38
Query 2-39 calculates and displays in an expression column (if you are using
DB-Access or INFORMIX-SQL) the interval between when the customer call
was received (call_dtime) and when the call was resolved (res_dtime), in
days, hours, and minutes.
Query 2-39
Query 2-40
Query Result 2-40 shows the label taxed is assigned to the expression in the
select list that displays the results of the operation unit_price * 1.07:
In Query 2-41, the label surcharge is defined for the column that displays the
results of the operation total_price + 6.50:
Query 2-41
Query 2-42 assigns the label span to the column that displays the results of
subtracting the DATETIME column call_dtime from the DATETIME column
res_dtime.
Query 2-42
The span column is labeled in the output, as shown in Query Result 2-42:
Query 2-43
Query 2-43 retrieves the same data from the cust_calls table as Query 2-42. In
Query 2-43, the ORDER BY clause causes the data to be displayed in ascending
order of the derived values in the span column, as shown in Query Result
2-43:
Query 2-44
Aggregate Functions
The aggregate functions are COUNT, AVG, MAX, MIN, and SUM. They take on
values that depend on all the rows selected and return information about
rows, not the rows themselves. You cannot use these functions with TEXT or
BYTE columns.
SELECT COUNT(*)
FROM stock
Query 2-45
(count(*))
73
Query 2-46 includes a WHERE clause to count specific rows in the stock table,
in this case, only those rows that have a manu_code of SHM:
Query 2-46
(count(*))
16
By including the keyword DISTINCT (or its synonym UNIQUE) and a column
name in Query 2-47, you can tally the number of different manufacturer
codes in the stock table:
Query 2-47
(count)
Query 2-48 computes the average unit_price of all rows in the stock table:
Query 2-48
(avg)
Query 2-49 computes the average unit_price of just those rows in the stock
table that have a manu_code of SHM:
Query 2-49
(avg)
Query 2-50
Query 2-50 finds and displays both the highest and lowest ship_charge in the
orders table, as shown in Query Result 2-50:
(max) (min)
You can apply functions to expressions, and you can supply display labels for
their results, as shown in Query 2-51:
Query 2-51
Query 2-51 finds and displays the maximum, minimum, and average amount
of time (in days, hours, and minutes) between the reception and resolution of
a customer call and labels the derived values appropriately. These amounts
of time are shown in Query Result 2-51:
Query 2-52 calculates the total ship_weight of orders shipped on July 13,
1993:
Query 2-52
(sum)
Time Functions
You can use the time functions DAY, MDY, MONTH, WEEKDAY, YEAR, and
DATE in either the SELECT clause or the WHERE clause of a query. These func-
tions return a value that corresponds to the expressions or arguments that
you use to call the function. You also can use the CURRENT function to return
a value with the current date and time, or the EXTEND function to adjust the
precision of a DATE or DATETIME value.
Query 2-53
106 12 12
110 7 7
119 1 2
121 10 10
127 31
116 28 28
116 21 27
Query 2-54 uses the DAY and CURRENT functions to compare column values
to the current day of the month. It selects only those rows where the value is
earlier than the current day.
Query 2-54
106 12 12
110 7 7
119 1 2
121 10 10
Query 2-55 shows another use of the CURRENT function, selecting rows
where the day is earlier than the current one:
Query 2-55
customer_num 106
call_code D
call_descr Order was received, but two of the cans of ANZ tennis
balls within the case were empty
customer_num 116
call_code I
call_descr Received plain white swim caps (313 ANZ) instead of
navy with team logo (313 SHM)
customer_num 116
call_code I
call_descr Second complaint from this customer! Received
two cases right-handed outfielder gloves (1 HRO) instead of
one case lefties.
Using MONTH
Query 2-56 uses the MONTH function to extract and show what month the
customer call was received and resolved and uses display labels for the
resulting columns. However, it does not make a distinction between years.
SELECT customer_num,
MONTH (call_dtime) call_month,
MONTH (res_dtime) res_month
FROM cust_calls
Query 2-56
106 6 6
110 7 7
119 7 7
121 7 7
127 7
116 11 11
116 12 12
Query 2-57 uses the MONTH function plus DAY and CURRENT to show what
month the customer call was received and resolved if DAY is earlier than the
current day:
SELECT customer_num,
MONTH (call_dtime) called,
MONTH (res_dtime) resolved
FROM cust_calls
WHERE DAY (res_dtime) < DAY (CURRENT)
Query 2-57
106 6 6
110 7 7
119 7 7
121 7 7
Using WEEKDAY
In Query 2-58, the WEEKDAY function is used to indicate which day of the
week calls are received and resolved (0 represents Sunday, 1 is Monday, and
so on), and the expression columns are labeled:
SELECT customer_num,
WEEKDAY (call_dtime) called,
WEEKDAY (res_dtime) resolved
FROM cust_calls
ORDER BY resolved
Query 2-58
127 3
110 0 0
119 1 2
121 3 3
116 3 3
106 3 3
116 5 4
Query 2-60 uses the COUNT and WEEKDAY functions to count how many
calls were received on a weekend. This kind of statement can give you an idea
of customer call patterns or indicate whether overtime pay might be
required.
SELECT COUNT(*)
FROM cust_calls
WHERE WEEKDAY (call_dtime) IN (0,6)
Query 2-59
(count(*))
Query 2-60 retrieves rows where the call_dtime is earlier than the beginning
of the current year.
Query 2-60
SELECT customer_num,
EXTEND (call_dtime, month to minute) call_time,
EXTEND (res_dtime, month to minute) res_time
FROM cust_calls
ORDER BY res_time
Query 2-61
Query Result 2-61 returns the month-to-minute range for the columns
labeled call_time and res_time and gives an indication of the workload:
Query 2-62
Query 2-63 converts DATETIME values to DATE format and displays the
values, with labels, only when call_dtime is greater than or equal to the
specified date.
SELECT customer_num,
DATE (call_dtime) called,
DATE (res_dtime) resolved
FROM cust_calls
WHERE call_dtime >= DATE ('1/1/93')
Query 2-63
SELECT customer_num,
LENGTH (fname) + LENGTH (lname) namelength
FROM customer
WHERE LENGTH (company) > 15
Query 2-64
customer_num namelength
101 11
105 13
107 11
112 14
115 11
118 10
119 10
120 10
122 12
124 11
125 10
126 12
127 10
128 11
Although it might not be useful when you work with the DB-Access or
INFORMIX-SQL Interactive Editor, the LENGTH function can be important to
determine the string length for programs and reports. LENGTH returns the
clipped length of a CHARACTER or VARCHAR string and the full number of
bytes in a TEXT or BYTE string.
The USER function can be handy when you want to define a restricted view
of a table that contains only your rows. For information on creating views, see
Chapter 11, “Granting and Limiting Access to Your Database,” in this manual
and the GRANT and CREATE VIEW statements in Chapter 1 of the Informix
Guide to SQL: Syntax.
Query 2-65a specifies the USER function and the cust_calls table:
Query 2-65a
Query 2-65b returns the user name (login account name) of the user who
executes the query. It is repeated once for each row in the table.
Query 2-65b
If the user name of the current user is richc, Query 2-65b retrieves only those
rows in the cust_calls table that are owned by that user.
customer_num 110
call_dtime 1993-07-07 10:24
user_id richc
call_code L
call_descr Order placed one month ago (6/7) not received.
res_dtime 1993-07-07 10:30
res_descr Checked with shipping (Ed Smith). Order sent
yesterday- we were waiting for goods from ANZ. Next
time will call with delay if necessary.
customer_num 119
call_dtime 1993-07-01 15:00
user_id richc
call_code B
call_descr Bill does not reflect credit from previous order
res_dtime 1993-07-02 08:21
res_descr Spoke with Jane Akant in Finance. She found the
error and is sending new bill to customer
Query 2-66, if issued when today’s system date is July 10, 1993, returns this
one row:
Query 2-66
order_num 1018
order_date 07/10/1993
customer_num 121
ship_instruct SW corner of Biltmore Mall
backlog n
po_num S22942
ship_date 07/13/1993
ship_weight 70.50
ship_charge $20.00
paid_date 08/06/1993
You can include the keyword DBSERVERNAME (or its synonym, SITENAME)
in a SELECT statement on INFORMIX-OnLine Dynamic Server to find the
name of the database server. You can query on the DBSERVERNAME for any
table that has rows, including system catalog tables.
In Query 2-67, you assign the label server to the DBSERVERNAME expression
and also select the tabid column from the systables system catalog table. This
table describes database tables, and tabid is the serial interval table identifier.
Query 2-67
server tabid
montague 1
montague 2
montague 3
montague 4
Without the WHERE clause to restrict the values in the tabid, the database
server name would be repeated for each row of the systables table.
In Query 2-68, the HEX function returns the hexadecimal format of three
specified columns in the customer table:
Query 2-68
Query 2-69
The output from this stored-procedure query is shown in Query Result 2-69:
101 Pauli 1
102 Sadler 0
103 Currie 0
104 Higgins 4
105 Vector 0
106 Watson 2
107 Ream 0
108 Quinn 0
109 Miller 0
110 Jaeger 2
111 Keyes 1
112 Lawson 1
113 Beatty 0
114 Albertson 0
115 Grant 1
116 Parmelee 1
117 Sipes 2
118 Baxter 0
119 Shorter 1
120 Jewell 1
121 Wallack 1
122 O’Brian 1
123 Hanlon 1
124 Putnum 1
125 Henry 0
126 Neelie 1
127 Satifer 1
128 Lessor 0
You can use stored procedures to encapsulate operations that you frequently
perform in your queries. For example, the condition in Query 2-70 contains a
procedure, conv_price, that converts the unit price of a stock item to a
different currency and adds any import tariffs:
Query 2-70
Query 2-71
Although only 52 rows exist in the state table and 28 rows in the customer
table, the effect of Query 2-71 is to multiply the rows of one table by the rows
of the other and retrieve an impractical 1456 rows, as shown in Query Result
2-71:
customer_num 101
fname Ludwig
lname Pauli
company All Sports Supplies
address1 213 Erstwild Court
address2
city Sunnyvale
state CA
zipcode 94086
phone 408-789-8075
code AK
sname Alaska
customer_num 101
fname Ludwig
lname Pauli
company All Sports Supplies
address1 213 Erstwild Court
address2
city Sunnyvale
state CA
zipcode 94086
phone 408-789-8075
code HI
sname Hawaii
customer_num 101
fname Ludwig
lname Pauli
company All Sports Supplies
address1 213 Erstwild Court
address2
city Sunnyvale
state CA
zipcode 94086
phone 408-789-8075
code CA
sname California
.
.
.
Note that some of the data displayed in the concatenated rows is inaccurate.
For example, although the city and state from the customer table indicate an
address in California, the code and sname from the state table might be for a
different state.
Creating a Join
Conceptually, the first stage of any join is the creation of a Cartesian product.
To refine or constrain this Cartesian product and eliminate meaningless rows
of data, include a WHERE clause with a valid join condition in your SELECT
statement.
This section illustrates equi-joins, natural joins, and multiple-table joins.
Additional complex forms, such as self-joins and outer joins, are covered in
Chapter 3, “Composing Advanced SELECT Statements.”
Equi-Join
An equi-join is a join based on equality or matching values. This equality is
indicated with an equal sign (=) in the comparison operation in the WHERE
clause, as shown in Query 2-72:
Query 2-72
Query 2-72 joins the manufact and stock tables on the manu_code column,
retrieving only those rows for which the values for the two columns are
equal, as shown in Query Result 2-72:
manu_code SMT
manu_name Smith
lead_time 3
stock_num 1
manu_code SMT
description baseball gloves
unit_price $450.00
unit case
unit_descr 10 gloves/case
manu_code SMT
manu_name Smith
lead_time 3
stock_num 5
manu_code SMT
description tennis racquet
unit_price $25.00
unit each
unit_descr each
manu_code SMT
manu_name Smith
lead_time 3
stock_num 6
manu_code SMT
description tennis ball
unit_price $36.00
unit case
unit_descr 24 cans/case
manu_code ANZ
manu_name Anza
lead_time 5
stock_num 5
manu_code ANZ
description tennis racquet
unit_price $19.80
unit each
unit_descr each
.
.
.
Query Result 2-72
Note that in this equi-join, Query Result 2-72 includes the manu_code
column from both the manufact and stock tables because the select list
requested every column.
You also can create an equi-join with additional constraints, one where the
comparison condition is based on the inequality of values in the joined col-
umns. These joins use a relational operator other than = in the comparison
condition specified in the WHERE clause.
When columns in the joined tables have the same name, the columns must be
preceded by the name of a specific table and a period, as shown in Query
2-73:
Query 2-73
Query 2-73 joins on the customer_num column and then selects only those
rows where the call_dtime in the cust_calls table is greater than or equal to
the ship_date in the orders table. It returns the rows shown in Query Result
2-73:
order_num 1004
order_date 05/22/1993
ship_date 05/30/1993
customer_num 106
call_dtime 1993-06-12 08:20
user_id maryj
call_code D
call_descr Order received okay, but two of the cans of
ANZ tennis balls within the case were empty
res_dtime 1993-06-12 08:25
res_descr Authorized credit for two cans to customer,
issued apology. Called ANZ buyer to report
the qa problem.
order_num 1008
order_date 06/07/1993
ship_date 07/06/1993
customer_num 110
call_dtime 1993-07-07 10:24
user_id richc
call_code L
call_descr Order placed one month ago (6/7) not received.
res_dtime 1993-07-07 10:30
res_descr Checked with shipping (Ed Smith). Order out
yesterday-was waiting for goods from ANZ.
Next time will call with delay if necessary.
order_num 1023
order_date 07/24/1993
ship_date 07/30/1993
customer_num 127
call_dtime 1993-07-31 14:30
user_id maryj
call_code I
call_descr Received Hero watches (item # 304) instead
of ANZ watches
res_dtime
res_descr Sent memo to shipping to send ANZ item 304
to customer and pickup HRO watches. Should
be done tomorrow, 8/1
Natural Join
A natural join is structured so that the join column does not display data
redundantly, as shown in Query 2-74:
Query 2-74
Like the example for equi-join, Query 2-74 joins the manufact and stock
tables on the manu_code column. Because the select list is more closely
defined, the manu_code is listed only once for each row retrieved, as shown
in Query Result 2-74:
manu_name Smith
lead_time 3
stock_num 1
manu_code SMT
description baseball gloves
unit_price $450.00
unit case
unit_descr 10 gloves/case
manu_name Smith
lead_time 3
stock_num 5
manu_code SMT
description tennis racquet
unit_price $25.00
unit each
unit_descr each
manu_name Smith
lead_time 3
stock_num 6
manu_code SMT
description tennis ball
unit_price $36.00
unit case
unit_descr 24 cans/case
manu_name Anza
lead_time 5
stock_num 5
manu_code ANZ
description tennis racquet
unit_price $19.80
unit each
unit_descr each
.
.
.
Query Result 2-74
All joins are associative, that is, the order of the joining terms in the WHERE
clause does not affect the meaning of the join.
Both of the statements in Query 2-75 create the same natural join:
Query 2-75
catalog_num 10017
stock_num 101
manu_code PRC
cat_descr
Reinforced, hand-finished tubular. Polyurethane belted.
Effective against punctures. Mixed tread for super wear
and road grip.
cat_picture <BYTE value>
Note that Query Result 2-75 includes a TEXT column, cat_descr; a BYTE
column, cat_picture; and a VARCHAR column, cat_advert.
Multiple-Table Join
A multiple-table join connects more than two tables on one or more associ-
ated columns; it can be an equi-join or a natural join.
Query 2-76 creates an equi-join on the catalog, stock, and manufact tables
and retrieves the following row:
Query 2-76
catalog_num 10025
stock_num 106
manu_code PRC
cat_descr
Hard anodized alloy with pearl finish; 6mm hex bolt hardware.
Available in lengths of 90-140mm in 10mm increments.
cat_picture <BYTE value>
Note that the manu_code is repeated three times, once for each table, and
stock_num is repeated twice.
Because of the considerable duplication of a multiple-table query in Query
2-76, it is wise to more closely define the SELECT statement by including
specific columns in the select list, as shown in Query 2-77:
Query 2-77
Query 2-77 uses a wildcard to select all columns from the table having the
most columns and then specifies columns from the other two tables. It pro-
duces the natural join, shown in Query Result 2-77, that displays the same
information as the previous example, but without duplication:
catalog_num 10025
stock_num 106
manu_code PRC
cat_descr
Hard anodized alloy with pearl finish. 6mm hex bolt hardware.
Available in lengths of 90-140mm in 10mm increments.
cat_picture <BYTE value>
Using Aliases
You can make multiple-table queries shorter and more readable by assigning
aliases to the tables in a SELECT statement. An alias is a word that immediately
follows the name of a table in the FROM clause. You can use it wherever the
table name would be used, for instance, as a prefix to the column names in
the other clauses.
Query 2-78a
The associative nature of the SELECT statement allows you to use an alias
before you define it. In Query 2-78a, the aliases s for the stock table, c for the
catalog table, and m for the manufact table are specified in the FROM clause
and used throughout the SELECT and WHERE clauses as column prefixes.
Compare the length of Query 2-78a with Query 2-78b, which does not use
aliases:
Query 2-78b
Query 2-78a and Query 2-78b are equivalent and retrieve the data shown in
Query Result 2-78:
stock_num 110
manu_code HRO
description helmet
unit_price $260.00
unit case
catalog_num 10033
cat_descr
Newest ultralight helmet uses plastic shell. Largest ventilation
channels of any helmet on the market. 8.5 oz.
cat_advert Lightweight Plastic Slatted with Vents Assures Cool
Comfort Without Sacrificing Protection
lead_time 4
stock_num 110
manu_code HSK
description helmet
unit_price $308.00
unit each
catalog_num 10034
cat_descr
Aerodynamic (teardrop) helmet covered with anti-drag fabric.
Credited with shaving 2 seconds/mile from winner’s time in
Tour de France time-trial. 7.5 oz.
cat_advert Teardrop Design Endorsed by Yellow Jerseys,
You Can Time the Difference
lead_time 5
stock_num 205
manu_code HRO
description 3 golf balls
unit_price $312.00
unit each
catalog_num 10048
cat_descr
Combination fluorescent yellow and standard white.
cat_advert HiFlier Golf Balls: Case Includes Fluorescent
Yellow and Standard White
lead_time 4
stock_num 301
manu_code HRO
description running shoes
unit_price $42.50
unit each
catalog_num 10050
cat_descr
Engineered for serious training with exceptional stability.
Fabulous shock absorption. Great durability. Specify
mens/womens, size.
cat_advert Pronators and Supinators Take Heart: A Serious
Training Shoe For Runners Who Need Motion Control
lead_time 4
Note that you cannot ORDER BY the TEXT column cat_descr or the BYTE
column cat_picture.
You also can use aliases to shorten your queries on external tables residing in
external databases.
Query 2-79 joins columns from two tables that reside in different databases
and systems, neither of which is the current database or system:
Query 2-79
Query 2-80
You can query on this table and join it with other tables, which avoids a mul-
tiple sort and lets you move more quickly through the database. Temporary
tables are discussed at greater length in Chapter 13, “Optimizing Your Que-
ries.”
Summary
This chapter introduced sample syntax and results for basic kinds of SELECT
statements that are used to query on a relational database. Earlier sections of
the chapter showed how to perform the following activities:
• Select all columns and rows from a table with the SELECT and FROM
clauses.
• Select specific columns from a table with the SELECT and FROM clauses.
• Select specific rows from a table with the SELECT, FROM, and WHERE
clauses.
• Use the DISTINCT or UNIQUE keyword in the SELECT clause to eliminate
duplicate rows from query results.
• Sort retrieved data with the ORDER BY clause and the DESC keyword.
• Select and order data containing foreign characters.
• Use the BETWEEN, IN, MATCHES, and LIKE keywords and various rela-
tional operators in the WHERE clause to create a comparison condition.
• Create comparison conditions that include values, exclude values, find a
range of values (with keywords, relational operators, and subscripting),
and find a subset of values.
• Perform variable text searches using exact text comparisons, variable-
length wildcards, and restricted and unrestricted wildcards.
• Use the logical operators AND, OR, and NOT to connect search conditions
or Boolean expressions in a WHERE clause.
• Use the ESCAPE keyword to protect special characters in a query.
• Search for null values with the IS NULL and IS NOT NULL keywords in the
WHERE clause.
• Use arithmetic operators in the SELECT clause to perform computations
on number fields and display derived data.
• Use substrings and subscripting to tailor your queries.
• Assign display labels to computed columns as a formatting tool for
reports.
• Use the aggregate functions COUNT, AVG, MAX, MIN, and SUM in the
SELECT clause to calculate and retrieve specific data.
• Include the time functions DATE, DAY, MDY, MONTH, WEEKDAY, YEAR,
CURRENT, and EXTEND plus the TODAY, LENGTH, and USER functions in
your SELECT statements.
• Include stored procedures in your SELECT statements.
This chapter also introduced simple join conditions that enable you to select
and display data from two or more tables. The section “Multiple-Table
SELECT Statements” described how to perform the following actions:
• Create a Cartesian product.
• Constrain a Cartesian product by including a WHERE clause with a valid
join condition in your query.
• Define and create a natural join and an equi-join.
• Join two or more tables on one or more columns.
• Use aliases as a shortcut in multiple-table queries.
• Retrieve selected data into a separate, temporary table with the INTO
TEMP clause to perform computations outside the database.
The next chapter explains more complex queries and subqueries; self-joins
and outer joins; the GROUP BY and HAVING clauses; and the UNION,
INTERSECTION, and DIFFERENCE set operations.
Composing
Advanced SELECT
Statements
Chapter Overview 3
3
Using the GROUP BY and HAVING Clauses 4
Using the GROUP BY Clause 4
Using the HAVING Clause 9
Creating Advanced Joins 11
Self-Joins 11
Outer Joins 21
Simple Join 22
Simple Outer Join on Two Tables 24
Outer Join for a Simple Join to a Third Table 26
Outer Join for an Outer Join to a Third Table 28
Outer Join of Two Tables to a Third Table 30
Subqueries in SELECT Statements 32
Using ALL 33
Using ANY 34
Single-Valued Subqueries 36
Correlated Subqueries 37
Using EXISTS 38
Set Operations 42
Union 43
Intersection 51
Difference 53
Summary 54
3-2 Composing Advanced SELECT Statements
Chapter Overview
Chapter 2, “Composing Simple SELECT Statements,” demonstrated some of
the basic ways to retrieve data from a relational database with the SELECT
statement. This chapter increases the scope of what you can do with this pow-
erful SQL statement and enables you to perform more complex database
queries and data manipulation.
Whereas the previous chapter focused on five of the clauses in SELECT
statement syntax, this chapter adds two more. You can use the GROUP BY
clause with aggregate functions to organize rows returned by the FROM
clause. You can include a HAVING clause to place conditions on the values
returned by the GROUP BY clause.
This chapter extends the earlier discussion of joins. It illustrates self-joins,
which enable you to join a table to itself, and four kinds of outer joins, where
you apply the keyword OUTER to treat two or more joined tables unequally.
It also introduces correlated and uncorrelated subqueries and their opera-
tional keywords, shows how to combine queries with the UNION operator,
and defines the set operations known as union, intersection, and difference.
Examples in this chapter show how to use some or all of the SELECT
statement clauses in your queries. The clauses must appear in the following
order:
1. SELECT
2. FROM
3. WHERE
4. GROUP BY
5. HAVING
6. ORDER BY
7. INTO TEMP
An additional SELECT statement clause, INTO, which you can use to specify
program and host variables in INFORMIX-4GL and SQL APIs is described in
Chapter 5, “Programming with SQL,” as well as in the manuals that come
with the product.
Using the GROUP BY clause without aggregates is much like using the
DISTINCT (or UNIQUE) keyword in the SELECT clause. Chapter 2, “Compos-
ing Simple SELECT Statements” included the statement found in Query 3-1a:
Query 3-1a
SELECT customer_num
FROM orders
GROUP BY customer_num
Query 3-1b
Query 3-1a and Query 3-1b return the rows shown in Query Result 3-1:
customer_num
101
104
106
110
111
112
115
116
117
119
120
121
122
123
124
126
127
The GROUP BY clause collects the rows into sets so that each row in each set
has equal customer numbers. With no other columns selected, the result is a
list of the unique customer_num values.
The power of the GROUP BY clause is more apparent when you use it with
aggregate functions.
Query 3-2 retrieves the number of items and the total price of all items for
each order:
Query 3-2
The GROUP BY clause causes the rows of the items table to be collected into
groups, each group composed of rows that have identical order_num values
(that is, the items of each order are grouped together). After you form the
groups, the aggregate functions COUNT and SUM are applied within each
group.
Query 3-2 returns one row for each group. It uses labels to give names to the
results of the COUNT and SUM expressions, as shown in Query Result 3-2:
1001 1 $250.00
1002 2 $1200.00
1003 3 $959.00
1004 4 $1416.00
1005 4 $562.00
1006 5 $448.00
1007 5 $1696.00
1008 2 $940.00
.
.
.
1015 1 $450.00
1016 4 $654.00
1017 3 $584.00
1018 5 $1131.00
1019 1 $1499.97
1020 2 $438.00
1021 4 $1614.00
1022 3 $232.00
1023 6 $824.00
Query Result 3-2 collects the rows of the items table into groups that have
identical order numbers and computes the COUNT of rows in each group and
the sum of the prices.
Note that you cannot include a column having a TEXT or BYTE data type in a
GROUP BY clause. To group, you must be able to sort, and no natural sort order
exists for TEXT or BYTE data.
Unlike the ORDER BY clause, the GROUP BY clause does not order data.
Include an ORDER BY clause after your GROUP BY clause if you want to sort
data in a particular order or to sort on an aggregate in the select list.
Query 3-3 is the same as Query 3-2 but includes an ORDER BY clause to sort
the retrieved rows in ascending order of price, as shown in Query Result 3-3:
Query 3-3
1010 2 $84.00
1011 1 $99.00
1013 4 $143.80
1022 3 $232.00
1001 1 $250.00
1020 2 $438.00
1006 5 $448.00
1015 1 $450.00
1009 1 $450.00
.
.
.
1018 5 $1131.00
1002 2 $1200.00
1004 4 $1416.00
1014 2 $1440.00
1019 1 $1499.97
1021 4 $1614.00
1007 5 $1696.00
Query 3-3 returns the same rows as Query 3-4, as shown in Query Result 3-3.
Query 3-4
When you build a query, remember that all nonaggregate columns that are in
the select list in the SELECT clause must also be included in the group list in
the GROUP BY clause. The reason for this is that a SELECT with GROUP BY
must return only one row per group. Columns that are listed after GROUP BY
are certain to reflect only one distinct value within a group, and that value
can be returned. However, a column not listed after GROUP BY might contain
different values in the rows that are contained in a group.
As shown in Query 3-5, you can use the GROUP BY clause in a SELECT
statement that joins tables:
Query 3-5
Query 3-5 joins the orders and items tables, assigns table aliases to them, and
returns the rows shown in Query Result 3-5:
order_num (sum)
1008 $940.00
1015 $450.00
Query 3-6
1003 3 $319.67
1004 4 $354.00
1005 4 $140.50
1006 5 $89.60
1007 5 $339.20
1013 4 $35.95
1016 4 $163.50
1017 3 $194.67
1018 5 $226.20
1021 4 $403.50
1022 3 $77.33
1023 6 $137.33
Query 3-7, a modified version of Query 3-6, returns just one row, the average
of all total_price values in the table:
Query 3-7
average
$270.97
If Query 3-7, like Query 3-6, had included the nonaggregate column
order_ num in the select list, you would have to include a GROUP BY clause
with that column in the group list. In addition, if the condition in the HAVING
clause was not satisfied, the output would show the column heading and a
message would indicate that no rows were found.
Query 3-8 contains all the SELECT statement clauses that you can use in the
Informix version of interactive SQL (the INTO clause naming program or host
variables is available only in an INFORMIX-4GL or an SQL API:
Query 3-8
Query 3-8 joins the orders and items tables; employs display labels, table
aliases, and integers used as column indicators; groups and orders the data;
and puts the following results in a temporary table, as shown in Query Result
3-8:
1017 $584.00
1016 $654.00
1012 $1040.00
1019 $1499.97 26
1005 $562.00 28
1021 $1614.00 30
1022 $232.00 40
1010 $84.00 66
1009 $450.00 68
1020 $438.00 71
Self-Joins
A join does not always have to involve two different tables. You can join a
table to itself, creating a self-join. This can be useful when you want to
compare values in a column to other values in the same column.
To create a self-join, list a table twice in the FROM clause, assigning it a
different alias each time. Use the aliases to refer to the table in the SELECT and
WHERE clauses as if it were two separate tables. (Aliases in SELECT state-
ments are shown in Chapter 2, “Composing Simple SELECT Statements” of
this manual and discussed in Chapter 1 of the Informix Guide to SQL: Syntax.)
Query 3-9
Suppose you want to select the results of a self-join into a temporary table.
You would, of course, append an INTO TEMP clause to the SELECT statement.
However, because you are, in effect, creating a new table, you also must
rename at least one set of column names by assigning them display labels.
Otherwise, you get an error message that indicates duplicate column names,
and the temporary table is not created.
Query 3-10, which is similar to Query 3-9, labels all columns selected from the
orders table and puts them in a temporary table called shipping:
Query 3-10
If you SELECT * from that table, you see the rows in Query Result 3-10:
You can join a table to itself more than once. The maximum number of
self-joins depends on the resources available to you.
The self-join in Query 3-11 creates a list of those items in the stock table that
are supplied by three manufacturers. By including the last two conditions in
the WHERE clause, it eliminates duplicate manufacturer codes in rows
retrieved.
Query 3-11
Say you want to select rows from a payroll table to determine which
employees earn more than their manager. You can construct the self-join
shown in Query 3-12a:
Query 3-12a
Query 3-12b uses a correlated subquery to retrieve and list the 10 highest-priced
items ordered:
Query 3-12b
order_num total_price
1018 $15.00
1013 $19.80
1003 $20.00
1005 $36.00
1006 $36.00
1013 $36.00
1010 $36.00
1013 $40.00
1022 $40.00
1023 $40.00
You can create a similar query to find and list the 10 employees in the
company who have the most seniority.
Query 3-13
Query 3-13 searches for duplicate values in the customer_num column, and
for their rowids, finding the pair shown in Query Result 3-13:
rowid customer_num
515 116
769 116
You can write the last condition in Query 3-13 as shown in the following
example:
Query 3-14
Query 3-14 locates the same two duplicate customer_num values as Query
3-13 and returns the rows shown in Query Result 3-14:
customer_num call_dtime
You can use the rowid, shown earlier in a self-join, to locate the internal
record number associated with a row in a database table. The rowid is, in
effect, a hidden column in every table. The sequential values of rowid have
no special significance and may vary depending on the location of the phys-
ical data in the chunk. Your rowid may vary from the example shown. See
Chapter 13, “Optimizing Your Queries” in this manual for a discussion of
performance issues and the rowid value. The use of rowid is also discussed
in detail in the INFORMIX-OnLine Dynamic Server Administrator’s Guide.
Query 3-16 uses rowid and the wildcard * in the SELECT clause to retrieve
every row in the manufact table and their corresponding rowids:
Query 3-15
You also can use rowid when you select a specific column, as shown in Query
3-16:
Query 3-16
rowid manu_code
258 ANZ
261 HRO
260 HSK
263 KAR
264 NKL
259 NRG
265 PRC
262 SHM
257 SMT
You also can use the rowid in the WHERE clause to retrieve rows based on
their internal record number. This method is handy when no other unique
column exists in a table. Query 3-17 uses the rowid from Query 3-16:
Query 3-17
KAR Karsten 21
Query 3-18
username rowid
zenda 257
zenda 258
zenda 259
zenda 513
zenda 514
zenda 515
zenda 769
You also can use the USER function in a WHERE clause when you select the
rowid.
Query 3-19 returns the rowid for only those rows inserted or updated by the
user who performs the query:
Query 3-19
For example, if the user richc used Query 3-19, the output would be as shown
in Query Result 3-19:
rowid
258
259
Query 3-20
Note that you should never store a rowid in a permanent table or attempt to
use it as a foreign key because the rowid can change. For example, if a table
is dropped and then reloaded from external data, all the rowids are different.
USER and DBSERVERNAME were discussed in Chapter 2, “Composing Sim-
ple SELECT Statements.”
Outer Joins
Chapter 2, “Composing Simple SELECT Statements,” showed how to create
and use some simple joins. Whereas a simple join treats two or more joined
tables equally, an outer join treats two or more joined tables unsymmetrically.
It makes one of the tables dominant (also called “preserved”) over the other
subservient tables.
Outer joins occur in four basic types:
• A simple outer join on two tables
• A simple outer join to a third table
• An outer join for a simple join to a third table
• An outer join for an outer join to a third table
This section discusses these types of outer joins. See the discussion of outer
joins in Chapter 1 of the Informix Guide to SQL: Syntax for full information on
their syntax, use, and logic.
In a simple join, the result contains only the combinations of rows from the
tables that satisfy the join conditions. Rows that do not satisfy the join conditions
are discarded.
In an outer join, the result contains the combinations of rows from the tables
that satisfy the join conditions. Rows from the dominant table that would other-
wise be discarded are preserved, even though no matching row was found in the sub-
servient table. The dominant-table rows that do not have a matching
subservient-table row receive a row of nulls before the selected columns are
projected.
An outer join applies conditions to the subservient table while sequentially
applying the join conditions to the rows of the dominant table. The condi-
tions are expressed in a WHERE clause.
An outer join must have a SELECT clause, a FROM clause, and a WHERE
clause. You transform a simple join into an outer join by inserting the key-
word OUTER directly before the name of the subservient tables in the FROM
clause. As shown later in this section, you can include the OUTER keyword
more than once in your query.
Before you use outer joins heavily, you should determine whether one or
more simple joins can work. You often can get by with a simple join when you
do not need supplemental information from other tables.
The examples in this section use table aliases for brevity. Table aliases are
discussed in the preceding chapter.
Simple Join
Query 3-21 is an example of the type of simple join on the customer and
cust_calls tables shown in Chapter 2, “Composing Simple SELECT State-
ments.”
Query 3-21
Query 3-21 returns only those rows where the customer has made a call to
customer service, as shown in Query Result 3-21:
customer_num 106
lname Watson
company Watson & Son
phone 415-389-8789
call_dtime 1993-06-12 08:20
call_descr Order was received, but two of the cans of
ANZ tennis balls within the case were empty
customer_num 110
lname Jaeger
company AA Athletics
phone 415-743-3611
call_dtime 1993-07-07 10:24
call_descr Order placed one month ago (6/7) not received.
customer_num 119
lname Shorter
company The Triathletes Club
phone 609-663-6079
call_dtime 1993-07-01 15:00
call_descr Bill does not reflect credit from previous order
customer_num 121
lname Wallack
company City Sports
phone 302-366-7511
call_dtime 1993-07-10 14:05
call_descr Customer likes our merchandise. Requests that we
stock more types of infant joggers. Will call back
to place order.
customer_num 127
lname Satifer
company Big Blue Bike Shop
phone 312-944-5691
call_dtime 1993-07-31 14:30
call_descr Received Hero watches (item # 304) instead of
ANZ watches
customer_num 116
lname Parmelee
company Olympic City
phone 415-534-8822
call_dtime 1992-11-28 13:34
call_descr Received plain white swim caps (313 ANZ) instead
of navy with team logo (313 SHM)
customer_num 116
lname Parmelee
company Olympic City
phone 415-534-8822
call_dtime 1992-12-21 11:24
call_descr Second complaint from this customer! Received
two cases right-handed outfielder gloves (1 HRO)
instead of one case lefties.
Query 3-22
The addition of the keyword OUTER in front of the cust_calls table makes it
the subservient table. An outer join causes the query to return information on
all customers, whether or not they have made calls to customer service. All
rows from the dominant customer table are retrieved, and null values are
assigned to corresponding rows from the subservient cust_calls table.
customer_num 101
lname Pauli
company All Sports Supplies
phone 408-789-8075
call_dtime
call_descr
customer_num 102
lname Sadler
company Sports Spot
phone 415-822-1289
call_dtime
call_descr
customer_num 103
lname Currie
company Phil’s Sports
phone 415-328-4543
call_dtime
call_descr
customer_num 104
lname Higgins
company Play Ball!
phone 415-368-1100
call_dtime
call_descr
customer_num 105
lname Vector
company Los Altos Sports
phone 415-776-3249
call_dtime
call_descr
customer_num 106
lname Watson
company Watson & Son
phone 415-389-8789
call_dtime 1993-06-12 08:20
call_descr Order was received, but two of the cans of
ANZ tennis balls within the case were empty
customer_num 107
lname Ream
company Athletic Supplies
phone 415-356-9876
call_dtime
call_descr
customer_num 108
lname Quinn
company Quinn’s Sports
phone 415-544-8729
call_dtime
call_descr
.
.
.
Query 3-23
Query 3-23 first performs a simple join on the orders and items tables,
retrieving information on all orders for items with a manu_code of KAR or
SHM. It then performs an outer join to combine this information with data
from the dominant customer table. An optional ORDER BY clause reorganizes
the data into the form shown in Query Result 3-23:
114 Albertson
118 Baxter
113 Beatty
103 Currie
115 Grant
123 Hanlon 1020 301 KAR 4
123 Hanlon 1020 204 KAR 2
125 Henry
104 Higgins
110 Jaeger
120 Jewell 1017 202 KAR 1
120 Jewell 1017 301 SHM 2
111 Keyes
112 Lawson
128 Lessor
109 Miller
126 Neelie
122 O’Brian 1019 111 SHM 3
116 Parmelee
101 Pauli
124 Putnum 1021 202 KAR 3
108 Quinn
107 Ream
102 Sadler
127 Satifer 1023 306 SHM 1
127 Satifer 1023 105 SHM 1
127 Satifer 1023 110 SHM 1
119 Shorter 1016 101 SHM 2
117 Sipes
105 Vector
121 Wallack 1018 302 KAR 3
106 Watson
Query 3-24
Query 3-24 first performs an outer join on the orders and items tables,
retrieving information on all orders for items with a manu_code of KAR or
SHM. It then performs an outer join, which combines this information with
data from the dominant customer table. Query 3-24 preserves order numbers
that the previous example eliminated, returning rows for orders that do not
contain items with either manufacturer code. An optional ORDER BY clause
reorganizes the data, as shown in Query Result 3-24:
114 Albertson
118 Baxter
113 Beatty
103 Currie
115 Grant 1010
123 Hanlon 1020 204 KAR 2
123 Hanlon 1020 301 KAR 4
125 Henry
104 Higgins 1011
104 Higgins 1001
104 Higgins 1013
104 Higgins 1003
110 Jaeger 1008
110 Jaeger 1015
120 Jewell 1017 301 SHM 2
120 Jewell 1017 202 KAR 1
111 Keyes 1009
112 Lawson 1006
128 Lessor
109 Miller
126 Neelie 1022
122 O’Brian 1019 111 SHM 3
116 Parmelee 1005
101 Pauli 1002
124 Putnum 1021 202 KAR 3
108 Quinn
107 Ream
102 Sadler
127 Satifer 1023 110 SHM 1
127 Satifer 1023 105 SHM 1
127 Satifer 1023 306 SHM 1
119 Shorter 1016 101 SHM 2
117 Sipes 1012
117 Sipes 1007
105 Vector
121 Wallack 1018 302 KAR 3
106 Watson 1014
106 Watson 1004
You can state the join conditions in two ways when you apply an outer join
to the result of an outer join to a third table. The two subservient tables are
joined, but you can join the dominant table to either subservient table with-
out affecting the results if the dominant table and the subservient table share
a common column.
Query 3-25
Query 3-25 individually joins the subservient tables orders and cust_calls to
the dominant customer table; it does not join the two subservient tables. An
INTO TEMP clause selects the results into a temporary table for further
manipulation or queries, as shown in Query Result 3-25.
114 Albertson
118 Baxter
113 Beatty
103 Currie
115 Grant 1010 06/17/1993
123 Hanlon 1020 07/11/1993
125 Henry
104 Higgins 1003 05/22/1993
104 Higgins 1001 05/20/1993
104 Higgins 1013 06/22/1993
104 Higgins 1011 06/18/1993
110 Jaeger 1015 06/27/1993 1993-07-07 10:24
110 Jaeger 1008 06/07/1993 1993-07-07 10:24
120 Jewell 1017 07/09/1993
111 Keyes 1009 06/14/1993
112 Lawson 1006 05/30/1993
109 Miller
128 Moore
126 Neelie 1022 07/24/1993
122 O’Brian 1019 07/11/1993
116 Parmelee 1005 05/24/1993 1992-12-21 11:24
116 Parmelee 1005 05/24/1993 1992-11-28 13:34
101 Pauli 1002 05/21/1993
124 Putnum 1021 07/23/1993
108 Quinn
107 Ream
102 Sadler
127 Satifer 1023 07/24/1993 1993-07-31 14:30
119 Shorter 1016 06/29/1993 1993-07-01 15:00
117 Sipes 1007 05/31/1993
117 Sipes 1012 06/18/1993
105 Vector
121 Wallack 1018 07/10/1993 1993-07-10 14:05
106 Watson 1004 05/22/1993 1993-06-12 08:20
106 Watson 1014 06/25/1993 1993-06-12 08:20
Note that if Query 3-25 had tried to create a join condition between the two
subservient tables o and x, as shown in Query 3-26, an error message would
have indicated the creation of a two-sided outer join:
Query 3-26
• ALL
• ANY
• IN
• EXISTS
You can use any of the relational operators with ALL and ANY to compare
something to every one of (ALL), or to any one of (ANY), the values that the
subquery produces. You can use the keyword SOME in place of ANY. The
operator IN is equivalent to =ANY. To create the opposite search condition,
use the keyword NOT or a different relational operator.
The EXISTS operator tests a subquery to see if it found any values; that is, it
asks if the result of the subquery is not null.
See Chapter 1 in the Informix Guide to SQL: Syntax for the complete syntax
used in creating a condition with a subquery. See also Chapter 13,
“Optimizing Your Queries,” of this manual for information on performance
implications for correlated and uncorrelated subqueries.
Using ALL
Use the keyword ALL preceding a subquery to determine whether a
comparison is true for every value returned. If the subquery returns no val-
ues, the search condition is true. (If it returns no values, the condition is true
of all of the zero values.)
Query 3-27 lists the following information for all orders that contain an item
for which the total price is less than the total price on every item in order
number 1023:
Query 3-27
Using ANY
Use the keyword ANY (or its synonym SOME) preceding a subquery to
determine whether a comparison is true for at least one of the values
returned. If the subquery returns no values, the search condition is false.
(Because there were no values, the condition cannot be true for one of them.)
Query 3-28 finds the order number of all orders that contain an item for
which the total price is greater than the total price of any one of the items in
order number 1005.
Query 3-28
order_num
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
Single-Valued Subqueries
You do not need to include the keyword ALL or ANY if you know the
subquery can return exactly one value to the outer-level query. A subquery that
returns exactly one value can be treated like a function. This kind of subquery
often uses an aggregate function because aggregate functions always return
single values
Query 3-29 uses the aggregate function MAX in a subquery to find the
order_num for orders that include the maximum number of volleyball nets.
Query 3-29
order_num
1012
Query 3-30 uses the aggregate function MIN in the subquery to select items
for which the total price is higher than 10 times the minimum price:
Query 3-30
Correlated Subqueries
Query 3-31 is an example of a correlated subquery, which returns a list of the
10 earliest shipping dates in the orders table. It includes an ORDER BY clause
after the subquery to order the results because you cannot include ORDER BY
within a subquery.
Query 3-31
Query 3-31 uses the COUNT function to return a value to the main query. The
ORDER BY clause then orders the data. The query locates and returns the 13
rows that have the 10 latest shipping dates, as shown in Query Result 3-31:
po_num ship_date
4745 06/21/1993
278701 06/29/1993
429Q 06/29/1993
8052 07/03/1993
B77897 07/03/1993
LZ230 07/06/1993
B77930 07/10/1993
PC6782 07/12/1993
DM354331 07/13/1993
S22942 07/13/1993
MA003 07/16/1993
W2286 07/16/1993
Z55709 07/16/1993
C3288 07/25/1993
KF2961 07/30/1993
W9925 07/30/1993
If you use a correlated subquery, such as Query 3-31, on a very large table,
you should index the ship_date column to improve performance. Otherwise,
this SELECT statement might be considered somewhat inefficient because it
executes the subquery once for every row of the table. Indexing and
performance issues are discussed in Chapter 10, “Tuning Your Data Model.”
Using EXISTS
The keyword EXISTS is known as an existential qualifier because the subquery
is true only if the outer SELECT, shown in Query 3-32a, finds at least one row:
Query 3-32a
You often can construct a query with EXISTS that is equivalent to one that uses
IN. You also can substitute =ANY for IN, as shown in Query 3-32b:
Query 3-32b
Query 3-32a and Query 3-32b return rows for the manufacturers that produce
a kind of shoe as well as the lead time for ordering the product. These results
are shown in Query Result 3-32:
manu_name lead_time
Anza 5
Hero 4
Karsten 21
Nikolus 8
ProCycle 9
Shimara 30
Note that you cannot use the predicate IN for a subquery that contains a
column with a TEXT or BYTE data type.
Add the keyword NOT to IN or to EXISTS to create a search condition that is
the opposite of the one in the preceding queries. You also can substitute
!=ALL for NOT IN.
Query 3-33 shows two ways to do the same thing. One way might allow the
database server to do less work than the other, depending on the design of
the database and the size of the tables. To find out which query might be
better, you can use the SET EXPLAIN command to get a listing of the query
plan. SET EXPLAIN is discussed in Chapter 13, “Optimizing Your Queries,” of
this manual and in Chapter 1 of the Informix Guide to SQL: Syntax.
Query 3-33
Each statement in Query 3-33 returns the rows shown in Query Result 3-33,
which identify customers who have not placed orders:
customer_num company
Note that the keywords EXISTS and IN are used for the set operation known
as intersection, and the keywords NOT EXISTS and NOT IN are used for the set
operation known as difference. These concepts are discussed in “Set Opera-
tions” on page 3-42.
Query 3-34 identifies all the items in the stock table that have not been
ordered yet by performing a subquery on the items table:
Query 3-34
Query 3-35
Query Result 3-35 returns only those rows for which the total price of an item
on an order is not equal to the stock unit price times the order quantity.
Assuming that no discount has been applied, such rows must have been
entered incorrectly in the database.
Query 3-35 returns rows only when errors occur. If information is correctly
inserted into the database, no rows are returned.
Set Operations
The standard set operations union, intersection, and difference let you
manipulate database information. These three operations enable you to use
SELECT statements to check the integrity of your database after you perform
an update, insert, or delete. They can be useful when you transfer data to a
history table, for example, and want to verify that the correct data is in the
history table before you delete it from the original table.
Union
The union operation uses the UNION keyword, or operator, to combine two
queries into a single compound query. You can use the UNION keyword
between two or more SELECT statements to unite them and produce a tempo-
rary table containing rows that exist in any or all of the original tables. (Note
that you cannot use a UNION operator inside a subquery or in the definition
of a view.) Figure 3-1 illustrates the union set operation.
less than
25.00 qualifies qualifies
unit_price quantity > 3
greater than
or equal to qualifies
25.00
The UNION keyword selects all rows from the two queries, removes
duplicates, and returns what is left. Because the results of the queries are
combined into a single result, the select list in each query must have the same
number of columns. Also, the corresponding columns selected from each
table must be of the same data type (CHARACTER type columns must be the
same length), and these corresponding columns must either all allow or all
disallow nulls.
UNION
Query 3-36
Query 3-36 selects those items that have a unit price of less than $25.00 or that
have been ordered in quantities greater than three and lists their stock_num
and manu_code, as shown in Query Result 3-36:
stock_num manu_code
5 ANZ
5 NRG
5 SMT
9 ANZ
103 PRC
106 PRC
201 NKL
301 KAR
302 HRO
302 KAR
If you include an ORDER BY clause, it must follow Query 3-36 and use an
integer, not an identifier, to refer to the ordering column. Ordering takes place
after the set operation is complete.
UNION
Query 3-37
The compound query in Query 3-37 selects the same rows as Query 3-36 but
displays them in order of manufacturer code, as shown in Query Result 3-37:
stock_num manu_code
5 ANZ
9 ANZ
302 HRO
301 KAR
302 KAR
201 NKL
5 NRG
103 PRC
106 PRC
5 SMT
By default, the UNION keyword excludes duplicate rows. Add the optional
keyword ALL, as shown in Query 3-38, to retain the duplicate values:
UNION ALL
Query 3-38
Query 3-38 uses the UNION ALL keywords to unite two SELECT statements
and puts the results into a temporary table by adding an INTO TEMP clause
after the final SELECT. It returns the same rows as Query 3-37 but also
includes duplicate values.
stock_num manu_code
9 ANZ
5 ANZ
9 ANZ
5 ANZ
9 ANZ
5 ANZ
5 ANZ
5 ANZ
302 HRO
302 KAR
301 KAR
201 NKL
5 NRG
5 NRG
103 PRC
106 PRC
5 SMT
5 SMT
Corresponding columns in the select lists for the combined queries must
have identical data types, but the columns do not need to use the same
identifier.
Query 3-39 selects the state column from the customer table and the
corresponding code column from the state table:
UNION
Query 3-39
Query Result 3-39 returns state code abbreviations for customer numbers 120
through 125, or for states whose sname ends in A or a:
state
AK
AL
AZ
CA
DE
FL
GA
IA
IN
LA
MA
MN
MT
NC
ND
NE
NJ
NV
OK
PA
SC
SD
VA
WV
In compound queries, the column names or display labels in the first SELECT
statement are the ones that appear in the results. Thus, in Query 3-40, the col-
umn name state from the first SELECT statement is used instead of the
column name code from the second.
Query 3-40 performs a union on three tables. The maximum number of
unions depends on the practicality of the application and any memory
limitations.
UNION ALL
UNION ALL
Query 3-40
Query 3-40 selects items where the unit_price in the stock table is greater
than $600, or the catalog_num in the catalog table is 10025, or the quantity
in the items table is 10, and orders it by manu_code. The results are shown
in Query Result 3-40:
stock_num manu_code
5 ANZ
9 ANZ
8 ANZ
4 HSK
1 HSK
203 NKL
5 NRG
106 PRC
113 SHM
See Chapter 1 of the Informix Guide to SQL: Syntax for the complete syntax of
the SELECT statement and the UNION operator. See also Chapter 5, “Pro-
gramming with SQL,”and Chapter 6, “Modifying Data Through SQL
Programs,”as well as the product manuals for information specific to the
INFORMIX-4GL and INFORMIX-ESQL/C products and any limitations
involving the INTO clause and compound queries.
Query 3-41 uses a combined query to select data into a temporary table and
then adds a simple query to order and display it. You must separate the
combined and simple queries with a semicolon.
The combined query uses a literal in the select list to tag the output of part of
a union so it can be distinguished later. The tag is given the label sortkey. The
simple query uses that tag as a sort key for ordering the retrieved rows.
UNION
Query 3-41
Query 3-41 creates a list where the California customers, the ones called most
frequently, appear first, as shown in Query Result 3-41:
sortkey 1
lname Baxter
fname Dick
company Blue Ribbon Sports
city Oakland
state CA
phone 415-655-0011
sortkey 1
lname Beatty
fname Lana
company Sportstown
city Menlo Park
state CA
phone 415-356-9982
sortkey 1
lname Currie
fname Philip
company Phil’s Sports
city Palo Alto
state CA
phone 415-328-4543
sortkey 1
lname Grant
fname Alfred
company Gold Medal Sports
city Menlo Park
state CA
phone 415-356-1123
.
.
.
sortkey 2
lname Satifer
fname Kim
company Big Blue Bike Shop
city Blue Island
state NY
phone 312-944-5691
sortkey 2
lname Shorter
fname Bob
company The Triathletes Club
city Cherry Hill
state NJ
phone 609-663-6079
sortkey 2
lname Wallack
fname Jason
company City Sports
city Wilmington
state DE
phone 302-366-7511
Intersection
The intersection of two sets of rows produces a table containing rows that exist
in both of the original tables. Use the keyword EXISTS or IN to introduce sub-
queries that show the intersection of two sets. Figure 3-2 illustrates the
intersection set operation.
exists in
stock table qualifies
stock_num items table
not in stock
table
Query 3-42
Query Result 3-42 contains all the elements from both sets, returning the
following 57 rows:
1 HRO $250.00
1 HSK $800.00
1 SMT $450.00
2 HRO $126.00
3 HSK $240.00
3 SHM $280.00
4 HRO $480.00
4 HSK $960.00
5 ANZ $19.80
5 NRG $28.00
5 SMT $25.00
6 ANZ $48.00
6 SMT $36.00
7 HRO $600.00
8 ANZ $840.00
9 ANZ $20.00
101 PRC $88.00
101 SHM $68.00
103 PRC $20.00
104 PRC $58.00
105 PRC $53.00
105 SHM $80.00
109 PRC $30.00
109 SHM $200.00
110 ANZ $244.00
110 HRO $260.00
110 HSK $308.00
110 PRC $236.00
110 SHM $228.00
111 SHM $499.99
114 PRC $120.00
201 ANZ $75.00
201 KAR $90.00
201 NKL $37.50
202 KAR $230.00
202 NKL $174.00
204 KAR $45.00
205 ANZ $312.00
205 HRO $312.00
205 NKL $312.00
301 ANZ $95.00
301 HRO $42.50
301 KAR $87.00
301 NKL $97.00
301 PRC $75.00
301 SHM $102.00
302 HRO $4.50
302 KAR $5.00
303 KAR $36.00
303 PRC $48.00
304 ANZ $170.00
304 HRO $280.00
306 PRC $160.00
306 SHM $190.00
307 PRC $250.00
309 HRO $40.00
309 SHM $40.00
Difference
The difference between two sets of rows produces a table containing rows in
the first set that are not also in the second set. Use the keywords NOT EXISTS
or NOT IN to introduce subqueries that show the difference between two sets.
Figure 3-3 illustrates the difference set operation.
exists in
stock table qualifies
stock_num items table
not in stock
table
Query 3-43
Query Result 3-43 contains all the elements from only the first set, returning
the following 17 rows:
Summary
This chapter was built on concepts introduced in Chapter 2, “Composing
Simple SELECT Statements.” It provided sample syntax and results for more
advanced kinds of SELECT statements, which are used to perform a query on
a relational database. This chapter
• Introduced the GROUP BY and HAVING clauses, which can be used with
aggregates to return groups of rows and apply conditions to those
groups.
• Described how to use the rowid to retrieve internal record numbers from
tables and system catalog tables and discussed the serial internal table
identifier or tabid.
• Showed how to join a table to itself with a self-join to compare values in
a column with other values in the same column and to identify
duplicates.
• Introduced the keyword OUTER, explained how an outer join treats two
or more tables asymmetrically, and provided examples of the four kinds
of outer join.
Modifying Data
Chapter Overview 3
Statements That Modify Data 3
Deleting Rows 4
Deleting All Rows of a Table 4
4
Deleting a Known Number of Rows 4
Deleting an Unknown Number of Rows 5
Complicated Delete Conditions 6
Inserting Rows 6
Single Rows 7
Multiple Rows and Expressions 9
Restrictions on the Insert-Selection 10
Updating Rows 11
Selecting Rows to Update 12
Updating with Uniform Values 13
Impossible Updates 13
Updating with Selected Values 14
Database Privileges 15
Displaying Table Privileges 16
Data Integrity 17
Entity Integrity 18
Semantic Integrity 18
Referential Integrity 19
Using the ON DELETE CASCADE Option 21
Interrupted Modifications 22
The Transaction 23
Transaction Logging 24
Logging and Cascading Deletes 24
Specifying Transactions 24
Archives and Logs 25
Archiving with INFORMIX-SE 26
Archiving with INFORMIX-OnLine Dynamic Server 26
Concurrency and Locks 27
Data Replication 28
INFORMIX-OnLine Dynamic Server Data Replication 29
Summary 29
Deleting Rows
The DELETE statement removes any row or combination of rows from a table.
You cannot recover a deleted row after the transaction is committed. (Trans-
actions are discussed under “Interrupted Modifications” on page 4-22. For
now, think of a transaction and a statement as the same thing.)
When deleting a row, you must also be careful to delete any rows of other
tables whose values depend on the deleted row. If, however, your database
enforces referential constraints, you can use the ON DELETE CASCADE option
of the CREATE TABLE or ALTER TABLE statements to allow deletes to cascade
from one table in a relationship to another. For more information on referen-
tial constraints and the ON DELETE CASCADE option, refer to the section
“Referential Integrity” on page 4-19.
Because this DELETE statement does not contain a WHERE clause, all rows
from the customer table are deleted. If you attempt an unconditional delete
using the DB-Access or INFORMIX-SQL menu options, the program warns
you and asks for confirmation. However, an unconditional delete from
within a program can occur without warning.
Because the column tested does not have a unique constraint, this statement
might delete more than one row. (Druid Cyclery may have two stores, both
with the same name but different customer numbers.)
You can find out how many rows might be affected by a DELETE statement
by selecting the count of qualifying rows from the customer table for Druid
Cyclery.
You can also select the rows and display them, to be sure they are the ones
you want to delete.
Using a SELECT statement as a test is only an approximation, however, when
the database is available to multiple users concurrently. Between the time you
execute the SELECT statement and the subsequent DELETE statement, other
users could have modified the table and changed the result. In this example,
another user might perform the following actions:
• Insert a new row for another customer named Druid Cyclery
• Delete one or more of the Druid Cyclery rows before you do so
• Update a Druid Cyclery row to have a new company name, or update
some other customer to have the name Druid Cyclery
Although it is not likely that other users would do these things in that brief
interval, the possibility does exist. This same problem affects the UPDATE
statement. Ways of addressing this problem are discussed under “Concur-
rency and Locks” on page 4-27, and in greater detail in Chapter 7, “Program-
ming for a Multiuser Environment.”
Another problem you may encounter is a hardware or software failure before
the statement finishes. In this case, the database may have deleted no rows,
some rows, or all specified rows. The state of the database is unknown, which
is undesirable. You can prevent this situation by using transaction logging, as
discussed in “Interrupted Modifications” on page 4-22.
Suppose you discover that some rows of the stock table contain incorrect
manufacturer codes. Rather than update them, you want to delete them so
they can be reentered. You know that these rows, unlike the correct ones,
have no matching rows in the manufact table. This allows you to write a
DELETE statement such as the one shown in the following example:
The subquery counts the number of rows of manufact that match; the count
is 1 for a correct row of stock and 0 for an incorrect one. The latter rows are
chosen for deletion.
One way to develop a DELETE statement with a complicated condition is
to first develop a SELECT statement that returns precisely the rows to be
deleted. Write it as SELECT *; when it returns the desired set of rows, change
SELECT * to read DELETE and execute it once more.
The WHERE clause of a DELETE statement cannot use a subquery that tests the
same table. That is, when you delete from stock, you cannot use a subquery
in the WHERE clause that also selects from stock.
The key to this rule is in the FROM clause. If a table is named in the FROM
clause of a DELETE statement, it cannot also appear in the FROM clause of a
subquery of the DELETE statement.
Inserting Rows
The INSERT statement adds a new row, or rows, to a table. The statement has
two basic functions: It can create a single new row using column values you
supply, or it can create a group of new rows using data selected from other
tables.
Single Rows
In its simplest form, the INSERT statement creates one new row from a list of
column values, and puts that row in the table. The following statement is an
example of adding a row to the stock table:
one already in such a column, the statement is rejected. Some columns may
even restrict the possible column values allowed. These restrictions are
placed on columns using data integrity constraints. For more information on
data restrictions, see the section “Database Privileges” on page 4-15.
Only one column in a table can have the SERIAL data type. The database
server generates values for a serial column. To make this happen, when you
insert values, specify the value zero for the serial column. The database
server generates the next actual value in sequence. Serial columns do not
allow null values.
You can specify a nonzero value for a serial column (as long as it does not
duplicate any existing value in that column) and the database server uses the
value. However, that nonzero value may set a new starting point for values
that the database server generates. The next value the database server gener-
ates for you is one greater than the maximum value in the column.
Do not specify the currency symbols for columns that contain money values.
Just specify the numeric value of the amount.
The database server can convert between numeric and character data types.
You can give a string of numeric characters (for example, '-0075.6') as the
value of a numeric column. The database server converts the numeric string
to a number. An error occurs only if the string does not represent a number.
You can specify a number or a date as the value for a character column. The
database server converts that value to a character string. For example, if you
specify TODAY as the value for a character column, a character string repre-
senting today’s date is used. (The format used is specified by the DBDATE
environment variable.)
Notice that only the data for the stock number, description, unit price, and
manufacturer code is provided. The database server supplies the following
values for the remaining columns:
• It generates a serial number for an unlisted serial column.
• It generates a default value for a column with a specific default associated
with it.
• It generates a null value for any column that allows nulls but does not
specify a default value for any column that specifies null as the default
value.
This means that you must list and supply values for all columns that do not
specify a default value or do not permit nulls. However, you can list the col-
umns in any order—as long as the values for those columns are listed in the
same order. For information about setting a default value for a column, see
Chapter 9, “Implementing Your Data Model.”
After the INSERT statement is executed, the following new row is inserted
into the stock table:
Both the unit and unit_descr are blank, indicating that null values are in
those two columns. Because the unit column permits nulls, one can only
guess the number of tire pumps that were purchased for $114. Of course, if a
default value of “box” was specified for this column, then “box” would be the
unit of measure. In any case, when inserting values into specific columns of
a table, pay attention to what data is needed for that row.
For example, suppose a follow-up call is required for every order that has
been paid for but not shipped. The INSERT statement in the following exam-
ple finds those orders and inserts a row in cust_calls for each order:
This SELECT statement returns two columns. The data from these columns (in
each selected row) is inserted into the named columns of the cust_calls table.
Then, an order number (from order_num, a serial column) is inserted into the
call description, which is a character column. Remember that the database
server allows you to insert integer values into a character column. It automat-
ically converts the serial number to a character string of decimal digits.
the Anza company, but at half the price. You want to add rows to the stock
table to reflect this. Optimally, you want to select data from all the Anza stock
rows and reinsert it with the Nikolus manufacturer code. However, you
cannot select from the same table into which you are inserting.
You can get around this restriction by selecting the data you want to insert
into a temporary table. Then, select from that table in the INSERT statement.
The following statements are required to accomplish this:
This SELECT statement takes existing rows from stock and substitutes a literal
value for the manufacturer code and a computed value for the unit price.
These rows are then saved in a temporary table, anzrows, which is immedi-
ately inserted into the stock table.
When you insert multiple rows, a risk exists that one of the rows contains
invalid data that might cause the database server to report an error. When
this happens, the statement terminates early. Even if no error occurs, a very
small risk exists that there might be a hardware or software failure while the
statement is executing (for example, the disk might fill up).
In either event, you cannot easily tell how many new rows were inserted. If
you repeat the statement in its entirety, you might create duplicate rows—or
you might not. Because the database is in an unknown state, you cannot
know what to do. The answer lies in using transactions, as discussed in
“Interrupted Modifications” on page 4-22.
Updating Rows
You use the UPDATE statement to change the contents of one or more
columns in one or more existing rows of a table. This statement takes two
fundamentally different forms. One lets you assign specific values to col-
umns by name; the other lets you assign a list of values (that might be
returned by a SELECT statement) to a list of columns. In either case, if you are
updating rows and some of the columns have data integrity constraints, the
data you change must be within the constraints placed on those columns. For
more information, refer to “Database Privileges” on page 4-15.
UPDATE customer
SET fname = 'Barnaby', lname = 'Dorfler'
WHERE customer_num = 103
The WHERE clause selects the row to be updated. In the stores6 database, the
customer.customer_num column is the primary key for that table, so this
statement can update no more than one row.
You can also use subqueries in the WHERE clause. Suppose that the Anza
Corporation issues a safety recall of their tennis balls. As a result, any
unshipped orders that include stock number 6 from manufacturer ANZ must
be put on back order, as shown in the following example:
UPDATE orders
SET backlog = 'y'
WHERE ship_date IS NULL
AND order_num IN
(SELECT DISTINCT items.order_num FROM items
WHERE items.stock_num = 6
AND items.manu_code = 'ANZ')
UPDATE stock
SET unit_price = unit_price * 1.05
WHERE manu_code = 'HRO'
You can also use a subquery as part of the assigned value. When a subquery
is used as an element of an expression, it must return exactly one value (one
column and one row). Suppose that you decide that for any stock number,
you must charge a higher price than any manufacturer of that product. You
need to update the prices of all unshipped orders. The SELECT statements in
the following example specify the criteria:
UPDATE items
SET total_price = quantity *
(SELECT MAX (unit_price) FROM stock
WHERE stock.stock_num = items.stock_num)
WHERE items.order_num IN
(SELECT order_num FROM orders
WHERE ship_date IS NULL)
The first SELECT statement returns a single value—the highest price in the
stock table for a particular product. This is a correlated subquery; because
when a value from items appears in its WHERE clause, you must execute it
for every row that you update.
The second SELECT statement produces a list of the order numbers of
unshipped orders. It is an uncorrelated subquery that is executed once.
Impossible Updates
Restrictions exist on the use of subqueries when you modify data. In
particular, you cannot query the table that is being modified. You can refer to
the present value of a column in an expression, as in the example in which the
unit_price column was incremented by 5 percent. You can refer to a value of
UPDATE customer
SET (fname, lname) = ('Barnaby', 'Dorfler')
WHERE customer_num = 103
separate table and applying them in a batch, outside of peak hours, is one of
the performance techniques covered in Chapter 10, “Tuning Your Data
Model.”)
UPDATE customer
SET (address1, address2, city, state, zipcode) =
((SELECT address1, address2, city, state, zipcode
FROM newaddr
WHERE newaddr.customer_num=customer.customer_num))
WHERE customer_num IN
(SELECT customer_num FROM newaddr)
Notice that the values for multiple columns are produced by a single SELECT
statement. If you rewrite this example in the other form, with an assignment
for each updated column, you must write five SELECT statements, one for
each column to be updated. Not only is such a statement harder to write, it
also takes much longer to execute.
Note: In INFORMIX-4GL and the SQL API programs, you can use record or host
variables to update values. For more information, refer to Chapter 5, “Programming
with SQL.”
Database Privileges
Two levels of privileges exist in a database: database-level privileges and
table-level privileges. When you create a database, you are the only one who
can access it until you, as the owner (or Database Administrator [DBA]) of the
database, grant database-level privileges to others. When you create a table
in a database that is not ANSI-compliant, all users have access privileges to
the table until you, as the owner of the table, revoke table-level privileges
from specific users.
The following list contains database-level privileges:
Connect privilege allows you to open a database, issue queries, and
create and place indexes on temporary tables.
Resource privilege allows you to create permanent tables.
DBA privilege allows you to perform several additional functions
as the DBA.
Seven table-level privileges exist. However, only the first four are covered
here:
The grantor is the user who grants the privilege. The grantor is usually the
owner of the table but can be another user empowered by the grantor. The
grantee is the user to whom the privilege is granted, and the grantee public
means “any user with Connect privilege.” If your user name does not appear,
you have only those privileges granted to public.
The tabauth column specifies the privileges granted. The letters in each row
of this column are the initial letters of the privilege names except that i
means Insert and x means Index. In this example, public has Select, Insert,
and Index privileges. Only the user mutator has Update privileges, and
only the user procrustes has Delete privileges.
Before the database server performs any action for you (for example, execute
a DELETE statement), it performs a query similar to the preceding one. If you
are not the owner of the table, and if it cannot find the necessary privilege on
the table for your user name or for public, it refuses to perform the operation.
Data Integrity
The INSERT, UPDATE, and DELETE statements modify data in an existing
database. Whenever you modify existing data, the integrity of the data can be
affected. For example, an order for a nonexistent product could be entered
into the orders table. Or a customer with outstanding orders could be deleted
from the customer table. Or the order number could be updated in the orders
table and not in the items table. In each of these cases, the integrity of the
stored data is lost.
Data integrity is actually made up of three parts:
• Entity integrity
Each row of a table has a unique identifier.
• Semantic integrity
The data in the columns properly reflects the types of information the
column was designed to hold.
• Referential integrity
The relationships between tables are enforced.
Well-designed databases incorporate these principles so that when you
modify data, the database itself prevents you from doing anything that might
harm the data integrity.
Entity Integrity
An entity is any person, place, or thing to be recorded in a database. Each
entity represents a table, and each row of a table represents an instance of that
entity. For example, if order is an entity, the orders table represents the idea of
order and each row in the table represents a specific order.
To identify each row in a table, the table must have a primary key. The
primary key is a unique value that identifies each row. This requirement is
called the entity integrity constraint.
For example, the orders table primary key is order_num. The order_num
column holds a unique system-generated order number for each row in the
table. To access a row of data in the orders table you can use the following
SELECT statement:
Using the order number in the WHERE clause of this statement enables you
to access a row easily because the order number uniquely identifies that row.
If the table allowed duplicate order numbers, it would be almost impossible
to access one single row, because all other columns of this table allow
duplicate values.
Refer to Chapter 8, “Building Your Data Model,” for more information on
primary keys and entity integrity.
Semantic Integrity
Semantic integrity ensures that data entered into a row reflects an allowable
value for that row. This means that the value must be within the domain, or
allowable set of values, for that column. For example, the quantity column of
the items table permits only numbers. If a value outside the domain can be
entered into a column, the semantic integrity of the data is violated.
Referential Integrity
Referential integrity refers to the relationship between tables. Because each
table in a database must have a primary key, it is possible that this primary
key appears in other tables because of its relationship to data within those
tables. When a primary key from one table appears in another table, it is
called a foreign key.
Foreign keys join tables and establish dependencies between tables. Tables
can form a hierarchy of dependencies in such a way that if you change or
delete a row in one table, you destroy the meaning of rows in other tables. For
example, in Figure 4-1, the customer_num column of the customer table is a
primary key for that table and a foreign key in the orders and cust_call tables.
Customer number 106, George Watson, is referenced in both the orders and
cust_calls tables. If customer 106 is deleted from the customer table, the link
between the three tables and this particular customer is destroyed.
When you delete a row containing a primary key or update it with a different
primary key, you destroy the meaning of any rows that contain that value as
a foreign key. Referential integrity is the logical dependency of a foreign key
on a primary key. The integrity of a row that contains a foreign key depends
on the integrity of the row that it references—the row that contains the
matching primary key.
customer Table
(detail)
customer_num fname lname
103 Philip Currie
106 George Watson
orders Table
(detail)
order_num order_date customer_num
1002 05/21/1993 101
1003 05/22/1993 104
1004 05/22/1993 106
cust_calls Table
(detail)
customer_num call_dtime user_id
106 1993-06-12 8:20 maryj
110 1993-07-07 10:24 richc
119 1993-07-01 15:00 richc
You can define primary and foreign keys, and the relationship between them,
using the CREATE TABLE and ALTER TABLE statements. For more informa-
tion on these statements, refer to Chapter 1 of the Informix Guide to SQL: Syn-
tax. For information on building data models using primary and foreign
keys, refer to Chapter 8, “Building Your Data Model.”
Example
Say you have two tables with referential integrity rules applied, a parent
table, accounts, and a child table, sub_accounts. The following CREATE
TABLE statements define the referential constraints:
Notice that the primary key of the accounts table, the acc_num column, uses
a SERIAL data type, and the foreign key of the sub_accounts table, the
ref_num column, uses an INTEGER data type. Combining the SERIAL data
type on the primary key and the INTEGER data type on the foreign key is
allowed. This is the only condition where you can mix and match data types.
The SERIAL data type is an INTEGER and the values for the column are auto-
matically generated by the database. All other primary and foreign key com-
binations must match explicitly. For example, a primary key defined as CHAR
must match a foreign key defined as CHAR.
To delete a row from the accounts table that will cascade a delete to the
sub_accounts table, you must turn on logging. After logging is turned on,
you can delete the account number 2 from both tables, as shown in the
following example:
Interrupted Modifications
Even if all the software is error-free and all the hardware is utterly reliable,
the world outside the computer can interfere. It is possible for lightning to
strike the building, interrupting the electrical supply and stopping the com-
puter in the middle of your UPDATE statement. It is more likely, however, that
a disk fills up or a user supplies incorrect data, causing your multirow insert
to stop early with an error. In any case, as you are modifying data, you must
assume that some unforeseen event can interrupt the modification.
When a modification is interrupted by an external cause, you cannot be sure
how much of the operation was completed. Even in a single-row operation,
you cannot know whether the data reached the disk or the indexes were
properly updated.
The Transaction
The solution to all these potential problems is called the transaction. A
transaction is a sequence of modifications that either must be accomplished
completely or not at all. The database server guarantees that operations per-
formed within the bounds of a transaction are either completely and perfectly
committed to disk, or the database is restored to the state it was in before the
transaction started.
The transaction is not merely protection against unforeseen failures; it also
offers a program a way to escape when the program detects a logical error.
(This is discussed further in Chapter 6, “Modifying Data Through SQL
Programs.”)
Transaction Logging
The database server can keep a record of each change that it makes to the
database during a transaction. If something happens to cancel the transac-
tion, the database server automatically uses the records to reverse the
changes. Many things can make a transaction fail. The program that issues
the SQL statements can crash or be terminated, or there might be a hardware
or software failure in any other component of the system. As soon as the data-
base server discovers that the transaction failed, which might be only after
the computer and the database server are restarted, it returns the database to
the state it was in before the transaction began using the records from the
transaction.
The process of keeping records of transactions is called transaction logging, or
simply logging. The records of the transactions, called log records, are stored in
a portion of disk space separate from the database. In INFORMIX-OnLine
Dynamic Server, this space is called the logical log (because the log records
represent logical units of the transactions). In INFORMIX-SE, the space used
to store log records is called the transaction log file.
Databases do not generate transaction records automatically. The database
administrator (or the INFORMIX-OnLine Dynamic Server administrator, for
OnLine databases) decides whether to make a database use transaction
logging. Without transaction logging, you cannot roll back transactions.
Specifying Transactions
The boundaries of transactions are specified with SQL statements. You can do
this in two ways. In the most common style, you specify the start of a multi-
statement transaction by executing the BEGIN WORK statement. In databases
that are created with the MODE ANSI option, no need exists to mark the
beginning of a transaction. One is always in effect; you indicate only the end
of each transaction.
In both styles, you specify the end of a successful transaction by executing the
COMMIT WORK statement. This statement tells the database server that you
reached the end of a series of statements that must succeed together. The
database server does whatever is necessary to make sure that all
modifications are properly completed and committed to disk.
It is also possible for a program to cancel a transaction deliberately. It does so
by executing the ROLLBACK WORK statement. This statement asks the
database server to cancel the current transaction and undo any changes.
For example, an order-entry application can use a transaction when creating
a new order in the following ways:
• Accept all data interactively
• Validate and expand it
• Wait for the operator to make a final commitment
• Execute BEGIN WORK
• Insert rows in the orders and items tables, checking the error code
returned by the database server
• If there were no errors, execute COMMIT WORK, otherwise execute
ROLLBACK WORK
If any external failure prevents the transaction from being completed, the
partial transaction rolls back when the system restarts. In all cases, the data-
base is in a predictable state: Either the new order is completely entered, or it
is not entered at all.
Data Replication
Data replication, in the broadest sense of the term, is when database objects
have more than one representation at more than one distinct site. For exam-
ple, a database that is copied to a database server on a different machine—so
that reports can be run against the data without disturbing client applications
using the original database—is one way data can be replicated.
The following list describes the advantages of data replication:
• Clients accessing replicated data locally—as opposed to remote data that
is not replicated—experience improved performance because they do not
have to use network services.
• Clients at all sites experience improved availability with replicated data,
because if local replicated data is unavailable, a copy of the data is still
available, albeit remotely.
These advantages do not come without a cost. Data replication obviously
requires more storage for replicated data than for unreplicated data, and
updating replicated data can take more processing time than updating a
single object.
Data replication can actually be implemented in the logic of client
applications, by explicitly specifying where data should be found or
updated. However, this way of achieving data replication is costly, error-
prone, and difficult to maintain. Instead, the concept of data replication is
often coupled with replication transparency. Replication transparency is func-
tionality built into a database server (instead of client applications) to
automatically handle the details of locating and maintaining data replicas.
Summary
Database access is regulated by the privileges that the database owner grants
to you. The privileges that let you query data are often granted automatically,
but the ability to modify data is regulated by specific Insert, Delete, and
Update privileges that are granted on a table-by-table basis.
If data integrity constraints are imposed on the database, your ability to
modify data is restricted by those constraints. Your database- and table-level
privileges, along with any data constraints, control how and when you can
modify data.
You can delete one or more rows from a table with the DELETE statement. Its
WHERE clause selects the rows; use a SELECT statement with the same clause
to preview the deletes.
Rows are added to a table with the INSERT statement. You can insert a single
row containing specified column values, or you can insert a block of rows
generated by a SELECT statement.
You use the UPDATE statement to modify the contents of existing rows. You
specify the new contents with expressions that can include subqueries, so
that you can use data based on other tables or the updated table itself. The
statement has two forms: in the first form you specify new values column by
column; you use the other form when the new values are generated as a set
from a SELECT statement or a record variable.
You use the REFERENCES clause of the CREATE TABLE and ALTER TABLE
statements to create relationships between tables. The ON DELETE CASCADE
option of the REFERENCES clause allows you to delete rows from parent and
associated child tables with one DELETE statement.
You use transactions to prevent unforeseen interruptions in a modification
from leaving the database in an indeterminate state. When modifications are
performed within a transaction, they are rolled back following an error. The
transaction log also extends the periodically made archive copy of the data-
base, so that if the database must be restored, it can be brought back to its
most recent state.
Data replication, which is transparent to users, offers another type of
protection from catastrophic failures.
Programming with
SQL
Chapter Overview 3
SQL in Programs 3
Static Embedding 5
Dynamic Statements 5
Program Variables and Host Variables 5
Calling the Database Server 8
The SQL Communications Area 8
The SQLCODE Field 11
End of Data 11
Negative Codes 11
The SQLERRD Array 12
The SQLAWARN Array 12
5
The SQLSTATE Value 12
Retrieving Single Rows 13
Data Type Conversion 14
Dealing with Null Data 15
Dealing with Errors 16
End of Data 17
Serious Errors 17
Using Default Values 17
End of Data with Databases that are not
ANSI-Compliant 18
Interpreting End of Data with Aggregate
Functions 18
Retrieving Multiple Rows 19
Declaring a Cursor 20
Opening a Cursor 20
Fetching Rows 21
Detecting End of Data 21
Locating the INTO Clause 22
Cursor Input Modes 23
The Active Set of a Cursor 24
Creating the Active Set 24
The Active Set for a Sequential Cursor 25
The Active Set for a Scroll Cursor 25
The Active Set and Concurrency 25
Using a Cursor: A Parts Explosion 26
Dynamic SQL 28
Preparing a Statement 29
Executing Prepared SQL 31
Using Prepared SELECT Statements 31
Dynamic Host Variables 32
Freeing Prepared Statements 33
Quick Execution 34
Embedding Data Definition Statements 34
Embedding Grant and Revoke Privileges 34
Summary 37
SQL in Programs
You can write a program in any of several languages and mix SQL statements
in among the other statements of the program, just as if they were ordinary
statements of that programming language. The SQL statements are said to be
embedded in the program, and the program is said to contain embedded SQL,
often abbreviated by Informix as ESQL.
Static Embedding
You can introduce SQL statements into a program in two ways. The simpler
and more common way is by static embedding, which means that the SQL
statements are written as part of the source program text. The statements are
static because they are a fixed part of the source text.
Dynamic Statements
Some applications require the ability to compose SQL statements in response
to user input. For example, a program might have to select different columns
or apply different criteria to rows, depending on what the user wants.
This can be done with dynamic SQL, in which the program composes an SQL
statement as a string of characters in memory and passes it to the database
server to be executed. Dynamic statements are not part of the program source
text; they are constructed in memory during execution.
MAIN
.
.
.
DEFINE drop_number INT
LET drop_number = 108
DELETE FROM items WHERE order_num = drop_number
.
.
.
In applications that use embedded SQL statements, the SQL statements can
refer to the contents of program variables. A program variable that is named
in an embedded SQL statement is called a host variable because the SQL
statement is thought of as being a “guest” in the program.
The following example is a DELETE statement as it might appear when
embedded in a COBOL source program:
EXEC SQL
DELETE FROM items
WHERE order_num = :o-num
END-EXEC.
The first and last lines mark off embedded SQL from the normal COBOL
statements. Between them you see an ordinary DELETE statement, as
described in Chapter 4, “Modifying Data.” When this part of the COBOL
program is executed, a row of the items table is deleted; multiple rows can
also be deleted.
The statement contains one new feature. It compares the order_num column
to an item written as :o-num, which is the name of a host variable.
Each SQL API product provides a means of delimiting the names of host
variables when they appear in the context of an SQL statement. In COBOL,
host variable names are designated with an initial colon. The example state-
ment asks the database server to delete rows in which the order number
equals the current contents of the host variable named :o-num. This is a
numeric variable that has been declared and assigned a value earlier in the
program.
EXEC SQL
DELETE FROM items
WHERE order_num = :onum
The same statement embedded in an Ada program looks like the following
example:
EXEC SQL
DELETE FROM items
WHERE order_num = $onum;
In short, when you embed SQL statements in a program, you can apply all the
power of the host language to them. You can hide the SQL under a multitude
of interfaces, and you can embellish its functions in a multitude of ways.
integer
SQLCODE
0 Success.
100 No more data/not found.
negative Error code.
array of 6
integers
SQLERRD
character SQLERRP
(8)
array of 8
characters SQLAWARN
sixth Set to W following execution of a statement that does not use ANSI-standard SQL syntax
(provided that the DBANSIWARN environment variable is set).
seventh
Not used.
eighth
Not used.
character
(71) SQLERRM
Contains the variable, such as table name, that is placed in the error message. For some
networked applications, contains an error message generated by networking software.
In particular, the subscript by which you name one element of the SQLERRD
and SQLAWARN arrays differs: array elements are numbered starting with
zero in INFORMIX-ESQL/C, but starting with one in the other languages. In
this discussion, the fields are named using specific words such as third, and
you must translate into the syntax of your programming language.
End of Data
The database server sets SQLCODE to 100 when the statement is performed
correctly but no rows are found. Two situations exist where this can occur.
The first situation involves a query that uses a cursor. (Queries using cursors
are described under “Retrieving Multiple Rows” on page 5-19.) In these que-
ries the FETCH statement retrieves each value from the active set into mem-
ory. After the last row is retrieved, a subsequent FETCH statement cannot
return any data. When this occurs the database server sets SQLCODE to 100,
which says end of data-no rows found.
The second situation involves a query that does not use a cursor. In this case
the server sets SQLCODE to 100 when no rows satisfy the query condition. In
ANSI-compliant databases, SELECT, DELETE, UPDATE, and INSERT state-
ments all set SQLCODE to 100 if no rows are returned. In databases that are
not ANSI-compliant, only a SELECT statement that returns no rows causes
SQLCODE to be set to 100.
Negative Codes
When something unexpected goes wrong during a statement, the database
server returns a negative number in SQLCODE to explain the problem. The
meanings of these codes are documented in the Informix Error Messages
manual and in the on-line error message file.
stored in a variable called SQLSTATE. The SQLSTATE error code, or value, tells
you the following information about the most recently executed SQL
statement:
• If the statement was successful
• If the statement was successful but generated warnings
• If the statement was successful but generated no data
• If the statement failed
For more information on GET DIAGNOSTICS, the SQLSTATE variable, and the
meanings of the SQLSTATE return codes, see the section called “GET DIAG-
NOSTICS” in Chapter 1 of the Informix Guide to SQL: Syntax. If your Informix
product supports GET DIAGNOSTICS and SQLSTATE, Informix recommends
that you use them as the primary structure to detect, handle, and diagnose
errors.
The INTO clause is the only detail that distinguishes this statement from any
example in Chapter 2, “Composing Simple SELECT Statements,” or
Chapter 3, “Composing Advanced SELECT Statements.” This clause
specifies the host variables that are to receive the data that is produced.
int avg_price;
double avg_price;
char avg_price[16];
dec_t avg_price; /* typedef of decimal number structure */
The data type of each host variable used in a statement is noted and passed
to the database server along with the statement. The database server does its
best to convert column data into the form used by the receiving variables.
Almost any conversion is allowed, although some conversions cause a loss of
precision. The results of the preceding example differ depending on the data
type of the receiving host variable, as described in the following list:
FLOAT The database server converts the decimal result to FLOAT,
possibly truncating some fractional digits.
If the magnitude of a decimal exceeds the maximum
magnitude of the FLOAT format, an error is returned.
INTEGER The database server converts the result to integer, truncating
fractional digits if necessary.
If the integer part of the converted number does not fit the
receiving variable, an error occurs.
CHARACTER The database server converts the decimal value to a
character string.
If the string is too long for the receiving variable, it is
truncated. The second field of SQLAWARN is set to W and the
value in the SQLSTATE variable is 01000.
puts a special value in the indicator variable to show whether the data is null.
In the following INFORMIX-ESQL/C example, a single row is selected and a
single value is retrieved into the host variable op_date:
SELECT paid_date
INTO op_date
FROM orders
WHERE order_num = the_order
IF op_date IS NULL THEN
LET op_date = date ('01/01/1900')
END IF
End of Data
One common event is that no rows satisfy a query. This is signalled by an
SQLSTATE code of 02000 and by a code of 100 in SQLCODE (sqlca.sqlcode,
as it is known in ESQL/C) following a SELECT statement. This code indicates
an error or a normal event, depending entirely on your application. If you are
sure that there ought to be a row or rows—for example, if you are reading a
row using a key value that you just read from a row of another table—then
the end-of-data code represents a serious failure in the logic of the program.
On the other hand, if you select a row based on a key supplied by a user or
some other source that is less reliable than a program, a lack of data can be a
normal event.
Serious Errors
Errors that set SQLCODE to a negative value are usually serious. Programs
which you have developed and are in production should rarely report these
errors. Nevertheless, it is difficult to anticipate every problematic situation,
so your program must be able to deal with them.
For example, a query can return error -206, which means table name is
not in the database. This happens if someone dropped the table since
the program was written or if, through some error of logic or mistake in
input, the program opened the wrong database.
This query does not use aggregates, so if no row matches the user-specified
customer number, SQLCODE is set to 100 and the host variables remain
unchanged.
Declaring a Cursor
You declare a cursor using the DECLARE statement. This statement gives the
cursor a name, specifies its use, and associates it with a statement. The
following simple example is written in INFORMIX-4GL:
The declaration gives the cursor a name (the_item in this case) and associates
it with a SELECT statement. (Chapter 6, “Modifying Data Through SQL
Programs,” discusses how a cursor also can be associated with an INSERT
statement.)
The SELECT statement in this example contains an INTO clause. That is one of
two ways in which you can specify the variables that receive data. The other
way, using the FETCH statement, is discussed in “Locating the INTO Clause”
on page 5-22.
The DECLARE statement is not an active statement; it merely establishes the
features of the cursor and allocates storage for it. You can use the cursor
declared in the preceding example to read once through the items table. Cur-
sors can be declared to read both backward and forward (see “Cursor Input
Modes” on page 5-23). This cursor, because it lacks a FOR UPDATE clause,
probably is used only to read data, not to modify it. (The use of cursors to
modify data is covered in Chapter 6, “Modifying Data Through SQL
Programs.”)
Opening a Cursor
The program opens the cursor when it is ready to use it. The OPEN statement
activates the cursor. It passes the associated SELECT statement to the database
server, which begins the search for matching rows. The database server pro-
cesses the query to the point of locating or constructing the first row of out-
put. It does not actually return that row of data, but it does set a return code
in SQLSTATE for SQL APIs and SQLCODE for INFORMIX-4GL and SQL APIs.
The following example shows the OPEN statement in INFORMIX-4GL:
OPEN the_item
Because this is the first time that the database server has seen the query, it is
the time when many errors are detected. After opening the cursor, the
program should test SQLSTATE or SQLCODE. If the SQLSTATE value is greater
than 02000 or the SQLCODE contains a negative number, the cursor is not
usable. There may be an error in the SELECT statement, or some other
problem may be preventing the database server from executing the
statement.
If SQLSTATE is equal to 00000 or SQLCODE contains a zero, the SELECT
statement is syntactically valid, and the cursor is ready for use. At this point,
however, the program does not know if the cursor can produce any rows.
Fetching Rows
The program uses the FETCH statement to retrieve each row of output. This
statement names a cursor, and also can name the host variables to receive the
data. Here is the INFORMIX-4GL example completed:
statement is valid yet finds no matching rows, the OPEN statement returns a
zero but the first fetch returns 100, end of data, and no data. The following
example shows another way to write the same loop:
In this version, the case of zero returned rows is handled early, so no second
test of sqlcode exists within the loop. These versions have no measurable dif-
ference in performance because the time cost of a test of sqlcode is a tiny
fraction of the cost of a fetch.
The second form has the advantage that different rows can be fetched into
different variables. For example, you can use this form to fetch successive
rows into successive elements of an array.
After it is opened, the cursor can be used only with a sequential fetch that
retrieves the next row of data, as shown in the following example:
A scroll cursor can be used with a variety of fetch options. The ABSOLUTE
option specifies the rank number of the row to fetch.
This statement fetches the row whose position is given in the host variable
numrow. It is also possible to fetch the current row again or to fetch the first
row and then scan through the entire list again. However, these features are
obtained at a price, as described in the next section.
Because this cursor queries only a single table in a simple way, the database
server can very quickly discover whether any rows satisfy the query and find
the first one. The first row is the only row it finds at this time. The rest of the
rows in the active set remain unknown.
The active set of this cursor is generated by joining three tables and grouping
the output rows. The optimizer might be able to use indexes to produce the
rows in the correct order, but in general the use of ORDER BY or GROUP BY
clauses requires the database server to generate all the rows, copy them to a
temporary table, and sort the table, before it can know which row to present
first. This is discussed in Chapter 13, “Optimizing Your Queries.”
In cases where the active set is entirely generated and saved in a temporary
table, the database server can take quite some time to open the cursor. After-
ward, it can tell the program exactly how many rows the active set contains.
This information is not made available, however. One reason is that you can
never be sure which method the optimizer uses. If it can avoid sorts and
temporary tables, it does; but very small changes in the query, in the sizes of
the tables, or in the available indexes can change its methods.
When the active set, or part of it, is saved in a temporary table, stale data can
present a problem. That is, the rows in the actual tables, from which the
active-set rows are derived, can change. If they do, some of the active-set
rows no longer reflect the current table contents.
These ideas may seem unsettling at first, but as long as your program only
reads the data, there is no such thing as stale data, or rather, all data is equally
stale. No matter when it is taken, the active set is a snapshot of the data as it
is at one moment in time. A row is different the next day; it does not matter
if it is also different in the next millisecond. To put it another way, no practical
difference exists between changes that occur while the program is running
and changes that are saved and applied the instant the program terminates.
The only time that stale data can cause a problem is when the program
intends to use the input data to modify the same database; for example, when
a banking application must read an account balance, change it, and write it
back. Chapter 6, “Modifying Data Through SQL Programs,” discusses
programs that modify data.
CONTAINS
PARENT CHILD
FK NN FK NN
123400 432100
432100 765899
The parts-explosion problem is this: given a part number, produce a list of all
parts that are components of that part. A sketch of one solution, as
implemented in INFORMIX-4GL, is shown in Figure 5-6.
LET next_to_do = 1
LET part_list[next_to_do] = top_part
LET next_free = 2
Technically speaking, each row of the contains table is the head node of a
directed acyclic graph, or tree. The function in Figure 5-6 performs a breadth-
first search of the tree whose root is the part number passed as its parameter.
The function uses a cursor named part_scan to return all the rows with a par-
ticular value in the parent column. This is very easy to implement using the
INFORMIX-4GL statement FOREACH, which opens a cursor, iterates once for
each row in the selection set, and closes the cursor.
This SELECT statement returns one row for each line of descent rooted in the
part given as top_part_number. Null values are returned for levels that do
not exist. (Use indicator variables to detect them.) You can extend this solu-
tion to more levels by selecting additional nested outer joins of the contains
table.You also can revise this solution to return counts of the number of parts
at each level.
Dynamic SQL
Although static SQL is extremely useful, it requires that you know the exact
content of every SQL statement at the time you write the program. For exam-
ple, you must state exactly which columns are tested in any WHERE clause
and exactly which columns are named in any select list.
This is no problem when you write a program to perform a well-defined task.
But the database tasks of some programs cannot be perfectly defined in
advance. In particular, a program that must respond to an interactive user
might need the ability to compose SQL statements in response to what the
user enters.
Preparing a Statement
In form, a dynamic SQL statement is like any other SQL statement that is
written into a program, except that it cannot contain the names of any host
variables.
This leads to two restrictions. First, if it is a SELECT statement, it cannot
include the INTO clause. The INTO clause names host variables into which
column data is placed, and host variables are not allowed in a dynamic state-
ment. Second, wherever the name of a host variable normally appears in an
expression, a question mark is written as a placeholder.
You can prepare a statement in this form for execution with the PREPARE
statement. The following example is in INFORMIX-ESQL/C:
Notice the two question marks in this example; they indicate that when the
statement is executed, the values of host variables are used at those two
points.
You can prepare almost any SQL statement dynamically. The only ones that
cannot be prepared are the ones directly concerned with dynamic SQL and
cursor management, such as the PREPARE and OPEN statements. After you
prepare an UPDATE or DELETE statement, it is a good idea to test the fifth
field of SQLAWARN to see if you used a WHERE clause (see
“The SQLAWARN Array” on page 5-12).
The result of preparing a statement is a data structure that represents the
statement. This data structure is not the same as the string of characters that
produced it. In the PREPARE statement, you give a name to the data structure;
it is query_2 in the preceding example. This name is used to execute the
prepared SQL statement.
The PREPARE statement does not limit the character string to one statement.
It may contain multiple SQL statements, separated by semicolons. Figure 5-7
shows a fairly complex example in INFORMIX-ESQL/COBOL:
TO BIG-QUERY.
EXEC SQL
PREPARE BIG-Q FROM :BIG-QUERY
END-EXEC.
When this list of statements is executed, host variables must provide values
for six place-holding question marks. Although it is more complicated to set
up a multistatement list, the performance is often better because fewer
exchanges take place between the program and the database server.
The USING clause of the EXECUTE statement supplies a list of host variables
whose values are to take the place of the question marks in the prepared
statement.
Quick Execution
For simple statements that do not require a cursor or host variables, you can
combine the actions of the PREPARE, EXECUTE, and FREE statements into a
single operation. The EXECUTE IMMEDIATE statement, shown in the follow-
ing example, takes a character string and in one operation prepares it,
executes it, and frees the storage.
The GRANT and REVOKE statements are especially good candidates for
dynamic SQL. Each statement takes the following parameters:
• A list of one or more privileges
• A table name
• The name of a user
You probably need to supply at least some of these values based on program
input (from the user, command-line parameters, or a file) but none can be
supplied in the form of a host variable. The syntax of these statements does
not allow host variables at any point.
The only alternative is to assemble the parts of a statement into a character
string, and prepare and execute the assembled statement. Program input can
be incorporated into the prepared statement as characters.
Figure 5-9 shows a function in INFORMIX-4GL that assembles a GRANT
statement from the function parameters, and then prepares and executes it.
Figure 5-9 A 4GL function that builds, prepares, and executes a GRANT statement
The opening statement, shown in the following example, defines the name of
the function and the names of its three parameters:
If the database server returns an error code in SQLCODE, the default action of
an INFORMIX-4GL program is to terminate. However, errors are quite likely
when you prepare an SQL statement composed of user-supplied parts, and
program termination is a poor way to diagnose the error. In the preceding
code, the WHENEVER statement prevents termination. Then the PREPARE
statement passes the assembled statement text to the database server for
parsing.
If the database server approves the form of the statement, it sets a zero return
code. This does not guarantee that the statement is executed properly; it
means only that the statement has correct syntax. It might refer to a nonexist-
ent table or contain many other kinds of errors that can only be detected
during execution.
IF status = 0 THEN
EXECUTE the_grant
END IF
Summary
SQL statements can be written into programs as if they were normal
statements of the programming language. Program variables can be used in
WHERE clauses, and data from the database can be fetched into them. A
preprocessor translates the SQL code into procedure calls and data structures.
Statements that do not return data, or queries that return only one row of
data, are written like ordinary imperative statements of the language. Que-
ries that can return more than one row are associated with a cursor that rep-
resents the current row of data. Through the cursor, the program can fetch
each row of data as it is needed.
Static SQL statements are written into the text of the program. However, the
program can form new SQL statements dynamically, as it runs, and execute
them also. In the most advanced cases, the program can obtain information
about the number and types of columns that a query returns and dynamically
allocate the memory space to hold them.
Modifying Data
Through SQL
Programs
Chapter Overview 3
Using DELETE 3
Direct Deletions 4
Errors During Direct Deletions 4
Using Transaction Logging 5
Coordinated Deletions 6
Deleting with a Cursor 7
Using INSERT 8
Using an Insert Cursor 8
Declaring an Insert Cursor 9
Inserting with a Cursor 10
Status Codes After PUT and FLUSH 11
Rows of Constants 11
6
An Insert Example 12
Using UPDATE 14
Using an Update Cursor 15
The Purpose of the Keyword UPDATE 15
Updating Specific Columns 16
UPDATE Keyword Not Always Needed 16
Cleaning up a Table 16
Summary 17
6-2 Modifying Data Through SQL Programs
Chapter Overview
The preceding chapter introduced the idea of putting SQL statements,
especially the SELECT statement, into programs written in other languages.
This enables a program to retrieve rows of data from a database.
This chapter covers the issues that arise when a program needs to modify the
database by deleting, inserting, or updating rows. As in Chapter 5, “Pro-
gramming with SQL,” this chapter aims to prepare you for reading the
manual for the Informix ESQL or 4GL product you are using.
The general use of the INSERT, UPDATE, and DELETE statements is covered in
Chapter 4, “Modifying Data.” This chapter examines their use from within a
program. It is quite easy to put the statements in a program, but it can be
quite difficult to handle errors and to deal with concurrent modifications
from multiple programs.
Using DELETE
A program deletes rows from a table by executing a DELETE statement. The
DELETE statement can specify rows in the usual way with a WHERE clause,
or it can refer to a single row, the last one fetched through a specified cursor.
Whenever you delete rows, you must consider whether rows in other tables
depend on the deleted rows. This problem of coordinated deletions is cov-
ered in Chapter 4, “Modifying Data.” The problem is the same when
deletions are made from within a program.
Direct Deletions
You can embed a DELETE statement in a program. The following example
uses INFORMIX-ESQL/C:
You can also prepare and execute a statement of the same form dynamically.
In either case, the statement works directly on the database to affect one or
more rows.
The WHERE clause in the example uses the value of a host variable named
onum. Following the operation, results are posted in the SQLSTATE and in
SQLCA, as usual. The third element of the SQLERRD array contains the count
of rows deleted even if an error occurs. The value in SQLCODE shows the
overall success of the operation. If it is not negative, no errors occurred and
the third element of SQLERRD is the count of all rows that satisfied the
WHERE clause and were deleted.
An important point in this example is that the program saves the important
return values in the SQLCA before it ends the transaction. The reason is that
both the ROLLBACK WORK and COMMIT WORK statements, as with all SQL
statements, set return codes in the SQLCA. Executing a ROLLBACK WORK
statement after an error wipes out the error code; unless it was saved, it
cannot be reported to the user.
The advantage of using transactions is that no matter what goes wrong, the
database is left in a known, predictable state. No question remains about how
much of the modification is completed; either all of it is or none of it is.
Coordinated Deletions
The usefulness of transaction logging is particularly clear when you must
modify more than one table. For example, consider the problem of deleting
an order from the demonstration database. In the simplest form of the prob-
lem, you must delete rows from two tables, orders and items, as shown in the
INFORMIX-4GL example in Figure 6-1.
The logic of this program is much the same regardless if transactions are
used. If they are not used, the person who sees the error message has a much
more difficult set of decisions to make. Depending on when the error
occurred one of the following situations applies:
• No deletions were performed; all rows with this order number remain in
the database.
• Some, but not all, item rows were deleted; an order record with only some
items remains.
• All item rows were deleted, but the order row remains.
• All rows were deleted.
In the second and third cases, the database is corrupted to some extent; it
contains partial information that can cause some queries to produce wrong
answers. You must take careful action to restore consistency to the
information. When transactions are used, all these uncertainties are
prevented.
int delDupOrder()
{
int ord_num;
int dup_cnt, ret_code;
Figure 6-2 An unsafe ESQL/C function that deletes through a cursor (see Warning)
Warning: The design of the ESQL/C function in Figure 6-2 is unsafe. It depends for
! correct operation on the current “isolation level,” which is discussed later in the
chapter. Even when it works as intended, its effects depend on the physical order of
rows in the table, which is not generally a good idea.
Using INSERT
You can embed the INSERT statement in programs. Its form and use in a
program are the same as described in Chapter 4, “Modifying Data,” with the
additional feature that you can use host variables in expressions, both in the
VALUES and WHERE clauses. Moreover, a program has the additional ability
to insert rows using a cursor.
When you open an insert cursor, a buffer is created in memory to hold a block
of rows. The buffer receives rows of data as the program produces them; then
they are passed to the database server in a block when the buffer is full. This
reduces the amount of communication between the program and the data-
base server, and it lets the database server insert the rows with less difficulty.
As a result, the insertions go faster.
The minimum size of the insert buffer is set for any implementation of
embedded SQL; you have no control over it (it is typically 1 or 2 kilobytes).
The buffer is always made large enough to hold at least two rows of inserted
values. It is large enough to hold more than two rows when the rows are
shorter than the minimum buffer size.
Figure 6-4 Continuing Figure 6-3, the 4GL code that uses the insert cursor
The code in Figure 6-4 calls next_cust repeatedly. When it returns non-null
data, the PUT statement sends the returned data to the row buffer. When the
buffer fills, the rows it contains are automatically sent to the database server.
The loop normally ends when next_cust has no more data to return. Then the
FLUSH statement writes any rows that remain in the buffer, after which the
transaction terminates.
Examine the INSERT statement in Figure 6-3 once more. The statement by
itself, not part of a cursor definition, inserts a single row into the customer
table. In fact, the whole apparatus of the insert cursor can be dropped from
the example code, and the INSERT statement can be written into Figure 6-4
where the PUT statement now stands. The difference is that an insert cursor
causes a program to run somewhat faster.
Rows of Constants
The insert cursor mechanism supports one special case where high
performance is easy to obtain. This is the case in which all of the values listed
in the INSERT statement are constants—no expressions and no host variables,
just literal numbers and strings of characters. No matter how many times
such an INSERT operation occurs, the rows it produces are identical. In that
case, there is no point in copying, buffering, and transmitting each identical
row.
Instead, for this kind of INSERT operation, the PUT statement does nothing
except to increment a counter. When a FLUSH operation is finally performed,
a single copy of the row, and the count of inserts, is passed to the database
server. The database server creates and inserts that many rows in one opera-
tion.
It is not common to insert a quantity of identical rows. You can do it when
you first establish a database, to populate a large table with null data.
An Insert Example
“Deleting with a Cursor” on page 6-7, contains an example of the DELETE
statement whose purpose is to look for and delete duplicate rows of a table.
A better way to do the same thing is to select the desired rows instead of
deleting the undesired ones. The code in Figure 6-5 shows one way to do this.
The example is written in INFORMIX-4GL to take advantage of some features
that make SQL programming easy.
BEGIN WORK
INSERT INTO new_orders
SELECT * FROM ORDERS main
WHERE 1 = (SELECT COUNT(*) FROM ORDERS minor
WHERE main.order_num = minor.order_num)
COMMIT WORK
BEGIN WORK
OPEN ins_row
LET last_ord = -1
FOREACH dup_row
IF ord_row.order_num <> last_ord THEN
PUT ins_row
LET last_ord = ord_row.order_num
END IF
END FOREACH
CLOSE ins_row
COMMIT WORK
This example begins with an ordinary INSERT statement that finds all the
nonduplicated rows of the table and inserts them into another table, presum-
ably created before the program started. That leaves only the duplicate rows.
(Remember, in the demonstration database the orders table has a unique
index and cannot have duplicate rows. This example deals with some other
database.)
In INFORMIX-4GL, you can define a data structure like a table; the structure is
automatically given one element for each column in the table. The ord_row
structure is a buffer to hold one row of the table.
The code in Figure 6-5 then declares two cursors. The first, called dup_row,
returns the duplicate rows in the table. Because it is for input only, it can use
the ORDER BY clause to impose some order on the duplicates other than the
physical record order used in Figure 6-2 on page 6-7. In this example, the
duplicate rows are ordered by their dates (the oldest one remains), but you
can use any other order based on the data.
Using UPDATE
You can embed the UPDATE statement in a program in any of the forms
described in Chapter 4, “Modifying Data,” with the additional feature that
you can name host variables in expressions, both in the SET and WHERE
clauses. Moreover, a program can update the row addressed by a cursor.
EXEC SQL
DECLARE names CURSOR FOR
SELECT fname, lname, company
FROM customer
FOR UPDATE
END-EXEC
The program that uses this cursor can fetch rows in the usual way.
EXEC SQL
FETCH names INTO :FNAME, :LNAME, :COMPANY
END-EXEC.
If the program then decides that the row needs to be changed, it can do so.
The words CURRENT OF names take the place of the usual test expressions
in the WHERE clause. In other respects, the UPDATE statement is the same as
usual—even including the specification of the table name, which is implicit
in the cursor name but still required.
EXEC SQL
DECLARE names CURSOR FOR
SELECT fname, lname, company, phone
INTO :FNAME,:LNAME,:COMPANY,:PHONE FROM customer
FOR UPDATE OF fname, lname
END-EXEC.
Only the fname and lname columns can be updated through this cursor. A
statement such as the following one is rejected as an error:
EXEC SQL
UPDATE customer
SET company = 'Siemens'
WHERE CURRENT OF names
END-EXEC.
Cleaning up a Table
A final, hypothetical example of using an update cursor presents a problem
that should never arise with an established database but could arise in the
initial design phases of an application.
A large table, named target, for example, is created and populated. A
character column, datcol, inadvertently acquires some null values. These
rows should be deleted. Furthermore, a new column, serials, is added to the
table with the ALTER TABLE statement. This column is to have unique integer
values installed. Figure 6-6 shows the INFORMIX-ESQL/C code needed to
accomplish these things.
Summary
A program can execute the INSERT, DELETE, and UPDATE statements as
described in Chapter 4, “Modifying Data.” A program also can scan through
a table with a cursor, updating or deleting selected rows. It also can use a cur-
sor to insert rows, with the benefit that the rows are buffered and sent to the
database server in blocks.
In all these activities, the program must take pains to detect errors and return
the database to a known state when one occurs. The most important tool for
doing this is the transaction. Without transaction logging, the program has a
more difficult time recovering from errors.
Programming for a
Multiuser
Environment
Chapter Overview 3
Concurrency and Performance 3
Locking and Integrity 3
Locking and Performance 3
Concurrency Issues 4
How Locks Work 5
Kinds of Locks 6
Lock Scope 6
Database Locks 6
Table Locks 7
Page, Row, and Key Locks 8
The Duration of a Lock 8
Locks While Modifying 9
Setting the Isolation Level 9
Dirty Read Isolation 10
Committed Read Isolation 10
7
Cursor Stability Isolation 11
Repeatable Read Isolation 12
Setting the Lock Mode 13
Waiting for Locks 13
Not Waiting for Locks 13
Waiting a Limited Time 14
Handling a Deadlock 14
Handling External Deadlock 14
Simple Concurrency 15
Locking with Other Database Servers 15
Isolation While Reading 16
Locking Updated Rows 17
Hold Cursors 17
Summary 19
rows), a whole table, or an entire database. The more locks it places and the
larger the objects it locks, the more concurrency is reduced. The fewer the
locks and the smaller the objects, the greater concurrency and performance
can be.
This section discusses how a program can achieve two goals:
• To place all the locks needed to ensure data integrity
• To lock the fewest, smallest pieces of data possible consistent with the
preceding goal
Concurrency Issues
To understand the hazards of concurrency, you must think in terms of
multiple programs, each executing at its own speed. The following example
suppose that your program is fetching rows through the following cursor:
The transfer of each row from the database server to the program takes time.
During and between transfers, other programs can perform other database
operations. Say that at about the same time your program fetches the rows
produced by that query, another user’s program executes the following
update:
UPDATE stock
SET unit_price = 1.15 * unit_price
WHERE manu_code = 'ANZ'
In other words, both programs are reading through the same table, one
fetching certain rows and the other changing the same rows. The following
possibilities concerning what happens next:
1. The other program finishes its update before your program fetches its first
row.
Your program shows you only updated rows.
2. Your program fetches every row before the other program has a chance to
update it.
Your program shows you only original rows.
3. After your program fetches some original rows, the other program
catches up and goes on to update some rows that your program has yet
to read; then it executes the COMMIT WORK statement.
Your program might return a mixture of original rows and updated rows.
4. Same as number 3, except that after updating the table, the other program
issues a ROLLBACK WORK statement.
Your program can show you a mixture of original rows and updated rows
that no longer exist in the database.
The first two possibilities are harmless. In number 1, the update is complete
before your query begins. It makes no difference whether it finished a
microsecond or a week ago.
In number 2, your query is, in effect, complete before the update begins. The
other program might have been working just one row behind yours, or it
might not start until tomorrow night; it does not matter.
The second pair of chances, however, can be very important to the design of
some applications. In number 3, the query returns a mix of updated and orig-
inal data. That can be a negative thing in some applications. In others, for
instance one that is taking an average of all prices, it might not matter at all.
In number 4, it can be disastrous if a program returns some rows of data that,
because their transaction was cancelled, can no longer be found in the table.
Another concern arises when your program uses a cursor to update or delete
the last-fetched row. Erroneous results occur with the following sequence of
events:
• Your program fetches the row.
• Another program updates or deletes the row.
• Your program updates or deletes WHERE CURRENT OF names.
You control concurrent events such as these using the locking and isolation
level features of the database server.
Kinds of Locks
INFORMIX-OnLine Dynamic Server supports the following three kinds of
locks, which it uses in different situations:
shared A shared lock reserves its object for reading only. It prevents
the object from changing while the lock remains. More than
one program can place a shared lock on the same object.
exclusive An exclusive lock reserves its object for the use of a single
program. It is used when the program intends to change the
object.
An exclusive lock cannot be placed where any other kind of
lock exists. Once one has been placed, no other lock can be
placed on the same object.
promotable A promotable lock establishes the intent to update. It can
only be placed where no other promotable or exclusive lock
exists. Promotable locks can exist with shared locks. They
are “promoted” to an exclusive lock.
Lock Scope
You can apply locks to entire databases, entire tables, disk pages, single rows,
or index-key values. The size of the object being locked is referred to as the
scope of the lock (also called the lock granularity). In general, the larger the
scope of a lock, the more concurrency is reduced but the simpler
programming becomes.
Database Locks
You can lock an entire database. The act of opening a database places a shared
lock on the name of the database. A database is opened with the CONNECT,
DATABASE, or CREATE DATABASE statements. As long as a program has a
database open, the shared lock on the name prevents any other program from
dropping the database or putting an exclusive lock on it.
You can lock an entire database exclusively with the following statement:
This statement succeeds if no other program has opened that database. Once
the lock is placed, no other program can open the database, even for reading
because its attempt to place a shared lock on the database name fails.
A database lock is released only when the database closes. That can be done
explicitly with the DISCONNECT or CLOSE DATABASE statements or
implicitly by executing another DATABASE statement.
Because locking a database reduces concurrency in that database to zero, it
makes programming very simple—concurrent effects cannot happen. How-
ever, you should lock a database only when no other programs need access.
Database locking is often used before applying massive changes to data
during off-peak hours.
Table Locks
You can lock entire tables. In some cases, this is done automatically.
INFORMIX-OnLine Dynamic Server always locks an entire table while it
performs any of the following statements:
• ALTER INDEX
• ALTER TABLE
• CREATE INDEX
• DROP INDEX
• RENAME COLUMN
• RENAME TABLE
The completion of the statement (or end of the transaction) releases the lock.
An entire table also can be locked automatically during certain queries.
You can use the LOCK TABLE statement to lock an entire table explicitly. This
statement allows you to place either a shared lock or an exclusive lock on an
entire table.
A shared table lock prevents any concurrent updating of that table while
your program is reading from it. INFORMIX-OnLine Dynamic Server
achieves the same degree of protection by setting the isolation level, as
described in the next section; this allows greater concurrency. However, all
Informix database servers support the LOCK TABLE statement.
An exclusive table lock prevents any concurrent use of the table. This has a
serious effect on performance if many other programs are contending for the
use of the table. As with an exclusive database lock, an exclusive table lock is
often used when massive updates are applied during off-peak hours. For
example, some applications do not update tables during the hours of peak
use. Instead, they write updates to an update journal. During off-peak hours,
that journal is read and all updates are applied in a batch.
4. Program B ends.
5. Program A, not aware that its copy of the Hero row is now invalid, inserts
a new row of stock using the manufacturer code HRO.
6. Program A ends.
At the end, a row occurs in stock that has no matching manufacturer code in
manufact. Furthermore, Program B apparently has a bug; it did not delete the
rows it was supposed to delete. The use of the Cursor Stability isolation level
prevents these effects.
(It is possible to rearrange the preceding scenario so that it fails even with
Cursor Stability. All that is required is for Program B to operate on tables in
the reverse sequence to Program A. If Program B deletes from stock before it
removes the row of manufact, no degree of isolation can prevent an error.
Whenever this kind of error is possible, it is essential that all programs
involved use the same sequence of access.)
Because Cursor Stability locks only one row at a time, it restricts concurrency
less than does a table lock or database lock.
database server cannot place a lock and returns an error code. The person
who administers an INFORMIX-OnLine Dynamic Server system can monitor
the lock table and tell you when it is heavily used.
Repeatable Read is automatically the isolation level in an ANSI-compliant
database. Repeatable Read is required to ensure operations behave in
accordance with the ANSI standard for SQL.
When this lock mode is set, your program usually ignores the existence of
other concurrent programs. When it needs to access a row that another pro-
gram has locked, your program waits until the lock is removed, then
proceeds. The delays are usually imperceptible.
This places an upper limit of 17 seconds on the length of any wait. If a lock is
not removed in that time, the error code is returned.
Handling a Deadlock
A deadlock is a situation in which a pair of programs block the progress of each
other. Each program has a lock on some object that the other program wants
to access. A deadlock arises only when all programs concerned set their lock
modes to wait for locks.
INFORMIX-OnLine Dynamic Server detects deadlocks immediately when
they involve only data at a single network server. It prevents the deadlock
from occurring by returning an error code (error -143 ISAM error: dead-
lock detected) to the second program to request a lock. The error code is
the one the program receives if it sets its lock mode to not wait for locks. Thus,
if your program receives an error code related to locks even after it sets lock
mode to wait, you know the cause is an impending deadlock.
Simple Concurrency
If you are not sure which choice to make concerning locking and concurrency,
and if your application is straightforward, have your program execute the
following commands when it starts up (immediately after the first
DATABASE statement):
#define LOCK_ONLINE 1
#define LOCK_KERNEL 2
#define LOCK_FILES 3
int which_locks()
{
int locktype;
locktype = LOCK_FILES;
exec sql set lock mode to wait 30;
if (sqlca.sqlcode == 0)
locktype = LOCK_ONLINE;
else
{
exec sql set lock mode to wait;
if (sqlca.sqlcode == 0)
locktype = LOCK_KERNEL;
}
/* restore default condition */
exec sql set lock mode to not wait;
return(locktype);
}
If the database server does not support the SET LOCK MODE statement, your
program is effectively always in NOT WAIT mode; that is, whenever it tries to
lock a row that is locked by another program, it receives an error code
immediately.
Hold Cursors
When transaction logging is used, the database server guarantees that
anything done within a transaction can be rolled back at the end of it. To do
this reliably, the database server normally applies the following rules:
• All cursors are closed by ending a transaction.
• All locks are released by ending a transaction.
These rules are normal with all database systems that support transactions,
and for most applications they do not cause any trouble. However, circum-
stances exist where using standard transactions with cursors are not possible.
For example, a situation is sketched in Figure 7-1 which works fine without
transactions. However, when transactions are added, closing the cursor
conflicts with using two cursors simultaneously.
In this design, one cursor is used to scan a table. Selected records are used as
the basis for updating a different table. The problem is that when each update
is treated as a separate transaction (as shown in the pseudocode in Figure
7-1), the COMMIT WORK statement following the UPDATE closes all cursors—
including the master cursor.
The simplest alternative is to move the COMMIT WORK and BEGIN WORK
statements to be the last and first ones, respectively, so that the entire scan
over the master table is one large transaction. This is sometimes possible, but
it may become impractical if many rows need to be updated. The number of
locks can be too large, and they are held for the duration of the program.
Summary
Whenever multiple programs have access to a database concurrently (and
when at least one of them can modify data), all programs must allow for the
possibility that another program can change the data even as they read it. The
database server provides a mechanism of locks and isolation levels that
usually allow programs to run as if they were alone with the data.
8
About Entity Occurrences 16
Diagramming Your Data Objects 16
How You Read Entity-Relationship Diagrams 18
The Telephone-Directory Example 18
What’s Next 19
Translating E-R Data Objects Into Relational Constructs 20
Rules for Defining Tables, Rows, and Columns 20
Placing Constraints on Columns 21
Determining Keys for Tables 22
Primary Keys 22
Foreign Keys (Join Columns) 24
Adding Keys to the Telephone-Directory Diagram 25
Resolving Your Relationships 26
Resolving m:n Relationships 26
Resolving Other Special Relationships 28
Normalizing Your Data Model 29
First Normal Form 29
Second Normal Form 31
Third Normal Form 32
Summary of Normalization Rules 32
Summary 33
Discovering Entities
An entity is a principal data object that is of significant interest to the user. It
is usually a person, place, thing, or event to be recorded in the database. If the
data model were a language, entities would be its nouns. The stores6
database contains the following entities: customer, orders, items, stock, catalog,
cust_calls, call_type, manufact, and state.
The first step in modeling is to choose the entities to record. Most of the
entities that you choose will become tables in the model.
These choices are neither simple nor automatic. To discover the best choice of
entities, you must think deeply about the nature of the data you want to store.
Of course, that is exactly the point of making a formal data model. The
following section describes the example shown in this chapter in further
detail.
ADDRESS ADDRESS W
866 Gage Rd. 866 Gage Rd. X
Klamath Falls Klamath Falls, OR 97601 Y
OR 97601 Z
The physical form of the existing data can be misleading. Do not let the layout
of pages and entries in the telephone directory mislead you into trying to
specify an entity that represents one entry in the book—some kind of alpha-
betized record with fields for name, number, and address. Remember it is not
the medium you want to model, it is the data.
At first glance, the entities recorded in a telephone directory include the
following items:
• Names (of persons and organizations)
• Addresses
• Telephone numbers
Do these entities meet the earlier criteria? They are clearly significant to the
model and are generic.
Are they fundamental? A good test is to ask if an entity can vary in number
independently of any other entity. After thinking about it, you realize that a
telephone directory sometimes lists people who have no number or current
address (people who move or change jobs). A telephone directory also can
list both addresses and numbers that are used by more than one person. All
three of these entities can vary in number independently; that strongly
suggests they are fundamental, not dependent.
Are they unitary? Names can be split into personal names and corporate
names. After thinking about it, you decide that all names should have the
same features in this model; that is, you do not plan to record different infor-
mation about a company than you would about a person. Likewise, you
decide only one kind of address exists; no need exists to treat home addresses
differently from business ones.
However, you also realize that more than one kind of telephone number
exists, three. Voice numbers are answered by a person, fax numbers connect
to a fax machine, and modem numbers connect to a computer. You decide that
you want to record different information about each kind of number, so these
three are different entities.
For the personal telephone-directory example, you decide that you want to
keep track of the following entities:
• Name
• Address (mailing)
• Telephone number (voice)
• Telephone number (fax)
• Telephone number (modem)
Connectivity
Connectivity refers to the number of entity instances. An entity instance is a
particular occurrence of an entity. The three types of connectivity are one-to-
one (written 1:1), one-to-many (written 1:n), and many-to-many (written
m:n) shown graphically in Figure 8-2.
Existence Dependency
Existence dependency describes whether an entity in a relationship is
optional or mandatory. Analyze your business rules to identify whether an
entity must exist in a relationship. For example, your business rules may dic-
tate that an address must be associated with a name. This would make the
existence dependency for the relationship between the name and address
entities mandatory. An optional existence dependency could be indicated by
a business rule that said a person may or may not have children.
Cardinality
Cardinality places a constraint on the number of times an entity can appear
in a relationship. The cardinality of a 1:1 relationship is always one. But the
cardinality of a 1:n relationship is open; n could be any number. If you need
to place an upper limit on n, you do it by specifying a cardinality for the rela-
tionship. For example, in a store sale example, you could limit the number of
sale items that a customer can purchase at one time. You usually place cardi-
nality constraints through your application program or through stored
procedures.
For additional information about cardinality, see any entity-relationship data
modeling text. References to two data modeling books are included in the
Summary of this chapter.
name
address
number
(voice)
number
(fax)
number
(modem)
Figure 8-3 A matrix that reflects the entities for a personal telephone directory
You can ignore the lower triangle of the matrix, as indicated by the shaded
area. You must consider the diagonal cells; that is, you must ask the question
“What is the relationship between an A and another A?” In this model, the
answer is always none. No relationship exists between a name and a name,
or an address and another address, at least none worth recording in this
model. When a relationship exists between an A and another A, you have
found a recursive relationship. (See “Resolving Other Special Relationships”
on page 8-28.)
For all cells for which the answer is clearly none, write none in the matrix.
Now the matrix looks like Figure 8-4.
name none
address none
number none
(voice)
number none
(fax)
number none
(modem)
Figure 8-4 A matrix with initial relationships included: No entities relate to themselves
A name (you decide) can have zero or one address but no more than one. You
write 0-1 opposite name and below address, as shown in the following
figure:
name address
name none
0-1
Ask yourself how many addresses can be associated with a name. You decide
that an address can be associated with more than one name. For example, you
can know several people at one company or more than two people who live
at the same address.
Can an address be associated with zero names? That is, should it be possible
for an address to exist when no names use it? You decide that yes, it can.
Below address and opposite name, you write 0-n, as shown in the following
figure:
name address
If you decide that an address could not exist without being associated with at
least one name, you write 1-n instead of 0-n.
When the cardinality of a relationship is limited on either side to 1, it is a 1:n
relationship. In this case, the relationship between names and addresses is a
1:n relationship.
Now consider the next cell, the relationship between a name and a voice
number. How many voice numbers can a name be associated with, one or
more than one? Glancing at your telephone directory, you see that you may
often have noted more than one telephone number for a person—for some
busy salesman you have a home number, an office number, a paging number,
and a car phone number. But there also can be names without associated
numbers. You write 0-n opposite name and below number (voice), as
shown in the following figure:
What is the other side of this relationship? How many names can be
associated with a voice number? You decide that only one name can be asso-
ciated with a voice number. Can a number be associated with zero names?
No, you decide; no point exists for recording a number unless it is used by
someone. You write 1 under number (voice) and opposite name.
Fill out the rest of the matrix in the same fashion, using the following
decisions:
• A name can be associated with more than one fax number; for example, a
company can have several fax machines. Going the other way, a fax num-
ber can be associated with more than one name; for example, several
people can use the same fax number.
• A modem number must be associated with exactly one name. (This is an
arbitrary decree to complicate the example; pretend it is a requirement of
the design.) However, a name can have more than one associated modem
number; for example, a company computer can have several dial-up
lines.
• Although some relationship exists between a voice number and an
address, a modem number and an address, and a fax number and an
address in the real world, none needs to be recorded in this model. There
already is an indirect relationship through name.
number none
(modem)
Identifying Attributes
Entities contain attributes, which are characteristics or modifiers, qualities,
amounts, or features. An attribute is a fact or nondecomposable piece of
information about an entity. Later, when you represent an entity as a table, its
attributes are added to the model as new columns.
name address
entity entity
relationship
optionality optionality
ames Addres
many exactly
one
A matrix such as Figure 8-5 is a useful tool when you are first designing your
model because, in filling it out, you are forced to think of every possible rela-
tionship. However, the same relationships appear in a diagram such as
Figure 8-10, and this type of diagram may be easier to read when you are
reviewing an existing model.
name
lname
fname
bdate address
anniv street
email city
child1 state
child2 zipcode
child3
What’s Next
Subsequent sections describe the following tasks:
• How to translate the entities, relationships, and attributes into relational
constructs
• How to resolve the entity-relationship data model
• How to normalize the entity-relationship data model
Chapter 9, “Implementing Your Data Model,” shows you how to create a
database from the entity-relationship data model.
Primary Keys
The primary key of a table is the column whose values are different in every
row. Because they are different, they make each row unique. If no one such
column exists, the primary key is a composite of two or more columns whose
values, taken together, are different in every row.
Every table in the model must have a primary key. This follows automatically
from the rule that all rows must be unique. If necessary, the primary key is
composed of all the columns taken together.
The primary key should be a numeric data type (INT or SMALLINT), SERIAL
data type, or a short character string (as used for codes). It is recommended
that you avoid using long character strings as primary keys.
Null values are never allowed in a primary-key column. Null values are not
comparable; that is, they cannot be said to be alike or different. Hence, they
cannot make a row unique from other rows. If a column permits null values,
it cannot be part of a primary key.
Composite Keys
Some entities lack features that are reliably unique. Different people can have
identical names; different books can have identical titles. You can usually find
a composite of attributes that work as a primary key. For example, it is rare
for people to have identical names and identical addresses or for different
books to have identical titles, authors, and publication dates.
System-Assigned Keys
A system-assigned primary key is usually preferable to a composite key. A
system-assigned key is a number or code that is attached to each instance of
an entity when it is first entered into the database. The easiest system-
assigned keys to implement are serial numbers because the database server
can generate them automatically. Informix offers the SERIAL data type for
serial numbers. However, the people who use the database might not like a
plain numeric code. Other codes can be based on actual data; for example, an
employee identification code could be based on the person’s initials com-
bined with the digits of the date they were hired. In the telephone-directory
example, a system-assigned primary key is used for the name table.
customer orders
customer_num order_num customer_num
Foreign keys are noted wherever they appear in the model because their
presence can restrict your ability to delete rows from tables. Before you can
delete a row safely, either you must delete all rows that refer to it through
foreign keys or you must define the relationship using special syntax that
allows you to delete rows from primary-key and foreign-key columns with a
single delete command. The database server disallows deletes that violate
referential integrity.
You can always preserve referential integrity by deleting all foreign-key rows
before you delete the primary key to which they refer. If you are imposing ref-
erential constraints on your database, the database server does not permit
you to delete primary keys with matching foreign keys. It also does not
permit you to add a foreign-key value that does not reference an existing
primary-key value. Referential integrity is discussed in Chapter 4,
“Modifying Data.”
name
rec_num PK
lname
fname address
bdate id_num PK
anniv rec_num FK
email street
child1 city
child2 state
child3 zipcode
Figure 8-12 Telephone-directory diagram with primary and foreign keys added
name
rec_num PK rec_num PK
lname lname
Intersect
fname fname
Entity
bdate bdate
anniv anniv
email faxname email
child1 fax_num PK FK child1
child2 rec_num PK FK child2
child3 child3
fax
fax_num PK fax
rec_num FK
oper_from fax_num PK
oper_till oper_from
oper_till
BEFORE AFTER
disk space, and make it more difficult to search for data. In the telephone-
directory example, it appears that the name table contains repeating columns,
child1, child2, and child3, as shown in Figure 8-14:
name
rec_num lname fname bdate anniv email child1 child2 child3
repeating columns
Some problems can be noted in the current table. Space is always reserved on
the disk for three child records, whether the person has children or not. The
maximum number of children that you could record is three; but some of
your acquaintances might have four or more children. If you look for a
particular child, you would have to search all three columns in every row.
You can eliminate the repeating columns and bring the table to first normal
form by separating the table into two tables as shown in Figure 8-15. Put the
repeating columns into one of the tables. The association between the two
tables is established with a primary and foreign key combination. Because a
child cannot exist without an association in the name table, we can reference
the name table with a foreign key, rec_num.
name
rec_num lname fname bdate anniv email
Primary Key
child
rec_num child_name
Foreign Key
as shown in Figure 8-16. A b_type attribute is added to the entity which can
contain occurrences of b300, b1200, and b2400. Figure 8-16 shows the data
model normalized through first normal form.
name child
rec_num PK rec_num FK
address
lname child_name
fname id_num PK
bdate rec_num FK
anniv street
email city
state
zipcode
voice faxname
vce_num PK fax_num PK FK
rec_num rec_num PK FK
vce_type modem
mdm_num PK
fax rec_num FK
fax_num PK b_type
operfrom
opertill
Summary
This chapter summarized and illustrated the following steps of entity-
relationship data modeling:
1. Identify and define your principal data objects, including the following
options:
• Entities
• Relationships
• Attributes
2. Diagram your data objects using the entity-relationship diagram
approach.
3. Translate your entity-relationship data objects into relational constructs.
• Determine the primary and foreign keys for each entity.
4. Resolve your relationships, particularly the following relationships:
• 1:1 relationships
• m:n relationships
• Other special relationships
5. Normalize your data model in one of the following forms:
• First normal form
• Second normal form
• Third normal form
When the process is done right, you must examine every aspect of the data
not once, but several times.
If you are interested in learning more about database design, you can attend
the Informix course, Relational Database Design. This thorough course
presents how to create an entity-relationship data model.
If you are interested in pursuing more about database design on your own,
the following excellent books are recommended:
• Database Modeling and Design, The Entity-Relationship Approach, by Toby J.
Teorey, Morgan Kauffman Publishers, Inc., 1990
• Handbook of Relational Database Design, by Candace C. Fleming and
Barbara von Halle, Addison-Wesley Publishing Company, 1989
Implementing Your
Data Model
Chapter Overview 3
Defining the Domains 3
Data Types 4
Choosing a Data Type 4
Numeric Types 7
Chronological Types 12
Character Types 15
Changing the Data Type 19
Default Values 19
Check Constraints 20
Creating the Database 20
Using CREATE DATABASE 21
Using CREATE DATABASE with INFORMIX-
OnLine Dynamic Server 21
Using CREATE DATABASE with Other Informix
Database Servers 23
Using CREATE TABLE 24
Using Command Scripts 26
Capturing the Schema 26
Executing the File 26
An Example 26
Populating the Tables 27
Summary 29
9
9-2 Implementing Your Data Model
Chapter Overview
Once a data model is prepared, it must be implemented as a database and
tables. This chapter covers the decisions that you must make to implement
the model.
The first step in implementation is to complete the data model by defining a
domain, or set of data values, for every column. The second step is to
implement the model using SQL statements.
The first section of this chapter covers defining domains in detail. The second
section shows how you create the database (using the CREATE DATABASE
and CREATE TABLE statements) and populate it with data.
Data Types
The first constraint on any column is the one that is implicit in the data type
for the column. When you choose a data type, you constrain the column so
that it contains only values that can be represented by that type.
Each data type represents certain kinds of information and not others. The
correct data type for a column is the one that represents all the data values
that are proper for that column but as few as possible of the values that are
not proper for it.
no
DECIMAL(p,0)
DECIMAL(p)
Numeric Types
Informix database servers support eight numeric data types. Some are best
suited for counters and codes, some for engineering quantities, and some for
money.
The sequence of generated numbers always increases. When rows are deleted
from the table their serial numbers are not reused. This means that rows
sorted on a SERIAL column are returned in the order in which they were
created. That cannot be said of any other data type.
You can specify the initial value in a SERIAL column in the CREATE TABLE
statement. This makes it possible to generate different subsequences of
system-assigned keys in different tables. The stores6 database uses this tech-
nique. In stores6, the customer numbers begin at 101, and the order numbers
start at 1001. As long as this small business does not register more than 899
customers, all customer numbers have three digits and order numbers have
four.
A SERIAL column is not automatically a unique column. If you want to be
perfectly sure no duplicate serial numbers occur, you must apply a unique
constraint (see “Using CREATE TABLE” on page 9-24). However, if you
define the table using the interactive schema editor in DB-Access or
INFORMIX-SQL, it automatically applies a unique constraint to any SERIAL
column.
The SERIAL data type has the following advantages:
• It provides a convenient way to generate system-assigned keys.
• It produces unique numeric codes even when multiple users are updating
the table.
• Different tables can use different ranges of numbers.
It has the following disadvantages:
• Only one SERIAL column is permitted in a table.
• It can produce only arbitrary numbers (then again, arbitrary numeric
codes might not be acceptable to the database users).
you also know the number of digits needed on the left, depending on whose
transactions are recorded—perhaps 5 digits for a personal budget, 7 for a
small business, and 12 or 13 for a national budget.
These numbers are fixed-point numbers because the decimal point is fixed at
a specific place, regardless of the value of the number. The DECIMAL(p,s) data
type is designed to hold them. When you specify a column of this type, you
write its precision (p) as the total number of digits it can store, from 1 to 32. You
write its scale (s) as the number of those digits that fall to the right of the dec-
imal point. (The relation between precision and scale is diagrammed in Fig-
ure 9-2.) Scale can be zero, meaning it stores only whole numbers. When this
is done, DECIMAL(p,s) provides a way of storing integers of up to 32 digits.
precision: 8 digits
DECIMAL(8,3) 31964.535
scale: 3 digits
Figure 9-2 The relation between precision and scale in a fixed-point number
Chronological Types
Informix database servers support three data types for recording time. The
DATE data type stores a calendar date. DATETIME records a point in time to
any degree of precision from a year to a fraction of a second. The INTERVAL
data type stores a span of time; that is, a duration.
a year, only a month and day, a date and time that is exact to the hour, or even
to the millisecond. The size of a DATETIME value ranges from 2 to 11 bytes
depending on its precision, as shown in Figure 9-3.
The advantage of DATETIME is that it can store dates more precisely than to
the nearest day, and it can store time values. Its sole disadvantage is an inflex-
ible display format, but this can be circumvented (see “Forcing the Format of
a DATETIME or INTERVAL Value” on page 9-16).
Figure 9-3 All possible precisions of the DATETIME data type, with their sizes in bytes
Durations: INTERVAL
The INTERVAL data type stores a duration, that is, a length of time. The
difference between two DATETIME values is an INTERVAL, which represents
the span of time that separates them. The following examples might help to
clarify the differences:
• An employee began working on January 21, 1993 (either a DATE or a
DATETIME).
• She has worked for 254 days (an INTERVAL, the difference between the
TODAY function and the starting DATE or DATETIME).
• She begins work each day at 0900 hours (a DATETIME).
• She works 8 hours (an INTERVAL) with 45 minutes for lunch (another
INTERVAL).
• Her quitting time is 1745 hours (the sum of the DATETIME when she
begins work and the two INTERVALs).
Like DATETIME, INTERVAL is a family of types with different precisions. An
INTERVAL can represent a count of years and months; or it can represent a
count of days, hours, minutes, seconds, or fractions of seconds; 18 possible
precisions in all. The size of an INTERVAL value ranges from 2 to 12 bytes,
depending on the formulas shown in Figure 9-4.
Figure 9-4 All possible precisions of the INTERVAL data type, with their sizes in bytes
INTERVAL values can be negative as well as positive. You can add or subtract
them, and you can scale them by multiplying or dividing by a number. This
is not true of either DATE or DATETIME. It is reasonable to ask, “What is one-
half the number of days until April 23?” but it is not reasonable to ask, “What
is one-half of April 23?”
Character Types
All Informix database servers support the CHAR(n) data type. When NLS has
been enabled, the Informix database servers support the NCHAR(n) data
type. INFORMIX-OnLine Dynamic Server also supports other special use
character data types.
SELECT ...
EXTEND (START_TIME, HOUR TO HOUR) H,
EXTEND (START_TIME, MINUTE TO MINUTE) M, ...
Then, in the report, combine the components in a PRINT expression with the
desired punctuation.:
The second parameter, r, is an optional reserve length that sets a lower limit
on the length of an item as stored on disk. When an item is shorter than r,
r bytes are nevertheless allocated to hold it. The purpose is to save time when
rows are updated. (See “Variable-Length Execution Time” on page 9-17.)
• It conserves disk space when the lengths of data items vary widely or
when only a few items are longer than average.
• Queries on the more compact tables can be faster.
The following list describes its disadvantages:
• It does not allow lengths that exceed 255 characters.
• Updates of a table can be slower in some circumstances.
• It is not available with all Informix database servers.
TEXT values are not stored with the rows of which they are a part. They are
allocated in whole disk pages, usually areas away from rows. (See “Locating
Blob Data” on page 10-18.)
The advantage of the TEXT data type over CHAR(n) and VARCHAR(m,r) is that
the size of a TEXT data item has no limit except the capacity of disk storage to
hold it. The disadvantages of the TEXT data type are found in the following
list:
• It is allocated in whole disk pages; a short item wastes space.
• Restrictions apply on how you can use a TEXT column in an SQL
statement. (See “How Blobs Are Used” on page 9-18.)
Default Values
A default value is the value inserted into a column when an explicit value is
not specified in an INSERT statement. A default value can be a literal charac-
ter string defined by you or one of the following SQL null, constant
expressions:
• USER
• CURRENT
• TODAY
• DBSERVERNAME
Not all columns need default values, but as you work with your data model
you may discover instances where the use of a default value saves data-entry
time or prevents data-entry error. For example, the telephone-directory
model has a State column. While looking at the data for this column, you dis-
cover that more than 50 percent of the addresses list California as the state. To
save time, you specify the string “CA” as the default value for the State
column.
Check Constraints
Check constraints specify a condition or requirement on a data value before
data can be assigned to a column during an INSERT or UPDATE statement. If
a row evaluates to false for any of the check constraints defined on a table dur-
ing an insert or update, the database server returns an error. You define a con-
straint using the CREATE TABLE or ALTER TABLE statements. For example,
the following requirement constrains the values of an integer domain to a
certain range:
You can express constraints on character-based domains this way using the
MATCHES predicate and the regular-expression syntax it supports. For exam-
ple, the following constraint restricts a Telephone domain to the form of a U.S.
local telephone number:
For additional information about check constraints, see the CREATE TABLE
and ALTER TABLE statements in the Informix Guide to SQL: Syntax.
Keep in mind that the telephone-directory data model is used for illustrative
purposes only. For the sake of the example, we translate it into SQL
statements.
You might have to create the same database model more than once. However,
the statements that create the model can be stored and executed automati-
cally. See “Using Command Scripts” on page 9-26 for more information
about using this topic.
When the tables exist, you must populate them with rows of data. You can do
this manually, with a utility program, or with custom programming.
Selecting a Dbspace
OnLine offers you the option of creating the database in a particular dbspace.
A dbspace is a named area of disk storage. Ask your OnLine administrator
whether you should use a particular dbspace. The administrator can put a
database in a dbspace to isolate it from other databases or to locate it on a par-
ticular disk device. (Chapter 10, “Tuning Your Data Model” discusses
dbspaces and their relationship to disk devices.)
Some dbspaces are mirrored (duplicated on two different disk devices for high
reliability); your database can be put in a mirrored dbspace if its contents are
of exceptional importance.
When you do not choose logging, BEGIN WORK and other SQL statements
related to transaction processing are not permitted in the database. This
affects the logic of programs that use the database.
• Regular (unbuffered) logging. This is the best choice for most databases.
In the event of a failure, only uncommitted transactions are lost.
• Buffered logging. If the database is lost, a few or possibly none of the most
recent alterations are lost. In return for this small risk, performance
during alterations is improves slightly.
Buffered logging is best for databases that are updated frequently (so that
speed of updating is important), but the updates can be re-created from
other data in the event of a crash. You can use the SET LOG statement to
alternate between buffered and regular logging.
• ANSI-compliant logging. This is the same as regular logging, but the ANSI
rules for transaction processing are also enforced. (See the discussion of
ANSI SQL in Chapter 1 of the Informix Guide to SQL: Reference.)
When you do not choose logging, BEGIN WORK and other SQL statements
related to transaction processing are not permitted in the database. This
affects the logic of programs that use the database.
• Regular logging. This is the best choice for most databases. If the database
is lost, only the alteration in progress at the time of failure is lost.
You must specify a file to contain the transaction log. (The form of the file
name depends on the rules of your operating system.) This file grows
whenever the database is altered. Whenever the database files are
archived, you should set the log file back to an empty condition so it
reflects only transactions following the latest archive.
• ANSI-compliant logging. This is the same as regular logging, but the ANSI
rules for transaction processing are also enabled. (See the discussion of
ANSI-compliant databases in Chapter 1 of the Informix Guide to SQL: Ref-
erence.)
You can add a transaction log to a nonlogged database later using the START
DATABASE statement.
Figure 9-5 The CREATE TABLE statements for the telephone-directory data model
An Example
Most Informix database server products come with a demonstration
database called stores6 (the one used for most of the examples in this book).
The stores6 database is delivered as an operating system command script
that calls Informix products to build the database. You can copy this
command script and use it as the basis for automating your own data model.
If you are using INFORMIX-SE, you can select the data you want from one
database and insert it into another database, as long as the databases are on
the same database server. As shown in the following example, you could
select information from the catalog table in the stores6 database to insert into
a new table by using a temporary table:
CONNECT TO 'sharky/db1';
DISCONNECT;
CONNECT TO 'sharky/db2';
If you want to select data from another database server in INFORMIX-SE, you
must export the data to a file. You can use the UNLOAD statement in
DB-Access, INFORMIX-SQL, or INFORMIX-4GL, or you can write a report in
ACE or INFORMIX-4GL and direct the output to a file.
When the source is another kind of file or database, you must find a way to
convert it into a flat ASCII file; that is, a file of printable data in which each line
represents the contents of one table row.
After you have the data in a file, you can load it into a table using the dbload
utility. Read about dbload in Chapter 5 of the Informix Guide to SQL: Reference.
The LOAD statement in DB-Access, INFORMIX-SQL, or INFORMIX-4GL can
also load rows from a flat ASCII file. See Chapter 1 of the Informix Guide to
SQL: Syntax for information about the LOAD and UNLOAD statements.
Inserting hundreds or thousands of rows goes much faster if you turn off
transaction logging. No point exists in logging these insertions because in the
event of a failure you can easily re-create the lost work. The following list
contains the steps of a large bulk-load operation:
• If any chance exists that other users are using the database, exclude them
with the DATABASE EXCLUSIVE statement.
• If you are using INFORMIX-OnLine Dynamic Server, ask the
administrator to turn off logging for the database.
The existing logs can be used to recover the database to its present state,
while the bulk insertion can be run again to recover those rows if they are
lost soon after.
9-28 Implementing Your Data Model
Summary
• Perform the statements or run the utilities that load the tables with data.
• Archive the newly loaded database.
If you are using INFORMIX-OnLine Dynamic Server, either ask the
administrator to perform a full or incremental archive, or use the
onunload utility to make a binary copy of your database only.
If you are using other database servers, use operating system commands
to back up the files that represent the database.
• Restore transaction logging and release the exclusive lock on the
database.
You can enclose the steps of populating a database in a script of operating
system commands. You can automate the INFORMIX-OnLine Dynamic
Server administrator commands by invoking the command-line equivalents
to ON-Monitor.
Summary
This chapter covered the following work, which you must do to implement
a data model:
• Specify the domains, or constraints, that are used in the model, and
complete the model diagram by assigning constraints to each column.
• Use interactive SQL to create the database and the tables in it.
• If you must create the database again, write the SQL statements to do so
into a script of commands for the operating system.
• Populate the tables of the model, first using interactive SQL and then by
bulk operations.
• Possibly write the bulk-load operation into a command script so you can
repeat it easily.
You can now use and test your data model. If it contains very large tables, or
if you must protect parts of it from certain classes of users, more work
remains to be done. That is the subject of Chapter 10, “Tuning Your Data
Model.”
10
Tuning Your Data
Model
Chapter Overview 3
INFORMIX-OnLine Dynamic Server Disk Storage 3
Chunks and Pages 4
Dbspaces and Blobspaces 4
Disk Mirroring 5
Databases 5
Tables and Spaces 6
Exploiting Mirroring 6
Sharing Temporary Space 6
Assigning Dedicated Hardware 6
Reducing Contention Between Programs Using the
Same Table 7
Tblspaces 7
Extents 8
Choosing Extent Sizes 8
Upper Limit on Extents 10
Reorganizing dbspaces and Tables 10
Calculating Table Sizes 12
Estimating Fixed-Length Rows 13
Estimating Variable-Length Rows 14
Estimating Index Pages 16
Estimating Blobpages 17
Locating Blob Data 18
Managing Indexes 19
Space Costs of Indexes 20
Time Costs of Indexes 20
Choosing Indexes 21
Join Columns 21
Selective Filter Columns in Large Tables 22
Order-By and Group-By Columns 22
Duplicate Keys Slow Index Modifications 22
Dropping Indexes 24
Clustered Indexes 25
Denormalizing 26
Shorter Rows for Faster Queries 26
Expelling Long Strings 26
Using VARCHAR Strings 26
Changing Long Strings to TEXT 27
Building a Symbol Table of Repeated Strings 27
Moving Strings to a Companion Table 28
Splitting Wide Tables 28
Division by Bulk 28
Division by Frequency of Use 28
Division by Frequency of Update 29
Costs of Companion Tables 29
Splitting Tall Tables 29
Redundant and Derived Data 30
Adding Derived Data 30
Adding Redundant Data 31
Maximizing Concurrency 32
Easing Contention 32
Rescheduling Modifications 33
Using an Update Journal 33
Isolating and Dispersing Updates 35
Splitting Tables to Isolate Volatile Columns 35
Dispersing Bottleneck Tables 35
Summary 36
device 0x7f
device 0x7d blobspace rasters
host file system
dbspace large
One dbspace, the root dbspace, is created first and always exists. It is the most
important space because it holds the control information that describes all
other spaces and chunks.
Parts of a single database can appear in two or more dbspaces. However, a
single table is always completely contained in one dbspace.
Disk Mirroring
Individual spaces can be mirrored. The chunks of a mirrored space are paired
with other chunks of equal size. Whenever a page is written to one of the
chunks, it is also written to the mirror chunk. When one chunk suffers a hard-
ware failure, the database server uses its mirror to continue processing with-
out interruption. When the broken chunk is restored to service (or when a
substitute chunk is assigned), OnLine automatically brings it back to equality
with the working chunk and continues operations.
When any dbspaces are mirrored, the root dbspace should also be mirrored.
Otherwise, if it is lost to hardware failure, all OnLine data is unusable
regardless of mirrors.
If your database has extreme requirements for reliability in the face of
hardware failure, you should place it in a mirrored dbspace. As indicated in
“Tables and Spaces” on page 10-6, it is possible to locate individual tables in
particular dbspaces. Hence, you can place some tables in mirrored spaces and
other tables in normal spaces.
Databases
A database resides initially in one dbspace. It is placed there by a parameter
of the CREATE DATABASE statement. The following example creates a
database in the dbspace named dev0x2d:
You can achieve many aims by placing a table in a specific dbspace. Some of
these aims are explored in the following paragraphs.
Exploiting Mirroring
Place all the tables used by a critically important application in a mirrored
dbspace. Alternatively, create the database in the mirrored dbspace and let
the important tables reside there by default. Tables that are part of the data-
base, but that are not used by the critical programs, can be located in
nonmirrored spaces.
dbspace three_arms
Tblspaces
The total of all disk space allocated to a table is the tblspace of the table. The
tblspace includes pages allocated to data (rows of that table) and pages allo-
cated to indexes. It also includes pages used by blob columns that are located
in the tblspace but not pages used by blob data in a separate blobspace or
blob data stored on an optical storage subsystem. (This choice is discussed
under “Locating Blob Data” on page 10-18.)
The tblspace is an accounting entity only; it does not correspond to any
particular part of a dbspace. The indexes and data extents that make up a
table can be scattered throughout the dbspace.
The oncheck utility (with the -pt option) returns information on the status of
tblspaces, including the counts of pages allocated and in use for each one.
You can use this information to monitor the growth of a table over time.
Extents
As you add rows to a table, OnLine allocates disk space to it in units called
extents. Each extent is a block of physically contiguous pages from the
dbspace. Even when the dbspace comprises more than one chunk, extents are
always allocated entirely within a single chunk to remain contiguous.
Contiguity is important to performance. When the pages of data are
contiguous, disk-arm motion is minimized when the database server reads
the rows sequentially. The mechanism of extents is a compromise between
the following competing requirements:
• Most dbspaces are shared among several tables.
• The size of some tables is not known in advance.
• Tables can grow at different times and different rates.
• All the pages of a table should be adjacent for best performance.
Because table sizes are not known, table space cannot be preallocated.
Therefore, extents are added only as they are needed, but all the pages in any
one extent are contiguous for better performance.
The next-extent sizes of the following kinds of tables are not very important
to performance:
• A small table has only one extent (otherwise it would not be small). If it is
heavily used, large parts of it are buffered in memory anyway.
• An infrequently used table is not important to performance no matter
what size it is.
• A table that resides in a dedicated dbspace always receives new extents
that are adjacent to its old extents. The size of these extents is not
important because, being adjacent, they perform like one large extent.
When you assign an extent size to these kinds of tables, the only
consideration is to avoid creating large numbers of extents. A large number
of extents causes the database server to spend a small amount of extra time
on bookkeeping. In addition, an upper limit exists on the number of extents
allowed. (This is covered in the section “Upper Limit on Extents” on
page 10-10.)
Next-extent sizes become important when two or more large and growing
tables share a dbspace. Because the extents added to the different tables are
interleaved, each new extent represents another long seek that must be made
when reading sequentially. It also extends the total distance over which the
disk arm must range when reading nonsequentially.
No upper limit exists on extent sizes except the size of the dbspace. When you
know the final size of a table (or can confidently predict it within 25 percent),
allocate all its space in the initial extent. When tables grow steadily to
unknown size, assign them next-extent sizes that let them share the dbspace
with a small number of extents each. The following list contains one possible
approach:
• Decide on the ratio in which the dbspace is shared among the tables. For
example, you might divide the dbspace among three tables in the ratio
0.4 : 0.2 : 0.3 (reserving 10 percent for small tables and overhead).
• Give each table one-fourth of its share of the dbspace as its initial extent.
• Assign each table one-eighth of its share as its next-extent size.
Monitor the growth of the tables regularly using oncheck.
What happens if, as the dbspace fills up, you do not have enough contiguous
space to create an extent of the size you specified? In that case, OnLine
allocates the largest contiguous extent that it can.
table 1
table 2
table 3
Figure 10-4 also shows gaps of unused space, perhaps created by tables that
existed when extents were allocated but that have since been dropped.
Disorganization such as that depicted in Figure 10-4 hurts performance in
two ways. During sequential access to any table, several long seeks must be
made. For nonsequential access to any table, the disk might have to seek
across the entire width of the dbspace. It is possible to rebuild a dbspace so
that tables are compact once again, as shown in Figure 10-5. The relative
order of the reorganized tables within the dbspace is not important; all that
matters is that the pages of each reorganized table are together. When reading
a table sequentially, no long seeks occur. When reading a table
nonsequentially, the disk arm ranges only over the space occupied by that
table.
table 1
table 2
table 3
You can also unload a table using the UNLOAD statement in DB-Access,
INFORMIX-SQL, or INFORMIX-4GL, and reload the table using the compan-
ion LOAD statement or the dbload utility. However, these operations convert
the table into character form, while onload and onunload work with binary
copies of disk pages.
You can reorganize a single table in two more ways. If you use the ALTER
TABLE statement to add or drop a column or to change the data type of a col-
umn, the table is copied and reconstructed. If you create a clustered index or
alter an index to cluster, the table is sorted and rewritten. (See “Clustered
Indexes” on page 10-25.) In both cases, the table is written on other areas of
the dbspace. However, if other tables are in the dbspace, no guarantee exists
that all the new extents are adjacent.
As rows are deleted and new ones inserted, the index can become sparse; that
is, the leaf pages might no longer be full of entries. On the other hand, if key
compression is effective, the index might be smaller. The method given here
should yield a conservative estimate for most indexes. If index space is
important, build a large test index using real data and check its size with the
oncheck utility.
Figure 10-8 Estimating the size of two indexes from the customer table
Estimating Blobpages
BYTE and TEXT data items that are stored on magnetic disk are stored in
separate pages, either interspersed among the row and index pages in the
tblspace or in a separate blobspace. (This discussion does not apply to blob
data stored on optical media.) Each blob data item occupies a whole number
of pages. For each blob column, let the values be as shown in the following
list:
typage = the number of whole pages required to store an item of
typical size.
nnpart = the fraction of rows in which this column has a non-null
value.
totpage= typage × estrows × nnpart.
The values for the column occupy approximately totpage pages. In the catalog
table (see Figure 10-6 on page 10-14) two blobpages occur. Their estimates
can be imagined as described in the following paragraphs:
For the cat_descr column, the text of a description is, at most, a
double-spaced page, which is 250 words or approximately 1,500 characters,
so typage = 1. A description exists for every entry, so nnpart = 1.0.
Thus, totpage = 1 × 5,000 × 1.0 = 5,000 pages of data.
The cat_picture column contains line art in a computer-readable form.
Examining several of these pictures reveals that they vary widely in size but
a typical file contains about 75,000 bytes of data. Thus typage = 38. The
marketing department estimates that they want to store a picture with one
entry in four: nnpart = 0.25. Therefore totpage = 38 × 5,000 × 0.25 = 47,500 pages
of data.
After a table is built and loaded, you can check the use of blobpages with the
oncheck utility -ptT option.
A TEXT or BYTE value is always stored apart from the rows of the table. Only
a 56-byte descriptor is stored with the row. However, the value itself occupies
at least one disk page.
When blob values are stored in the tblspace, the pages of their data are
interspersed among the pages containing rows. The result is to inflate the size
of the table. The blobpages separate the pages containing rows and spread
them out on the disk. When the database server reads only the rows and not
the blob data, the disk arm must move farther than it would if the blobpages
were stored apart. The database server scans only the row pages on any
SELECT operation that retrieves no blob column and whenever it tests rows
using a filter expression.
Another consideration is that disk I/O to and from a dbspace is buffered.
Pages are held in storage in case they are needed again soon; and, when
pages are written, the requesting program is allowed to continue before the
actual disk write takes place.
However, disk I/O to and from blobspaces is not buffered. Blobspace pages
are not retained in buffers to be read again, and the requesting program is not
allowed to proceed until all output to them is complete. The reason is that
blobspace I/O is expected to be voluminous. If these pages are passed
through the normal buffering mechanisms, they could monopolize the
buffers, driving out index pages and other pages that are useful to good
performance.
For best performance, then, you should locate a TEXT or BYTE column in a
blobspace in either of the following circumstances:
• When single data items are larger than one or two pages each; if kept in
the dbspace, their transfer dilutes the effectiveness of the page buffers.
• When the number of pages of blob data is more than half the number of
pages of row data; if kept in the dbspace, the table is inflated and queries
against it are slowed.
For a table that is both relatively small and nonvolatile, you can achieve the
effect of a dedicated blobspace by the following means: Load the entire table
with rows in which the blob columns are null. Create all indexes. The row
pages and the index pages are now contiguous. Update all the rows to install
the blob data. The blob pages follow the pages of row and index data in the
tblspace.
Managing Indexes
An index is necessary on any column (or composition of columns) that must
be unique. However, as discussed in Chapter 13, “Optimizing Your Queries,”
the presence of an index can also allow the query optimizer to speed up a
query. The optimizer can use an index in the following ways:
• To replace repeated sequential scans of a table with nonsequential access
• To avoid reading row data at all when processing expressions that name
only indexed columns
column value must be located in the same index (two or three more pages
in) and the row entered (one more page out).
Insertions and deletions change the number of entries on a leaf page. In
virtually every pagents operation, some additional work must be done
because a leaf page has either filled up or been emptied. However, because
pagents is usually greater than 100, this occurs less than 1 percent of the time
and can be disregarded for estimating.
In short, when a row is inserted or deleted at random, allow three to four
added page I/O operations per index. When a row is updated, allow six to
eight page I/O operations for each index that applies to an altered column.
Bear in mind also that if a transaction is rolled back, all this work must be
undone. For this reason, rolling back a transaction can take a long time.
Because the alteration of the row itself requires only two page I/O operations,
it is clear that index maintenance is the most time-consuming part of data
modification. One way to reduce this cost is discussed under “Dropping
Indexes” on page 10-24.
Choosing Indexes
Indexes are required on columns that must be unique and are not specified as
primary keys. In addition, you should add an index in the following cases:
• Columns used in joins that are not specified as foreign keys
• Columns frequently used in filter expressions
• Columns frequently used for ordering or grouping
Join Columns
As discussed in Chapter 13, “Optimizing Your Queries,” at least one column
named in any join expression should have an index. If no index exists, the
database server may build a temporary index or perform a sort-merge before
the join and discard it afterward; that is almost always faster than performing
a join by repeated sequential scans over a table.
When both columns in a join expression have indexes, the optimizer has
more options when it constructs the query plan. As a general rule, you should
put an index on any column that is not identified as a primary or foreign key
and is used in a join expression more than occasionally.
For example, in an index on a column whose only values are M for married
and S for single, all the index entries are contained in just two lists of dupli-
cates. Such an index is not of much use, but at least it works for querying; the
database server can read out the list of rows that have one value or the other.
When an entry must be deleted from a list of duplicates, the database server
must read the whole list and rewrite some part of it. When it adds an entry,
the database server puts the new row at the end of its list. Neither operation
is a problem when the list is short, which is normal. But when a list fills many
pages, the database server must read all the rows to find the end. When it
deletes an entry, it typically must update and rewrite half the pages in the list.
Thus, an index on a column that has a small number of distinct values, in a
table that has a large number of rows, can drastically reduce the speed of
updating. An example is a column whose values are the names or abbrevia-
tions of states or provinces. If 50 unique values occur in a mailing list of
100,000 rows, an average of 2,000 duplicates exists per value. But real data is
never so well distributed; in such a table, the more common values likely
have 10,000 or more duplicates, and their lists might approach 50 pages in
length.
When the database server inserts or deletes an entry in such a list, it is busy
for a long time. Worse still, it has to lock all the affected index pages while it
does the work, greatly reducing concurrent access to the table.
You can avoid this problem fairly simply at some cost in disk space. The trick
is to know that the database server uses the leading column of a composite
index in the same way as it uses an index on that column alone. So instead of
creating an index on a column with few unique values, create a composite
index on that column followed by one other column that has a wide
distribution of values.
For example, change the index on the column whose only values are M and S
into a composite index on that column and a birthdate column. You can use
any second column to disperse the key values as long as its value does not
change or changes at the same time as the real key. The shorter the second
column the better because its values are copied into the index and expand its
size.
Dropping Indexes
In some applications, the majority of table updates can be confined to a single
time period. Perhaps all updates are applied overnight or on specified dates.
When this is the case, consider dropping all non-unique indexes while you
perform updates and then create new indexes afterward. This can have two
good effects.
First, because fewer indexes occur to update, the updating program can run
faster. Often, the total time to drop the indexes, update without them, and re-
create them afterward is less than the time to update with the indexes in
place. (The time cost of updating indexes is discussed under “Time Costs of
Indexes” on page 10-20.)
Second, newly made indexes are the most efficient ones. Frequent updates
tend to dilute the index structure, causing it to contain many partly full leaf
pages. This reduces the effectiveness of an index and wastes disk space.
As another timesaving measure, make sure that a batch-updating program
calls for rows in the sequence defined by the primary-key index. That
sequence causes the pages of the primary-key index to be read in order and
only one time each.
The presence of indexes also slows down the population of tables when you
use the LOAD statement or the dbload utility. Loading a table that has no
indexes is a very quick process (little more than a disk-to-disk sequential
copy), but updating indexes adds a great deal of overhead.
The fastest way to load a table is as described in the following list:
1. Drop the table (if it exists).
2. Create the table without specifying any unique constraints.
3. Load all rows into the table.
4. Alter the table to apply the unique constraints.
5. Create the non-unique indexes.
If you cannot guarantee that the loaded data satisfies all unique constraints,
you must create the unique indexes before you load the rows. It saves time if
the rows are presented in the correct sequence for at least one of the indexes
(if you have a choice, make it the one with the largest key). This minimizes
the number of leaf pages that must be read and written.
Clustered Indexes
The term clustered index is a misnomer. The index is nothing special; it is the
table that is modified so that its rows are physically ordered to agree with the
sequence of entries in the index. (Do not confuse the clustered index with an
optical cluster, which is a method for storing logically related blobs together
on an optical volume. For information on optical clusters, see the
INFORMIX-OnLine/Optical User Manual.)
When you know that a table is ordered by a certain index, you can take
advantage of the knowledge to avoid sorting. You can also be sure that when
the table is searched on that column, it is read (effectively) in sequential order
instead of nonsequentially. These points are covered in Chapter 13,
“Optimizing Your Queries.”
In the stores6 database, the orders table has an index, zip_ix, on the zip code
column. The following command causes the database server to put the rows
of the customer table into descending order by zip code:
To reorder a table, the database server must copy the table. In the preceding
example, the database server reads all rows of the table and constructs an
index. Then it reads the index entries in sequence. For each entry, it reads the
matching row of the table and copies it to a new table. The rows of the new
table are in the desired sequence. This new table replaces the old table.
Clustering is not preserved when you alter a table. When you insert new
rows, they are stored physically at the end of the table regardless of their con-
tents. When you update rows and change the value of the clustering column,
the rows are written back into their original location in the table.
When clustering is disturbed by updates, it can be restored. The following
command reorders the table to restore the physical sequence:
Denormalizing
The entity-relationship data model described in Chapter 8, “Building Your
Data Model,” produces tables that contain no redundant or derived data;
tables that are well-structured by the tenets of relational theory.
Sometimes, to meet extraordinary demands for high performance, you might
have to modify the data model in ways that are undesirable from a theoretical
standpoint. This section describes some modifications and their associated
costs.
existing fixed width of the column. (When NLS is enabled, NCHAR columns
may replace CHAR columns, and NVARCHAR columns may replace
VARCHAR columns.)
You can change the definition of the customer table so that its city column
becomes a foreign key that references the city_num column in the cities table.
You must change any program that inserts a new row into customer to insert
the city of the new customer into cities. The database server return code in
the SQLCODE field can indicate that the insert failed because of a duplicate
key. It is not a logical error; it simply means that some existing customer is
located in that city. (However, a 4GL program must use the WHENEVER
statement to trap errors; otherwise the negative value in SQLCODE terminates
the program.)
Besides changing programs that insert data, you also must change all
programs and stored queries that retrieve the city name. They must use a join
into the new cities table to obtain their data. The extra complexity in pro-
grams that insert rows and the extra complexity in some queries is the cost of
giving up theoretical correctness in the data model. Before you make the
change, be sure it returns a reasonable savings in disk space or execution
time.
Division by Bulk
One principle on which you can divide an entity table is bulk: Move the
bulky attributes, which are usually character strings, to the companion table.
Keep the numeric and other small attributes in the primary table. In the dem-
onstration database, you can split the ship_instruct column from the orders
table. You can call the companion table orders_ship. It has two columns, a
primary key that is a copy of orders.order_num and the original
ship_instruct column.
The benefits of splitting a large table are that the segments can be treated
separately for copying, sorting, indexing, archiving, and restoring. All these
operations become easier. The segments can be assigned to tblspaces in dif-
ferent ways to make the best use of disk devices. And, as long as most queries
are based on the attribute used for segmenting, queries should be
dramatically faster.
The drawback of splitting a table is that operations that apply to the whole
table become much more complicated. If a query cannot be directed to one
subtable, it must be written in the form of a UNION of many subqueries, each
on a different subtable. This greatly complicates the design of reports and
browsing programs.
Although the join to the items table reads only three or four additional pages,
that might be too much time for an interactive program. One solution is to
add an order-total column to the orders table.
The costs of derived data are in disk space, complexity, and data integrity.
The disk space devoted to an order-total column is wasted because the same
information is stored twice. Also, the presence of the column makes the rows
of the table wider; fewer of them occur in a page and querying the table
becomes slower. Most important, any program that updates the base
attributes must be changed to also update the derived column. Inevitably,
times occur when the derived column is wrong, when it does not contain the
right derived value.
Derived data is not reliable data. In the example of a derived order price, the
unreliability occurs while an order is being entered. When rows are added to
the items table, times occur when the order total in orders is not equal to the
sum of the corresponding rows from items. In general, before you allow
derived data to appear in the database, you must define its accuracy as care-
fully as possible; actually, you should define as closely as possible the
conditions under which the derived column is unreliable.
The integrity risk is simply that the redundant copies of the data might not
be accurate. If a lead time is changed in manufact, the stock column is out-
dated until it, too, is updated. As with derived data, you should take pains to
define the conditions under which the redundant data might be wrong.
Maximizing Concurrency
Some databases are used by only one program at a time; others are used
concurrently by multiple programs. The following factors make concurrent
programs inherently slower than doing the same amount of work serially:
• Multiple programs interfere with the use of buffers and disk drives. The
pages read for one program might be driven from the buffers used by a
query from the next program and might have to be read again. Disk I/O
for one query displaces the disk-access arm, slowing the sequential access
of another program.
• Programs that modify data lock pages, delaying all other programs that
use the same data.
Easing Contention
Contention is inevitable between programs using the same resources. You
can deal with it in the following ways:
1. Make programs use fewer resources, either by making them do less work
or by making them work more efficiently.
2. Arrange the resources better, for instance, by allocating tables to dbspaces
to minimize contention.
3. Supply more resources: more memory, more and faster disk drives, and
more and faster computers.
The first point is the subject of Chapter 13, “Optimizing Your Queries,”
which deals with making queries faster. Sometimes you also must consider
making queries do less; that is, reducing the functions available to on-line
users. You can look for any allowed transaction that entails scanning an entire
large table, such as any kind of summation, average, or management report,
especially if it requires a join. Consider removing such transactions from on-
line programs. Instead, offer a new facility that interactively schedules an
off-peak job, with the output returned the next day.
Rescheduling Modifications
To the greatest extent possible, schedule modifications for times when no
interactive users are using the database. One reason for this is that concurrent
modifications must be done with all indexes in place; that means they incur
all the time costs noted earlier. Another reason is that modifications not only
lock table rows they also lock index pages. That increases the number of locks
in use and the number of lock delays for all users.
The means of rescheduling modifications depend entirely on the details of
your application.
One way to update the base table is to use two cursors. The first cursor is a
hold cursor; it is used to scan the rows of the journal. (See “Hold Cursors” in
Chapter 7.) For each row of the journal, the program goes through the
following steps:
1. Issue the BEGIN WORK statement.
2. Fetch the rows from the tables being updated using an update cursor.
(This locks only these rows.)
3. Validate the update information from the journal against the data in the
target rows.
4. Apply the updates to the target tables.
5. Update the journal row in some way to mark it as finished.
6. Issue the COMMIT WORK statement (or the ROLLBACK WORK statement,
if an error is found).
You run a different program to drop and re-create the journal table only after
every journal row is validated, applied, and marked.
The obvious disadvantage of an update journal is that the base tables do not
reflect the most current data. If it is essential that updates be instantly visible,
the journal scheme does not work.
The great advantages of reduced I/O and reduced locking delays during
peak hours are a powerful argument in favor of an update journal. Deferred
updates are accepted in many applications. For example, no bank promises
to know your account balance more precisely than as of the close of business
the preceding day, and for exactly this reason: the bank records transactions
in a journal during the day and applies the updates overnight.
Summary
When tables are moderate in size and only one user at a time accesses the
database, carefully applied relational theory is sufficient to produce good
performance.
When both the number of tables and the number of users become larger and
the response time begins to degrade, you must turn to practical solutions.
The first step is to understand and take advantage of the tools that
INFORMIX-OnLine Dynamic Server offers. It permits you to arrange your
tables on the hardware for maximum benefit. Then, one step at a time and
always measuring, you can begin complicating the structure of the data
model and the programs that use it.
Granting and
Limiting Access to
11
Your Database
Chapter Overview 3
Controlling Access to Databases 4
Securing Database Files 4
Multiuser Systems 4
Single-User Systems 4
Securing Confidential Data 5
Granting Privileges 5
Database-Level Privileges 5
Connect Privilege 6
The Users and the Public 6
Resource Privilege 7
Database Administrator Privilege 7
Ownership Rights 7
Table-Level Privileges 7
Access Privileges 8
Index, Alter, and References Privileges 8
Privileges in the System Catalog 9
Column-Level Privileges 10
Procedure-Level Privileges 12
Automating Privileges 13
Automating with INFORMIX-4GL 13
Automating with a Command Script 14
Controlling Access to Data Using Stored Procedures 15
Restricting Reads of Data 16
Restricting Changes to Data 16
Monitoring Changes to Data 17
Restricting Object Creation 18
Using Views 19
Creating Views 20
Duplicate Rows from Views 22
Restrictions on Views 22
When the Basis Changes 22
Modifying Through a View 23
Deleting Through a View 24
Updating a View 24
Inserting into a View 25
Using WITH CHECK OPTION 25
Privileges and Views 27
Privileges When Creating a View 27
Privileges When Using a View 28
Summary 30
Multiuser Systems
You can deny access to the database by denying access to the database
directory. The means by which you can do this depend on your operating
system and your computer hardware. Multiuser operating systems have
software facilities such as UNIX file permissions.
Note: In UNIX, the database directory is created with group identity informix, and
the database server always runs under group identity informix. Thus, you cannot
use group permissions to restrict access to a particular group of users. You can, how-
ever, only remove all group permissions (file mode 700) and deny access to anyone
except the owner of the directory.
You also can deny access to individual tables in this way; for example, by
making the files that represent those tables unavailable to certain users, while
leaving the rest of the files accessible. However, the database servers are not
designed for tricks of this kind. When an unauthorized user tries to query one
of the tables, the database server probably returns an error message about not
being able to locate a file. This may confuse users.
Single-User Systems
Typical single-user systems have few software controls on file access; you can
make a database inaccessible to others only by writing it on a disk that you
can detach from the machine and keep locked.
None of these techniques apply when you use the INFORMIX-OnLine
Dynamic Server database server. It controls its own disk space at the device
level, bypassing the file-access mechanisms of the operating system.
Granting Privileges
The authorization to use a database is called a privilege. For example, the
authorization to use a database at all is called the Connect privilege, and the
authorization to insert a row into a table is called the Insert privilege. You
control the use of a database by granting these privileges to other users or by
revoking them.
Two groups of privileges exist that control the actions a user can perform on
data. These are database-level privileges, which affect the entire database,
and table-level privileges, which relate to individual tables. In addition to
these two groups, procedure-level privileges exist, which determine who can
execute a procedure.
Database-Level Privileges
The three levels of database privilege provide an overall means of controlling
who accesses a database.
Connect Privilege
The least of the privilege levels is Connect, which gives a user the basic ability
to query and modify tables. Users with the Connect privilege can perform the
following functions:
• Execute the SELECT, INSERT, UPDATE, and DELETE statements, provided
that they have the necessary table-level privileges.
• Execute a stored procedure, provided that they have the necessary
table-level privileges.
• Create views, provided that they are permitted to query the tables on
which the views are based.
• Create temporary tables and create indexes on the temporary tables.
Resource Privilege
The Resource privilege carries the same authorization as the Connect
privilege. In addition, users with the Resource privilege can create new, per-
manent tables, indexes, and stored procedures, thus permanently allocating
disk space.
Ownership Rights
The database, and every table, view, index, procedure, and synonym in it, has
an owner. The owner of an object is usually the person who created it,
although a user with the DBA privilege can create objects to be owned by
others.
The owner of an object has all rights to that object and can alter or drop it
without needing additional privileges.
Table-Level Privileges
You can apply seven privileges, table by table, to allow nonowners the
privileges of owners. Four of them—the Select, Insert, Delete, and Update
privileges—control access to the contents of the table. The Index privilege
Access Privileges
Four privileges govern how users can access a table. As the owner of the
table, you can grant or withhold the following privileges independently:
• The Select privilege allows selection, including selecting into temporary
tables.
• The Insert privilege allows a user to add new rows.
• The Update privilege allows a user to modify existing rows.
• The Delete privilege allows a user to delete rows.
The Select privilege is necessary for a user to retrieve the contents of a table.
However, The Select privilege is not a precondition for the other privileges.
A user can have Insert or Update privileges without having the Select
privilege.
For example, your application might have a usage table. Every time a certain
program is started, it inserts a row into the usage table to document that it
was used. Before the program terminates, it updates that row to show how
long it ran and perhaps to record counts of work performed by its user.
If you want any user of the program to be able to insert and update rows in
this usage table, you grant Insert and Update privileges on it to public.
However, you might grant the Select privilege to only a few users.
You can grant the Index privilege to anyone, but to exercise the ability, the
user must also hold the Resource database privilege. So, although the Index
privilege is granted automatically (except in ANSI-compliant databases),
users who have only the Connect privilege to the database cannot exercise
their Index privilege. This is reasonable because an index can fill a large
amount of disk space.
The Alter privilege permits its holder to use the ALTER TABLE statement on
the table, including the power to add and drop columns, reset the starting
point for SERIAL columns, and so on. You should grant the Alter privilege
only to users who understand the data model very well and whom you trust
to exercise their power very carefully.
The References privilege allows you to impose referential constraints on a
table. As with the Alter privilege, you should grant the References privilege
only to users who understand the data model very well.
Column-Level Privileges
You can qualify the Select, Update, and References privileges with the names
of specific columns. This allows you to grant very specific access to a table:
You can permit a user to see only certain columns, you can allow a user to
update only certain columns, or you can allow a user to impose referential
constraints on certain columns.
Using INFORMIX-OnLine Dynamic Server (so that table data can be
inspected only through a call to the database server), this feature solves the
problem posed earlier: that only certain users should know the salary, perfor-
mance review or other sensitive attributes of an employee. To make the
example specific, suppose a table of employee data is defined as shown in
Figure 11-1.
Because this table contains sensitive data, you execute the following
statement immediately after creating it:
For selected persons in the Human Resources department and for all
managers, you execute a statement such as the following one:
In this way, you permit certain users to view all columns. (The final section
of this chapter discusses a way to limit the view of managers to only their
own employees.) For the first-line managers who carry out performance
reviews, you could execute a statement such as the following one:
For the clerks in the Human Resources department, you could execute a
statement such as the following one:
This statement gives certain users the ability to maintain the nonsensitive
columns but denies them authorization to change performance ratings or sal-
aries. The person in the MIS department who assigns computer user-ids is the
beneficiary of a statement such as the following one:
On behalf of all users who are allowed to connect to the database but who are
not authorized to see salaries or performance reviews, you execute
statements such as the following one to permit them to see the nonsensitive
data:
However, any attempt to execute a query such as the following one produces
an error message and no data:
Procedure-Level Privileges
You can apply the Execute privilege on a procedure to authorize nonowners
to run a procedure. If you create a procedure in a database that is not ANSI-
compliant, the default procedure-level privilege is Public; you do not need to
grant the Execute privilege to specific users unless you have first revoked it.
If you create a procedure in an ANSI-compliant database, no other users have
the Execute privilege by default; you must grant specific users the Execute
privilege. The following example grants the Execute privilege to the user
orion so that orion can use the stored procedure named read-address:
Automating Privileges
It might seem that this design forces you to execute a tedious number of
GRANT statements when you first set up the database. Furthermore, privi-
leges require constant maintenance as people change their jobs. For example,
if a clerk in Human Resources is terminated, you want to revoke the Update
privilege as soon as possible; otherwise you risk the unhappy employee
executing a statement such as the following one:
UPDATE hr_data
SET (emp_name, hire_date, dept_num) = (NULL, NULL, 0)
Less dramatic, but equally necessary, changes of privilege are required daily,
or even hourly, in any model that contains sensitive data. If you anticipate
this need, you can prepare some automated tools to help maintain privileges.
Your first step should be to specify privilege classes that are based on the jobs
of the users, not on the structure of the tables. For example, a first-line
manager needs the following privileges:
• The Select and limited Update privilege on the hypothetical hr_data table
• The Connect privilege to this and other databases
• Some degree of privilege on several tables in those databases
When the manager is promoted to a staff position or sent to a field office, you
must revoke all those privileges and grant a new set of privileges.
Define the privilege classes you support, and for each class specify the
databases, tables, and columns to which you must give access. Then devise
two automated procedures for each class: one to grant the class to a user and
one to revoke it.
Figure 11-2 A 4GL function that builds, prepares, and executes a GRANT statement
The details depend on your operating system and the version of DB-Access
or INFORMIX-SQL that you are using. In essence, you want to create a
command script that performs the following functions:
• Takes a user-id whose privileges are to be changed as its parameter
• Prepares a file of GRANT or REVOKE statements customized to contain
that user-id
• Invokes DB-Access or INFORMIX-SQL with parameters that tell it to select
the database and execute the prepared file of GRANT or REVOKE
statements
In this way, you can reduce the change of the privilege class of a user to one
or two commands.
END PROCEDURE;
limit users to deleting one row at a time to ensure that they do not
accidentally remove all the rows in the table, set up the database with the
following privileges:
• You are the DBA of the database.
• All the users have the Connect privilege to the database. They may or
may not have the Resource privilege. They do not have the Delete (for this
example) privilege on the table being protected.
• Your stored procedure is created using the DBA keyword.
• Your stored procedure performs the deletion.
Write a stored procedure similar to the one shown in Figure 11-4, which
deletes rows from the customer table using a WHERE clause with the
customer_num provided by the user.
END PROCEDURE;
Write a stored procedure similar to the one in Figure 11-6, which updates a
table using a customer number provided by the user. If the user happens to
be acctclrk, a record of the deletion is put in the file updates.
Figure 11-5 A procedure to delete rows and record changes made by a certain user
You can monitor all the deletions made through the procedure by removing
the IF statement and making the SYSTEM statement more general. If you
change the procedure in Figure 11-6 to record all deletions, it looks like the
procedure in Figure 11-6.
SYSTEM
'echo Deletion made from customer table, by '||username ||'>>/hr/records/deletes';
END PROCEDURE;
CREATE TABLE learn1 (intone SERIAL, inttwo INT NOT NULL, charcol CHAR(10) )
CREATE INDEX learn_ix ON learn1 (inttwo).
CREATE TABLE toys (name CHAR(15) NOT NULL UNIQUE,
description CHAR(30), on_hand INT);
END PROCEDURE;
Figure 11-7 DBA-mode procedure that adds tables and indexes to the database
Using Views
A view is a synthetic table. You can query it as if it were a table, and in some
cases you can update it as if it were a table. However, it is not a table, rather,
it is a synthesis of the data that exists in real tables and other views.
The basis of a view is a SELECT statement. When you create a view, you define
a SELECT statement that generates the contents of the view at the time the
view is accessed. A user also queries a view using a SELECT statement. The
database server merges the SELECT statement of the user with the one
defined for the view and then actually performs the combined statements.
The result has the appearance of a table; it is enough like a table that a view
even can be based on other views, or on joins of tables and other views.
Because you write a SELECT statement that determines the contents of the
view, you can use views for any of the following purposes:
• To restrict users to particular columns of tables
You name only permitted columns in the select list in the view.
• To restrict users to particular rows of tables
You specify a WHERE clause that returns only permitted rows.
• To constrain inserted and updated values to certain ranges
You can use the WITH CHECK OPTION (discussed on page 11-25) to
enforce constraints.
• To provide access to derived data without having to store redundant data
in the database
You write the expressions that derive the data into the select list in the
view. Each time you query the view, the data is derived anew. The derived
data is always up to date, yet no redundancies are introduced into the
data model.
• To hide the details of a complicated SELECT statement
You hide complexities of a multitable join in the view so that neither users
nor application programmers need to repeat them.
Creating Views
The following example creates a view based on a table in the stores6
database:
The view exposes only three columns of the table. Because it contains no
WHERE clause, the view does not restrict the rows that can appear.
The following example creates a view based on a table that is available when
NLS has been enabled. In it, the view, column, and table names contain
foreign characters.
The table of state names reduces the redundancy of the database; it allows for
storing the full state names only once, which can be very useful for lengthy
state names such as Minnesota. This full_addr view lets users retrieve the
address as if the full state name were stored in every row. The following two
queries are equivalent:
However, be careful when you define views that are based on joins. Such
views are not modifiable; that is, you cannot use them with UPDATE, DELETE,
or INSERT statements. (Modifying through views is covered beginning on
page 11-23.)
The following example restricts the rows that can be seen in the view:
This view exposes all columns of the customer table, but only certain rows.
The following example is a view that restricts users to rows that are relevant
to them:
All the columns of the cust_calls table are available but only in those rows
that contain the user-ids of the users who execute the query.
Restrictions on Views
Because a view is not really a table, it cannot be indexed, and it cannot be the
object of such statements as ALTER TABLE and RENAME TABLE. The columns
of a view cannot be renamed with RENAME COLUMN. To change anything
about the definition of a view, you must drop the view and re-create it.
Because it must be merged with the user’s query, the SELECT statement on
which a view is based cannot contain any of the following clauses:
INTO TEMP The user’s query might contain INTO TEMP; if the view also
contains it, the data would not know where to go.
UNION The user’s query might contain UNION. No meaning has
been defined for nested UNION clauses.
ORDER BY The user’s query might contain ORDER BY. If the view also
contains it, the choice of columns or sort directions could be
in conflict.
When a table is renamed, any views in the same database that depend on it
are modified to use the new name. When a column is renamed, views in the
same database that depend on that table are updated to select the proper col-
umn. However, the names of columns in the views themselves are not
changed. For an example of this, recall the following view on the customer
table:
Now suppose that the customer table is changed in the following way:
To select last names of customers directly, you must now select the new
column name. However, the name of the column as seen through the view is
unchanged. The following two queries are equivalent:
When you alter a table by dropping a column, views are not modified. If they
are used, error -217 (Column not found in any table in the query)
occurs. The reason views are not dropped is that you can change the order of
columns in a table by dropping a column and then adding a new column of
the same name. If you do this, views based on that table continue to work.
They retain their original sequence of columns.
INFORMIX-OnLine Dynamic Server permits you to base a view on tables and
views in external databases. Changes to tables and views in other databases
are not reflected in views. Such changes might not be apparent until someone
queries the view and gets an error because an external table changed.
Updating a View
You can use a modifiable view with an UPDATE statement as if it were a table.
However, a modifiable view can still contain derived columns; that is, col-
umns that are produced by expressions in the select list of the CREATE VIEW
statement. You cannot update derived columns (sometimes called virtual
columns).
When a column is derived from a simple arithmetic combination of a column
with a constant value (for example, order_date+30), the database server
can, in principle, figure out how to invert the expression (in this case, by sub-
tracting 30 from the update value) and perform the update. However, much
more complicated expressions are possible, most of which cannot easily be
inverted. Therefore, the database server does not support updating any
derived column.
Figure 11-8 shows a modifiable view that contains a derived column, and an
UPDATE statement that can be accepted against it.
If this is improper, you can add the clause WITH CHECK OPTION when you
create the view. This clause asks the database server to test every inserted or
updated row to ensure that it meets the conditions set by the WHERE clause
of the view. The database server rejects the operation with an error if the
conditions are not met.
In Figure 11-8, the view named call_response is defined as shown in the
following example:
The view requires rows in which user_id equals USER. If this update is
performed by a user named tony, the updated rows vanish from the view.
However, you can create the view as shown in the following example:
You can use the WITH CHECK OPTION feature to enforce any kind of data
constraint that can be stated as a Boolean expression. In the following exam-
ple, you can create a view of a table in which all the logical constraints on data
are expressed as conditions of the WHERE clause. Then you can require all
modifications to the table to be made through the view.
Because of EXISTS and other tests, all of which are expected to be successful
when retrieving existing rows, this is a most inefficient view for displaying
data from orders. However, if insertions to orders are made only through this
view (and you are not already using integrity constraints to constrain data),
it is impossible to insert a back-dated order, an invalid customer number, or
an excessive shipping weight and shipping charge.
The database server tests the view definition to see if the view is modifiable.
If it is, the database server grants you the Insert, Delete, and Update privi-
leges on the view, provided that you also have those privileges on the under-
lying table or view. In other words, if the new view is modifiable, the
database server copies your Insert, Delete, and Update privileges from the
underlying table or view, and grants them on the new view. If you have only
the Insert privilege on the underlying table, you receive only the Insert
privilege on the view.
This test ensures that users cannot use a view to gain access to any privileges
that they did not already have.
Because you cannot alter or index a view, the Alter and Index privileges are
never granted on a view.
Users who are given the Select privilege for this view can see nonsensitive
data and update nothing. For the clerks in the Human Resources department
who must enter new rows, you create a different view, as shown in the
following example:
You grant these users both Select and Insert privileges on this view. Because
you, the creator of both the table and the view, have the Insert privilege on
the table and the view, you can grant the Insert privilege on the view to others
who have no privileges on the table.
On behalf of the clerk in the MIS department who enters or updates new
user-ids, you create still another view, as shown in the following example:
This view differs from the previous view in that it does not expose the
department number and date of hire.
Finally, the managers need access to all columns and need the ability to
update the performance-review data for their own employees only. These
requirements can be met by creating a table, hr_data, that contains a
department number and a computer user-id for each employee. Let it be a
rule that the managers are members of the departments that they manage.
Then the following view restricts managers to rows that reflect only their
employees:
The final condition is required so that the managers do not have update
access to their own row of the table. It is, therefore, safe to grant the Update
privilege to managers for this view, but only on selected columns, as shown
in this statement:
Summary
In a database that contains public material or is used only by you and trusted
associates, security is not an important consideration and few of the ideas in
this chapter are needed. But as more people are allowed to use and modify
the data, and as the data becomes increasingly confidential, you must spend
more time and be ever more ingenious at controlling the way people can
approach the data.
The techniques discussed here can be divided into the following two groups:
• Keeping data confidential
When the database resides in operating system files you can use features
of the operating system to deny access to the database. In any case, you
control the granting of the Connect privilege to keep people out of the
database.
When different classes of users have different degrees of authorization,
you must allow them all the Connect privilege. You can use table-level
privileges to deny access to confidential tables or columns. Or, you can
use a stored procedure to provide limited access to confidential tables or
columns. In addition, you can deny all access to tables and allow it only
through views that do not expose confidential rows or columns.
Understanding
Informix
Networking
Chapter Overview 3
12
What Is a Network? 4
Database Management System Configurations 4
A Single-User Configuration 4
Advantages and Disadvantages of a Single-User
System 6
A Local Multiuser Configuration 6
Advantages and Disadvantages of Local Multiuser
Systems 7
A Remote Configuration 8
Advantages and Disadvantages of Remote
Network Connections 8
Single-Machine Configuration Using Network
Communication 9
Advantages and Disadvantages of Local
Loopback 10
Distributed Databases 10
Advantages and Disadvantages of Distributed
Databases 11
Distributed Databases Using Multiple Vendor
Servers 11
Connecting to Data on a UNIX Network 12
Example of Client / Server Connections 13
Environment Variables 14
Connection Information 15
SQL Connection Statements 16
Accessing Tables 16
Using Synonyms with Table Names 17
Synonym Chains 18
Protecting Your Data in a Networked Environment 19
Data Protection with INFORMIX-SE 19
Data Protection with INFORMIX-OnLine Dynamic Server 19
Data Replication 19
Archives 20
Data Integrity for Distributed Data 20
Two-Phase Commit 20
Summary 21
What Is a Network?
A computer network is a group of computers, workstations, and other devices
connected together over some kind of communications system to share
resources and data. A network site is simply the location of one of the com-
puters on the network. Sometimes the network sites are widely separated,
but they may also be in the same room or building. Two network sites can
even coexist on the same machine.
To make a practical computer network work, you must master a multitude of
technical details regarding hardware and software. There are far too many of
these details, and they change too fast to cover them in this book. This chap-
ter gives a conceptual discussion of some of the issues that you will encounter
when you use a computer network. For more information, refer to the man-
ual that accompanies the Informix client/server product that you use and/or
to a textbook on computer networks.
A Single-User Configuration
Figure 12-1 shows a diagram of a simple database management system on a
single computer. The organization in Figure 12-1 is one you would typically
find on a personal computer running the DOS operating system. It is unusual
to have a single-user situation on a UNIX system, but you certainly can. One
example of a single-user UNIX system would be a desktop workstation in a
development environment.
personal computer
Connection
INFORMIX-
SE
application
user
databases
The components of the system in Figure 12-1 are found in the following list:
• An application program
Any program that issues a query can be the application. It could, for
example, be a program written in INFORMIX-4GL, a C language program
with embedded SQL, or compiled screen forms and reports.
• A connection
On a simple system such as this one, the communication component is
frequently so well integrated with the system that it is usually omitted
from diagrams and not discussed. However, it does exist.
• A database server
The database server receives queries from the application, searches the
database, and returns information to the application. The database server
manages or administers the databases that it controls.
Because Figure 12-1 illustrates a personal computer, the database server
must be INFORMIX-SE. The database server in this diagram is a local
server because it resides on the same host computer as the client
application.
UNIX computer
application
user databases
Connection
application
database
server
user
The components of the systems in Figure 12-2 are similar to the components
in Figure 12-1, as described in the following list:
• Application programs
Two or more applications use the same database server to access informa-
tion in the databases. You might have two users at individual terminals,
as shown, or you might have multiple windows on a single workstation.
• A connection
On a local UNIX system, the following types of connection are possible:
o Inter-process communication (IPC)
o Network connection
IPC is a UNIX feature that transfers information very quickly between the
application and the database server. It is available only when the applica-
tion and the database server reside on the same computer. INFORMIX-SE
databases use a type of IPC connection called unnamed pipes and
INFORMIX-OnLine Dynamic Server use an IPC connection technique
called shared memory.
• A database server, either INFORMIX-OnLine Dynamic Server or
INFORMIX-SE
• Databases
A Remote Configuration
Figure 12-3 shows a remote configuration, where the application resides on
one computer, and the database server and its associated databases reside on
another computer on the network. In contrast, the database servers in Figure
12-1 and Figure 12-2 are local database servers.
host 1 host 2
application
user
network
connection
database
network
server
application connection databases
user
computer
application
user
network database
connection
server
databases
Distributed Databases
Although a network lets you separate the application from the data, the
application still is limited to the contents of a single database. With most
database servers, you only can query or modify tables in the current
database.
A distributed database has information on multiple databases organized so that
it appears as a single database to the user. The data can be maintained by a
variety of database servers and located on computers supported by different
operating systems and communication networks.
transaction
manager
INFORMIX
interface OnLine/XA
user
vendor a’s
DBMS/XA
interface
This section summarizes how connections are made for Version 6.0 clients
and servers. Detailed instructions for setting up local and network connec-
tions for both Version 6.0 products and earlier products are given in the
INFORMIX-OnLine Dynamic Server Administrator’s Guide and the
INFORMIX-SE Administrator’s Guide.
host 1 host 2
4
6.0 6.0 6.0 client Y
OnLine A OnLine B
1 2 sqlexecd
3-1 3-1
6.0
6.0 client X SE
3
Environment Variables
The Informix administrator must make sure that each user sets the correct
environment variables. The following list shows the most important
environment variables used by INFORMIX-OnLine Dynamic Server and
INFORMIX-SE:
• PATH
• INFORMIXDIR
• INFORMIXSERVER
• TERM
• DBPATH
The INFORMIXDIR environment variable must be set to the full pathname of
the directory where the Informix files reside. The PATH environment variable
must include the full pathname of the directory where the executables for
INFORMIX-SE and/or INFORMIX-OnLine Dynamic Server reside. These two
environment variables are required. After the Informix administrator has
specified them, you usually do not change them.
The INFORMIXSERVER environment variable is the name of the default
database server. It is also a required variable. You may choose to change
INFORMIXSERVER when you change applications.
The DBPATH environment variable is also used to specify directory names for
reports, forms, and command files used by both INFORMIX-OnLine
Dynamic Server and INFORMIX-SE.
Connection Information
When the INFORMIX-OnLine Dynamic Server or INFORMIX-SE
administrator installs and configures a database server, he or she must
cooperate with the UNIX system administrator to specify the information
that allows a client application to locate a database server. The application
specifies a database server and the Informix connectivity tools make the
connection. The connection is transparent; the client does not need to know
where the database server resides.
The connection information is specified in the $INFORMIXDIR/etc/sqlhosts
file and two UNIX systems files, /etc/hosts and /etc/services. The three files,
working together, specify the location of the database server and the type of
connection (protocol) for the database server. (See Figure 12-7.) On each com-
puter, every database server that might be accessed by an application must
have an entry in the $INFORMIXDIR/etc/sqlhosts file and corresponding
entries in the /etc/hosts and /etc/services files. These files are described in
detail in the INFORMIX-OnLine Dynamic Server Administrator’s Guide and
INFORMIX-SE Administrator’s Guide.
/etc/hosts
$INFORMIXDIR/etc/sqlhosts address of serverA
serverA
serverB
serverC /etc/services
protocol for serverA
CONNECT TO databasename@servername
Accessing Tables
The database that is opened by a CONNECT, DATABASE or CREATE
DATABASE statement is the current database. If you are using
INFORMIX-OnLine Dynamic Server, you can query tables that are not in the
current database. To refer to a table in a database other than the current data-
base, include the database name as part of the table name, as illustrated in the
following SELECT statement:
The database is salesdb. The table in salesdb is named contacts. You can use
the same notation in a join. When you must specify the database name explic-
itly, the long table names can become cumbersome unless you use aliases to
shorten them. This is shown in the following example:
In the example, two tables are being joined. The joined rows are stored in a
temporary table in the current database. The tables are located in two data-
base servers; central and boston. Informix allows you to over-qualify (to give
more information than is required) table names, so it is possible, in this
example, that the current database is masterdb or sales.
The CREATE SYNONYM statement stores the synonym name in the system
catalog table syssyntable in the current database. The synonym is available
to any query made within that database.
A short synonym makes it easier to write queries, but synonyms can play
another role. They allow you to move a table to a different database, or even
to a different computer, while leaving your queries the same.
Suppose you have several queries that refer to the tables customer and
orders. The queries are embedded in programs, forms, and reports. The
tables are part of database stores6, which is kept on database server avignon.
Now the decision is made that the same programs, forms, and reports are to
be made available to users of a different computer on the network (database
server nantes). Those users have a database that contains a table named
orders containing the orders at their location, but they need access to the
table customer at avignon.
To those users, the customer table is external. Does this mean you must pre-
pare special versions of the programs and reports, versions in which the
customer table is qualified with a database server name? A better solution is
to create a synonym in the users’ database, as shown in the following
example:
DATABASE stores6@nantes;
CREATE SYNONYM customer FOR stores6@avignon:customer
When the stored queries are executed in your database, the name customer
refers to the actual table. When they are executed in the other database, the
name is translated through the synonym into a reference to the external table.
Synonym Chains
To continue the preceding example, suppose that a new computer is added
to your network. Its name is db_crunch. The customer table and other tables
are moved to it to reduce the load on avignon. You can reproduce the table
on the new database server easily enough, but how can you redirect all
accesses to it? One way is to install a synonym to replace the old table, as
shown in the following example:
Data Replication
In a general sense, data replication means that a given piece of data has several
distinct representations on several distinct servers. OnLine does data replica-
tion by using two networked computers. Each computer has an OnLine
database server and databases that have identical characteristics. One data-
base server is the primary and the other is the secondary. Data is always writ-
ten to the primary server and then transferred to the secondary server.
Applications can read data from either database server. Thus the secondary
site can provide a dual purpose: It provides data protection and it provides
improved performance for users at the secondary site who need to read, but
not write, data.
If the primary server (call it serverA) fails for any reason, the secondary
server (call it serverB) can become an independent server. Users who would
normally use the primary (serverA) can be switched to serverB. Service to all
the users can continue with a minimum of disruption while the original
primary server (serverA) is being repaired.
Data replication provides good data protection and continuity of service, but
it is expensive: Memory must be provided for two complete copies of the
data, shipping the data to a remote site affects performance, and manage-
ment requires the attention of the OnLine administrators on both sites.
Archives
OnLine provides specialized tools for making archives. Archives can be
prepared locally or on a networked computer. Archives should be stored in a
location that is physically removed from the database server, so it may be
convenient to build the archives on a networked computer located at a
different physical site.
Two-Phase Commit
Two-phase commit is a protocol that coordinates work performed at multiple
database servers on behalf of a single transaction. Unlike the data-replication
and archiving tools discussed earlier in this section, two-phase commit does
not make two copies of the data. It protects the validity of one transaction,
Phase 1
The current database server asks each participating database server if it can
commit its local transactions. Each database server responds “Yes” or “No.”
Phase 2
If all the database servers respond affirmatively, the current database server
tells each one to commit its transactions and then the global transaction is
complete. If any database server responds negatively or does not respond, all
database servers are instructed to abort the local transactions.
Summary
A network allows a client application to run in one machine, while the
database server operates in another computer to which the data is physically
attached. This provides distributed processing and the possibility of distrib-
uted database access. Many possible combinations exist of network software,
operating systems, and database servers, and each has subtleties that must be
mastered.
Optimizing Your
Queries
Chapter Overview 3
Optimizing Techniques 4
Verifying the Problem 4
Considering the Total System 5
Understanding the Application 5
Measuring the Application 6
Manual Timing 6
13
Time from Operating System Commands 6
Time from the Programming Language 6
Finding the Guilty Functions 7
Keeping an Open Mind 7
The Query Optimizer 8
How the Optimizer Works 8
How the Optimizer Joins Tables 8
Obtaining Input 9
Assessing Filters 10
Selecting Table-Access Paths 11
Selecting the Query Plan 11
Reading the Plan 12
Time Costs of a Query 14
Activities in Memory 14
Disk-Access Management 14
Page Buffers 16
The Cost of Reading a Row 16
The Cost of Sequential Access 17
The Cost of Nonsequential Access 18
The Cost of Rowid Access 18
The Cost of Indexed Access 18
The Cost of Small Tables 19
The Cost of NLS Functionality 19
The Cost of Network Access 20
The Importance of Table Order 22
A Join Without Filters 22
A Join with Column Filters 23
Using Indexes 26
The Sort-Merge Join Technique 27
Making Queries Faster 27
Preparing a Test Environment 28
Studying the Data Model 28
Studying the Query Plan 29
Examining the Indexes 29
Replacing Autoindexes with Indexes 29
Creating Data Distributions on Filtered Columns 29
Using Composite Indexes 31
Using oncheck on Suspect Indexes 31
Dropping and Rebuilding Indexes After Updates 31
Refining the Column Filters 31
Avoiding Correlated Subqueries 32
Avoiding Difficult Regular Expressions 32
Avoiding Noninitial Substrings 33
Rethinking the Query 33
Rewriting Joins Through Views 33
Avoiding or Simplifying Sorts 33
Eliminating Sequential Access to Large Tables 34
Using Unions to Avoid Sequential Access 35
Reviewing the Optimization Level 36
Using a Temporary Table to Speed Queries 36
Using a Temporary Table to Avoid Multiple Sorts 36
Substituting Sorting for Nonsequential Access 37
Summary 41
Optimizing Techniques
Before you begin optimizing your SQL statements, begin considering them as
part of a larger system that includes the following components:
• One or more programs
The saved queries, compiled screen forms and reports, and programs in
one or more languages in which SQL statements are embedded
• One or more stored procedures
The compiled procedures, comprising SQL and SPL statements, which are
stored in an executable form in the database
• One or more computers
The machines that store the programs and the databases
• One or more maintainers
The people responsible for maintaining the programs
• One or more users
The people whose work the system is supposed to amplify or simplify
• One or more organizations
The groups that own the computers and choose what work is to be done
You may work in a large corporation where each of these components is
separate, or you may be the proprietor, maintainer, and sole user of a desktop
workstation. In every case, it is important to recognize two points about the
system as a whole. First, the goal of the system is to serve its users. Any effort
you spend optimizing programs is wasted unless the result helps the users in
some way. Second, SQL statements are only a small part of the system:
Effective improvements can be found in many parts of a system.
The following paragraphs outline a general procedure for analyzing any
computer-performance problem. Follow the procedure to help avoid over-
looking possible solutions, including the nontechnical ones that sometimes
provide the best answer to performance problems.
Manual Timing
You can obtain repeatable measurements with a hand-operated stopwatch.
With practice, most people can obtain timings that are repeatable within two-
tenths of a second. Manual timing is useful if you are measuring only a few
events that are at least several seconds long. (Very short events should be
measured over several cycles of averaging to reduce the error in
measurement.)
INFORMIX-4GL, you can use the CURRENT function to obtain the current
time as a DATETIME value. A 4GL program can perform automated timing
with code similar to that shown in the following example:
The optimizer forms all possible join pairs between the tables and then
removes redundant join pairs. It keeps the least-expensive join triples as
shown in the following example.
Obtaining Input
The optimizer can be successful only if its estimates are accurate. (They need
not be accurate in absolute terms, but they must be relatively accurate so that
better plans produce lower estimates than worse plans.) However, the opti-
mizer has only limited information. To make its work take a small fraction of
the execution time, it has to make do with the information in the system cat-
alog tables and other summary information. No time exists, for example, for
the optimizer to perform a SELECT COUNT(*) operation to obtain an accurate
count of the rows in a table.
The information available to the optimizer comes from the system catalog
tables. (See Chapter 2 of the Informix Guide to SQL: Reference for information
on system catalog tables.) In all Informix database servers, this information
includes
• The number of rows in a table (as of the most recent UPDATE STATISTICS
command)
• Whether a column is constrained to be unique
• The indexes that exist on a table, including the columns they encompass,
whether they are ascending or descending, and whether they are
clustered
• Data distribution information about filtered columns
The system catalog tables maintained by INFORMIX-OnLine Dynamic
Server supply the following additional input:
• The number of disk pages occupied by row data
• The depth of the index B+ tree structure (a measure of the amount of work
needed to perform an index lookup)
• The number of disk pages occupied by index entries
• The number of unique entries in an index (divided by the number of
rows, this suggests how many rows might match to a given key)
• Second-largest and second-smallest key values in an indexed column
Only the second-largest and second-smallest key values are noted because
the extreme values might be special out-of-range signals. The database server
assumes that key values are distributed smoothly between the second largest
and second smallest. Only the initial four bytes of these keys are stored. In
addition, if the index columns have distributions, the distributions, rather
than the key value, can be used to estimate the number of rows that match a
filter.
Assessing Filters
The optimizer first examines the expressions in the WHERE clause by looking
for filters. The optimizer estimates the selectivity of each filter it finds. The
selectivity is a number between 0 and 1 that indicates the fraction of rows the
optimizer thinks the filter can pass. A very selective filter that passes very few
rows is assigned a selectivity near 0; a filter that passes most rows is assigned
a selectivity near 1. For details on this process, see “Filter Selectivity
Assignments” on page 13-30.
The optimizer also notes other information about the query, such as what
filter columns are indexed and whether an index is sufficient. If only the val-
ues in an index are required (INFORMIX-OnLine Dynamic Server), then no
table read can be required (it is faster to read the index pages without the data
pages).
In addition, the optimizer notes whether an index can be used to evaluate a
filter. For this purpose, an indexed column is a column that has an index, or
one that is named first in a composite index. Consider the following cases:
• When an indexed column is compared to a literal, a host variable, or an
uncorrelated subquery, the database server can look up matching values
in the index instead of reading the rows.
• When an indexed column is compared to a column in another table (a join
expression), the database server can use the index to find matching
values, provided that the query plan calls for reading rows from the other
table first. The following join expression is an example:
The optimizer adds any final work to the completed join plans. For example,
if the query contains an ORDER BY or GROUP BY clause, and a plan does not
produce rows in ordered sequence, the optimizer adds to the plan an estimate
of the cost of sorting the output. Sorting is discussed in “Time Cost of a Sort”
on page 13-15.
Finally, the optimizer selects a plan that appears to promise the least amount
of work, and passes it to the main part of the database server to be executed.
QUERY:
------
SELECT C.customer_num, O.order_num, SUM (I.total_price)
FROM customer C, orders O, items I
WHERE C.customer_num = O.customer_num
AND O.order_num = I.order_num
GROUP BY C.customer_num, O.order_num;
Figure 13-1 Typical output produced by the optimizer with SET EXPLAIN ON
The optimizer also reveals its estimate of the number of rows that the query
produces. In Figure 13-1, the optimizer incorrectly estimates 1. In this exam-
ple, the estimate is incorrect because the optimizer has no way to estimate the
number of groups the GROUP BY clause produces.
In the body of the explanation, the optimizer lists the order in which tables
are accessed and the method, or access path, by which it reads each table. The
following breakdown clarifies the plan:
1. The orders table is read first. Because no filter exists on the orders table,
all of its rows must be read, that is, reading the table in physical order is
the “least costly” approach.
2. For each row of orders, a search is made for matching rows in the
customer table. The search uses the index on customer_num.
The notation Key-Only means that because only the c.customer_num
column is used in the join and output, only the index is read; no row is
read from the table.
3. For each row of orders that has a matching customer_num, a search is
made in the items table using the index on order_num.
It is not always obvious why the optimizer makes its choices. By comparing
the plans produced by several variations in the query, you can usually
deduce some of its logic.
Activities in Memory
The database server can process only data in memory. It must read a row into
memory before it can test it with a filter expression. It must read rows from
both tables before it can test a join condition. The database server prepares an
output row in memory by assembling the selected columns from other rows
in memory.
Most of these activities execute very quickly. Depending on the computer, the
database server can perform hundreds or even thousands of comparisons
each second. As a result, the time spent on in-memory work is usually a small
part of the whole execution time.
Two in-memory activities can take a significant amount of time. One is sort-
ing, as described in “Time Cost of a Sort” on page 13-15. The other activity is
processing comparisons using LIKE and MATCHES, when they begin with
“wild card” characters.
Disk-Access Management
It takes much longer to read a row from disk than to examine a row in
memory. The main goal of the optimizer is to reduce the amount of data that
must be read from disk, but it can eliminate only the most obvious
inefficiencies.
Disk Pages
The database server deals with disk storage in units called pages. A page is a
block of fixed size. The same size is used for all databases managed by one
database server. Indexes are stored in page-size units.
Page Buffers
The database server has a set of memory spaces in which it keeps copies of
the disk pages it read most recently. It does this in case these pages are needed
again. If they are, the database server does not have to read them from disk.
As with the size of a disk page, the number of these page buffers depends on
the database server and the host operating system.
If a table is very large, so that the number of index leaf pages is much larger
than the buffer space, almost every search causes a leaf page to be read in
addition to the page containing the row. The number of pages read is approx-
imately r * (index - height - 1), where r is the number of rows to be looked up.
Although it is costly, this kind of access is still a bargain, because the alterna-
tive is to perform each look up by reading the entire orders table, with disk
costs proportional to r 2 .
The other way the database server uses an index is to read it sequentially. It
does this to fetch the rows of a table in a specific order other than the physical
order. For this kind of access, the database server reads the leaf pages in
sequence, treating them as a list of rows in key sequence. Because the index
pages are read only once, the total of disk operations is proportional to r+i; i
is the number of leaf pages in the index.
...
... ...
leaf page leaf page
... ...
The size of one entry is the width of the indexed columns in bytes, plus 4. If
you know that and the page size, you can estimate the number of entries per
page. This estimate is approximate because first, some data compression is
used in storing keys and second, not all pages are full.
The number of levels depends on the number of rows to be indexed and the
number of entries per page. Suppose a page holds 100 keys. Then a table of
100 rows has a single index page, the root page. A table with between 101
and 10,000 rows has a two-level index consisting of a root page and from 2
to 100 leaf pages. A table with as many as 1,000,000 rows has only a 3-level
index (so the preceding index must belong to a table of considerable size).
attached disk. The output rows are returned over the network to the
application.
• Using the distributed data capability of INFORMIX-OnLine Dynamic
Server, a database server in one machine can read and update rows from
tables in databases located on other machines.
The data sent over a network consists of command messages and buffer-
sized blocks of row data. Although many differences of detail exist between
the two contexts, they can be treated identically under a simple model in
which one machine, the sender, sends a request to another, the responder,
which responds with a block of data from a table.
Whenever data is exchanged over a network, delays are inevitable in the
following situations:
• If the network is busy, the sender must wait its turn to transmit. Such
delays are typically less than a millisecond. But in a heavily loaded net-
work, they can increase exponentially to tenths of seconds and more.
• The responder may be handling requests from more than one sender, so
when the request arrives, it may be queued for a time that can range from
milliseconds to seconds.
• When the responder acts on the request, it incurs the time costs of disk
access and in-memory operations as described in the preceding topics.
• Transmission of the response is again subject to network delays.
The important point about network access is its extreme variability. In the
best case, when neither the network nor the responder is busy, transmission
and queueing delays are insignificant and the responder sends a row almost
as quickly as a local database server could do it. Furthermore, when the
sender asks for a second row, the page is likely still to be in the responder
page buffers.
Unfortunately, as network load increases, all these factors tend to worsen at
the same rate. Transmission delays rise in both directions. The queue at the
responder gets longer. And the odds of a page remaining in the responder
buffer become worse. Thus, network access costs can change quite suddenly
from very low to extremely high.
The optimizer that INFORMIX-OnLine Dynamic Server uses assumes that
access to a row over the network takes longer than access to a row in a local
database. This estimate includes the cost of retrieving the row from disk and
transmitting it across the network. The optimizer has no way to account for
varying network loads, so it is too pessimistic at times and too optimistic at
others.
For the moment, imagine that indexes were never invented. Without indexes,
the database server has no choice but to perform this operation using a sim-
ple nested loop. One of two practical query plans is displayed in Figure 13-2,
which is expressed in a programming pseudocode. A query plan states the
order in which the database server examines tables and the methods by
which it accesses the tables.
The expression O.paid_date IS NULL filters out some rows, reducing the
number of rows that are used from the orders table. As before, two query
plans are possible. The plan that starts by reading from orders is displayed in
pseudocode in Figure 13-3.
Let pdnull represent for the number of rows in orders that pass the filter. It is
the number that the following query returns:
Assume that just one customer exists for every order, as there should be. Then
we can say that the plan in Figure 13-3 reads the following rows:
• All rows of the orders table once
• All rows of the customer table, pdnull times
• All rows of the items table, pdnull times
Because the filter is not applied in the first step, shown in Figure 13-4, this
plan reads the following rows:
• All rows of the customer table once
• All rows of the orders table, once for every row of customer
• All rows of the items table, pdnull times
The query plans in Figure 13-3 and Figure 13-4 produce the same output,
although in different sequences. They differ in that one reads a table pdnull
times and the other reads a table SELECT COUNT(*) FROM customer
times. The choice the optimizer makes between them could make a difference
of thousands of disk accesses in a real application.
Using Indexes
The preceding examples do not use indexes or constraints, which is
unrealistic. Almost all tables have one or more indexes or constraints, and
their presence makes a difference in the query plan. Figure 13-5 shows the
outline of a query plan for the previous query as it might be constructed
using indexes. (Also see “The Structure of an Index” on page 13-20.)
The keys in an index are sorted so that when the first matching key is found,
any other rows with identical keys can be read without further searching.
This query plan reads only the following rows:
• All rows of the customer table once
• All rows of the orders table once
• Those rows of the items table that match to pdnull rows from orders
This is a huge reduction in effort compared with the plans without indexes.
(An inverse plan, reading orders first and looking up rows in customer by its
index, is equally effective.)
However, any plan that uses an index must read index data from disk as well
as read row data. It is difficult to predict the number of index pages that are
read, because some number of recently used index pages are retained in
memory and are found there when they are needed. (See “Disk-Access Man-
agement” on page 13-14.)
The physical order of a table also affects the cost of index use. The physical
order of the customer table is customer-number order if a clustered index is
on that column. It is approximately that order if customer numbers are
SERIAL values generated by the database server.
Selectivities are more accurate with distributions than through current index
information due to finer granularity statistics. However, if data distributions
are not used, filter selectivities are used as shown in the following chart.
An index cannot be used with such a filter so the table in this example must
be accessed sequentially.
If a difficult test for a regular expression is essential, avoid combining it with
a join. If necessary, process the single table, applying the test for a regular
expression to select the desired rows. Save the result in a temporary table,
and join that table to the others.
Regular-expression tests with wildcards in the middle or at the end of the
operand do not prevent the use of an index when one exists.
However, you should avoid or simplify repeated sorts of large tables. The
optimizer avoids a sort step whenever it can produce the output in its proper
order automatically by using an index. The following factors prevent the
optimizer from using an index:
• One or more of the ordered columns is not included in the index.
• The columns are named in a different sequence in the index and the
ORDER BY or GROUP BY clause.
• The ordered columns are taken from different tables.
Another way to avoid sorts is discussed in “Using a Temporary Table to
Speed Queries” on page 13-36.
If a sort is necessary, look for ways to simplify it. As discussed in “Time Cost
of a Sort” on page 13-15, the sort is quicker if you can sort on fewer or
narrower columns.
The key element is that two (or more) separate sets of rows are retrieved. The
sets are defined by relational expressions that are connected by OR. In the
following example, one set is selected by this test:
The other set is selected by the test shown in the following example:
order_num = 1008
The optimizer uses a sequential access path even though indexes exist on the
customer_num and order_num columns.
You can speed queries of this form by converting them into UNION queries.
Write a separate SELECT statement for each set of rows and connect them
with the UNION keyword. The following example shows a rewritten version
of the preceding example:
UNION
This query reads the entire cust table. For every row with the right postcode,
the database server searches the index on rcvbles.customer_id and performs
a nonsequential disk access for every match. The rows are written to a
temporary file and sorted.
This procedure is acceptable if the query is done only once, but this example
includes a series of queries, each incurring the same amount of work.
Now you can direct queries against the temporary table in this form, as
shown in the following example:
SELECT *
FROM cust_with_balance
WHERE postcode LIKE '98_ _ _'
Each query reads the temporary table sequentially, but the table has fewer
rows than the primary table. No nonsequential disk accesses are performed.
No sort is required because the physical order of the table is the desired order.
The total effort should be considerably less than before.
One possible disadvantage exists: Any changes made to the primary table
after the temporary table has been created are not reflected in the output. This
is not a problem for some applications, but it may be for some.
The second, vendor, contains data about the vendors who provide the parts.
The third, parven, records which parts are available from which vendors and
at what price.
part vendor
part_num part_desc vendor_num vendor_name
pk pk
100,000 spiral spanner 9,100,000 Wrenchers SA
999,999 spotted paint 9,999,999 Spottiswode
parven
part_num vendor_num price
pk, fk pk, fk
100,000 9,100,000 $14.98
999,999 9,999,999 $0.066
The following query is run regularly against these tables to produce a report
of all available prices:
The best query plan for this query (not necessarily the one the optimizer
chooses) is to read the part table sequentially first, then use the value of
part_num to access the matching rows of parven (about 1.5 of them per part),
and then use the value of parven.vendor_num to access vendor through its
index.
DISK PAGES 5,000 10,000 15,000 20,000 25,000 30,000 35,000 40,000 45,000 50,000
vendor
Figure 13-8 Breaking a query into three steps using temporary tables
The first step is to get the data of the parven table in vendor_num order, as
shown in the following example:
This statement reads parven sequentially (50 pages), writes a temporary table
(50 pages), and sorts it. The cost of the sort, assuming one merge level, is
about 200 pages, for a total of 300.
Join this temporary table to vendor and put the result in another temporary
table, ordered by part_num, as shown in the following example:
Summary
Poor performance can come from several sources, not solely the SQL opera-
tions in a program. Before you focus your attention on the code, take the
following steps:
• Examine the application in its context of machines, people, procedures,
and organization.
• Understand exactly what the application does, for whom, and why.
• Look for nontechnical solutions in the surrounding context.
in the Informix Guide to SQL: Syntax. The CREATE PROCEDURE and CREATE
PROCEDURE FROM statements are also described in Chapter 1 of the Informix
Guide to SQL: Syntax.
DOCUMENT 'This procedure takes the last name of a customer as', --brief description
'its only argument. It returns the full name and address of',
'the customer.'
WITH LISTING IN '/acctng/test/listfile' -- compile-time warnings go here
; -- end of the procedure read_address
Figure 14-2 shows how the previous SQL statement looks in an ESQL/C
program.
main()
{
$database play;
$create procedure from 'read_add_source';
}
Figure 14-2 SQL statement that compiles and stores the read_address procedure in an ESQL/C
program
Figure 14-3 shows how to trap for a syntax error when you are creating a
procedure. It also shows how to display a message and character position
where the error occurred.
#include <stdio.h>
$include sqlca;
$include sqlda;
$include datetime;
/* Program to create a procedure from procfile in pwd */
main()
{
long char_num;
$ database play;
$create procedure from 'procfile';
if (sqlca.sqlcode != 0 )
{
printf('\nSqlca.sqlcode = %ld\n', sqlca.sqlcode);
char_num = sqlca.sqlerrd[4];
printf('\nError in creating read_address. Check character position %ld\n',
char_num);
}
.
.
.
Figure 14-3 Checking for failure when creating a procedure using ESQL/C
In Figure 14-3, if the CREATE PROCEDURE FROM statement fails, the program
displays a message in addition to the character position at which the syntax
error occurred.
If you are working on a network, the listing file is created on the machine
where the database resides. If you provide an absolute pathname and file-
name for the file, the file is created where you specify. If you provide a relative
pathname for the listing file, the file is created in your home directory on the
machine where the database resides. (If you do not have a home directory, the
file is created in the root directory.)
After you create the procedure, you can view the file specified in the WITH
LISTING IN clause to see the warnings it contains.
Executing a Procedure
You can execute a procedure in several ways. You can use the SQL statement
EXECUTE PROCEDURE or either the LET or CALL SPL statement. In addition,
you can dynamically execute procedures, as described in the section,
“Executing a Stored Procedure Dynamically” on page 14-11.
The read_address procedure returns the full name and address of a customer.
To run read_address on a customer called “Putnum” using EXECUTE
PROCEDURE, enter the following statement:
#include <stdio.h>
$include sqlca;
$include sqlda;
$include datetime;
/* Program to execute a procedure in the database named 'play' */
main()
{
$ char lname[16], fname[16], address[21];
$ char city[16], state[3], zip[6];
$ connect to play;
$EXECUTE PROCEDURE read_address ('Putnum')
INTO $lname, $fname, $address, $city, $state, $zip;
if (sqlca.sqlcode != 0 )
printf('\nFailure on execute');
}
If you are executing a procedure within another procedure, you can use the
SPL statements CALL or LET to run the procedure. To use the CALL statement
with the read_address procedure, you can use the code shown in Figure 14-5.
Figure 14-5 Calling a procedure inside another procedure with the CALL statement
Figure 14-6 provides an example of using the LET statement to assign values
to procedural variables through a procedure call.
Figure 14-6 Assigning values from a procedure call with a LET statement
Debugging a Procedure
Once you successfully create and run a procedure, you can encounter logical
errors. If logical errors are in the procedure, use the TRACE statement to help
find them. You can trace the values of the following procedural entities:
• Variables
• Procedure arguments
• Return values
• SQL error codes
• ISAM error codes
To generate a listing of traced values, first use the SQL statement SET DEBUG
FILE to name the file that is to contain the traced output. When you create
your procedure, include the TRACE statement in one of its forms.
LET lcount = 1;
END PROCEDURE
Each time you execute the traced procedure, entries are added to the file you
specified using the SET DEBUG FILE statement. To see the debug entries, view
the output file using any text editor.
The following list contains some of the output generated by the procedure in
Figure 14-7. Next to each traced statement is an explanation of its contents.
TRACE ON echoed TRACE ON statement.
TRACE Foreach starts traced expression, in this case, the literal
string Foreach starts.
start select cursor notification that a cursor is opened to
handle a FOREACH loop.
select cursor iteration notification of the start of each iteration
of the select cursor.
expression: (+lcount, 1) the encountered expression,
(lcount+1) evaluates to 2.
let lcount = 2 each LET statement is echoed with the
value.
Re-creating a Procedure
If a procedure exists in a database, you must drop it explicitly using the DROP
PROCEDURE statement before you can create another procedure with the
same name. If you debug your procedure and attempt to use the CREATE
PROCEDURE statement with the same procedure name again, the attempt
fails unless you first drop the existing procedure from the database.
DBA-privileged Owner-privileged
procedure procedure
Can be created by: Any user with the Any user with at least the
DBA privilege Resource privilege
ANSI-compliant:
The procedure owner and any
user with the DBA privilege
Owner-Privileged Procedures
When you execute an owner-privileged procedure, the database server
checks the existence of any referenced objects. In addition, the database
server verifies that you have the necessary privileges on the referenced
objects.
If you execute a procedure that only references objects that you own, no
privilege conflicts occurs. If you do not own the referenced objects and you
execute a procedure that contains, say, SELECT statements, for example, you
need the Select privilege on the appropriate tables to run the procedure
without generating errors.
If the owner has the necessary privileges with the WITH GRANT option, those
privileges are automatically conferred to you when the owner issues a
GRANT EXECUTE statement.
Unqualified objects created in the course of the procedure are owned by the
owner of the procedure, not the user running the procedure. For example, the
following example shows lines in an owner-privileged stored procedure that
create two tables. If this procedure is owned by tony and a user marty runs
the procedure, the first table, gargantuan, is owned by tony. The second table,
tiny, is owned by libby. The table gargantuan is an unqualified name; there-
fore, tony owns the table gargantuan. The table tiny is qualified by the owner
libby, so libby owns the table tiny.
END PROCEDURE
DBA-Privileged Procedures
When you execute a DBA-privileged procedure, you assume the privileges of
a DBA for the duration of the procedure. A DBA-privileged procedure acts as
if the user running the procedure is first granted DBA privilege, then executes
each statement of the procedure manually, and finally has DBA privilege
revoked.
Objects created in the course of running a DBA procedure are owned by the
user running the procedure, unless the data-definition statement in the
procedure explicitly names the owner to be someone else.
Creating and Using Stored Procedures 14-15
Variables and Expressions
Revoking Privileges
The owner of a procedure can revoke Execute privilege from a user. If a user
loses the Execute privilege on a procedure, the Execute privilege also is
revoked from all users who were granted the Execute privilege by that user.
Variables
You can use a variable in a stored procedure in several ways. You can use a
variable in a database query or other SQL statement wherever a constant is
expected. You can use a variable with SPL statements to assign and calculate
values, keep track of the number of rows returned from a query, and execute
a loop as well as handle other tasks.
The value of a variable is held in memory; the variable is not a database
object. Hence, rolling back a transaction does not restore values of procedural
variables.
Format of Variables
A variable follows the rules of an SQL identifier. (See Chapter 1 of the Informix
Guide to SQL: Syntax.) Once you define a variable, you can use it anywhere in
the procedure as appropriate.
If you are using an SQL API, you do not have to set off the variable with a
special symbol (unlike host variables in an SQL API).
Defining Variables
You define variables using the DEFINE statement. If you list a variable in the
argument list of a procedure, the variable is defined implicitly, and you do
not need to define it formally with the DEFINE statement. You must assign a
value, which may be null, to a variable before you can use it.
DEFINE x INT;
DEFINE name CHAR(15);
DEFINE this_day DATETIME YEAR TO DAY ;
If you define a variable for TEXT or BYTE data, the variable does not actually
contain the data; instead, it serves as a pointer to the data. However, you use
this procedural variable as you would use any other procedural variable.
When you define a TEXT or BYTE variable, you must use the word
REFERENCES, which emphasizes that these variables do not contain the data;
they simply reference the data. The following example shows the definition
of a TEXT and a BYTE variable:
The portion of the variable contents that is delimited by the two subscripts is
referred to as a substring.
Scope of Variables
A variable is valid within the statement block in which it is defined. It is valid
within statement blocks nested within that statement block as well, unless it
is masked by a redefinition of a variable with the same name.
In the beginning of the procedure in Figure 14-9, the integer variables x, y,
and z are defined and initialized. The BEGIN and END statements mark a
nested statement block in which the integer variables x and q are defined, as
well as the CHAR variable z. Within the nested block, the redefined variable
x masks the original variable x. After the END statement, which marks the
end of the nested block, the original value of x is accessible again.
Variable/Keyword Ambiguity
If you define a variable as a keyword, ambiguities can occur. The following
rules for identifiers help you avoid ambiguities for variables, procedure
names, and system function names:
• Defined variables take the highest precedence.
• Procedures defined as such in a DEFINE statement take precedence over
SQL functions.
• SQL functions take precedence over procedures that exist but are not
identified as procedures in a DEFINE statement.
In some cases, you must change the name of the variable. For example, you
cannot define a variable with the name count or max, because these are the
names of aggregate functions. Refer to Chapter 1 of the Informix Guide to SQL:
Syntax for a list of the keywords that can be used ambiguously.
BEGIN
DEFINE user CHAR(15); -- disables user function
LET user = 'Miller';
LET name = user; -- assigns 'Miller' to variable name
END
.
.
.
LET name2 = user; -- SQL function again
SPL Expressions
You can use any SQL expression in a stored procedure except for an aggregate
expression. The complete syntax and notes for SQL expressions are described
in Chapter 1 of the Informix Guide to SQL: Syntax.
The following examples contain SQL expressions:
var1
var1 + var2 + 5
read_address('Miller')
read_address(lastname = 'Miller')
get_duedate(acct_num) + 10 UNITS DAY
fname[1,5] || ''|| lname
'(415)' || get_phonenum(cust_name)
LET a = b + a;
LET a, b = c, d;
LET a, b = (SELECT fname, lname FROM customer
WHERE customer_num = 101);
LET a, b = read_name(101);
Use the SELECT statement to assign a value directly from the database to a
variable. The statement in the following example accomplishes the same task
as the third LET statement in the previous example:
CALL read_address('Smith')
RETURNING p_fname, p_lname, p_add, p_city, p_state, p_zip;
Branching
Use an IF statement to form a logic branch in a stored procedure. An IF
statement first evaluates a condition and, if the condition is true, the
statement block contained in the THEN portion of the statement is executed.
If the condition is not true, execution falls through to the next statement,
unless the IF statement includes an ELSE clause or ELIF (else if) clause. Figure
14-10 shows an example of an IF statement.
Looping
Three methods exist of looping in SPL, accomplished with one of the
following statements:
FOR initiates a controlled loop. Termination is guaranteed.
FOREACH allows you to select and manipulate more than one row
from the database. It declares and opens a cursor
implicitly.
WHILE initiates a loop. Termination is not guaranteed.
Four ways exist to leave a loop, which can accomplished with one of the
following statements:
CONTINUE skips the remaining statements in the present, identified
loop and starts the next iteration of that loop.
EXIT exits the present, identified loop. Execution resumes at the
first statement after the loop.
RETURN exits the procedure. If a return value is specified, that
value is returned upon exit.
RAISE EXCEPTION exits the loop if the exception is not trapped (caught) in
the body of the loop.
See Chapter 2 of the Informix Guide to SQL: Syntax for more information
concerning the syntax and use of these statements.
Function Handling
You can call procedures as well as run operating system commands from
within a procedure.
Figure 14-12 Making a system call from a procedure with a SYSTEM statement
Returning Results
A procedure that returns one or more values must contain two lines of code
to accomplish the transfer of information: one line to state the data types that
are going to be returned and one line to return the values explicitly.
LET lcount = 0;
TRACE ON;
CREATE VIEW myview AS SELECT * FROM customer;
TRACE 'Foreach starts';
FOREACH
SELECT fname, lname, address1, city, state, zipcode
INTO p_fname, p_lname, p_add, p_city, p_state, p_zip
FROM customer
WHERE lname = lastname
RETURN p_fname, p_lname, p_add, p_city, p_state, p_zip
WITH RESUME;
LET lcount = lcount +1;
END FOREACH;
FOR i IN (1 TO 5)
BEGIN
RETURN 'a', 'b', 'c', 'd', 'e' WITH RESUME;
END
END FOR;
END PROCEDURE
Figure 14-13 Procedure that returns values from a FOREACH loop and a FOR loop
When you execute this procedure, it returns the name and address for each
person with the specified last name. It also returns a sequence of letters. The
calling procedure or program must be expecting multiple returned values,
and it must use a cursor or a FOREACH statement to handle the multiple
returned values.
Exception Handling
You can trap any exception (or error) returned by the database server to your
procedure, or raised by your procedure, with the ON EXCEPTION statement.
The RAISE EXCEPTION statement enables you to generate an exception within
your procedure.
BEGIN
DEFINE c INT;
ON EXCEPTION IN
(
-206, -- table does not exist
-217 -- column does not exist
) SET err_num
When an error occurs, the SPL interpreter searches for the innermost ON
EXCEPTION declaration that traps the error. Note that the first action after
trapping the error is to reset the error. When execution of the error action
code is complete, and if the ON EXCEPTION declaration that was raised
included the WITH RESUME keywords, execution resumes automatically
with the statement following the statement that generated the error. If the ON
EXCEPTION declaration did not include the WITH RESUME keywords,
execution exits the current block completely.
The pseudocode in Figure 14-15 shows where the exception is valid within
the procedure. That is, if error 201 occurs in any of the indicated blocks, the
action labeled a201 occurs.
END
BEGIN -- begin statement block B
-- do something
-- a201 is NOT valid here
END
END PROCEDURE
Figure 14-15 Pseudocode showing the ON EXCEPTION statement is valid within a procedure
User-Generated Exceptions
You can generate your own error using the RAISE EXCEPTION statement, as
shown in the following pseudocode example. In this example, the ON
EXCEPTION statement uses two variables, esql and eisam, to hold the error
numbers returned by the database server. If an error occurs and the SQL error
number is -206, the action defined in the IF clause is taken. If any other SQL
error is caught, it is passed out of this BEGIN...END block to the block that con-
tains this block.
BEGIN
ON EXCEPTION SET esql, eisam -- trap all errors
IF esql = -206 THEN -- table not found
-- recover somehow
ELSE
RAISE exception esql, eisam ; -- pass the error up
END IF
END EXCEPTION
-- do something
END
BEGIN
IF user = 'pault' THEN
RAISE EXCEPTION -273; -- deny Paul update privilege
END IF
END
BEGIN
ON EXCEPTION IN (1)
END EXCEPTION WITH RESUME -- do nothing significant (cont)
BEGIN
FOR i IN (1 TO 1000)
FOREACH select ..INTO aa FROM t
IF aa < 0 THEN
RAISE EXCEPTION 1 ; -- emergency exit
END IF
END FOREACH
END FOR
RETURN 1;
END
Figure 14-16 Breaking out of nested loop with a RAISE EXCEPTION statement
Summary
Stored procedures provide many opportunities for streamlining your
database process, including enhanced database performance, simplified
applications, and limited or monitored access to data. See the Informix Guide
to SQL: Syntax for syntax diagrams of SPL statements.
UPDATE
trigger event
Notice that this portion of the statement identifies the table on which you
create the trigger. If the trigger event is an insert or delete, only the type of
statement and the table name are required, as shown in the following
example:
Note that if a database object in the trigger definition, such as the stored
procedure upd_items_p1 in this example, does not exist when the database
server processes the CREATE TRIGGER statement, it returns an error.
After the triggering update completes, you can calculate the total again to see
how much it has changed. The following stored procedure, upd_items_p2,
calculates the total of quantity again and stores the result in the local variable
new_qty. Then it compares new_qty to the global variable old_qty to see if
the total quantity for all orders has increased by more than 50 percent. If so
the procedure uses the RAISE EXCEPTION statement to simulate an SQL
error.
If an update raises the total quantity on order for all items by more than 50
percent, the RAISE EXCEPTION statement in upd_items_p2 terminates the
trigger with an error. When a trigger fails in INFORMIX-OnLine Dynamic
Server and the database has logging, the database server rolls back the
changes made by both the triggering statement and the triggered actions. See
CREATE TRIGGER in Chapter 1 of the Informix Guide to SQL: Syntax for more
information on what happens when a trigger fails.
A FOR EACH ROW triggered action executes once for each row in the items
table in which the manu_code column has a value of ‘KAR’.
If the triggering statement does not process any rows, a FOR EACH ROW
triggered action does not execute.
To supply values for the old_qty and new_qty columns in this table, you
must be able to refer to the old and new values of quantity in the items table-
that is, the values before and after the effect of the triggering statement. The
REFERENCING clause enables you to do this.
The REFERENCING clause lets you create two prefixes that you can combine
with a column name, one to reference the old value of the column and one to
reference its new value. These prefixes are called correlation names. You can
create one or both correlation names, depending on your requirements. You
indicate which one you are creating with the keywords OLD and NEW. The
following REFERENCING clause creates the correlation names pre_upd and
post_upd to refer to the old and new values in a row:
The correlation names defined in the REFERENCING clause apply to all rows
affected by the triggering statement.
If you refer to a column name in the triggering table without using a correla-
tion name, the database server makes no special effort to search for the col-
umn in the definition of the triggering table. You must always use a
correlation name with a column name in SQL statements within a FOR EACH
ROW triggered action, unless the statement is valid independent of the trig-
gered action. See CREATE TRIGGER in Chapter 1 of the Informix Guide to SQL:
Syntax.
See CREATE TRIGGER in Chapter 1 of the Informix Guide to SQL: Syntax for
more information on the WHEN condition.
returned by the stored procedure. SPL also lets you define variables, assign
data to them, make comparisons, and use procedural statements to
accomplish complex tasks within a triggered action.
Passing data to a stored procedure allows you to use it in the operations that
the procedure performs.
In this example, SPL enables the trigger to derive data that is not directly
available from the triggering table.
Figure 15-3 shows sample trace output from the items_pct procedure as it
appears in the file /usr/mydir/trig.trace. The output reveals the values of
procedure variables, procedure arguments, return values, and error codes.
See Chapter 14, “Creating and Using Stored Procedures” for more
information on using the TRACE statement to diagnose logic errors in stored
procedures.
If you are using DB-Access, the text of the message for error -745 displays on
the bottom of the screen, as seen in Figure 15-4.
SQL: New Run Modify Use-editor Output Choose Save Info Drop Exit
Modify the current SQL statements using the SQL editor.
If you trigger the erring procedure through an SQL statement in your SQL API,
the database server sets the SQL error status variable to -745 and returns it to
your program. To display the text of the message, follow the procedure that
your Informix application development tool provides for retrieving the text
of an SQL error message.
SQL: New Run Modify Use-editor Output Choose Save Info Drop Exit
Modify the current SQL statements using the SQL editor.
If you invoke the trigger through an SQL statement in an SQL API, the
database server sets sqlcode to -746 and returns the message text in the
sqlerrm field of the SQL Communications Area (SQLCA). See Chapter 5, “Pro-
gramming with SQL” for your SQL API for a description of the SQLCA.
Summary
In introducing triggers, this chapter explains the following topics:
• The purpose of each component of the CREATE TRIGGER statement
• How to create BEFORE and AFTER triggered actions and how to use them
to determine the impact of the triggering statement
• How to create a FOR EACH ROW triggered action and how to use the
REFERENCING clause to refer to the values of columns both before and
after the action of the triggering statement
• The advantages of using stored procedures as triggered actions
• How to trace triggered actions if they are behaving unexpectedly
• How to generate two types of error messages within a triggered action
Index
This index covers the Tutorial, Reference, and Syntax manuals.
Page numbers that end in T can be found in the Tutorial, those that
end in R can be found in the Reference Manual, and those that end
in S can be found in the Syntax manual. Special symbols are listed
in ASCII order at the end of the index.
A
ABS function
syntax in expression 1-444S
use in expression 1-445S
ABSOLUTE keyword
syntax in FETCH 1-194S
use in FETCH 1-196S
Access control. See Privilege.
ACCESS FOR keywords, in INFO statement 1-243S
Accessing tables 12-16T
ACOS function
syntax in expression 1-458S
use in expression 1-460S
Action clause
AFTER 1-117S
definition of 1-116S
FOR EACH ROW 1-116S
subset, syntax 1-121S
syntax 1-116S
Action statements
in triggered action clause 1-122S
list of 1-122S
order of execution 1-122S
Active set
constructing with OPEN 1-264S, 1-265S
definition of 2-29T
of a cursor 5-24T
retrieving data with FETCH 1-194S
ADD CONSTRAINT keywords, syntax use
in ALTER TABLE 1-15S in Condition subquery 1-415S
AFTER in expression 1-463S
action 1-117S in GRANT 1-236S
keyword 1-117S in SELECT 1-313S
Aggregate function with UNION operator 1-344S
ALL keyword, syntax 1-462S ALLOCATE DESCRIPTOR statement
and GROUP BY clause 3-5T syntax 1-9S
AVG function, syntax 1-462S with concatenation operator 1-432S
description of 2-53T Allocating memory with the ALLOCATE
DISTINCT keyword, syntax 1-462S DESCRIPTOR statement 1-9S
in ESQL 1-467S, 5-14T ALTER INDEX statement
in EXISTS subquery 1-414S creating clustered index 1-12S, 10-25T
in expressions 1-314S dropping clustered index 1-13S
in SELECT 1-315S locks table 7-7T
in SPL expressions 14-21T syntax 1-12S
in subquery 3-36T See also Index Name segment.
MAX function, syntax 1-462S ALTER keyword
MIN function, syntax 1-462S syntax
null value signalled 5-12T in GRANT 1-231S
restrictions in modifiable view 11-24T in REVOKE 1-301S
restrictions with GROUP BY 1-334S use
SUM function, syntax 1-462S in GRANT 1-236S
summary 1-465S in REVOKE 1-302S
Algebraic functions Alter privilege 1-236S, 11-8T
ABS function 1-445S
MOD function 1-446S ALTER TABLE statement
POW function 1-446S ADD clause 1-17S
ROOT function 1-446S ADD CONSTRAINT clause 1-30S
ROUND function 1-446S adding a column 1-17S
SQRT function 1-447S adding a column constraint 1-29S
syntax 1-444S and NCHAR column 1-19R
TRUNC function 1-447S and NVARCHAR column 1-19R
cascading deletes 1-22S
Alias changing column data type 1-27S,
for a table in SELECT 1-323S 9-19T
for table name 2-79T changing table lock mode 1-33S
to assign column names in temporary CHECK clause 1-25S
table 3-12T DEFAULT clause 1-18S
use in ORDER BY clause 1-338S DROP clause 1-26S
use with GROUP BY clause 1-334S DROP CONSTRAINT clause 1-32S
with self-join 3-11T dropping a column 1-26S
See also Synonym. dropping a column constraint 1-32S
ALL keyword LOCK MODE clause 1-33S
beginning a subquery 1-330S, 3-33T MODIFY NEXT SIZE clause 2-9R,
DISCONNECT statement 1-169S 1-33S
syntax NEXT SIZE clause 10-8T
in expression 1-462S ON DELETE CASCADE keyword
in GRANT 1-235S 1-21S
in REVOKE 1-301S PAGE keyword 1-33S
in SELECT 1-312S privilege for 1-231S, 11-10T
with UNION operator 1-310S reclustering a table 1-13S
2 Index
REFERENCES clause 1-21S SQL statements allowed 1-14R
ROW keyword 1-33S table privileges 1-85S, 11-7T
rules for primary key constraints using with INFORMIX-SE 1-61S
1-31S with BEGIN WORK 1-36S
rules for unique constraints 1-31S ANY keyword
American National Standards Institute. beginning a subquery 1-330S, 3-34T
See ANSI. in WHENEVER 1-398S
AND keyword use in Condition subquery 1-415S
syntax in Condition segment 1-404S Application
use common features 1-18T
in Condition segment 1-417S description of 1-16T
with BETWEEN keyword 1-327S design of order-entry 4-23T
AND logical operator 1-417S, 2-36T handling errors 5-16T
ANSI 1-15T performance analysis of 13-5T
report generator 1-17T
ANSI compliance screen forms 1-17T
determining 1-10R
table naming 1-296S Archives
with INFORMIX-SE 12-19T
ANSI-compliance
-ansi flag 4-15R, Intro-7S, 1-78S, 1-85S, Archiving
1-137S description of 1-10T, 4-25T
described 1-9R INFORMIX-OnLine Dynamic Server
list of SQL statements 1-7S methods 4-26T
reserved words 1-470S transaction log 4-26T
updating rows 1-385S ARC_DEFAULT environment variable
ANSI-compliant database 4-14R
buffered logging restricted in 9-23T ARC_KEYPAD environment variable
create with START DATABASE 4-14R
1-376S Arithmetic functions. See Algebraic
description of 1-59S, 1-15T functions.
designating 1-10R Arithmetic operator, in expression
effect on 1-431S, 2-46T
cursor behavior 1-13R Array, moving rows into with FETCH
decimal data type 1-13R 1-199S
default isolation level 1-13R
escape characters 1-13R AS keyword
object privileges 1-12R in SELECT 1-312S
owner-naming 1-12R syntax
SQLCODE 1-14R in CREATE VIEW 1-136S
transaction logging 1-12R in GRANT 1-231S
transactions 1-11R use
FOR UPDATE not required in 1-148S, in CREATE VIEW 1-137S
6-16T in GRANT 1-239S
index naming 1-419S, 1-484S, 1-505S with display labels 1-316S
owner-naming 1-12R with table aliases 1-325S
privileges 1-12R ASC keyword
procedure naming 1-495S syntax
reason for creating 1-9R in CREATE INDEX 1-63S
Repeatable Read isolation standard in in SELECT 1-337S
7-13T use
signalled in SQLAWARN 5-12T in CREATE INDEX 1-66S
in SELECT 1-338S
Index 3
Ascending order in SELECT 2-14T syntax in Condition segment 1-405S
ASCII collating order 1-15R, 1-501S use
ASIN function in Condition segment 1-408S
syntax in expression 1-458S in SELECT 1-327S
use in expression 1-460S BETWEEN keyword, used to test for
Asterisk equality in WHERE clause 2-29T
wild card character in SELECT 2-12T BETWEEN operator 2-32T
Asterisk (*) Binary Large Object (BLOB)
arithmetic operator 1-431S choosing location for 10-18T
use in SELECT 1-312S disk storage for 10-4T, 10-6T
At (@) sign, in database name 1-421S effect of isolation on retrieval 1-368S
estimating disk space for 10-17T
ATAN function in a LOAD statement 1-257S
syntax in expression 1-458S in an UNLOAD statement 1-379S
use in expression 1-460S See also BYTE data type.
ATAN2 function See also TEXT data type.
syntax in expression 1-458S blobspace 10-4T, 10-18T
use in expression 1-461S
BLOB. See Binary Large Object.
Attribute
identifying 8-14T Boolean expression
important qualities of 8-15T and logical operator 2-36T
nondecomposable 8-15T in Condition segment 1-404S
Audit trail Bourne shell
applying with RECOVER TABLE how to set environment variables
1-292S 4-5R
dropping with DROP AUDIT 1-171S .profile file 4-4R
manipulating audit trail file 1-293S BUFFERED keyword, syntax in SET LOG
no clustered index 1-64S 1-372S
starting with CREATE AUDIT 1-55S BUFFERED LOG keywords
Automatic type conversion. See Data syntax in CREATE DATABASE 1-57S
type conversion. use in CREATE DATABASE 1-59S
AVG function Buffered logging 1-57S, 9-22T
as aggregate function 2-53T Building your data model 8-3T to 8-33T
syntax in expression 1-462S BYTE data type
use in expression 1-464S choosing location for 10-18T
considerations for UNLOAD
B statement 1-379S
description of 3-5R, 9-19T
Bachman, C.R. 8-17T disk storage for 10-4T
Backslash (\) estimating disk space for 10-17T
as escape character with LIKE 1-410S inserting data 3-5R
as escape character with MATCHES requirements for LOAD statement
1-411S 1-257S
Backup. See Archive. restrictions
BEFORE keyword 1-116S in Boolean expression 3-5R
with GROUP BY 3-5R
BEGIN WORK statement with LIKE or MATCHES 3-5R
locking in a transaction 1-35S with ORDER BY 3-5R
specifies start of a transaction 4-24T restrictions with GROUP BY 3-7T
syntax 1-35S restrictions with LIKE or MATCHES
BETWEEN keyword 2-37T
4 Index
restrictions with relational expression CHAR data type 9-15T
2-29T changing data types 3-23R
selecting a BYTE column 3-5R description of 3-6R
syntax 1-425S in INSERT 1-498S
with stored procedures 2-9S, 2-13S in relational expressions 2-29T
BYTE value, displaying 2-11T replacing with TEXT 10-27T
replacing with VARCHAR 10-26T
subscripting 2-44T
C substrings of 2-27T
C shell syntax 1-425S
how to set environment variables truncation signalled 5-12T
4-5R using as default value 1-19S, 1-89S
.cshrc file 4-4R versus NCHAR data type 1-19R
.login file 4-4R CHARACTER data type. See CHAR data
Calculated expression type.
restrictions with GROUP BY 1-334S Character mapping files 5-5R
See also Expression segment. Character string
CALL keyword, in the WHENEVER as DATE values 3-29R
statement 1-398S, 1-401S as DATETIME values 3-10R, 3-29R
CALL statement as INTERVAL values 3-15R
assigning values with 14-21T processing with NLS 1-15R
executing a procedure 14-9T See also Quoted String segment.
syntax 2-3S Character-position form of FILE and
call_type table in stores6 database, INSERT statements 5-28R
columns in A-5R Check constraint
Candidate key adding with ALTER TABLE 1-25S
defined 8-23T definition of 1-98S, 4-19T
Cardinality 8-9T specifying at column level 1-98S
specifying at table level 1-98S
Cardinality in relationship 8-13T
CHECK keyword
Caret (^) wildcard in Condition segment use in ALTER TABLE 1-25S
1-411S use in CREATE TABLE 1-98S
Cartesian product CHECK TABLE statement, syntax and
basis of any join 2-71T use 1-37S
description of 2-69T
Checking contents of environment
Cascading deletes configuration file 5-4R
defined 1-22S, 1-97S, 4-21T
locking associated with 1-24S, 1-98S, Checking for corrupted tables 1-37S
4-21T chkenv utility
logging 1-24S, 1-98S, 4-21T description of 5-4R
restriction 1-24S, 1-98S, 4-22T error message for 5-4R
syntax 1-21S, 1-94S Chunk
Cascading triggers description of 10-4T
and triggering table 1-127S, 1-131S mirrored 10-5T
description of 1-130S Client/server environment 1-133S
maximum number of 1-130S CLOSE DATABASE statement
scope of correlation names 1-125S effect on database locks 7-7T
triggered actions 1-118S prerequisites to close 1-41S
Catalog. See System catalog. syntax 1-41S
Chaining synonyms 12-18T CLOSE statement
Index 5
closing in relational model 1-12T, 8-20T
a select cursor 1-38S in stores6 database A-2R to A-6R
closing an insert cursor 1-39S inserting into 1-246S
cursors affected by transaction end label on 3-48T
1-40S modifying with ALTER TABLE 1-27S
syntax 1-38S naming conventions 1-87S, 1-102S,
with concatenation operator 1-432S 1-294S
CLUSTER keyword naming, allowable characters 1-469S
syntax naming, in ALTER TABLE 1-17S
in ALTER INDEX 1-12S naming, in CREATE TABLE 1-87S
in CREATE INDEX 1-63S number allowed when defining
use constraint 1-86S
in ALTER INDEX 1-12S putting a constraint on 1-86S
in CREATE INDEX 1-64S referenced and referencing 1-22S,
Clustered index 1-94S
creating with CREATE INDEX 1-64S renaming 1-294S
description of 10-25T specifying check constraint for 1-98S
with ALTER INDEX 1-12S specifying with CREATE TABLE
with audit trails 1-64S 1-87S
virtual 1-137S
COBOL 5-6T See also Constraint.
Codd, E. F. 1-11T, 8-4T, 8-32T See also Data Type segment.
Code set Column expression
for crtcmap text file 5-6R in SELECT 1-314S
mapping non-standard to standard syntax 1-433S
5-5R See also Expression segment.
mapping with crtcmap utility 5-5R Column filter. See Filter expression.
Collation Column name
COLLCHAR environment variable allowable characters 1-469S
4-45R in UPDATE clause 1-114S
LC_COLLATE environment variable naming in ALTER TABLE 1-17S
4-50R using functions as names 1-472S
simultaneous, and performance 1-20R using keywords as names 1-473S
with NLS activated 1-15R when qualified 1-124S
Collation order and NLS 2-25T Column number 2-24T
COLLCHAR environment variable effect on triggers 1-115S
1-16R, 4-45R Column value
Colon (:) in triggered action 1-125S
as delimiter in DATETIME 3-9R qualified vs. unqualified 1-126S
as delimiter in INTERVAL 3-15R when unqualified 1-125S
Color, setting INFORMIXTERM for Column-level privilege 1-236S, 11-10T
4-38R COLUMNS FOR keywords, in INFO
Column statement 1-242S
changing data type 3-23R Command file, dbload 5-23R
creating with NLS 1-19R
defined 2-5T Command script, creating database
defining 8-20T 9-26T
defining as foreign key 1-93S Commit, two-phase 12-20T
defining as primary key 1-93S COMMIT WORK statement
description of 1-12T closes cursors 7-18T
displaying information for 1-242S releases locks 7-8T, 7-18T
6 Index
sets SQLCODE 6-5T kinds of locks 7-6T
syntax 1-43S lock duration 7-8T
Committed Read isolation level 1-367S, lock scope 7-6T
7-10T maximizing 10-32T, 10-35T
COMMITTED READ keywords, syntax Repeatable Read isolation 1-367S,
in SET ISOLATION 1-366S 7-12T
SERIAL values 9-7T
Comparison condition table lock 7-7T
description of 2-29T
syntax and use 1-405S Condition segment
See also Boolean expression. ALL, ANY, SOME subquery 1-415S
boolean expressions 1-405S
Compiler comparison condition 1-405S
setting environment variable for C description of 1-404S
4-31R join conditions 1-331S
setting environment variable for null values 1-405S
COBOL 4-32R, 4-33R relational operators in 1-407S
specifying storage mode for COBOL subquery in SELECT 1-413S
4-33R syntax 1-404S
Complex use of functions in 1-405S
relationship 8-28T wildcards in searches 1-410S
Complex condition. See Condition with BETWEEN keyword 1-408S
segment. with ESCAPE keyword 1-411S
Complex query with EXISTS keyword 1-414S
example of 1-364S with IN keyword 1-408S
Composite column list, multiple-column with IS keyword 1-409S
restrictions 1-30S, 1-31S with MATCHES keyword 1-409S
with NOT keyword 1-410S
Composite index
column limit 1-65S Configuring a database server 12-15T
creating with CREATE INDEX 1-63S CONNECT keyword
definition of 1-65S in GRANT 1-232S
order of columns 13-31T in REVOKE 1-303S
use 13-31T Connect privilege 1-232S, 1-303S, 11-6T
Composite key 8-23T CONNECT statement
Compound assignment 2-28S and INFORMIXSERVER
Compound query 3-43T environment variable 4-37R,
1-46S
Computer network 12-4T connection context 1-45S
Concatenation operator (||) 1-432S connection identifiers 1-45S
Concurrency database environment 1-49S
Committed Read isolation 1-367S, DEFAULT option 1-46S
7-10T implicit connections 1-46S
Cursor Stability isolation 1-367S, opening a database 12-16T
7-11T syntax 1-44S
database lock 7-6T use 1-44S
deadlock 7-14T USER clause 1-52S
defining with SET ISOLATION WITH CONCURRENT
1-366S TRANSACTION option 1-47S
description of 4-27T, 7-3T CONNECT TO statement
Dirty Read isolation 1-367S, 7-10T with concatenation operator 1-432S
effect on performance 7-3T Connecting to data 12-12T
isolation level 7-9T
Index 7
Connection exiting a loop 14-23T
context 1-45S syntax 2-6S
dormant 1-169S Conventions
identifiers 1-45S example code Intro-8R, Intro-10S, 5T
setting the INFORMIXCONRETRY for naming tables 1-84S
environment variable 4-34R syntax Intro-5S
setting the INFORMIXCONTIME typographical Intro-5R, Intro-5S, 5T
environment variable 4-35R Converting data types 3-23R
Connectivity in relationship 8-8T, 8-11T, Coordinated deletes 6-6T
8-17T
Correlated subquery
Constant expression definition of 1-413S, 3-32T
in SELECT 1-314S restriction with cascading deletes
inserting with PUT 1-286S 4-22T
restrictions with GROUP BY 1-334S
syntax 1-436S Correlation name
See also Expression segment. and stored procedures 1-125S
See also Literal Number. in COUNT DISTINCT clause 1-125S
in DELETE REFERENCING clause
Constraint 1-119S
adding with ALTER TABLE 1-29S, in GROUP BY clause 1-125S
1-86S in INSERT REFERENCING clause
cardinality 8-9T 1-118S
checking 1-131S in SET clause 1-125S
defining domains 9-3T in stored procedure 1-128S
definition of 1-85S in UPDATE REFERENCING clause
dropping with ALTER TABLE 1-32S, 1-120S
1-86S new 1-120S
enforcing 1-86S old 1-120S
modifying a column that has rules for 1-124S
constraints 1-27S scope of 1-125S
number of columns allowed 1-86S, table of values 1-126S
1-92S using 1-124S
optimizer uses 13-9T when to use 1-125S
privileges needed to create 1-31S
rules for unique constraints 1-30S COS function
setting checking mode 1-349S syntax in expression 1-458S
specifying at table level 1-92S use in expression 1-459S
with DROP INDEX 1-174S COUNT DISTINCT clause 1-125S
See also Primary key constraint. COUNT field
See also Referential constraint. getting contents with GET
See also Unique constraint. DESCRIPTOR 1-210S
CONSTRAINT keyword setting value for WHERE clause
in ALTER TABLE 1-29S 1-354S
in CREATE TABLE 1-91S use in GET DESCRIPTOR 1-212S
Contention COUNT function
for bottleneck tables 10-35T and GROUP BY 3-6T
for disk access arms 10-7T as aggregate function 2-53T
reducing 10-32T, 10-35T count rows to delete 4-5T
CONTINUE keyword, in the use in a subquery 4-6T
WHENEVER statement 1-398S, use in expression 1-463S, 1-465S
1-402S with DISTINCT 2-54T
CONTINUE statement
8 Index
COUNT keyword, use in SET synonym for a table 1-80S
DESCRIPTOR 1-355S synonym for a view 1-80S
CREATE AUDIT statement syntax 1-80S
need for archive 1-55S use of dbschema 5-34R
starts audit trail 1-55S with CREATE SCHEMA 1-77S
syntax 1-55S CREATE TABLE
CREATE DATABASE statement use of dbschema 5-34R
and dbspace 10-5T CREATE TABLE statement
ANSI compliance 1-59S and COLLCHAR environment
in command script 9-26T variable 4-46R
logging with OnLine 1-59S and NCHAR column 1-19R
sets shared lock 7-6T and NVARCHAR column 1-19R
SQLAWARN after 5-12T cascading deletes 1-97S
syntax 1-57S CHECK clause 1-98S
using with creating temporary table 1-100S
CREATE SCHEMA 1-77S DEFAULT clause 1-88S
INFORMIX-SE 1-60S, 9-23T defining constraints
OnLine 9-21T at column level 1-91S
PREPARE 1-58S at table level 1-92S
CREATE INDEX statement description of 9-24T
composite indexes 1-65S EXTENT SIZE clause 10-8T
implicit table locks 1-63S in command script 9-26T
locks table 7-7T IN dbspace clause 1-105S
syntax 1-62S locating BLOB column 10-18T
using LOCK MODE clause 1-108S
with CREATE SCHEMA 1-77S naming conventions 1-84S
using with NEXT SIZE clause 10-8T
ASC keyword 1-66S ON DELETE CASCADE keyword
CLUSTER keyword 1-64S 1-94S
DESC keyword 1-66S REFERENCES clause 1-94S
UNIQUE keyword 1-64S rules for primary keys 1-94S
See also Index Name segment. rules for referential constraints 1-94S
CREATE PROCEDURE FROM rules for unique constraints 1-94S
statement sets initial SERIAL value 9-8T
in embedded languages 14-5T setting columns NOT NULL 1-20S,
syntax and use 1-76S 1-90S
specifying extent size 1-107S
CREATE PROCEDURE statement specifying table columns 1-87S
inside a CREATE PROCEDURE storing database tables 1-105S
FROM 14-5T syntax 1-84S
syntax 1-68S with BLOB data types 1-91S
use of dbschema 5-34R with CREATE SCHEMA 1-77S
using 14-5T
CREATE TRIGGER statement
CREATE SCHEMA statement in ESQL/C 1-111S
defining a trigger 1-111S in ESQL/COBOL 1-111S
syntax 1-77S privilege to use 1-111S
with CREATE sequences 1-78S purpose 1-110S
with GRANT 1-78S syntax 1-110S
CREATE SYNONYM statement triggered action clause 1-121S
ANSI-compliant naming 1-80S use 1-111S
chaining synonyms 1-83S CREATE VIEW statement
Index 9
column data types 1-137S associating with prepared statements
privileges 1-137S 1-154S
restrictions on 11-22T characteristics 1-149S
syntax 1-136S closing 1-38S, 7-18T
use of dbschema 5-34R closing with ROLLBACK WORK
using 11-20T 1-307S
virtual column 1-137S declaring 1-145S, 5-20T
WITH CHECK OPTION 1-138S definition of types 1-148S
with CREATE SCHEMA 1-77S for insert 6-8T
with SELECT * notation 1-136S for update 6-15T, 7-9T
Creating hold 7-18T
a database from ASCII files 5-14R manipulation statements 1-6S
a dbload command file 5-23R opening 1-264S, 1-265S, 5-20T, 5-24T
crtcmap utility retrieving values with FETCH 1-194S,
creating mapping files 5-5R 5-21T
description of 5-5R scroll 1-149S, 5-23T
error messages for 5-7R sequential 1-149S, 5-23T, 5-25T
formats for mapping files 5-6R statement, as trigger event 1-112S
using with transactions 1-155S
Currency, representing with NLS 1-15R with
Current database DELETE 1-159S
specifying with DATABASE 1-140S INTO keyword in SELECT 1-319S
CURRENT function prepared statements 1-148S, 5-32T
4GL example 13-6T WITH HOLD 7-18T, 10-34T
comparing column values 2-56T See also CLOSE statement.
syntax See also Hold cursor.
in Condition segment 1-405S See also Insert cursor.
in expression 1-436S See also OPEN statement.
in INSERT 1-250S See also Scroll cursor.
use See also Select cursor.
in ALTER TABLE 1-18S See also Sequential cursor.
in CREATE TABLE 1-88S See also Update cursor.
in expression 1-440S Cursor Stability isolation level 1-367S,
in INSERT 1-252S 7-11T
in WHERE condition 1-441S CURSOR STABILITY keywords, syntax
input for DAY function 1-441S in SET ISOLATION 1-366S
CURRENT keyword Cursory procedure 2-21S
DISCONNECT statement 1-168S
syntax in FETCH 1-194S customer table in stores6 database,
use in FETCH 1-196S columns in A-2R
CURRENT OF keywords cust_calls table in stores6 database,
syntax columns in A-5R
in DELETE 1-159S Cyclic query 4-22T
in UPDATE 1-383S
use
in DELETE 1-161S
D
in UPDATE 1-390S Daemon 12-14T
Cursor Data
activating with OPEN 1-263S connecting to 12-12T
active set of 5-24T containing foreign characters 1-19R
affected by transaction end 1-40S inserting with the LOAD statement
1-255S
10 Index
integrity 12-20T floating-point 3-12R, 9-9T
Data access statements 1-6S in SPL variables 14-17T
Data definition statements 1-5S, 5-34T INT 3-13R
INTEGER 3-13R, 9-7T
Data distributions INTERVAL 3-13R, 9-14T
confidence 1-397S MONEY 3-16R, 9-10T
creating on filtered columns 13-9T, NCHAR 3-17R
13-29T NCHAR, mapping to CHAR 4-46R
on temporary tables 1-397S NUMERIC 3-18R
RESOLUTION 1-396S, 1-397S numeric 9-7T
use with optimizer 13-9T NVARCHAR 3-18R
DATA field REAL 3-19R, 9-9T
setting with SET DESCRIPTOR 1-357S requirements for referential
Data integrity 4-22T to 4-25T, 12-20T constraints 1-22S, 1-96S
statements 1-6S segment 1-424S
Data manipulation statements 1-6S SERIAL 3-19R, 9-7T
Data model SMALLFLOAT 3-20R, 9-9T
attribute 8-14T SMALLINT 3-20R
building 8-3T to 8-33T specifying with CREATE VIEW
defining relationships 8-8T 1-137S
denormalizing 10-26T to 10-32T summary table 3-4R
description of 1-3T, 8-3T syntax 1-425S
entity-relationship 8-4T TEXT 3-21R, 9-17T
many-to-many relationship 8-11T VARCHAR 3-22R, 9-15T
one-to-many relationship 8-11T See also Data Type segment.
one-to-one relationship 8-11T Data types
See also Relational model. creating NCHAR columns 1-19R
telephone-directory example 8-6T creating NVARCHAR columns 1-19R
Data protection OnLine specific 1-4R
with OnLine 12-19T Database
Data replication 12-19T ANSI-compliant 1-15T
application 1-16T
Data type archiving 1-10T
automatic conversions 5-15T closing with CLOSE DATABASE
BYTE 3-5R, 9-19T 1-41S
changing with ALTER TABLE 1-28S concurrent use 1-8T
CHAR 3-6R, 9-15T creating ANSI-compliant 1-376S
CHARACTER 3-7R creating in NLS mode 1-20R
character data 9-15T creating with CREATE DATABASE
CHAR, mapping to NCHAR 4-46R 1-57S
choosing 9-19T data types 3-4R
chronological 9-12T default isolation levels 1-368S
considerations for INSERT 1-251S, defined 1-3T, 1-11T
1-498S dropping 1-172S
conversion 3-23R, 4-8T implicit connection 1-168S
DATE 3-7R, 9-12T lock 1-142S
DATETIME 3-7R, 9-12T management of 1-9T
DEC 3-10R map of
DECIMAL 3-10R, 9-10T stores6 A-6R
DOUBLE PRECISION 3-12R system catalog tables 2-33R
fixed-point 9-10T mission-critical 1-10T
FLOAT 3-12R naming conventions 1-422S
Index 11
naming unique to engine 9-21T for database outside DBPATH 1-141S
naming with variable 1-423S locking 7-6T
NLS 1-16T specifying current database 1-140S
NLS versus non-NLS 1-20R SQLAWARN after 1-141S, 5-12T
NLS, accessing 1-20R syntax 1-140S
opening in exclusive mode 1-142S using with program variables 1-141S
optimizing queries 1-394S See also Database Name segment.
populating new tables 9-27T Database-level privilege
relation to dbspace 10-5T description of 1-232S, 4-15T
relational, defined 1-11T granting 1-232S
remote 1-422S passing grant ability 1-237S
restoring 1-308S revoking 1-303S
server 1-8T, 1-16T See also Privilege.
server, definition of 1-16T DATE data type
stopping logging on 1-376S converting to DATETIME 3-25R
stores6 Intro-9R, Intro-12S, 7T description of 3-7R, 9-12T
stores6 description of A-1R functions in 1-454S, 2-56T
table names 12-16T in ORDER BY sequence 2-14T
See also Database Name segment. range of operations 3-25R
Database Administrator (DBA) 1-233S, representing DATE values 3-29R
11-7T syntax 1-425S
Database application. See Application. using with DATETIME and
Database lock 7-6T INTERVAL values 3-28R
Database management system 12-4T DATE function
Database Name segment as time function 2-56T
database outside DBPATH 1-423S syntax in expression 1-454S
for remote database 1-422S use in expression 1-455S, 2-61T
naming conventions 1-421S DATE value
naming with variable 1-423S setting DBDATE environment
syntax 1-421S variable 4-16R
using quotes, slashes 1-423S specifying European format with
Database server DBDATE 4-17R
choosing OnLine or SE 1-3R DATETIME data type
configuration 12-15T 4GL example 13-6T
definition of 1-16T adding or subtracting INTERVAL
effect of server type on values 3-27R
available data types 1-4R as quoted string 1-498S
isolation level 1-6R character string values 3-10R
locking 1-5R converting to DATE 3-25R
rolling back transactions 1-4R description of 9-12T
SQL statements supported 1-7R displaying format 2-61T, 9-16T
system catalog tables 1-7R field qualifiers 3-8R, 1-428S
transaction logging 1-5R functions on 2-56T
local 12-5T in
NLS versus non-NLS 1-20R expression 1-441S
remote 12-8T INSERT 1-498S
specifying default for connection ORDER BY sequence 2-14T
4-36R relational expressions 2-29T
DATABASE statement multiplying values 3-26R
determining database type 1-140S precision and size 3-8R, 9-13T
exclusive mode 1-142S, 7-6T range of expressions 3-26R
12 Index
range of operations with DATE and destination options 5-10R
INTERVAL 3-25R Interrupt key 5-9R
representing DATETIME values specifying field delimiter with
3-29R DBDELIMITER 4-18R
syntax 1-425S, 1-488S unloading a database 5-8R
using the DBTIME environment using with NLS 5-12R
variable 4-27R dbimport utility
with EXTEND function 3-26R, 3-28R create options 5-16R
See also Literal DATETIME. creating a database 5-14R
DATETIME Field Qualifier segment description of 5-13R
1-428S input file location options 5-15R
DATETIME formats, using the DBTIME Interrupt key 5-14R
environment variable 4-27R using with NLS 5-13R, 5-18R
Date, representing with NLS 1-15R DBINFO function
DAY function syntax in expression 1-448S
as time function 2-57T use in expression 1-448S
syntax in expression 1-454S DBLANG environment variable 4-19R
use dbload utility
as time function 2-56T creating a command file 5-23R
in expression 1-455S description of 5-19R
DAY keyword INSERT statement, compared to SQL
syntax INSERT statement 5-30R
in DATETIME data type 1-428S Interrupt key 5-21R
in INTERVAL data type 1-485S loading data from a command file
use 5-20R
as DATETIME field qualifier 3-8R, loading data into a table 9-28T, 10-12T
1-488S options
as INTERVAL field qualifier 3-14R, bad-row limits 5-23R
1-491S batch size 5-22R
DBA keyword command-file syntax check 5-21R
in GRANT 1-233S load start point 5-22R
in REVOKE 1-303S specifying field delimiter with
DBDELIMITER 4-18R
DB-Access writing a command file in
creating database with 5-34T, 9-26T character-position form 5-31R
UNLOAD statement 9-28T writing a command file in delimiter
DBANSIWARN environment variable form 5-26R
4-15R, 1-78S, 1-85S, 1-137S, 5-10T DBMONEY environment variable 4-20R,
DBAPICODE environment variable 9-12T
1-16R, 4-47R DBMS. See Database management system.
relation to crtcmap utility 5-5R
DBNLS environment variable 1-16R,
DBA-privileged procedure 14-13T 4-48R
DBA. See Database Administrator. DBPATH environment variable 4-21R,
DBDATE environment variable 4-16R, 1-141S, 1-423S, 12-14T
4-8T, 9-13T DBPRINT environment variable 4-24R
DBDELIMITER environment variable DBREMOTECMD environment variable
4-18R, 1-258S 4-25R
DBEDIT environment variable 4-18R Directory, extension,.dbs extension
dbexport utility 1-101S
description of 5-8R .dbs extension Intro-11R, 1-58S, 1-141S
Index 13
dbschema utility as delimiter in INTERVAL 3-15R
create schema for a database 5-34R DECLARE statement
description of 5-33R cursor characteristics 1-149S
options cursor types 1-148S
obtaining privilege schema 5-36R cursors with prepared statements
obtaining synonym schema 5-35R 1-154S
specifying a table, view, or cursors with transactions 1-155S
procedure 5-37R definition and use
owner conventions 5-35R hold cursor 1-150S
use of 9-26T insert cursor 1-149S, 1-157S
DBSERVERNAME function procedure cursor 1-148S
returning servername 1-438S scroll cursor 1-149S
use select cursor 1-148S
in ALTER TABLE 1-18S sequential cursor 1-149S
in CREATE TABLE 1-88S update cursor 1-148S, 1-152S
in expression 1-438S description of 5-20T
in SELECT 2-63T, 2-65T, 3-20T FOR INSERT clause 6-8T
dbspace FOR UPDATE 6-15T
definition of 10-4T insert cursor 1-148S
division into extents 10-8T insert cursor with hold 1-157S
for temporary tables 10-6T procedure cursor 1-148S
mirrored 10-5T restrictions with SELECT with
multiple access arms in 10-7T ORDER BY 1-340S
on dedicated device 10-6T SCROLL keyword 5-23T
relation to tblspace 10-7T syntax 1-145S
root 10-5T update cursor 1-148S
selecting with CREATE DATABASE updating specified columns 1-153S
1-57S, 9-22T use
DBSPACETEMP environment variable with concatenation operator
4-26R, 1-100S 1-432S
with FOR UPDATE keywords
DBTEMP environment variable 4-27R 1-148S
DBTIME environment variable 4-27R WITH HOLD clause 7-19T
DBUPSPACE environment variable with SELECT 1-321S
4-30R Default assumptions for your
DDL statements, summary 1-5S environment 4-6R
Deadlock detection 1-371S, 7-14T DEFAULT keyword 1-169S
DEALLOCATE DESCRIPTOR statement in the CONNECT statement 1-46S
syntax 1-143S Default value
with concatenation operator 1-432S description of 4-19T
DEC data type. See DECIMAL data type. specifying
DECIMAL data type with ALTER TABLE 1-19S
changing data types 3-23R with CREATE TABLE 1-88S
description of 3-11R Deferred checking 1-349S
fixed-point 9-10T DEFERRED keyword, in the SET
floating-point 3-11R, 9-10T CONSTRAINTS statement 1-349S
signalled in SQLAWARN 5-12T DEFINE statement
syntax 1-425S in stored procedures 14-17T
using as default value 1-19S, 1-89S placement of 2-8S
Decimal point (.) syntax 2-7S
as delimiter in DATETIME 3-9R
14 Index
DELETE keyword copying Intro-10R, Intro-13S, 8T
syntax installation script Intro-9R, Intro-12S,
in GRANT 1-235S 7T
in REVOKE 1-301S map of A-6R
use overview Intro-9R, Intro-12S, 7T
in GRANT 1-236S structure of tables A-2R
in REVOKE 1-302S tables in A-2R to A-6R
Delete privilege 1-235S, 11-8T, 11-28T See also stores6 database.
DELETE REFERENCING clause Denormalizing 10-26T
and FOR EACH ROW section 1-121S Derived data
correlation name 1-119S introduced for performance 10-30T
syntax 1-119S produced by view 11-20T
DELETE statement DESC keyword 1-338S
all rows of table 4-4T syntax
and end of data 6-14T in CREATE INDEX 1-63S
applied to view 11-24T in SELECT 1-337S
as triggering statement 1-112S use
cascading 1-160S in CREATE INDEX 1-66S
coordinated deletes 6-6T in SELECT 1-338S
count of rows 6-4T Descending order in SELECT 2-14T
CURRENT OF clause 1-161S DESCRIBE statement
description of 4-4T and COLLCHAR environment
embedded 5-6T, 6-3T to 6-8T variable 4-46R
in trigger event 1-111S and the USING SQL DESCRIPTOR
in triggered action 1-122S clause 1-164S
number of rows 5-12T describing statement type 1-163S,
preparing 5-30T 5-33T
privilege for 1-235S, 11-6T, 11-8T INTO sqlda pointer clause 1-165S
syntax 1-159S relation to GET DESCRIPTOR 1-213S
time to update indexes 10-20T syntax 1-162S
transactions with 6-5T using with concatenation operator
using subquery 4-6T 1-432S
WHERE clause restricted 4-6T values returned by SELECT 1-163S
with Condition segment 1-404S
with cursor 1-152S, 6-7T Descriptor 1-164S
with select..for update 1-340S Determining ANSI-compliance 1-10R
within a transaction 1-159S Device
Delete, cascading optical 12-6T
See Cascading deletes storage 12-6T
Delimiter Directory, extension, .dbs 1-58S, 1-141S
for DATETIME values 3-9R Dirty Read isolation level 1-367S, 7-10T
for INTERVAL values 3-15R DIRTY READ keywords, syntax in SET
for LOAD input file 1-258S ISOLATION 1-366S
specifying with UNLOAD 1-380S DISCONNECT statement 1-169S
Delimiter form of FILE and INSERT ALL keyword 1-169S
statements 5-24R CURRENT keyword 1-168S
DELIMITER keyword with
in LOAD 1-258S concatenation operator 1-432S
in UNLOAD 1-380S Disk access
Demonstration database chunk 10-4T
Index 15
cost to read a row 13-16T DML statements, summary 1-6S
dbspace 10-4T DOCUMENT keyword, use in stored
latency of 13-17T procedures 14-6T
nonsequential 13-18T Documentation notes Intro-8R,
nonsequential avoided by sorting Intro-11S, 6T
13-37T
performance 13-17T to 13-19T, 13-34T Dominant table 3-21T
reducing contention 10-7T Dormant connection 1-169S
seek time 13-17T DOS operating system 12-4T
sequential 13-17T, 13-34T DOUBLE PRECISION data type. See
sequential forced by query 13-32T, FLOAT data type.
13-33T, 13-35T DROP AUDIT statement 1-171S
using rowid 13-18T
DROP CONSTRAINT keywords
Disk buffer. See Page buffer. syntax in ALTER TABLE 1-15S
Disk contention use in ALTER TABLE 1-32S
effect of 13-17T DROP DATABASE statement 1-172S
multiple arms to reduce 10-7T
DROP INDEX statement
Disk extent 10-8T locks table 7-7T
Disk mirroring 10-5T releasing an index 13-34T
Disk page syntax 1-174S
buffer for 13-16T, 13-18T DROP keyword
size of 10-4T, 13-14T syntax in ALTER TABLE 1-15S
Display label use in ALTER TABLE 1-26S
in ORDER BY clause 2-52T DROP SYNONYM statement 1-177S
syntax in SELECT 1-312S DROP TABLE statement 1-179S
with SELECT 2-49T
DROP TRIGGER statement
Display schema for a database 5-34R syntax 1-181S
DISTINCT keyword use of 1-181S
relation to GROUP BY 3-5T DROP VIEW statement 1-183S
restrictions in modifiable view 11-24T
syntax Duplicate index keys 10-22T
in CREATE INDEX 1-63S Duplicate values
in expression 1-462S finding 3-16T
in SELECT 1-312S in a query 1-313S
use Dynamic management statements 1-6S
in CREATE INDEX 1-64S Dynamic SQL
in SELECT 1-313S, 2-19T cursor use with 5-32T
no effect in subquery 1-414S description of 5-5T, 5-28T
with COUNT function 2-54T freeing prepared statements 5-33T
Distributed deadlock 7-15T
Distributed processing 12-8T E
Distributions
dropping with DROP Editor, specifying with DBEDIT 4-18R
DISTRIBUTIONS clause 1-396S Effective checking 1-349S
privileges required to create 1-396S Ellipses (...), wildcard in Condition
using the HIGH keyword 1-396S segment 1-411S
using the MEDIUM keyword 1-397S Embedded SQL
Division (/) symbol, arithmetic operator defined 5-3T
1-431S languages available 5-4T
See also ESQL.
16 Index
End of data defining in environment
signal in SQLCODE 5-11T, 5-17T configuration file 4-4R
signal only for SELECT 6-14T definition of 4-3R
when opening cursor 5-20T ENVIGNORE 4-30R
Entity ENVIGNORE, and chkenv utility
attributes associated with 8-15T 5-4R
business rules 8-5T how to set in Bourne shell 4-5R
criteria for choosing 8-7T how to set in C shell 4-5R
defined 8-4T how to set in Korn shell 4-5R
important qualities of 8-5T INFORMIX environment variables,
in telephone-directory example 8-7T listing 4-8R
integrity 4-18T INFORMIXC 4-31R
naming 8-4T INFORMIXCOB 4-32R
represented by a table 8-22T INFORMIXCOBDIR 4-32R
Entity occurrence, defined 8-16T INFORMIXCOBSTORE 4-33R
INFORMIXCONRETRY 4-34R
Entity-relationship diagram INFORMIXCONTIME 4-34R
connectivity 8-17T INFORMIXDIR 4-36R, 12-14T
discussed 8-17T INFORMIXSERVER 4-36R, 12-14T
meaning of symbols 8-17T INFORMIXSHMBASE 4-37R
reading 8-18T INFORMIXSTACKSIZE 4-38R
ENVIGNORE environment variable INFORMIXTERM 4-38R
4-30R LANG 4-49R
relation to chkenv utility 5-4R LANG, and crtcmap utility 5-5R
Environment configuration file LC_COLLATE 4-50R
debugging with chkenv 5-4R LC_CTYPE 4-51R
example 4-4R LC_MONETARY 4-52R
where stored 4-5R LC_NUMERIC 4-53R
Environment variable LC_TIME 4-53R
and case sensitivity 4-6R listed 4-8R
ARC_DEFAULT 4-14R listed, by topic 4-9R
ARC_KEYPAD 4-14R listed, for NLS 4-9R
COLLCHAR 4-45R listed, for UNIX 4-9R
DBANSIWARN 4-15R NLS environment variables, listing
DBAPICODE 4-47R 4-9R
DBAPICODE, and crtcmap utility ONCONFIG 4-39R
5-5R overriding a setting 4-4R, 4-30R
DBDATE 4-16R PATH 4-54R, 12-14T
DBDELIMITER 4-18R PSORT_DBTEMP 4-40R
DBEDIT 4-18R PSORT_NPROCS 4-41R
DBLANG 4-19R rules of precedence 4-7R
DBLANG, and crtcmap utility 5-5R setting at the command line 4-4R
DBMONEY 4-20R setting in a shell file 4-4R
DBNLS 4-48R SQLEXEC 4-41R
DBPATH 4-21R, 12-14T SQLRM 4-41R, 4-42R
DBPRINT 4-24R SQLRMDIR 4-43R
DBREMOTECMD 4-25R TERM 4-55R
DBSPACETEMP 4-26R TERMCAP 4-56R, 12-14T
DBTEMP 4-27R TERMINFO 4-56R
DBTIME 4-27R UNIX environment variables, listing
DBUPSPACE 4-30R 4-9R
default assumptions 4-6R where to set 4-4R
Index 17
Equals (=) relational operator 2-30T, indicator variable 5-15T
2-71T INSERT in 6-8T
Equi-join 2-71T NLS errors in SQLERRM field 1-19R
ERROR 1-400S overview 5-3T to 5-37T, 6-3T to 6-17T
preprocessor 5-4T
Error checking scroll cursor 5-23T
continuing after error in stored selecting single rows 5-13T
procedure 2-34S SQL Communications Area 5-8T
error status with ON EXCEPTION SQLCODE 5-11T
2-32S SQLERRD fields 5-12T
exception handling 14-27T static embedding 5-5T
in stored procedures 14-27T UPDATE in 6-14T
simulating errors 14-31T
with SYSTEM 2-40S Estimating
blobpages 10-17T
ERROR keyword, in the WHENEVER maximum number of extents 10-10T
statement 1-398S size of index 10-16T
Error messages table size with fixed-length rows
for NLS 1-21R 10-13T
for trigger failure 15-14T table size with variable-length rows
generating in a trigger 15-14T 10-14T
retrieving trigger text in a program Example database. See Demonstration
15-16T, 15-17T database.
Errors EXCLUSIVE keyword
after DELETE 6-4T syntax
at compile time 14-6T in DATABASE 1-140S
codes for 5-11T in LOCK TABLE 1-260S
dealing with 5-16T use
detected on opening cursor 5-20T in DATABASE 1-142S
during updates 4-22T in LOCK TABLE 1-262S
in stored procedure syntax 14-7T
inserting with a cursor 6-11T Exclusive lock 7-6T
ISAM error code 5-12T EXECUTE IMMEDIATE statement
using to identify NLS database server description of 5-34T
1-19R restricted statement types 1-191S
ESCAPE keyword syntax and usage 1-190S
syntax in Condition segment 1-405S using with concatenation operator
use 1-432S
in Condition segment 1-409S EXECUTE ON keywords
with LIKE keyword 1-328S, 1-411S syntax
with MATCHES keyword 1-329S, in GRANT 1-231S
1-412S in REVOKE 1-300S
with WHERE keyword 1-328S, use
2-43T in GRANT 1-237S
ESQL in REVOKE 1-300S
cursor use 5-19T to 5-28T EXECUTE PROCEDURE statement
DELETE statement in 6-3T 1-192S
delimiting host variables 5-6T assigning values with 14-21T
dynamic embedding 5-5T, 5-28T associating cursor with DECLARE
error handling 5-16T 1-148S
fetching rows from cursor 5-21T in FOREACH 2-20S
host variable 5-6T, 5-8T in triggered action 1-122S
using 14-9T
18 Index
with .dbs Intro-11R
INTO keyword 1-198S .idx Intro-11R
EXECUTE statement .lok 1-370S
and sqlca record 1-186S Extension checking, specifying with
description of 5-31T DBANSIWARN 4-15R
parameterizing a statement 1-186S Extension, to SQL
syntax 1-184S symbol for Intro-7S
USING DESCRIPTOR clause 1-188S with ANSI-compliant database 1-14R
with concatenation operator 1-432S Extent
with USING keyword 1-186S changing size of for system table 2-9R
Existence dependency 8-9T description of 10-8T
EXISTS keyword next extent doubles 10-10T
beginning a subquery 1-330S sizes of 10-8T
in a WHERE clause 3-33T upper limit on 10-10T
use in condition subquery 1-414S, EXTENT SIZE keywords 1-107S, 10-8T
11-27T
EXIT statement
exiting a loop 14-23T
F
syntax 2-14S FETCH statement
EXP function ABSOLUTE keyword 5-23T
syntax in expression 1-451S as affected by CLOSE 1-39S
use in expression 1-451S checking results with SQLCA 1-202S
Explicit temporary table 1-100S description of 5-21T
fetching a row for update 1-201S
Exponential function locking for update 1-201S
EXP function 1-451S relation to GET DESCRIPTOR 1-210S
Exponential function. See EXP function. sequential 5-23T
Expression specifying a value’s memory location
date-oriented 2-56T 1-198S
description of 2-46T syntax 1-194S
display label for 2-49T with
in UPDATE 1-387S concatenation operator 1-432S
ordering by 1-339S INTO keyword 1-319S
Expression segment program arrays 1-199S
aggregate expressions 1-462S scroll cursor 1-196S
column expressions 1-433S sequential cursor 1-195S, 5-25T
combined expressions 1-467S X/Open mode 1-195S
constant expressions 1-436S Field qualifier
expression types 1-431S for DATETIME 3-8R, 1-428S
function expressions 1-443S for INTERVAL 3-13R, 1-485S, 1-491S
in SPL expressions 1-468S File
syntax 1-431S compared to database 1-3T
EXTEND function environment configuration 4-4R
syntax in expression 1-454S environment configuration, checking
use in expression 1-456S with chkenv 5-4R
with DATE, DATETIME and extension
INTERVAL 3-26R, 3-28R, 2-56T, .lok 1-370S
2-61T mapping, and COLLCHAR 4-45R
extension mapping, and crtcmap utility 5-5R
.dat Intro-11R mapping, and DBAPICODE 4-47R
mapping, format for 5-6R
Index 19
permissions in UNIX 11-4T specifying multiple ranges 2-18S
sending output with the OUTPUT syntax 2-16S
statement 1-271S using expression lists 2-18S
shell 4-4R using increments 2-17S
temporary for OnLine 4-26R FOR TABLE keywords, in UPDATE
temporary for SE 4-27R STATISTICS 1-393S
FILE statement FOR UPDATE keywords
character-position form 5-28R conflicts with ORDER BY 6-8T
delimiter form 5-24R not needed in ANSI-compliant
syntax for character-position form database 6-16T
5-29R relation to UPDATE 1-390S
syntax for delimiter form 5-25R specific columns 6-16T
with dbload 5-23R syntax in DECLARE 1-145S
Filter expression use
effect on performance 13-23T, 13-32T, in DECLARE 1-148S, 1-152S,
13-33T 1-155S
evaluated from index 13-10T, 13-31T in SELECT 1-340S
optimizer uses 13-10T, 13-23T with column list 1-153S
selectivity estimates 13-30T FOREACH keyword
finding location of row 1-435S in CONTINUE statement 2-6S
FIRST keyword in EXIT 2-14S
syntax in FETCH 1-194S FOREACH keyword. See also FOR EACH
use in FETCH 1-196S ROW action.
First normal form 8-29T FOREACH statement
Fixed point 9-10T looping in a stored procedure 14-23T
FLOAT data type syntax 2-20S
changing data types 3-23R Foreign characters, using NLS 1-14R
description of 3-12R, 9-9T Foreign key 1-22S, 1-93S, 1-94S, 4-19T
syntax 1-425S See also Referential constraint.
using as default value 1-19S, 1-89S FOREIGN KEY keywords
Floating point 9-9T in ALTER TABLE 1-29S
FLUSH statement in CREATE TABLE 1-92S
count of rows inserted 6-11T Format
syntax 1-204S for crtcmap mapping file 5-6R
with concatenation operator 1-432S specifying for DATE value with
writing rows to buffer 6-10T DBDATE 4-16R
FOR EACH ROW action specifying for DATETIME value with
SELECT statement in 1-117S DBTIME 4-27R
triggered action list 1-116S specifying for MONEY value with
FOR EACH ROW action.See also DBMONEY 4-20R
FOREACH keyword. FRACTION keyword
FOR keyword syntax
in CONTINUE 2-6S in DATETIME data type 1-428S
in CREATE AUDIT 1-55S in INTERVAL data type 1-485S
in CREATE SYNONYM 1-80S use
in EXIT 2-14S as DATETIME field qualifier 3-8R,
1-488S
for locating temporary tables 1-100S as INTERVAL field qualifier 3-14R,
FOR statement 1-491S
looping in a stored procedure 14-23T FREE statement
20 Index
effect on cursors 1-269S syntax 1-217S
freeing prepared statements 5-33T Global transaction 12-21T
syntax 1-207S GOTO keyword, in the WHENEVER
with concatenation operator 1-432S statement 1-398S
FROM keyword GRANT statement
alias names 2-79T automated 11-13T
syntax changing grantor 1-238S
in PUT 1-284S creating a privilege chain 1-238S
in REVOKE 1-300S database-level privileges 1-232S,
in SELECT 1-310S 11-5T
use default table privileges 1-237S
in PUT 1-287S in 4GL 11-13T
in SELECT 1-323S in embedded SQL 5-34T to 5-37T
Function passing grant ability 1-237S
aggregate 2-53T privileges on a view 1-239S
algebraic 1-444S syntax 1-231S
date-oriented 2-56T table-level privileges 1-235S, 11-7T
in SELECT statements 2-53T use of dbschema 5-34R
within a stored procedure 14-24T with CREATE SCHEMA 1-77S
Function expression GROUP BY clause 1-125S
DBINFO function 1-448S GROUP BY keywords
description of 1-443S column number with 3-7T
in SELECT 1-314S composite index used for 13-31T
Functional dependency 8-31T description of 3-4T
indexes for 13-10T, 13-34T
G restrictions in modifiable view 11-24T
sorting rows 13-12T
GET DESCRIPTOR statement syntax in SELECT 1-310S
syntax 1-210S use in SELECT 1-334S
the COUNT keyword 1-212S
use with FETCH statement 1-200S
with concatenation operator 1-432S H
X/Open mode 1-213S HAVING keyword
GET DIAGNOSTICS statement description of 3-9T
CLASS_ORIGIN keyword 1-225S syntax in SELECT 1-310S
CONNECTION_NAME keyword use in SELECT 1-336S
1-227S Header, of a procedure 14-25T
exception clause 1-223S HEX function 1-435S
MESSAGE_LENGTH keyword syntax in expression 1-452S
1-225S use in expression 1-452S
MESSAGE_TEXT keyword 1-225S
MORE keyword 1-222S HIGH keyword 1-374S
NUMBER keyword 1-223S Hold cursor
purpose 1-217S definition of 1-149S, 7-18T
RETURNED_SQLSTATE keyword insert cursor with hold 1-157S
1-225S use of 1-150S
ROW_COUNT keyword 1-223S Host machine 12-8T
SERVER_NAME keyword 1-225S Host variable
statement clause 1-222S delimiter for 5-6T
keywords 1-222S description of 5-6T
SUBCLASS_ORIGIN keyword 1-225S dynamic allocation of 5-33T
Index 21
fetching data into 5-21T SET DESCRIPTOR statement 1-357S
in DELETE statement 6-4T with X/Open programs 1-213S
in INSERT 6-8T IMMEDIATE keyword, in the SET
in UPDATE 6-14T CONSTRAINTS statement 1-349S
in WHERE clause 5-14T Implicit connection
INTO keyword sets 5-13T defined 1-46S
null indicator 5-15T with DISCONNECT 1-168S
restrictions in prepared statement
5-29T Implicit temporary table 1-100S
truncation signalled 5-12T IN keyword
using non-English characters in 1-22R locating BLOB column 10-18T
with EXECUTE 5-31T syntax
HOUR keyword in CREATE AUDIT 1-55S
syntax in CREATE DATABASE 1-57S
in DATETIME data type 1-428S in CREATE TABLE 1-105S
in INTERVAL data type 1-485S in LOCK TABLE 1-260S
use use
as DATETIME field qualifier 3-8R, in Condition segment 1-408S
1-488S in Condition subquery 1-414S
as INTERVAL field qualifier 3-14R, in CREATE DATABASE 10-5T
1-491S in CREATE TABLE 10-6T, 10-8T
with WHERE keyword 1-327S
Hyphen (-)
as delimiter in DATETIME 3-9R IN keyword, used to test for equality in
as delimiter in INTERVAL 3-15R WHERE clause 2-29T
IN relational operator 3-33T
Index
I adding for performance 10-21T,
Icon, explanation of Intro-6S 13-34T
IDATA field allowable characters in index name
SET DESCRIPTOR statement 1-357S 1-469S
with X/Open programs 1-213S building with NLS 1-20R
Identifier segment clustered 10-25T
column names 1-476S composite 13-31T
column naming, allowable characters creating with CREATE INDEX 1-62S
1-469S disk space used by 10-16T, 10-20T,
cursor name 1-482S 13-34T
cursor names 1-479S displaying information for 1-242S
database objects that use 1-469S dropping 10-24T
stored procedures 1-479S dropping with DROP INDEX 1-174S
syntax 1-469S duplicate entries 10-16T, 10-22T
table names 1-475S, 1-477S effect of physical order 13-27T
used in column naming 1-88S in GROUP BY 13-10T
using keywords as column names in ORDER BY 13-10T
1-473S locks table 7-7T
variable name 1-481S managing 10-19T
naming conventions 1-419S, 1-469S,
IF statement 1-484S, 1-505S
branching 14-22T optimizer 13-29T
syntax 2-24S optimizer uses 13-9T, 13-10T, 13-26T
syntax and use 2-24S ordering columns in composite
with null values 2-25S 13-31T
ILENGTH field performance effects 13-18T
22 Index
sharing with constraints 1-86S STATUS variable 5-11T
sorting with NLS 1-15R terminates on errors 5-36T, 6-14T
time cost of 10-20T timing operations in 13-6T
updating affects 13-31T using SQLCODE with 5-11T
utility to test or repair 13-31T WHENEVER ERROR statement 5-36T
when not used by optimizer 13-32T, INFORMIXC environment variable
13-33T, 13-35T 4-31R
with temporary tables 1-343S INFORMIXCOB environment variable
INDEX keyword 4-32R
syntax INFORMIXCOBDIR environment
in GRANT 1-235S variable 4-32R
in REVOKE 1-301S
use INFORMIXCOBSTORE environment
in GRANT 1-236S variable 4-33R
in REVOKE 1-302S INFORMIXCOBTYPE environment
Index Name segment variable 4-33R
syntax 1-419S, 1-495S INFORMIXCONRETRY environment
use 1-504S variable 4-34R
Index privilege 1-236S, 11-8T INFORMIXCONTIME environment
INDEXES FOR keywords, in INFO variable 4-34R
statement 1-242S INFORMIXDIR environment variable
Indexes, with dbload utility 5-21R 4-36R, 12-14T
INDICATOR field INFORMIX-OnLine
setting with SET DESCRIPTOR 1-358S disk access by 13-17T
INDICATOR keyword, in SELECT INFORMIX-OnLine Dynamic Server
1-319S, 1-320S, 1-321S, 1-432S allows views on external tables 11-23T
and triggering statement 1-112S
Indicator variable archiving 4-26T
definition of 5-15T characteristics of 1-10T
in EXECUTE 1-186S creating demonstration database
in expression 1-467S Intro-10R, Intro-13S
in SELECT 1-319S, 1-320S, 1-321S, disk page size 13-16T
1-432S disk storage methods 10-3T to 10-12T
using non-English characters in 1-22R is NLS-ready 1-15R
INFO statement optimizer input with 13-9T
displaying privileges and status signalled in SQLAWARN 5-12T
1-242S when tables are locked 7-7T
displaying tables, columns, and INFORMIX-OnLine/Optical 12-6T
indexes 1-241S list of statements 1-7S
syntax 1-241S
INFORMIX-SE
informix characteristics of 1-10T
environment configuration file 4-4R creating database 9-23T
privileges associated with user 1-234S creating demonstration database
Informix extension checking, specifying Intro-10R, Intro-13S
with DBANSIWARN 4-15R is NLS-ready 1-15R
INFORMIX-4GL 12-5T INFORMIXSERVER environment
detecting null value 5-16T variable 4-36R, 1-46S, 12-14T
example of dynamic SQL 11-13T INFORMIXSHMBASE environment
indicator variable not used 5-16T variable 4-37R
program variable 5-5T
INFORMIX-SQL
Index 23
creating database with 5-34T, 9-26T effect of transactions 1-249S
UNLOAD statement 9-27T embedded 6-8T to 6-14T
INFORMIXSTACKSIZE environment filling insert buffer with PUT 1-285S
variable 4-38R in dynamic SQL 1-253S
INFORMIXTERM environment variable in trigger event 1-111S
4-38R in triggered action 1-122S
inserting
informix.rc file 4-4R multiple rows 4-9T
Insert buffer nulls with the VALUES clause
counting inserted rows 1-205S, 1-290S 1-252S
filling with constant values 1-286S rows 4-6T
inserting rows with a cursor 1-248S rows through a view 1-246S
storing rows with PUT 1-285S rows with a cursor 1-248S
triggering flushing 1-289S single rows 4-7T
Insert cursor 1-148S values into SERIAL columns 3-19R
closing 1-39S null values in 4-7T
definition of 1-148S, 6-8T number of rows 5-12T
in INSERT 1-248S privilege for 11-6T, 11-8T
in PUT 1-286S SELECT statement in 4-9T
opening 1-266S SERIAL columns 1-251S
reopening 1-267S specifying values to insert 1-250S
result of CLOSE in SQLCA 1-39S syntax 1-245S
use of 1-149S, 6-11T for character position form 5-29R
with hold 1-157S for delimiter form 5-25R
writing buffered rows with FLUSH time to update indexes 10-20T
1-204S use with insert cursor 1-157S
INSERT INTO keywords VALUES clause 4-7T
in INSERT 1-245S with
in LOAD 1-258S a view 11-25T
INSERT keyword DECLARE 1-145S
syntax SELECT 1-253S
in GRANT 1-235S with dbload 5-23R
in REVOKE 1-301S Inserting rows of constant data 6-11T
use Installation directory, specifying with
in GRANT 1-236S INFORMIXDIR 4-36R
in REVOKE 1-302S INT data type. See INTEGER data type.
Insert privilege 11-8T, 11-28T INTEGER data type
INSERT REFERENCING clause changing data types 3-23R
and FOR EACH ROW section 1-121S description of 3-13R, 9-7T
correlation name 1-118S syntax 1-425S
syntax 1-118S using as default value 1-19S, 1-89S
INSERT STATEMENT Integrity. See Data integrity.
using functions in the VALUES clause Integrity. See Referential integrity.
1-252S Integrity. See Semantic integrity.
INSERT statement Intensity attributes, setting
and end of data 6-14T INFORMIXTERM for 4-38R
character-position form 5-28R
constant data with 6-11T Interrupt key
count of rows inserted 6-11T with dbexport 5-9R
delimiter form 5-24R with dbimport 5-14R
duplicate values in 4-7T with dbload 5-21R
24 Index
Interrupted modifications 4-22T IS NOT keywords, syntax in Condition
INTERVAL data type segment 1-405S
adding or subtracting from 3-30R IS NULL keywords 1-327S
adding or subtracting from ISAM error code 2-31S, 2-36S, 5-12T
DATETIME values 3-27R Isolation level
as quoted string 1-498S Committed Read 1-367S, 7-10T
description of 3-13R, 9-14T Cursor Stability 1-367S, 7-11T
display format 9-16T default in ANSI-compliant database
field delimiters 3-15R 1-13R
field qualifier, syntax 1-485S definitions 1-367S
in expression 1-441S description of 7-9T
in INSERT 1-498S Dirty Read 1-367S, 7-10T
in relational expressions 2-29T in external tables 1-368S
multiplying or dividing values 3-31R Repeatable Read 1-367S, 7-12T
precision and size 9-14T setting 7-9T
range of expressions 3-26R use with FETCH statement 1-201S
range of operations with DATE and
DATETIME 3-25R items table in stores6 database, columns
syntax 1-425S, 1-491S in A-3R
with EXTEND function 3-26R, 3-28R ITYPE field
See also Literal INTERVAL. SET DESCRIPTOR statement 1-357S
INTERVAL Field Qualifier segment setting with SET DESCRIPTOR 1-359S
1-485S with X/Open programs 1-213S
INTO keyword
choice of location 5-22T J
in FETCH statement 5-22T Join
in SELECT 1-318S associative 2-76T
mismatch signalled in SQLAWARN creating 2-71T
5-12T definition of 2-8T
restrictions in INSERT 4-10T dominant table 3-21T
restrictions in prepared statement effect of large join on optimization
5-29T 13-36T
retrieving multiple rows 5-20T equi-join 2-71T
retrieving single rows 5-13T in Condition segment 1-331S
syntax multiple-table join 1-332S, 2-77T
in FETCH 1-194S natural 2-75T
in SELECT 1-310S nested outer 3-28T
use nested simple 3-25T
in FETCH 1-199S outer 3-21T
in SELECT 1-318S outer join 1-333S
INTO TEMP keywords restrictions in modifiable view 11-24T
description of 2-83T self-join 1-333S, 3-11T
restrictions in view 11-22T sort merge 13-27T
syntax in SELECT 1-310S subservient table 3-21T
use two-table join 1-332S
in SELECT 1-341S Join column. See Foreign key.
with UNION operator 1-344S
Join condition. See Condition segment.
IS keyword
in Condition segment 1-409S Journal updates 10-33T
with WHERE keyword 1-327S
Index 25
K LET statement
assigning values 14-21T
Key lock 7-8T executing a procedure 14-9T
Keywords, using in triggered action syntax 2-28S
1-123S LIKE keyword
Key, candidate. See Candidate key. syntax in Condition segment 1-405S
Key, composite 8-23T use in SELECT 1-328S
Key, foreign. See Foreign key. wildcard characters 1-328S
Key, primary 8-22T LIKE keyword, used to test for equality
in WHERE clause 2-29T
Key, primary. See Primary key
constraint. LIKE relational operator 2-37T
Korn shell LIKE test 13-32T
how to set environment variables Literal
4-5R DATETIME
.profile file 4-4R in Condition segment 1-405S
in expression 1-436S, 1-441S
segment 1-487S
L syntax 1-488S
Label 2-49T, 3-48T syntax in INSERT 1-250S
LANG environment variable 1-16R, use in ALTER TABLE 1-18S
4-49R use in CREATE TABLE 1-88S
with IN keyword 1-327S
Language supplement for added NLS DATE, using as a default value 1-19S,
functionality 1-22R 1-89S
LAST keyword INTERVAL
syntax in FETCH 1-194S in Condition segment 1-405S
use in FETCH 1-196S in expression 1-436S, 1-441S
Latency 13-17T segment 1-490S
LC_COLLATE environment variable syntax 1-491S
1-16R, 4-50R syntax in INSERT 1-250S
LC_CTYPE environment variable 1-16R, using as default value 1-19S, 1-89S
4-51R Number
in Condition segment 1-405S
LC_MONETARY environment variable in expression 1-436S, 1-439S
1-17R, 4-52R segment 1-493S
LC_NUMERIC environment variable syntax 1-493S
1-17R, 4-53R syntax in INSERT 1-250S
LC_TIME environment variable 1-17R, with IN keyword 1-409S
4-53R LOAD statement
LENGTH field DELIMITER clause 1-258S
setting with SET DESCRIPTOR 1-357S input formats for data 1-256S
with DATETIME and INTERVAL INSERT INTO clause 1-258S
types 1-358S loading VARCHAR, TEXT, or BYTE
with DECIMAL and MONEY types data types 1-257S
1-358S specifying field delimiter with
LENGTH function DBDELIMITER 4-18R
in expression 1-314S specifying the table to load into 1-258S
on TEXT 2-64T syntax 1-255S
on VARCHAR 2-64T the LOAD FROM file 1-256S
syntax in expression 1-443S, 1-453S Loading data from a command file into a
use in expression 1-453S, 2-63T table 5-20R
26 Index
Local loopback 12-9T update cursors effect on 1-152S
Local server 12-5T update locks 1-385S
LOCK MODE keywords waiting period 1-370S
syntax with
in ALTER TABLE 1-15S DELETE 6-4T
in CREATE TABLE 1-108S FETCH 1-201S
use scroll cursor 1-369S
in ALTER TABLE 1-33S SET ISOLATION 1-366S
in CREATE TABLE 1-108S SET LOCK MODE 1-370S
UNLOCK TABLE 1-381S
LOCK TABLE statement update cursor 7-9T
in databases with transactions 1-261S within transaction 1-35S
in databases without transactions See also Table locking.
1-262S
locking a table explicitly 7-7T LOG IN keywords, syntax in CREATE
syntax 1-260S DATABASE 1-57S
Locking LOG10 function
and concurrency 4-27T syntax in expression 1-452S
and integrity 7-3T use in expression 1-452S
deadlock 7-14T Logarithmic function
description of 7-5T syntax
during LOG10 function 1-451S
delete 1-159S LOGN function 1-451S
inserts 1-249S use
updates 1-152S, 1-385S LOG10 function 1-452S
granularity 7-6T LOGN function 1-452S
in OnLine 1-5R Logging
in SE 1-6R buffered 9-22T
lock duration 7-8T buffered vs. unbuffered 1-372S
lock mode 7-13T cascading deletes 1-24S, 1-98S
not-wait 7-14T changing mode with SET LOG 1-372S
wait 7-13T choosing for OnLine database server
locks released at end of transaction 9-22T
7-18T choosing for SE database server 9-23T
mode 1-5R finding log file location 1-60S
overriding row-level 1-261S renaming log 1-377S
releasing with COMMIT WORK 1-43S setting with CREATE TABLE 1-104S
releasing with ROLLBACK WORK starting with START DATABASE
1-306S 1-60S, 1-376S
scope 1-5R, 7-6T stopping 1-377S
scope of lock 7-6T stopping with START DATABASE
setting lock mode 7-13T 1-376S
shared locks 1-6R unbuffered 9-22T
types of locks with INFORMIX-OnLine 1-59S
database lock 7-6T with INFORMIX-SE 1-60S
exclusive lock 7-6T with triggers 1-134S
key lock 7-8T Logical log
page lock 1-108S, 7-8T definition of 4-25T
promotable lock 7-6T, 7-9T Logical operator
row lock 1-108S, 7-8T AND 2-36T
shared lock 7-6T in Condition segment 1-417S
table lock 7-7T NOT 2-36T
Index 27
OR 2-36T MIN function
LOGN function as aggregate function 2-53T
syntax in expression 1-452S syntax in expression 1-462S
use in expression 1-452S use in expression 1-464S
.lok extension 1-370S Minus (-) sign, arithmetic operator
Loop 1-431S
controlled 2-16S MINUTE keyword
creating and exiting in SPL 14-23T syntax
exiting using RAISE exception 14-32T in DATETIME data type 1-428S
indefinite with WHILE 2-46S in INTERVAL data type 1-485S
Loopback, local 12-9T use
as DATETIME field qualifier 3-8R,
LOW keyword 1-374S 1-488S
as INTERVAL field qualifier 3-14R,
M 1-491S
Machine notes Intro-9R, Intro-11S, 6T Mirror. See Disk mirroring.
Mandatory, entity in relationship 8-9T MOD function
syntax in expression 1-444S
Many-to-many relationship 8-9T, 8-11T, use in expression 1-446S
8-26T
MODE ANSI keywords
Mapping files for non-standard code sets ANSI-compliant database 1-15T
5-5R ANSI-compliant logging 9-23T
MATCHES keyword specifying ANSI-compliance 1-11R
syntax in Condition segment 1-405S specifying transactions 4-24T
use syntax
in Condition segment 1-409S in CREATE DATABASE 1-57S
in SELECT 1-328S in START DATABASE 1-376S
with NLS 2-42T use
used to test for equality in WHERE in CREATE DATABASE 1-60S
clause 2-29T in START DATABASE 1-377S
wildcard characters 1-329S Model. See Data model.
MATCHES relational operator MODIFY keyword
in WHERE clause 2-37T syntax in ALTER TABLE 1-15S
MAX function use in ALTER TABLE 1-27S
as aggregate function 2-53T MODIFY NEXT SIZE keywords
syntax in expression 1-462S syntax in ALTER TABLE 1-15S
use in expression 1-464S use in ALTER TABLE 1-33S
MDY function MONEY data type 9-12T
as time function 2-56T changing data types 3-23R
syntax in expression 1-454S description of 3-16R, 9-10T
Memory display format 9-12T
allocating for a system sqlda structure in INSERT 4-8T
1-9S syntax 1-425S
shared 12-7T using as default value 1-19S, 1-89S
Message files See also DECIMAL data type.
error messages Intro-9R, Intro-11S, 7T MONEY value
setting LANG for NLS 4-49R setting DBMONEY environment
specifying subdirectory for NLS 1-22R variable 4-20R
specifying subdirectory with setting LC_MONETARY
DBLANG 4-19R environment variable 4-52R
28 Index
specifying European format with connection information 12-15T
DBMONEY 4-20R data sent over 13-21T
specifying for NLS 4-53R performance of 13-20T
Money, representing with NLS 1-15R simple model of 13-21T
MONTH function site 12-4T
as time function 2-56T Network environment variable
syntax in expression 1-454S DBPATH 4-21R
use in expression 1-456S SQLRM 4-42R
MONTH keyword SQLRMDIR 4-43R
syntax NEW keyword
in DATETIME data type 1-428S in DELETE REFERENCING clause
in INTERVAL data type 1-485S 1-119S
use in INSERT REFERENCING clause
as DATETIME field qualifier 3-8R, 1-118S
1-488S in UPDATE REFERENCING clause
as INTERVAL field qualifier 3-13R, 1-120S
1-491S NEXT keyword
Multiple triggers syntax in FETCH 1-194S
column numbers in 1-115S use in FETCH 1-196S
example 1-114S NEXT SIZE keywords
order of execution 1-115S specifying size of extents 10-8T
preventing overriding 1-132S use in CREATE TABLE 1-107S
Multiple-table join 2-77T use in GRANT 1-233S
Multi-row query NLS 1-14R
destination of returned values 1-198S activating 2-25T
managing with FETCH 1-195S activating in Informix products 1-16R
and collation order 2-25T
and dbexport utility 5-12R
N and dbimport utility 5-13R
Naming convention and MATCHES keyword 2-42T
column 1-87S, 1-102S, 1-294S and ORDER BY keywords 2-25T,
database 1-422S 2-42T
index 1-419S, 1-484S, 1-505S checking products for functionality
table 1-84S, 1-470S, 1-507S 1-18R
See also Database Name segment. COLLCHAR environment variable
See also Index Name segment. 4-45R
See also Table Name segment. creating character mapping files for
Naming conventions 5-5R
tables 12-16T data types for 1-19R
database server compatibility 1-19R
Native Language Support. See NLS. DBAPICODE environment variable
Natural join 2-75T 4-47R
NCHAR data type DBNLS environment variable 4-48R
description of 3-17R, 9-15T environment variables listed 4-9R
syntax 1-425S error messages for incompatibility
versus CHAR data type 1-19R 1-21R
Nested ordering, in SELECT 1-339S, functionality in Informix products
2-15T 1-22R
Network functionality listed 1-15R
computer 12-4T installation notes for language
supplement 1-22R
Index 29
LANG environment variable 4-49R with LIKE, MATCHES keywords
LC_COLLATE environment variable 1-328S
4-50R NOT logical operator 2-36T
LC_CTYPE environment variable NOT NULL keywords
4-51R syntax
LC_MONETARY environment in ALTER TABLE 1-17S
variable 4-52R in CREATE TABLE 1-88S
LC_NUMERIC environment variable use
4-53R in ALTER TABLE 1-27S
LC_TIME environment variable 4-53R in CREATE TABLE 1-90S, 9-24T
NCHAR data type 3-17R with IS keyword 1-327S
NVARCHAR data type 3-18R
populating with dbimport 5-18R NOT operator
setting environment variables 1-16R, condition 1-405S
4-44R NOT relational operator 2-32T
specifying a language environment NOT WAIT keywords, in SET LOCK
2-25T MODE 1-370S
viewing characteristics of 1-18R NULL keyword, ambiguous as
NLS Database procedure variable 1-480S
description of 1-16T NULL relational operator 2-35T
NLS database NULL value
versus non-NLS database 1-19R testing in BYTE expression 3-5R
Nondecomposable attributes 8-15T testing with TEXT data type 3-21R
Nonsequential access. See Disk access, Null value
nonsequential. checking for in SELECT 1-184S, 1-318S
Normal form 8-29T defined 8-23T
Normalization detecting in ESQL 5-15T
benefits 8-29T in INSERT statement 4-7T
first normal form 8-29T in SPL IF statement 2-25S
of data model 8-29T inserting with the VALUES clause
rules 8-29T 1-252S
rules, summary 8-32T restrictions in primary key 8-22T
second normal form 8-31T returned implicitly by stored
third normal form 8-32T procedure 2-38S
specifying as default value 1-20S
NOT CLUSTER keywords testing for 2-35T
syntax in ALTER INDEX 1-12S updating a column 1-387S
use in ALTER TABLE 1-13S used in Condition with NOT operator
NOT FOUND keywords, in the 1-405S
WHENEVER statement 1-398S, used in the ORDER BY clause 1-339S
1-400S with logical operator 2-36T
NOT IN keywords, use in Condition with SPL WHILE statement 2-46S
subquery 1-414S NUMERIC data type. See DECIMAL data
NOT keyword type.
syntax NVARCHAR data type
in Condition segment 1-404S, description of 3-18R, 9-15T
1-405S syntax 1-425S
with BETWEEN keyword 1-327S versus VARCHAR data type 1-19R
with IN keyword 1-329S
use
in Condition segment 1-410S
30 Index
O constructing the active set 1-264S
opening a procedure cursor 1-265S
OF keyword opening an insert cursor 1-266S
syntax in DECLARE 1-145S opening select or update cursors
use in DECLARE 1-153S 1-264S, 5-20T
OLD keyword reopening a cursor 1-267S
in DELETE REFERENCING clause substituting values for ? parameters
1-119S 1-268S
in INSERT REFERENCING clause syntax 1-263S
1-119S with concatenation operator 1-432S
in UPDATE REFERENCING clause with FREE 1-269S
1-120S Opening a cursor 5-20T, 5-24T
ON DELETE CASCADE keyword Operating system
DELETE trigger event 1-112S DOS 12-4T
ON EXCEPTION statement UNIX 12-4T
placement of 2-32S Optical device 12-6T
scope of control 14-29T Optimization, specifying a high or low
syntax 2-31S level 1-374S
trapping errors 14-27T
user-generated errors 14-30T Optimizer
and GROUP BY 13-10T, 13-12T,
ON keyword 13-27T
syntax and ORDER BY 13-10T, 13-12T,
in CREATE INDEX 1-63S 13-27T
in GRANT 1-231S and SET OPTIMIZATION statement
in REVOKE 1-300S 1-374S, 13-36T
use autoindex path 13-29T
in CREATE INDEX 1-64S composite index use 13-31T
in GRANT 1-237S data distributions 13-29T
ON-Archive utility, using the disk access 13-14T
ARC_DEFAULT environment display query plan 13-12T
variable 4-14R filter selectivity 13-30T
ON-Archive utility, using the index not used by 13-32T, 13-35T
ARC_KEYPAD environment index used by 13-9T, 13-10T
variable 4-15R methods of 13-8T
oncheck utility 10-7T, 10-12T, 13-31T query plan 13-22T
ONCONFIG environment variable 4-39R sort merge join 13-27T
sorting 13-12T
onconfig file, specifying with specifying high or low level of
ONCONFIG 4-40R optimization 13-36T
One-to-many relationship 8-9T, 8-11T system catalog use 13-9T
One-to-one relationship 8-9T, 8-11T when index not used 13-33T
OnLine 5-10T with UPDATE STATISTICS 1-394S
On-line Optimizing
files Intro-8R, Intro-11S, 6T a query 1-360S
help Intro-9R, Intro-11S, 7T a server 1-374S
onload utility 4-27T, 10-11T across a network 1-374S
techniques 13-3T
onstat utility 10-12T
Optional, entity in relationship 8-9T
onunload utility 4-27T, 10-11T
OR keyword
OPEN statement syntax in Condition segment 1-404S
activating a cursor 5-20T
Index 31
use in Condition segment 1-417S P
OR logical operator 2-36T
Page buffer
OR relational operator 2-33T cost of nonsequential access 13-18T
ORDER BY keywords description of 13-16T
and NLS 2-25T effect on performance 13-17T
ascending order 1-338S, 2-14T restrictions with BLOB data 10-19T
DESC keyword 2-15T, 2-25T PAGE keyword
descending order 1-338S use in ALTER TABLE 1-33S
display label with 2-52T use in CREATE TABLE 1-108S
indexes for 13-10T, 13-34T
multiple columns 2-15T Page lock 7-8T
relation to GROUP BY 3-7T Page, definition of 10-4T
restrictions in INSERT 1-253S, 4-10T Parameter
restrictions in view 11-22T BYTE or TEXT in SPL 2-13S
restrictions with FOR UPDATE 6-8T in CALL statement 2-4S
select columns by number 1-339S, to a stored procedure 14-25T
2-24T Parameterizing a statement
sorting rows 2-13T, 13-12T with SQL identifiers 1-279S
syntax in SELECT 1-310S Parent-child relationship 1-21S, 1-94S
use
in SELECT 1-337S Parts explosion 5-26T
with UNION operator 1-344S PATH environment variable 4-54R,
Order of execution, of action statements 12-14T
1-122S Pathname
orders table in stores6 database, columns including in SQLEXEC 4-42R
in A-3R specifying with DBPATH 4-21R
specifying with PATH 4-54R
Outer join
forming 1-324S Percent (%) sign, wildcard in Condition
segment 1-410S
OUTER keyword, with FROM keyword
in SELECT 1-323S PERFORM keyword, in the WHENEVER
statement 1-398S
Output from TRACE command 15-14T
Performance
OUTPUT statement, syntax and use adding indexes 13-34T
1-271S assigning table to dedicated disk
Owner 10-6T
in ALTER TABLE 1-16S bottleneck tables 10-35T
in CREATE SYNONYM 1-80S buffered log 9-22T
in dbschema 5-35R clustered index 10-25T
in Index Name segment 1-419S, depends on concurrency 7-3T
1-484S, 1-495S, 1-505S disk access 13-14T, 13-17T, 13-34T
in RENAME COLUMN 1-294S disk access by rowid 13-18T
in RENAME TABLE 1-296S disk arm motion 10-8T
in Table Name segment 1-469S, 1-507S disk latency 13-17T
in View Name segment 1-510S dropping indexes to speed
of view in CREATE VIEW 1-511S modifications 10-24T
Owner-privileged procedure 14-13T duplicate keys slow modifications
Ownership 11-7T 10-22T
effect of
BLOB location 10-18T
correlated subquery 13-32T
32 Index
filter expression 13-23T, 13-32T, Permission, with SYSTEM 2-40S
13-33T Phantom row 1-367S
index damage 13-31T PIPE keyword, in the OUTPUT
indexes 10-21T to 10-22T, 13-26T statement 1-272S
regular expressions 13-32T
table size 13-19T, 13-34T Pipe symbol. See concatenation operator.
updates 13-31T Pipes, unnamed 12-7T
filter selectivity 13-30T Plus (+) sign, arithmetic operator 1-431S
“hot spots,” finding 13-7T Populating tables 9-27T
improved by specifying optimization POW function
level 13-36T syntax in expression 1-444S
improved with temporary table use in expression 1-446S
13-36T
improving 13-27T Precedence, rules for environment
increasing with stored procedures variables 4-7R
14-4T PRECISION field
index time during modification setting with SET DESCRIPTOR 1-358S
10-20T with GET DESCRIPTOR 1-214S
interleaved dbspaces 10-10T PREPARE statement
journal updates 10-33T description of 5-29T
measurement 13-6T error return in SQLERRD 5-12T
multiple access arms per table 10-7T executing 1-184S
network access 13-20T increasing performance efficiency
nonsequential access 13-18T 1-283S
optimizing 13-3T to 13-42T missing WHERE signalled 5-10T
references to other books 13-3T multiple SQL statements 5-30T
reorganizing a dbspace 10-10T multi-statement text 1-277S, 1-281S
row access 13-16T parameterizing a statement 1-278S
seek time 13-17T parameterizing for SQL identifiers
sequential access 13-17T, 13-34T 1-279S
sorting replaces nonsequential access preparing GRANT 11-13T
13-37T question (?) mark as placeholder
splitting tall tables 10-29T 1-273S
splitting wide tables 10-28T releasing resources with FREE 1-208S
time costs of query 13-14T restrictions with SELECT 1-276S
use of derived data 10-30T statement identifier use 1-274S
use of redundant data 10-31T syntax 1-273S
using CHAR instead of NCHAR valid statement text 1-275S
1-19R with concatenation operator 1-432S
Performance analysis Prepared statement
“80-20 rule” 13-7T describing returned values with
measurement 13-6T DESCRIBE 1-162S
methods 13-27T to 13-41T executing 1-184S
nonsequential access 13-37T to 13-41T prepared object limit 1-274S
optimizing techniques 13-4T valid statement text 1-275S
setting up test environment 13-28T See also PREPARE statement.
timing PREVIOUS keyword
from 4GL program 13-6T syntax in FETCH 1-194S
from command script 13-6T use in FETCH 1-196S
from watch 13-6T Primary key
using query plan 13-29T definition of 8-22T
verifying problem 13-4T
Index 33
restrictions with 8-22T overview 1-8T
Primary key constraint 1-22S Resource 1-233S, 11-7T, 13-34T
composite 8-23T Select 11-8T, 11-10T, 11-27T
data type conversion 1-28S Update 1-236S, 11-8T, 11-10T, 11-28T
defining column as 1-93S when privileges conflict 1-232S
definition of 4-19T with DBA-privileged procedures
dropping 1-32S 14-13T
enforcing 1-86S with owner-privileged procedures
modifying a column with 1-28S 14-13T
referencing 1-22S See also Database-level privilege.
requirements for 1-20S, 1-93S See also Table-level privilege.
rules of use 1-31S, 1-94S PRIVILEGES FOR keywords, in INFO
PRIMARY KEY keywords statement 1-243S
in ALTER TABLE 1-29S PRIVILEGES keyword
in ALTER TABLE statement 1-20S syntax
in CREATE TABLE 1-91S, 1-92S in GRANT 1-235S
Primary site 12-20T in REVOKE 1-301S
Printing, specifying print program with use
DBPRINT 4-24R in GRANT 1-236S
in REVOKE 1-302S
PRIOR keyword
syntax in FETCH 1-194S Procedure cursor
use in FETCH 1-196S opening 1-265S
reopening 1-267S
Privilege
Alter 1-236S, 11-8T procedure cursor 1-148S
and views 11-27T to 11-30T Procedure name
ANSI-compliant databases 1-12R conflict with function name 1-495S
automating grants of 11-13T naming conventions 1-495S
column-level 11-10T Procedure, stored. See Stored procedure.
Connect 1-232S, 11-6T Processing, distributed 12-8T
DBA 1-233S, 11-7T Projection, described 2-7T
default for stored procedures 14-14T
default for table using CREATE Project, description of 1-13T
TABLE 1-85S Promotable lock 1-152S, 7-6T, 7-9T
Delete 1-236S, 11-8T, 11-28T PSORT_DBTEMP environment variable
displaying 4-16T 4-40R
displaying with the INFO statement PSORT_NPROCS environment variable
1-242S 4-41R
encoded in system catalog 2-28R, PUBLIC keyword
2-32R, 11-9T privilege granted to all users 11-6T
Execute 11-12T, 14-14T syntax
for triggered action 1-129S in GRANT 1-231S
granting 11-5T to 11-15T in REVOKE 1-300S
Index 1-236S, 11-8T use
Insert 1-236S, 11-8T, 11-28T in GRANT 1-234S
needed in REVOKE 1-302S
to create a view 1-239S, 11-27T
to drop an index 1-174S PUT statement
to modify data 1-236S, 4-15T constant data with 6-11T
on a synonym 1-80S count of rows inserted 6-11T
on a view 1-137S, 11-28T impact on trigger 1-112S
on stored procedures 14-13T sends returned data to buffer 6-10T
34 Index
source of row values 1-285S with LIKE, MATCHES keywords
syntax 1-284S 1-328S
use in transactions 1-285S See also Quoted String segment.
with concatenation operator 1-432S Quoted String segment
with FLUSH 1-285S DATETIME, INTERVAL values as
strings 1-498S
Q syntax 1-497S
wildcards 1-498S
Qualifier, field with LIKE in a condition 1-498S
for DATETIME 3-8R, 1-428S, 1-488S Quotes, single and double Intro-6S
for INTERVAL 3-13R, 1-485S, 1-491S
Query
cyclic 4-22T R
improving performance of 13-27T to RAISE EXCEPTION statement
13-41T exiting a loop 14-23T
performance of 13-3T to 13-42T syntax 2-36S
piping results to another program REAL data type. See SMALLFLOAT data
1-272S type.
self-referencing 4-22T
sending results to an operating RECOVER TABLE statement
system file 1-271S archiving a database with audit trails
sending results to another program 1-292S
1-272S manipulating audit trail file 1-293S
stated in terms of data model 1-7T syntax 1-292S
time costs of 13-14T Recursion, in a stored procedure 14-24T
Query optimization information Recursive relationship 8-11T, 8-28T
statements 1-6S Redundant data, introduced for
Query optimizer. See Optimizer. performance 10-31T
Query plan Redundant relationship 8-29T
autoindex path 13-29T REFERENCES FOR keywords, in INFO
chosen by optimizer 13-11T statement 1-243S
description of 13-22T REFERENCES keyword
display with SET EXPLAIN 13-12T in ALTER TABLE 1-21S
indexes in 13-26T in CREATE TABLE 1-94S, 1-96S
use in analyzing performance 13-29T syntax
Question (?) mark in GRANT 1-235S
as placeholder in PREPARE 1-273S in REVOKE 1-301S
naming variables in PUT 1-287S use
replacing with USING keyword in GRANT 1-236S
1-268S in REVOKE 1-302S
wildcard in Condition segment 1-411S References privilege
Quoted string definition of 1-236S
in expression 1-436S displaying with the INFO statement
syntax 1-243S
in Condition segment 1-405S REFERENCING clause
in expression 1-462S DELETE REFERENCING clause
in INSERT 1-250S 1-119S
use INSERT REFERENCING clause
in expression 1-438S 1-118S
in INSERT 1-498S UPDATE REFERENCING clause
1-120S
Index 35
using referencing 1-125S, 15-9T cardinality 8-9T, 8-13T
Referential constraint complex 8-28T
and a DELETE trigger 1-112S connectivity 8-8T, 8-11T
data type restrictions 1-96S defining in data model 8-8T
definition of 1-21S, 1-94S, 4-19T entity 8-5T
dropping 1-32S existence dependency 8-9T
enforcing 1-86S mandatory 8-9T
modifying a column with 1-28S many-to-many 8-9T, 8-11T
rules of use 1-94S many-to-many, resolving 8-26T
Referential integrity 4-19T one-to-many 8-9T, 8-11T
defining primary and foreign keys one-to-one 8-9T, 8-11T
8-24T optional 8-9T
recursive 8-28T
Regular expression redundant 8-29T
effect on performance 13-32T using matrix to discover 8-10T
evaluating with NLS 1-15R
RELATIVE keyword
Relational calculus. See also relational syntax in FETCH 1-194S
model. use in FETCH 1-196S
Relational database, defined 1-11T Relay Module
Relational model SQLRM environment variable 4-42R
attribute 8-14T SQLRMDIR environment variable
denormalizing 10-26T 4-43R
description of 1-11T, 8-3T to 8-33T Release notes Intro-9R, Intro-11S, 6T
entity 8-4T
join 2-8T Remote database server 12-8T
many-to-many relationship 8-11T RENAME COLUMN statement
normalizing data 8-29T restrictions 1-294S
one-to-many relationship 8-11T syntax 1-294S
one-to-one relationship 8-11T RENAME TABLE statement
projection 2-6T ANSI-compliant naming 1-296S
resolving relationships 8-26T syntax 1-296S
rules for defining tables, rows, and REPAIR TABLE statement, syntax and
columns 8-20T use 1-299S
selection 2-5T Repeatable Read isolation level
Relational operation 2-5T description of 1-367S, 7-12T
Relational operator emulating during update 1-202S
BETWEEN 2-32T REPEATABLE READ keywords, syntax
equals 2-30T in SET ISOLATION 1-366S
EXISTS 3-33T Replication of data 12-19T
IN 3-33T
in a WHERE clause 2-29T to 2-45T Report generator 1-17T
in Condition segment 1-405S Reserved words 1-470S
LIKE 2-37T Resolution
NOT 2-32T in UPDATE STATISTICS 1-396S,
NULL 2-35T 1-397S
OR 2-33T with data distributions 1-396S
segment 1-500S RESOURCE keyword
with WHERE keyword in SELECT use in GRANT 1-233S
1-326S use in REVOKE 1-303S
Relationship Resource manager 12-11T
attribute 8-15T Resource privilege 1-233S, 11-7T, 13-34T
36 Index
Restricting access, using file system defining 8-20T
11-4T deleting 1-159S, 4-4T
Result of triggering statement 1-123S description of 1-12T
RETURN statement engine response to locked row 1-370S
exiting a loop 14-23T in relational model 1-12T, 8-20T
returning insufficient values 2-38S inserting 4-6T
returning null values 2-38S inserting through a view 1-246S
syntax 2-38S inserting with a cursor 1-248S
multi-row queries with FETCH
REVOKE statement 1-195S
column-specific privileges 1-303S order, guaranteeing independence of
database-level privileges 1-303S 1-117S
granting privileges 11-5T to 11-15T phantom 1-367S
in embedded SQL 5-34T to 5-37T retrieving with FETCH 1-197S
privileges needed 1-301S rowid definition 1-197S
syntax 1-300S size of fixed-length 10-13T
table-level privileges 1-301S updating through a view 1-384S
with a view 11-29T writing buffered rows with FLUSH
ROLLBACK WORK statement 1-204S
cancels a transaction 4-25T ROW keyword
closes cursors 7-18T use in ALTER TABLE 1-33S
releases locks 7-8T, 7-18T use in CREATE TABLE 1-108S
sets SQLCODE 6-5T
syntax 1-306S Row lock 7-8T
use with WHENEVER 1-36S, 1-42S, Rowid
1-307S locating internal row numbers 3-17T
with DROP DATABASE 1-173S use in a column expression 1-435S
with DROP INDEX statement 1-175S use in a join 3-16T
with DROP PROCEDURE statement use in ORDER BY clause 1-338S
1-176S used as column name 1-474S
with DROP SYNONYM statement Rowid function 13-18T
1-177S ROWID keyword 1-435S
with DROP TABLE statement 1-179S Rules for stored procedures 1-128S
with DROP TRIGGER statement
1-181S Run-time program
with DROP VIEW statement 1-183S setting DBANSIWARN 4-15R
setting INFORMIXCOBDIR 4-32R
ROLLFORWARD DATABASE
statement
applies log to restored database 4-26T S
exclusive locking 1-308S SCALE field
syntax 1-308S setting with SET DESCRIPTOR 1-358S
Root dbspace, definition of 10-5T with GET DESCRIPTOR 1-214S
ROOT function Schema. See Data Model.
syntax in expression 1-444S Scroll cursor
use in expression 1-446S active set 5-25T
ROUND function definition of 1-149S, 5-23T
syntax in expression 1-444S use of 1-149S
use in expression 1-446S with FETCH 1-196S
Row with hold, in a transaction 1-369S
cost of reading from disk 13-16T SCROLL keyword
defined 2-5T syntax in DECLARE 1-145S
Index 37
use in DECLARE 1-149S, 5-23T selecting all columns 2-12T
Search condition. See Condition segment. selecting specific columns 2-18T
secheck utility 13-31T specifying a substring in 2-27T
SECOND keyword Select privilege
syntax column level 11-10T
in DATETIME data type 1-428S definition of 1-236S, 11-8T
in INTERVAL data type 1-485S with a view 11-27T
use SELECT statement
as DATETIME field qualifier 3-8R, active set 2-29T
1-488S aggregate functions in 1-462S, 2-53T
as INTERVAL field qualifier 3-14R, alias names 2-79T
1-491S and COLLCHAR environment
Second normal form 8-31T variable 4-46R
and LC_COLLATE environment
Secondary site 12-20T variable 4-51R
Security and NLS collation order 1-15R
constraining inserted values 11-20T, as an argument to a stored procedure
11-25T 2-4S
database-level privileges 11-5T assigning values with 14-21T
making database inaccessible 11-5T associating with cursor with
restricting access to columns 11-20T DECLARE 1-148S
restricting access to rows 11-20T, BETWEEN condition 1-327S
11-21T column numbers 1-339S
restricting access to view 11-27T compound query 3-43T
table-level privileges 11-10T cursor for 5-19T, 5-20T
using host file system 11-4T date-oriented functions in 2-56T
using operating system facilities describing returned values with
11-4T DESCRIBE 1-162S
with stored procedures 11-3T description of advanced 3-4T to 3-55T
Seek time 13-17T description of simple 2-3T to 2-83T
Select display label 2-49T
description of 1-13T DISTINCT keyword 2-19T
Select cursor embedded 5-13T to 5-16T
definition of 1-148S for joined tables 2-69T to 2-83T
opening 1-264S, 5-20T for single tables 2-11T to 2-66T
reopening 1-267S FROM Clause 1-323S
use of 1-148S, 5-20T functions 2-53T to 2-66T
GROUP BY clause 1-334S, 3-4T
SELECT keyword HAVING clause 1-336S, 3-9T
ambiguous use as procedure variable IN condition 1-327S
1-480S in FOR EACH ROW section 1-117S
syntax in modifiable view 11-24T
in GRANT 1-235S INTO clause with ESQL 1-318S
in REVOKE 1-301S INTO TEMP clause 1-341S, 2-83T
use IS NULL condition 1-327S
in GRANT 1-236S join 2-71T to 2-79T
in REVOKE 1-302S joining tables in WHERE clause
Select list 1-331S
display label 2-49T LIKE or MATCHES condition 1-328S
expressions in 2-46T multiple-table 2-69T
functions in 2-53T to 2-66T natural join 2-75T
labels in 3-48T
38 Index
null values in the ORDER BY clause definition of 1-149S, 5-23T
1-339S use of 1-149S
ORDER BY clause 1-337S, 2-13T with FETCH 1-195S
ORDER BY clause and NLS 1-15R SERIAL data type
outer join 3-21T to 3-31T description of 3-19R, 9-7T
privilege for 11-6T, 11-8T generated number in SQLERRD 5-12T
relational-operator condition 1-326S in ALTER TABLE 1-17S
restrictions with INTO clause 1-276S in INSERT 1-251S
rowid 3-16T, 3-21T inserting a starting value 4-8T
ROWID keyword 1-435S inserting values 3-19R
SELECT clause 1-312S, 2-12T to 2-28T resetting values 3-19R
select numbers 1-339S syntax 1-425S
selecting a substring 2-27T treatment by dbschema 5-34R
selecting expressions 2-46T with stored procedures 2-8S
selection list 2-12T Server. See Database server.
self-join 3-11T
single-table 2-11T SET clause 1-125S, 4-14T
singleton 1-318S, 2-29T SET CONNECTION statement
subquery 3-32T to 3-42T syntax and use 1-346S
subquery with WHERE keyword with concatenation operator 1-432S
1-326S SET CONSTRAINTS statement
syntax 1-310S syntax and use 1-349S
UNION operator 1-344S, 3-43T use with CREATE TRIGGER 1-131S
use of expressions 1-313S SET DEBUG FILE TO statement
using syntax and use 1-351S
for join 2-8T with TRACE 2-42S
for projection 2-7T SET DESCRIPTOR statement
for selection 2-5T syntax 1-353S
WHERE clause and NLS 1-15R the VALUE option 1-355S
with with concatenation operator 1-432S
Condition segment 1-404S X/Open mode 1-357S
DECLARE 1-145S
FOREACH 2-20S Set difference 3-53T
INSERT 1-253S SET EXPLAIN statement
INTO keyword 1-198S interpreting output 1-361S, 13-29T
LET 2-29S MERGE JOIN information 1-362S
writing rows retrieved to an ASCII file optimizer access paths 1-361S
1-378S output examples 1-362S
Selection, described 2-5T SORT SCAN information 1-362S
syntax 1-360S
Self-join writes query plan 13-12T
assigning column names with INTO
TEMP 3-12T Set intersection 3-51T
description of 1-333S, 3-11T SET ISOLATION statement
See also Join. controlling the effect of locks 4-28T
Self-referencing query 3-11T, 4-22T default database levels 1-368S
definition of isolation levels 1-367S
Self-referencing query. See also Self-join. effects of isolation 1-368S
Semantic integrity 4-18T, 9-3T restrictions 7-9T
Sequential access. See Disk access, syntax 1-366S
sequential. SET keyword
Sequential cursor syntax in UPDATE 1-383S
use in UPDATE 1-386S, 4-12T
Index 39
SET LOCK MODE statement description of 3-20R, 9-9T
controlling the effect of locks 4-28T syntax 1-425S
description of 7-13T SMALLINT data type
kernel locking 1-370S changing data types 3-23R
setting wait period 1-371S description of 3-20R, 9-7T
syntax 1-370S syntax 1-425S
SET LOG statement using as default value 1-19S, 1-89S
buffered vs. unbuffered 1-372S, 9-22T SOME keyword
syntax 1-372S beginning a subquery 1-330S, 3-33T
SET OPTIMIZATION statement, syntax use in Condition subquery 1-415S
and use 1-374S Sort merge join 13-27T
Setting environment variables 4-5R Sorting
SHARE keyword, syntax in LOCK avoiding nonsequential access 13-37T
TABLE 1-260S avoiding with temporary table 13-36T
Shared memory effect on performance 13-33T
network connection 12-7T in a combined query 1-344S
Shared memory parameters, specifying in SELECT 1-337S
file with ONCONFIG 4-39R nested 2-15T
optimizer estimates cost 13-12T
Shell PSORT_DBTEMP environment
setting environment variables in a file variable 4-40R
4-4R PSORT_NPROCS environment
specifying with DBREMOTECMD variable 4-41R
4-25R sort merge join 13-27T
Simple assignment 2-28S time costs of 13-15T
SIN function when there are multiple active NLS
syntax in expression 1-458S locales 1-20R
use in expression 1-459S with NLS activated 1-15R, 2-25T
Single-precision floating-point number, with ORDER BY 2-14T
storage of 3-12R See also ORDER BY keywords.
Singleton SELECT statement 1-318S, Space ( )
2-29T as delimiter in DATETIME 3-9R
Site as delimiter in INTERVAL 3-15R
network 12-4T Specifying ANSI-compliance 1-11R
primary 12-20T SPL
secondary 12-20T flow control statements 14-22T
SITENAME function program variable 5-5T
returns servername 1-438S relation to SQL 14-3T
syntax See also Stored procedure.
in expression 1-436S SQL
in INSERT 1-250S ANSI standard 1-15T
use cursor 5-19T
in ALTER TABLE 1-18S description of 1-14T
in CREATE TABLE 1-88S error handling 5-16T
in expression 1-438S history 1-14T
in INSERT 1-252S in NLS-ready products 1-22R
in SELECT 2-63T, 2-65T, 3-20T Informix SQL and ANSI SQL 1-15T
Slash (/), arithmetic operator 1-431S interactive use 1-17T
SMALLFLOAT data type optimizing. See Optimizer.
changing data types 3-23R standardization 1-14T
40 Index
statement types 1-5S in OPEN 1-269S
SQL Communications Area (SQLCA) in PUT 1-288S
altered by end of transaction 6-5T use with EXECUTE statement 1-186S
description of 5-8T SQLERRD array
effect of setting DBANSIWARN 4-15R count of deleted rows 6-4T
inserting rows 6-11T count of inserted rows 6-11T
result after CLOSE 1-39S count of rows 6-14T
result after DATABASE 1-140S description of 5-12T
result after DESCRIBE 1-163S syntax of naming 5-11T
result after FETCH 1-202S SQLERROR keyword, in the
result after FLUSH 1-204S WHENEVER statement 1-398S
result after OPEN 1-264S, 1-265S SQLEXEC environment variable 4-41R
result after PUT 1-290S
result after SELECT 1-321S sqlexecd 12-14T
returning NLS error messages to sqlhosts. See
1-19R $INFORMIXDIR/etc/sqlhosts.
See also SQLAWARN, SQLCODE, and SQLNOTFOUND
SQLERRD. error conditions with EXECUTE
SQL DESCRIPTOR clause. See statement 1-188S
DESCRIBE statement. SQLRM environment variable 4-42R
SQL Descriptor. See SQL SQLRMDIR environment variable 4-43R
Communications Area (SQLCA). SQLSTATE
SQL statements in databases that are not
FILE 5-23R ANSI-compliant 5-18T
INSERT 5-23R use with a cursor 5-21T
SQLAWARN array SQLWARNING keyword, in the
description of 5-12T WHENEVER statement 1-400S
syntax of naming 5-11T SQRT function
with PREPARE 5-30T syntax in expression 1-444S
sqlca record and EXECUTE statement use in expression 1-447S
1-186S START DATABASE statement
SQLCA. See SQL Communications Area. adding a transaction log 9-24T
SQLCODE field syntax and use 1-376S
after opening cursor 5-20T state table in stores6 database, columns
description of 5-11T in A-6R
end of data on SELECT only 6-14T Statement
end of data signalled 5-17T naming with NLS 1-15R
set by DELETE 6-4T SQL, ANSI compliance and
set by DESCRIBE 5-33T DBANSIWARN 4-15R
set by PUT, FLUSH 6-11T SQL, CONNECT and
sqlda structure INFORMIXSERVER 4-37R
syntax SQL, CREATE TABLE and
in DESCRIBE 1-162S COLLCHAR 4-46R
in EXECUTE 1-184S SQL, DESCRIBE and COLLCHAR
in FETCH 1-194S 4-46R
in OPEN 1-263S SQL, editing and DBEDIT 4-18R
in PUT 1-284S SQL, LOAD and DBDELIMITER
use 4-18R
in DESCRIBE 1-164S SQL, SELECT and COLLCHAR 4-46R
in FETCH 1-201S
Index 41
SQL, SELECT and LC_COLLATE definition of 14-3T
4-51R displaying contents 14-9T
SQL, UNLOAD and DBDELIMITER displaying documentation 14-9T
4-18R executing 14-9T
SQL, UPDATE STATISTICS and general programming 1-17T
DBUPSPACE 4-30R granting privileges on 1-237S, 11-12T,
Statement identifier 14-15T
associating with cursor 1-148S handling multiple rows 2-39S
definition of 1-274S header 2-8S, 14-25T
releasing 1-274S in SELECT statements 1-315S, 2-67T
syntax in WHEN condition 1-122S
in DECLARE 1-145S introduction to 14-3T
in DESCRIBE 1-162S looping 14-23T
in EXECUTE 1-184S name confusion with SQL functions
in FREE 1-207S 14-21T
in PREPARE 1-273S naming output file for TRACE
use statement 1-351S
in DECLARE 1-154S owner-privileged 1-129S, 14-13T
in FREE 1-208S privileges 1-129S
in PREPARE 1-274S privileges necessary at execution
Statement types 1-5S 14-14T
program flow control 14-22T
Statement variable name, definition receiving data from SELECT 1-318S
1-190S recursion 14-24T
Static SQL 5-5T REFERENCES clause 14-18T
STATUS FOR keywords, in INFO returning values 14-25T
statement 1-244S revoking privileges on 1-301S, 14-16T
STATUS variable (4GL) 5-11T security purposes 11-3T
Status, displaying with INFO statement simulating errors 2-36S
1-244S tracing triggered actions 15-12T
use 14-3T
stock table in stores6 database, columns variable 14-16T
in A-4R
Stored Procedure Language. See SPL.
STOP keyword, in the WHENEVER
statement 1-398S, 1-402S stores6 database
call_type table columns A-5R
Storage device 12-6T catalog table columns A-4R
Stored procedure copying Intro-10R, Intro-13S, 8T
altering 14-13T creating Intro-10R, Intro-13S, 8T
as triggered action 1-128S, 15-10T customer table columns A-2R
branching 14-22T cust_calls table columns A-5R
BYTE and TEXT data types 2-9S, 2-13S data values A-15R
checking references 1-129S description of A-1R
comments in 14-6T items table columns A-3R
creating from an embedded language manufact table columns A-5R
14-5T map of A-6R
creating from DB-Access 14-5T orders table columns A-3R
cursors with 2-20S overview Intro-9R, Intro-12S, 7T
DBA-privileged, use with triggers primary-foreign key relationships
1-129S, 14-13T A-8R to A-15R
debugging 2-42S, 14-11T state table columns A-6R
default privileges 14-14T stock table columns A-4R
DEFINE statement 14-17T structure of tables A-2R
42 Index
Structured Query Language. See SQL. altering contents 2-9R
Subquery character column data type when
beginning with ALL/ANY/SOME NLS activated 1-19R
keywords 1-330S database entries 1-57S
beginning with EXISTS keyword description of 2-3R
1-330S map of tables 2-33R
beginning with IN keyword 1-329S NCHAR columns in 1-19R
correlated 1-413S, 3-32T, 4-22T, 13-32T privileges in 4-16T, 11-9T
definition of 1-326S querying 4-16T
in Condition segment 1-413S sysblobs 2-11R
in DELETE statement 4-6T syschecks 2-11R
in SELECT 3-32T to 3-42T syscolauth 2-12R, 1-302S, 11-9T
in UPDATE-SET 4-13T syscoldepend 2-13R
in UPDATE-WHERE 4-12T syscolumns 2-13R
performance of 13-32T sysconstraints 2-16R
restrictions with UNION operator sysdefaults 2-17R
1-344S sysdepend 2-18R
with DISTINCT keyword 1-313S sysdistrib 2-18R
See also Condition segment. sysindexes 2-20R
Subscripting sysopclstr 2-22R
in a WHERE clause 2-44T sysprocauth 2-23R
on character columns 1-434S sysprocbody 2-24R, 14-8T
SPL variables 14-18T sysprocedures 2-25R
sysprocplan 2-26R
Subservient table 3-21T sysreferences 2-26R
Substring 2-27T, 14-18T syssynonyms 2-27R
SUM function syssyntable 2-27R
as aggregate function 2-53T systabauth 2-28R, 1-239S, 1-302S,
syntax in expression 1-462S 4-16T, 11-9T
use in expression 1-465S systables 2-29R
Symbol table 10-27T systrigbody 2-31R
Synonym systriggers 2-32R
ANSI-compliant naming 1-80S sysusers 2-32R, 11-9T
chaining 1-83S sysviews 2-33R
chains 12-18T updating 2-9R
creating with CREATE SYNONYM updating statistics 2-9R
1-80S used by optimizer 13-9T
difference from alias 1-80S System catalog tables. See System
dropping 1-177S catalog.
in ANSI-compliant database 1-14R System descriptor area 1-164S
synonym behavior assigning values to 1-354S
in ANSI-compliant database 1-14R modifying contents 1-354S
Synonyms for table names 12-17T resizing 1-355S
use with EXECUTE statement 1-187S
Syntax diagram
conventions Intro-5S System name, in database name 1-422S
elements of Intro-9S SYSTEM statement
sysdepend system catalog table 1-183S syntax 2-40S
syssyntable 12-18T
System catalog
accessing 2-8R
Index 43
T represents an entity 8-22T
restoring with audit trail 1-292S
Table structure in stores6 database A-2R
adding a constraint 1-29S system catalog tables 2-11R to 2-33R
alias in SELECT 1-323S unlocking 1-381S
ANSI-compliant naming 1-507S variable-length rows 10-14T
bottleneck 10-35T See also ALTER TABLE statement.
candidate keys, defined 8-23T See also CREATE TABLE statement.
changing the data type of a column See also Join.
3-23R See also Table Name segment.
checking with the CHECK TABLE TABLE keyword, syntax in UPDATE
statement 1-37S STATISTICS 1-393S
composite key, defined 8-23T
contained in one dbspace 10-5T Table Name segment 1-506S
creating Table size
a synonym for 1-80S calculating 10-12T, 10-19T
a table 1-84S, 9-24T cost of access 13-19T, 13-34T
a temporary table 1-100S with fixed-length rows 10-13T
dedicated device for 10-6T with variable-length rows 10-14T
description of 1-11T Table-level privilege
dropping column-specific privileges 1-303S,
a constraint 1-32S 11-10T
a synonym 1-177S default with GRANT 1-237S
a table 1-179S definition and use 1-236S, 11-7T
engine response to locked table 1-370S granting 1-235S
extent sizes of 10-8T passing grant ability 1-237S
fixed-length rows 10-13T revoking 1-301S
in mirrored storage 10-6T See also ALTER TABLE statement.
in relational model 1-11T, 8-20T TABLES keyword, in INFO statement
interleaved dbspaces 10-10T 1-242S
joins in Condition segment 1-331S tabtype 2-29R, 2-30R, 1-60S
loading data with the LOAD
statement 1-255S TAN function
lock 7-7T syntax in expression 1-458S
locking use in expression 1-460S
changing mode 1-33S tblspace
with ALTER INDEX 1-13S description of 10-7T
with LOCK TABLE 1-260S used for BLOB data 10-18T
logging 1-104S TEMP keyword
multiple access arms for 10-7T syntax in SELECT 1-310S
names 12-16T use in SELECT 1-341S
names, synonyms 12-17T TEMP TABLE keywords, syntax in
naming conventions 1-84S, 1-470S, CREATE TABLE 1-84S
1-507S Temporary
naming with NLS 1-15R files, specifying directory with
optimizing queries 1-394S DBTEMP 4-27R
ownership 11-7T tables, specifying dbspace with
primary key in 8-22T DBSPACETEMP 4-26R
primary key, defined 8-22T
relation to dbspace 10-6T Temporary table
repairing with REPAIR TABLE and active set of cursor 5-24T
statement 1-299S assigning column names 3-12T
building distributions 1-397S
44 Index
creating constraints for 1-102S syntax 1-425S
DBSPACETEMP environment use in Boolean expression 3-21R
variable 1-100S used for performance 10-27T
example 4-11T with control characters 3-21R
explicit 1-100S with LENGTH function 2-64T
implicit 1-100S with stored procedures 2-9S, 2-13S
location of 1-100S Text editor, specifying with DBEDIT
naming 1-100S 4-18R
shared disk space for 10-6T TEXT value, displaying 2-11T
updating statistics 1-394S
using to speed query 13-36T Third normal form 8-32T
when deleted 1-100S Time function
TERM environment variable 4-55R restrictions with GROUP BY 1-334S
use in SELECT 1-314S
TERMCAP environment variable 4-56R,
12-14T Time, representing with NLS 1-15R
termcap file TO CLUSTER keywords, in ALTER
and TERMCAP environment variable INDEX 1-12S
4-56R TO keyword
selecting with INFORMIXTERM in expression 1-462S
4-39R in GRANT 1-231S
Terminal handling TODAY function
and TERM environment variable syntax
4-55R in Condition segment 1-405S
and TERMCAP environment variable in expression 1-436S
4-56R in INSERT 1-250S
and TERMINFO environment use
variable 4-56R in ALTER TABLE 1-18S
terminfo directory in constant expression 1-439S,
and TERMINFO environment 2-63T, 4-8T
variable 4-56R in CREATE TABLE 1-88S
selecting with INFORMIXTERM in INSERT 1-252S
4-39R TP/XA. See Transaction manager.
TERMINFO environment variable 4-56R TRACE command
TEXT data type output from 15-14T
choosing location for 10-18T TRACE statement
description of 3-21R, 9-17T debugging a stored procedure 14-11T
disk storage for 10-4T syntax 2-42S
estimating disk space for 10-17T Transaction
inserting values 3-21R and CREATE DATABASE 1-60S
requirements for LOAD statement ANSI-compliant database, effects
1-257S 1-11R
restrictions committing with COMMIT WORK
with aggregate functions 3-21R 1-43S
with GROUP BY 3-21R, 3-7T cursors closed at end 7-18T
with IN clause 3-21R description of 4-22T
with LIKE or MATCHES 3-21R, example with DELETE 6-5T
2-37T global 12-21T
with ORDER BY 3-21R locks held to end of 7-9T
with relational expression 2-29T locks released at end 7-8T, 7-18T
selecting a column 3-22R logging 1-376S
recovering transactions 1-308S
Index 45
rolling back 1-4R, 1-306S syntax 1-121S
scroll cursor and data consistency WHEN condition 1-121S
1-369S correlation name in 1-125S, 1-128S
starting with BEGIN WORK 1-35S FOR EACH ROW 15-8T
stopping logging 1-376S generating an error message 15-14T
transaction log 4-24T, 4-26T in client/server environment 1-133S
transaction log required 9-22T in relation to triggering statement
use signalled in SQLAWARN 5-12T 15-6T
using cursors in 1-155S list
Transaction logging AFTER 1-117S
ANSI-compliant database, effects BEFORE 1-116S
1-12R FOR EACH ROW 1-116S
buffered 9-22T for multiple triggers 1-117S
effect on database server type 1-5R sequence of 1-116S
establishing with CREATE merged 1-117S
DATABASE 9-21T preventing overriding 1-132S
OnLine methods of 9-22T statements 15-3T
renaming log 1-377S tracing 15-12T
stopping 1-377S using 15-7T
turning off for faster loading 9-28T using stored procedures 15-10T
turning off not possible 9-24T WHEN condition 1-121S, 15-10T
Transaction log, contents of 4-25T Triggering statement
Transaction manager 12-11T affecting multiple rows 1-117S
execution of 1-113S
Transfer of database files 5-19R guaranteeing same result 1-112S
Transitive dependency 8-32T result of 1-123S
Trigger UPDATE 1-115S
creating 15-4T Triggering table
definition of 15-3T action on 1-127S
in client/server environment 1-133S and cascading triggers 1-131S
number on a table 1-112S Trigonometric function
preventing overriding 1-132S ACOS function 1-460S
when to use 15-3T ASIN function 1-460S
Trigger event ATAN function 1-460S
definition of 1-111S, 15-5T ATAN2 function 1-461S
example of 15-5T COS function 1-459S
in CREATE TRIGGER statement SIN function 1-459S
1-111S TAN function 1-460S
INSERT 1-119S TRUNC function
privileges on 1-113S syntax in expression 1-444S
with cursor statement 1-112S use in expression 1-447S
Trigger name Truncation, signalled in SQLAWARN
assigning 15-5T 5-12T
syntax 1-113S
Two-phase commit 12-20T
Triggered action
action on triggering table 1-127S TYPE field
anyone can use 1-129S changing from BYTE or TEXT 1-359S
BEFORE and AFTER 15-7T setting in SET DESCRIPTOR 1-356S
cascading 1-118S setting in X/Open programs 1-357S
clause 1-121S with X/Open programs 1-213S
action statements 1-122S
46 Index
Typographical conventions Intro-5R, TERMINFO environment variable
Intro-5S, 5T 4-56R
UNIX operating system 12-4T, 12-6T
U UNLOAD statement
DELIMITER clause 1-380S
Unbuffered logging 9-22T exporting data to a file 9-27T
Underscore (_), wildcard in Condition specifying field delimiter with
segment 1-410S DBDELIMITER 4-18R
UNION operator syntax 1-378S
description of 3-43T UNLOAD TO file 1-378S
display labels with 3-48T unloading VARCHAR, TEXT, or
restrictions in view 11-22T BYTE columns 1-379S
restrictions on use 1-344S UNLOAD TO file 1-378S
syntax in SELECT 1-310S Unloading a database 5-8R
use in SELECT 1-344S
UNLOCK TABLE statement, syntax and
Unique constraint use 1-381S
dropping 1-32S
modifying a column with 1-28S Unnamed pipes 12-7T
rules of use 1-30S, 1-92S, 1-94S Updatable view 1-139S
UNIQUE keyword UPDATE clause, syntax 1-114S
constraint in CREATE TABLE 9-24T Update cursor 1-148S
restrictions in modifiable view 11-24T definition of 1-148S, 6-15T
syntax locking considerations 1-152S
in CREATE INDEX 1-63S opening 1-264S
in CREATE TABLE 1-91S restricted statements 1-152S
in SELECT 1-312S use in UPDATE 1-390S
use using 1-152S
in ALTER TABLE 1-29S Update journal 10-33T
in CREATE INDEX 1-64S UPDATE keyword
in CREATE TABLE 1-92S syntax
in expression 1-462S in GRANT 1-235S
in SELECT 1-313S, 2-19T in REVOKE 1-301S
no effect in subquery 1-414S use
UNITS keyword in GRANT 1-236S
syntax in expression 1-436S in REVOKE 1-302S
use in expression 1-442S Update privilege
UNIX column level 11-10T
BSD definition of 1-236S, 11-8T
default print capability 4-7R, 4-24R with a view 1-384S, 11-28T
viewing environment settings 4-5R UPDATE REFERENCING clause
environment variables listed 4-9R and FOR EACH ROW section 1-121S
PATH environment variable 4-54R correlation name 1-120S
specifying directories for syntax 1-120S
intermediate writes 4-40R
System V UPDATE statement
default print capability 4-7R, 4-24R and end of data 6-14T
terminfo library support 4-39R and transactions 1-384S
viewing environment settings 4-5R applied to view 11-24T
TERM environment variable 4-55R as triggered action 1-122S
TERMCAP environment variable as triggering statement 1-112S, 1-114S,
4-56R 1-115S
Index 47
description of 4-12T in expression 1-438S, 2-63T, 2-64T,
embedded 6-14T to 6-17T 3-19T
in trigger event 1-111S in INSERT 1-252S
locking considerations 1-385S User informix, privileges associated with
missing WHERE signalled 5-10T 1-234S
multiple assignment 4-14T Using correlation names 1-124S
number of rows 5-12T
preparing 5-30T USING DESCRIPTOR keywords
privilege for 11-6T, 11-8T information from DESCRIBE 1-164S
restrictions on columns for update syntax
1-153S in EXECUTE 1-184S
restrictions on subqueries 4-13T in FETCH 1-194S
rolling back updates 1-385S in OPEN 1-263S
syntax 1-383S in PUT 1-284S
time to update indexes 10-20T use
updating a column to null 1-387S in FETCH 1-201S
updating through a view 1-384S in OPEN 1-269S
updating with cursor 1-390S in PUT 1-188S, 1-288S, 1-289S
use of expressions 1-388S USING keyword
with syntax
Condition segment 1-404S in EXECUTE 1-186S
FETCH 1-201S in OPEN 1-263S
SET keyword 1-386S use
WHERE CURRENT OF keywords in EXECUTE 1-186S, 5-31T
1-390S in OPEN 1-268S
WHERE keyword 1-388S USING SQL DESCRIPTOR keywords
with a select..for update 1-340S in DESCRIBE 1-164S
with an update cursor 1-152S in EXECUTE 1-187S
UPDATE STATISTICS statement Utility program
affect on sysdistrib 2-19R chkenv 5-4R
and DBUPSPACE environment crtcmap 5-5R
variable 4-30R dbexport 5-8R
creating distributions 1-396S dbimport 5-13R
dropping data distributions 1-396S dbload 5-19R, 9-28T, 10-12T
examining index pages 1-394S dbschema 5-33R, 9-26T
optimizing search strategies 1-394S oncheck 10-7T, 10-12T
syntax 1-392S onload 4-27T, 10-11T
using the LOW keyword 1-395S onstat 10-12T
when to execute 1-395S onunload 4-27T, 10-11T
Update trigger, defining multiple 1-114S
USER function V
as affected by ANSI compliance
1-231S, 1-300S, 1-438S VALUE clause
syntax after NULL value is fetched 1-215S
in Condition segment 1-405S relation to FETCH 1-214S
in expression 1-436S use in GET DESCRIPTOR 1-212S
in INSERT 1-250S use in SET DESCRIPTOR 1-355S
use VALUES clause
in ALTER TABLE 1-18S effect with PUT 1-286S
in CREATE TABLE 1-88S syntax in INSERT 1-245S
use in INSERT 1-250S, 4-7T
48 Index
VARCHAR data type virtual column 1-137S, 11-24T
considerations for UNLOAD with SELECT * notation 1-136S
statement 1-379S View Name segment 1-510S
description of 3-22R, 9-15T
effect on table size 10-14T
requirements for LOAD statement W
1-257S WAIT keyword, in the SET LOCK
syntax 1-425S MODE statement 1-370S
used for performance 10-26T WARNING keyword, in the
using as default value 1-19S, 1-89S WHENEVER statement 1-398S
versus NVARCHAR data type 1-19R
with LENGTH function 2-64T Warnings, with stored procedures at
compile time 14-8T
VARCHAR value, displaying 2-11T
WEEKDAY function
Variable as time function 2-56T, 2-60T
default values in SPL 2-11S, 2-12S syntax in expression 1-454S
define in SPL 2-7S use in expression 1-456S
global, in SPL 2-10S, 14-17T
in SPL 14-16T WHEN condition
local, in SPL 2-12S, 14-17T in triggered action 1-122S
scope of SPL variable 2-8S restrictions 1-122S
unknown values in IF 2-25S use of 1-122S
with same name as a keyword 14-19T WHENEVER statement, syntax and use
View 1-398S
creating a view 1-136S, 11-20T WHERE clause, subscripting 2-44T
creating synonym for 1-80S WHERE CURRENT OF clause, impact
deleting rows in 11-24T on trigger 1-112S
description of 11-19T WHERE CURRENT OF keywords
display description with dbschema syntax
5-34R in DELETE 1-159S
dropped when basis is dropped in UPDATE 1-383S
11-22T use
dropping 1-183S in DELETE 6-7T
effect of changing basis 11-23T in UPDATE 1-390S, 6-15T
effect on performance 13-33T WHERE keyword
inserting rows in 11-25T Boolean expression in 2-36T
modifying 11-23T to 11-27T comparison condition 2-29T to 2-45T
naming with NLS 1-15R date-oriented functions in 2-60T
null inserted in unexposed columns enforcing data constraints 11-27T
11-25T host variables in 5-14T
privilege when accessing 11-28T in DELETE 4-4T to 4-6T
privilege when creating 1-137S joining tables 1-331S
privileges 11-27T to 11-30T null data tests 2-35T
privileges with GRANT 1-239S prevents use of index 13-32T, 13-33T,
produces duplicate rows 11-22T 13-35T
restrictions with UNION operator range of values 2-32T
1-344S relational operators 2-29T
system catalog table 2-33R selecting rows 2-28T
updatable 1-139S setting descriptions of items 1-354S
updating 1-384S subqueries in 3-33T
updating duplicate rows 11-25T syntax
using CHECK OPTION 11-25T in DELETE 1-159S
Index 49
in SELECT 1-310S warnings in a stored procedure 14-8T
in UPDATE 1-383S WITH LOG IN keywords, syntax in
testing a subscript 2-44T START DATABASE 1-376S
use WITH MAX keywords
in DELETE 1-160S relationship with COUNT field 1-354S
in UPDATE 1-388S
with a subquery 1-326S WITH NO LOG keywords
with ALL keyword 1-330S syntax
with ANY keyword 1-330S in CREATE TABLE 1-84S
with BETWEEN keyword 1-327S in SELECT 1-341S
with IN keyword 1-327S use
with IS keyword 1-327S in CREATE TABLE 1-104S
with LIKE keyword 1-328S in SELECT 1-343S
with MATCHES keyword 1-328S WITH NO LOG keywords, syntax in
with NOT keyword 2-32T START DATABASE 1-376S
with OR keyword 2-33T WITH RESUME keywords, in RETURN
with relational operator 1-326S 2-39S
with SOME keyword 1-330S WITHOUT HEADINGS keywords, in
wildcard comparisons 2-37T the OUTPUT statement 1-271S
See also Condition segment. WORM drive 12-6T
WHILE keyword Write-once read-many-times device. See
in CONTINUE statement 2-6S WORM drive.
in EXIT 2-14S
Writing a dbload command file
WHILE statement in character-position form 5-31R
looping in a stored procedure 14-23T in delimiter form 5-26R
syntax 2-46S
with NULL expressions 2-46S
Wildcard character X
asterisk 2-12T X/Open
Wildcard characters, with LIKE or and Informix implementation of NLS
MATCHES 1-498S 1-15R
Wildcard comparison setting NLS environment variables
in WHERE clause 2-37T to 2-44T 4-43R
WITH APPEND keywords, in the SET setting the LC_COLLATE category
DEBUG FILE TO statement 1-351S 4-50R
setting the LC_CTYPE category 4-51R
WITH CHECK keywords setting the LC_MONETARY category
syntax in CREATE VIEW 1-136S 4-52R
use in CREATE VIEW 1-138S setting the LC_NUMERIC category
WITH CHECK OPTION keywords 4-53R
11-25T setting the LC_TIME category 4-53R
WITH GRANT keywords specifications, icon for Intro-8S
syntax in GRANT 1-231S X/Open mode
use in GRANT 1-237S FETCH statement 1-195S
WITH HOLD keywords GET DESCRIPTOR 1-213S
declaring a hold cursor 7-19T, 10-34T SET DESCRIPTOR statement 1-357S
syntax in DECLARE 1-145S X/Open specification of NLS 1-15R
use in DECLARE 1-150S, 1-157S
WITH keyword, syntax in CREATE
DATABASE 1-57S
WITH LISTING IN keywords
50 Index
Y as placeholder in PREPARE 1-273S,
5-29T
YEAR function naming variables in PUT 1-287S
as time function 2-56T replacing with USING keyword
syntax in expression 1-454S 1-268S
use in expression 1-456S wildcard in Condition segment 1-411S
YEAR keyword @, at sign, in database name 1-421S
syntax \, backslash, as escape character
in DATETIME data type 1-428S with LIKE 1-410S
in INTERVAL data type 1-485S with MATCHES 1-411S
use
as DATETIME field qualifier 3-8R, ^, caret, wildcard in Condition segment
1-488S 1-411S
as INTERVAL field qualifier 3-13R, _, underscore, wildcard in Condition
1-491S segment 1-410S
||, concatenation operator 1-432S
Symbols
$INFORMIXDIR/etc/sqlhosts 12-15T
%, percent sign, wildcard in Condition
segment 1-410S
( ), space, as delimiter
in DATETIME 3-9R
in INTERVAL 3-15R
*, asterisk
arithmetic operator 1-431S
use in SELECT 1-312S
+, plus sign, arithmetic operator 1-431S
-, hyphen, as delimiter
in DATETIME 3-9R
in INTERVAL 3-15R
-, minus sign, arithmetic operator 1-431S
. 4-4R
., decimal point, as delimiter
in DATETIME 3-9R
in INTERVAL 3-15R
..., ellipses, wildcard in Condition
segment 1-411S
/etc/hosts 12-15T
/etc/services 12-15T
/, division symbol, arithmetic operator
1-431S
/, slash, arithmetic operator 1-431S
:, colon, as delimiter
in DATETIME 3-9R
in INTERVAL 3-15R
=, equals, relational operator 2-30T,
2-71T
?, question mark
Index 51
52 Index
Reader Response Card
Informix Guide to SQL: Tutorial, Version 6.0
Dear Reader,
At Informix Software, we think documentation is very important. After all, manuals are
an integral part of our product line. Because documentation is important, we want to know
what you think about our manuals. You can tell us by filling out and returning the Reader
Response Card.
Thanks for your help!
1. Overall, how do you rate this manual?
Outstanding Very good Good Average Poor
4. When you need to find information quickly, which part of the documentation
do you use?
• Index: Often Sometimes Rarely Never
• Table of Contents: Often Sometimes Rarely Never
• Quick Reference Card: Often Sometimes Rarely Never
• Chapter summaries: Often Sometimes Rarely Never
• On-line help: Often Sometimes Rarely Never
• Browse through manuals: Often Sometimes Rarely Never
January 1993
9. What other Informix products do you use?
Address:
City: State/Province:
NO POSTAGE
BUSINESS REPLY MAIL NECESSARY
IF MAILED
FIRST CLASS PERMIT NO. 25 MENLO PARK, CA. IN THE
UNITED STATES
POSTAGE WILL BE PAID BY ADDRESSEE