informix guide to sql-tutorial
TRANSCRIPT
Informix Guide to SQL
Tutorial
Version 7.1December 1994Part No. 000-7634
ii Informix Guide to
Published by INFORMIX® Press Informix Software, Inc.4100 Bohannon DriveMenlo Park, CA 94025
The following are worldwide trademarks of Informix Software, Inc., or its subsidiaries, registered in theUnited States of America as indicated by an “®,” and in numerous other countries worldwide:
INFORMIX®; C-ISAM®
The following are worldwide trademarks of the indicated owners or their subsidiaries, registered in theUnited States of America as indicated by an “®,” and in numerous other countries worldwide:
X/Open Company Ltd.: UNIX®; X/Open®
Adobe Systems Incorporated: PostScript®
Some of the products or services mentioned in this document are provided by companies other than Informix.These products or services are identified by the trademark or servicemark of the appropriate companies. If youhave a question about one of these products or services, please contact the company in question directly.
Documentation Team: Sally Cox, Geeta Karmarkar, Susan Koehler, Mary Kraemer, Catherine Lyman,Eileen Wollam
Copyright © 1981-1994 by Informix Software, Inc. All Rights Reserved.
No part of this work covered by the copyright hereon may be reproduced or used in any form or by anymeans—graphic, electronic, or mechanical, including photocopying, recording, taping, or information storageand retrieval systems—without permission of the publisher.
RESTRICTED RIGHTS LEGEND
Software and accompanying materials acquired with United States Federal Government funds or intended foruse within or for any United States federal agency are provided with “Restricted Rights” as defined in DFARS252.227-7013(c)(1)(ii) or FAR 52.227-19.
SQL: Tutorial
Preface
This book is a tutorial on the Structured Query Language (SQL) as it isimplemented by Informix products. The Informix Guide to SQL: Tutorial and itscompanion volumes, the Informix Guide to SQL: Reference and the InformixGuide to SQL: Syntax, tell you how to create, manage, and use relationaldatabases with Informix software tools.
Examples in this manual represent a number of Informix products andoperating systems at different release levels.
You must have the following Informix software:
■ An INFORMIX-OnLine Dynamic Server database server or anINFORMIX-SE database server
The database server either must be installed on your computer or onanother computer to which you are connected over a network.
■ Either an Informix application development tool, such asINFORMIX-4GL or INFORMIX-NewEra; or an SQL application pro-gramming interface (API), such as INFORMIX-ESQL/C; or theDB-Access database access utility, which is shipped as part of yourdatabase server
The application development tool, SQL API, or DB-Access enablesyou to compose queries, send them to the database server, and viewthe results that the database server returns. You can use DB-Access totry out all the SQL statements described in this guide.
Preface iii
iv Informix Guide to SQ
Summary of Chapters
Summary of ChaptersThe Informix Guide to SQL: Tutorial includes the following chapters:
■ This Preface provides general information about the book and listsadditional reference materials that can help you understandrelational database management.
■ The “Introduction” tells how SQL fits into the Informix family ofproducts and books, explains how to use this book, introduces thedemonstration database from which the product examples aredrawn, and lists the new features for Version 6.0 of Informix databaseserver products.
Part I – “Using Basic SQL.” This part contains introductory chapters on howto use SQL. Read these chapters first if you are new to databases and SQL.
■ Chapter 1, “Informix Databases,” contains an overview of databaseterminology and defines some important terms and ideas that areused throughout the book.
■ Chapter 2, “Composing Simple SELECT Statements,” begins theexploration of making simple queries to retrieve and displaydatabase data.
■ Chapter 3, “Composing Advanced SELECT Statements,” discussesmaking advanced queries to retrieve and display database data.
■ Chapter 4, “Modifying Data,” describes the statements you use toinsert, delete, or update data, and introduces the concepts of data-base privileges, maintaining data integrity, and archiving data.
■ Chapter 5, “Programming with SQL,” discusses calling the databaseserver, retrieving rows, and embedding data.
■ Chapter 6, “Modifying Data Through SQL Programs,” provides anin-depth look at INSERT, DELETE, and UPDATE statements and usingthese statements in SQL programs.
■ Chapter 7, “Programming for a Multiuser Environment,” provides acomplete discussion on concurrency, isolation levels, and locking.
L: Tutorial
Summary of Chapters
Part II – “Designing and Managing Databases.” This part contains overviewchapters about designing and managing databases. Read these chapters tounderstand the entity-relationship data model for databases and how tocreate a database.
■ Chapter 8, “Building Your Data Model,” describes the componentsof a data model and provides a step-by-step procedure for buildingone.
■ Chapter 9, “Implementing Your Data Model,” tells you how todefine database data types and create a database.
■ Chapter 10, “Granting and Limiting Access to Your Database,”details how you can ensure data security by granting privileges andusing stored procedures and views.
■ Chapter 11, “Understanding Informix Networking,” discussesnetworks and how you can best set up a database to work over anetwork.
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 needbetter performance in your database.
■ Chapter 12, “Creating and Using Stored Procedures,” describes howto create and use stored procedures.
■ Chapter 13, “Creating and Using Triggers,” describes how to createand use triggers.
Preface v
vi Informix Guide to SQ
Informix Welcomes Your Comments
Informix Welcomes Your CommentsA reader-response card is provided with this manual. Please use this card totell us what you like or dislike about this manual. To help us with future ver-sions of the manual, please tell us about any corrections or clarifications thatyou would find useful. Return this card to:
Informix Software, Inc.Technical Publications Department4100 Bohannon DriveMenlo Park, CA 94025
If you prefer to share your comments on-line, address your e-mail to:
Related ReadingIf you want additional technical information on database management,consult the following books. The first book is an introductory text for readerswho are new to database management, while the second book is a more com-plex technical work for SQL programmers and database administrators.
■ Database: A Primer by C. J. Date (Addison-Wesley Publishing, 1983)
■ An Introduction to Database Systems by C.J. Date (Addison-WesleyPublishing, 1994)
If you are interested in learning more about the SQL language, consider thefollowing books:
■ A Guide to the SQL Standard by C.J. Date with H. Darwen (Addison-Wesley Publishing, 1993)
■ Understanding the New SQL: A Complete Guide by J. Melton and A.Simon (Morgan Kaufmann Publishers, 1993)
■ Using SQL by J. Groff and P. Weinberg (Osborne McGraw-Hill, 1990)
L: Tutorial
Related Reading
This manual assumes that you are familiar with your computer operatingsystem. If you have limited UNIX system experience, you might want to lookat your operating system manual or a good introductory text before you readthis manual. Some texts about UNIX systems are suggested in the followinglist:
■ Introducing the UNIX System by H. McGilton and R. Morgan(McGraw-Hill Book Company, 1983)
■ Learning the UNIX Operating System, by G. Todino, J. Strang, andJ. Peek (O’Reilly & Associates, 1993)
■ A Practical Guide to the UNIX System, by M. Sobell(Benjamin/Cummings Publishing, 1989)
■ UNIX for People by P. Birns, P. Brown, and J. Muster (Prentice-Hall,1985)
■ UNIX System V: A Practical Guide by M. Sobell (Benjamin/CummingsPublishing, 1995)
Preface vii
Table of Contents
Table ofContents
Preface
Introduction
Informix Products That Use SQL . . . . . . . . 3
Products Covered in This Manual . . . . . . . . 4
Other Useful Documentation . . . . . . . . . 4
How to Use This Manual . . . . . . . . . . . 5Typographical Conventions . . . . . . . . 5Example Code Conventions . . . . . . . . 7
Useful On-Line Files . . . . . . . . . . . . 8
ASCII and PostScript Error Message Files . . . . . 8
The Demonstration Database . . . . . . . . . 9Creating the Demonstration Database . . . . . 10
Compliance with Industry Standards . . . . . . 12
New Features in Informix Version 7.1 ProductsThat Use SQL . . . . . . . . . . . . 12
x Inform
Section I Using Basic SQL
Chapter 1 Informix Databases
Databases: What and Why? . . . . . . . . . . 1-3The Data Illustration of a Data Model . . . . . 1-4Concurrent Use and Security . . . . . . . . 1-9Centralized Management . . . . . . . . . 1-10
Important Database Terms . . . . . . . . . . 1-12The Relational Model . . . . . . . . . . . 1-12
Structured Query Language . . . . . . . . . . 1-16Standard SQL . . . . . . . . . . . . . 1-17Informix SQL and ANSI SQL . . . . . . . . 1-17ANSI-Compliant Databases. . . . . . . . . 1-18NLS Databases . . . . . . . . . . . . . 1-18
The Database Software . . . . . . . . . . . . 1-19The Applications . . . . . . . . . . . . 1-19The Database Server . . . . . . . . . . . 1-19Interactive SQL . . . . . . . . . . . . . 1-20Reports and Forms . . . . . . . . . . . . 1-20General Programming . . . . . . . . . . 1-21Applications and Database Servers . . . . . . 1-21
Summary . . . . . . . . . . . . . . . . 1-22
Chapter 2 Composing Simple SELECT Statements
Introducing the SELECT Statement . . . . . . . 2-4Some Basic Concepts . . . . . . . . . . . 2-5The Forms of SELECT. . . . . . . . . . . 2-11Special Data Types . . . . . . . . . . . . 2-11
Single-Table SELECT Statements . . . . . . . . 2-12Selecting All Columns and Rows . . . . . . . 2-12Selecting Specific Columns . . . . . . . . . 2-18Using the WHERE Clause . . . . . . . . . 2-28Creating a Comparison Condition . . . . . . 2-29
ix Guide to SQL: Tutorial
Expressions and Derived Values . . . . . . . 2-47Using Functions in SELECT Statements . . . . . 2-53Using Stored Procedures in SELECT
Statements . . . . . . . . . . . . 2-67
Multiple-Table SELECT Statements . . . . . . . 2-69Creating a Cartesian Product . . . . . . . . 2-69Creating a Join . . . . . . . . . . . . . 2-71Some Query Shortcuts . . . . . . . . . . . 2-80
Summary . . . . . . . . . . . . . . . . 2-84
Chapter 3 Composing Advanced SELECT Statements
Using the GROUP BY and HAVING Clauses . . . . 3-4Using the GROUP BY Clause . . . . . . . . 3-4Using the HAVING Clause . . . . . . . . . 3-8
Creating Advanced Joins . . . . . . . . . . . 3-11Self-Joins . . . . . . . . . . . . . . . 3-11Outer Joins. . . . . . . . . . . . . . . 3-21
Subqueries in SELECT Statements . . . . . . . . 3-31Using ALL . . . . . . . . . . . . . . . 3-33Using ANY . . . . . . . . . . . . . . 3-34Single-Valued Subqueries . . . . . . . . . 3-35Correlated Subqueries . . . . . . . . . . . 3-36Using EXISTS . . . . . . . . . . . . . . 3-37
Set Operations . . . . . . . . . . . . . . . 3-41Union . . . . . . . . . . . . . . . . 3-42Intersection . . . . . . . . . . . . . . 3-50Difference . . . . . . . . . . . . . . . 3-52
Summary . . . . . . . . . . . . . . . . 3-54
Chapter 4 Modifying Data
Statements That Modify Data . . . . . . . . . 4-4Deleting Rows . . . . . . . . . . . . . 4-4Deleting a Known Number of Rows . . . . . . 4-5Inserting Rows . . . . . . . . . . . . . 4-7Updating Rows . . . . . . . . . . . . . 4-12
Table of Contents xi
xii Info
Database Privileges . . . . . . . . . . . . . 4-16Displaying Table Privileges . . . . . . . . . 4-18
Data Integrity . . . . . . . . . . . . . . . 4-19Entity Integrity . . . . . . . . . . . . . 4-19Semantic Integrity . . . . . . . . . . . . 4-20Referential Integrity . . . . . . . . . . . . 4-21
Interrupted Modifications . . . . . . . . . . . 4-25The Transaction . . . . . . . . . . . . . 4-26Transaction Logging . . . . . . . . . . . . 4-26Specifying Transactions. . . . . . . . . . . 4-27
Archives and Logs . . . . . . . . . . . . . 4-28Archiving with INFORMIX-SE . . . . . . . . 4-28Archiving with INFORMIX-OnLine
Dynamic Server . . . . . . . . . . 4-29
Concurrency and Locks . . . . . . . . . . . . 4-30
Data Replication . . . . . . . . . . . . . . 4-31INFORMIX-OnLine Dynamic Server
Data Replication . . . . . . . . . . 4-32
Summary . . . . . . . . . . . . . . . . . 4-32
Chapter 5 Programming with SQL
SQL in Programs . . . . . . . . . . . . . . 5-4SQL in SQL APIs . . . . . . . . . . . . . 5-4SQL in Application Languages . . . . . . . . 5-5Static Embedding. . . . . . . . . . . . . 5-5Dynamic Statements. . . . . . . . . . . . 5-5Program Variables and Host Variables . . . . . 5-6
Calling the Database Server . . . . . . . . . . 5-8The SQL Communications Area. . . . . . . . 5-9The SQLCODE Field . . . . . . . . . . . 5-12The SQLERRD Array . . . . . . . . . . . 5-13The SQLWARN Array . . . . . . . . . . . 5-13The SQLSTATE Value . . . . . . . . . . . 5-14
rmix Guide to SQL: Tutorial
Retrieving Single Rows . . . . . . . . . . . . 5-14Data Type Conversion . . . . . . . . . . . 5-16Dealing with Null Data . . . . . . . . . . 5-17Dealing with Errors. . . . . . . . . . . . 5-18
Retrieving Multiple Rows . . . . . . . . . . . 5-21Declaring a Cursor . . . . . . . . . . . . 5-21Opening a Cursor . . . . . . . . . . . . 5-22Fetching Rows . . . . . . . . . . . . . 5-23Cursor Input Modes . . . . . . . . . . . 5-24The Active Set of a Cursor . . . . . . . . . 5-25Using a Cursor: A Parts Explosion . . . . . . 5-28
Dynamic SQL . . . . . . . . . . . . . . . 5-30Preparing a Statement . . . . . . . . . . . 5-31Executing Prepared SQL . . . . . . . . . . 5-33Dynamic Host Variables . . . . . . . . . . 5-35Freeing Prepared Statements . . . . . . . . 5-36Quick Execution . . . . . . . . . . . . . 5-36
Embedding Data Definition Statements . . . . . . 5-36Embedding Grant and Revoke Privileges . . . . 5-37
Summary . . . . . . . . . . . . . . . . 5-40
Chapter 6 Modifying Data Through SQL Programs
Using DELETE . . . . . . . . . . . . . . 6- 3Direct Deletions . . . . . . . . . . . . . 6- 4Deleting with a Cursor . . . . . . . . . . 6- 7
Using INSERT . . . . . . . . . . . . . . . 6- 9Using an Insert Cursor . . . . . . . . . . 6- 9Rows of Constants . . . . . . . . . . . . 6- 12An Insert Example . . . . . . . . . . . . 6- 12
Using UPDATE . . . . . . . . . . . . . . 6- 15Using an Update Cursor . . . . . . . . . . 6- 15Cleaning up a Table. . . . . . . . . . . . 6- 17
Summary . . . . . . . . . . . . . . . . 6- 18
Table of Contents xiii
xiv Inf
Chapter 7 Programming for a Multiuser Environment
Concurrency and Performance . . . . . . . . . 7-3
Locking and Integrity . . . . . . . . . . . . 7-3
Locking and Performance . . . . . . . . . . . 7-4
Concurrency Issues . . . . . . . . . . . . . 7-4
How Locks Work . . . . . . . . . . . . . . 7-6Kinds of Locks. . . . . . . . . . . . . . 7-6Lock Scope . . . . . . . . . . . . . . . 7-7The Duration of a Lock . . . . . . . . . . . 7-9Locks While Modifying. . . . . . . . . . . 7-10
Setting the Isolation Level . . . . . . . . . . . 7-11Comparing SET TRANSACTION with
SET ISOLATION . . . . . . . . . . 7-11ANSI Read Uncommitted and Informix
Dirty Read Isolation . . . . . . . . . 7-12ANSI Read Committed and Informix
Committed Read Isolation . . . . . . . 7-13Informix Cursor Stability Isolation . . . . . . . 7-13ANSI Serializable, ANSI Repeatable
Read and Informix RepeatableRead Isolation . . . . . . . . . . . 7-15
Controlling Data Modification withAccess Modes . . . . . . . . . . . . 7-16
Setting the Lock Mode . . . . . . . . . . . . 7-17Waiting for Locks . . . . . . . . . . . . . 7-17Not Waiting for Locks . . . . . . . . . . . 7-17Waiting a Limited Time. . . . . . . . . . . 7-18Handling a Deadlock . . . . . . . . . . . 7-18Handling External Deadlock . . . . . . . . . 7-19
Simple Concurrency . . . . . . . . . . . . . 7-19
Locking with Other Database Servers . . . . . . . 7-20Isolation While Reading . . . . . . . . . . 7-21Locking Updated Rows . . . . . . . . . . 7-21
ormix Guide to SQL: Tutorial
Hold Cursors . . . . . . . . . . . . . . . 7-22
Summary . . . . . . . . . . . . . . . . 7-23
Section II Designing and Managing Databases
Chapter 8 Building Your Data Model
Why Build a Data Model . . . . . . . . . . . 8-3Entity-Relationship Data Model Overview. . . . 8-4
Identifying and Defining Your Principal DataObjects . . . . . . . . . . . . . . 8-5
Discovering Entities . . . . . . . . . . . 8-5Defining the Relationships . . . . . . . . . 8-9Identifying Attributes . . . . . . . . . . . 8-17
Diagramming Your Data Objects . . . . . . . . 8-19
Translating E-R Data Objects Into RelationalConstructs . . . . . . . . . . . . . 8-23
Rules for Defining Tables, Rows, andColumns . . . . . . . . . . . . 8-24
Determining Keys for Tables . . . . . . . . 8-26
Resolving Your Relationships . . . . . . . . . 8-30
Normalizing Your Data Model . . . . . . . . . 8-33
Summary . . . . . . . . . . . . . . . . 8-38
Chapter 9 Implementing Your Data Model
Defining the Domains . . . . . . . . . . . . 9-3Data Types . . . . . . . . . . . . . . . 9-4Null Values . . . . . . . . . . . . . . 9-22Default Values . . . . . . . . . . . . . 9-22Check Constraints . . . . . . . . . . . . 9-23
Table of Contents xv
xvi Inf
Creating the Database . . . . . . . . . . . . 9-24Using CREATE DATABASE . . . . . . . . . 9-24Using CREATE TABLE . . . . . . . . . . . 9-28Using Command Scripts . . . . . . . . . . 9-30Populating the Tables . . . . . . . . . . . 9-31
Fragmenting Tables and Indexes . . . . . . . . . 9-34
Creating a Fragmented Table . . . . . . . . . . 9-34Fragmenting a New Table . . . . . . . . . . 9-35Creating A Fragmented Table from
Nonfragmented Tables . . . . . . . . 9-36
Modifying a Fragmented Table . . . . . . . . . 9-37Modifying Fragmentation Strategies . . . . . . 9-38Dropping A Fragment . . . . . . . . . . . 9-40
Accessing Data Stored in Fragmented Tables . . . . 9-41Use Primary Keys Instead of Rowids . . . . . . 9-41
Summary . . . . . . . . . . . . . . . . . 9-43
Chapter 10 Granting and Limiting Access to Your Database
Controlling Access to Databases . . . . . . . . . 11-4Securing Database Files . . . . . . . . . . 11-4Securing Confidential Data . . . . . . . . . 11-5
Granting Privileges . . . . . . . . . . . . . 11-6Database-Level Privileges . . . . . . . . . . 11-6Ownership Rights . . . . . . . . . . . . 11-8Table-Level Privileges . . . . . . . . . . . 11-8Procedure-Level Privileges . . . . . . . . . 11-13Automating Privileges . . . . . . . . . . . 11-13
Controlling Access to Data Using StoredProcedures . . . . . . . . . . . . . 11-16
Restricting Reads of Data . . . . . . . . . . 11-16Restricting Changes to Data . . . . . . . . . 11-17Monitoring Changes to Data . . . . . . . . . 11-18Restricting Object Creation . . . . . . . . . 11-20
ormix Guide to SQL: Tutorial
Using Views . . . . . . . . . . . . . . . 11-21Creating Views . . . . . . . . . . . . . 11-22Modifying Through a View . . . . . . . . . 11-25
Privileges and Views . . . . . . . . . . . . 11-28Privileges When Creating a View . . . . . . . 11-28Privileges When Using a View . . . . . . . . 11-29
Summary . . . . . . . . . . . . . . . . 11-32
Chapter 11 Understanding Informix Networking
What Is a Network? . . . . . . . . . . . . . 12-4
Database Management System Configurations . . . 12-4A Single-User Configuration . . . . . . . . 12-5A Local Multiuser Configuration . . . . . . . 12-7A Remote Configuration . . . . . . . . . . 12-9Single-Computer Configuration Using
Network Communication. . . . . . . 12-10Distributed Databases . . . . . . . . . . . 12-12Distributed Databases Using Multiple
Vendor Servers . . . . . . . . . . 12-13
Connecting to Data on a UNIX Network . . . . . . 12-14Example of Client / Server Connections . . . . 12-15Environment Variables . . . . . . . . . . 12-16Connection Information . . . . . . . . . . 12-17SQL Connection Statements . . . . . . . . . 12-17
Accessing Tables . . . . . . . . . . . . . . 12-18Using Synonyms with Table Names . . . . . . 12-19Synonym Chains . . . . . . . . . . . . 12-20
Protecting Your Data in a NetworkedEnvironment . . . . . . . . . . . . 12-21
Data Protection with INFORMIX-SE . . . . . . 12-21Data Protection with INFORMIX-OnLine
Dynamic Server . . . . . . . . . . 12-21Data Integrity for Distributed Data . . . . . . 12-22
Summary . . . . . . . . . . . . . . . . 12-23
Table of Contents xvii
xviii In
Section III Using Advanced SQL
Chapter 12 Creating and Using Stored Procedures
Introduction to Stored Procedures and SPL . . . . . 14-3What You Can Do with Stored Procedures . . . . 14-4Relationship Between SQL and a Stored
Procedure . . . . . . . . . . . . 14-4
Creating and Using Stored Procedures . . . . . . . 14-5Creating a Procedure Using DB-Access . . . . . 14-6Creating a Procedure in a Program . . . . . . . 14-6Commenting and Documenting a Procedure . . . 14-7Diagnosing Compile-Time Errors . . . . . . . 14-7Looking at Compile-Time Warnings . . . . . . 14-9Generating the Text or Documentation . . . . . 14-10Executing a Procedure . . . . . . . . . . . 14-11Executing a Stored Procedure Dynamically . . . . 14-13Debugging a Procedure . . . . . . . . . . 14-13
Privileges on Stored Procedures . . . . . . . . . 14-16Privileges Necessary at Creation . . . . . . . 14-17Privileges Necessary at Execution . . . . . . . 14-17Revoking Privileges . . . . . . . . . . . . 14-19
Variables and Expressions . . . . . . . . . . . 14-19Variables . . . . . . . . . . . . . . . . 14-19SPL Expressions . . . . . . . . . . . . . 14-24
Program Flow Control . . . . . . . . . . . . 14-25Branching . . . . . . . . . . . . . . . 14-25Looping . . . . . . . . . . . . . . . . 14-26Function Handling . . . . . . . . . . . . 14-27
Passing Information into and out of a Procedure . . . 14-28Returning Results. . . . . . . . . . . . . 14-28
formix Guide to SQL: Tutorial
Exception Handling . . . . . . . . . . . . . 14-31Trapping an Error and Recovering . . . . . . 14-31Scope of Control of an ON EXCEPTION
Statement . . . . . . . . . . . . 14-32User-Generated Exceptions . . . . . . . . . 14-34
Summary . . . . . . . . . . . . . . . . 14-36
Chapter 13 Creating and Using Triggers
When to Use Triggers . . . . . . . . . . . . 15-3
How to Create a Trigger . . . . . . . . . . . 15-4Assigning a Trigger Name . . . . . . . . . 15-5Specifying the Trigger Event . . . . . . . . 15-5Defining the Triggered Actions . . . . . . . . 15-6A Complete CREATE TRIGGER Statement . . . 15-7
Using Triggered Actions . . . . . . . . . . . 15-7Using BEFORE and AFTER Triggered
Actions . . . . . . . . . . . . . 15-7Using FOR EACH ROW Triggered Actions . . . 15-9Using Stored Procedures as Triggered
Actions . . . . . . . . . . . . . 15-11
Tracing Triggered Actions . . . . . . . . . . . 15-13
Generating Error Messages . . . . . . . . . . 15-15Applying a Fixed Error Message . . . . . . . 15-15Generating a Variable Error Message. . . . . . 15-17
Summary . . . . . . . . . . . . . . . . 15-18
Index
Table of Contents xix
xx Info
rmix Guide to SQL: TutorialIntroduction
Introduction
Informix Products That Use SQL . . . . . . . . . . . . . . 3
Products Covered in This Manual. . . . . . . . . . . . . . 4
Other Useful Documentation . . . . . . . . . . . . . . . 4
How to Use This Manual . . . . . . . . . . . . . . . . . 5Typographical Conventions . . . . . . . . . . . . . . 5Example Code Conventions . . . . . . . . . . . . . . 7
Useful On-Line Files . . . . . . . . . . . . . . . . . . 8
ASCII and PostScript Error Message Files . . . . . . . . . . . 8
The Demonstration Database . . . . . . . . . . . . . . . 9Creating the Demonstration Database . . . . . . . . . . . 10
Compliance with Industry Standards . . . . . . . . . . . . 12
New Features in Informix Version 7.1 ProductsThat Use SQL . . . . . . . . . . . . . . . . . . 12
2 Infor
mix Guide to SQL: TutorialStructured Query Language (SQL) is an English-like language thatyou can use when creating, managing, and using relational databases. TheSQL provided with Informix products is an enhanced version of the industry-standard query language developed by International Business MachinesCorporation (IBM).
In addition to SQL, Informix provides the Stored Procedure Language (SPL)with which you can write stored procedures. Stored procedures are programsthat are stored as database objects.
Informix Products That Use SQLInformix produces many application development tools and SQL applicationprogramming interfaces (API). Application development tools currentlyavailable include products such as INFORMIX-SQL, INFORMIX-4GL, andINFORMIX-NewEra. SQL APIs currently available include INFORMIX-ESQL/Cand INFORMIX-ESQL/COBOL.
The INFORMIX-NewEra development environment can access Informixdatabase servers directly through embedded SQL statements as well asthrough the call-level interface of the CCL/INFORMIX and CCL/ODBCfunction libraries.
Informix products work with a database server, either INFORMIX-OnLineDynamic Server, INFORMIX-SE, or an INFORMIX-Gateway product. TheDB-Access database-access utility is shipped as a part of each database server.
If you are running client applications developed with Version 4.1 and 5.0application development tools, you use INFORMIX-NET to connect the clientto the network.
Introduction 3
4 Informix Guide to SQL
Products Covered in This Manual
Products Covered in This ManualAll the information presented in this manual is valid for the followingproducts. Differences in their use of SQL is indicated where appropriate.
■ INFORMIX-ESQL/C, Version 7.1
■ INFORMIX-ESQL/COBOL, Version 7.1
■ INFORMIX-SE, Version 7.1
■ INFORMIX-OnLine Dynamic Server, Version 7.1
In addition, some examples in this manual are built using Informix productsat earlier release levels.
Other Useful DocumentationYou can refer to the following related Informix documents that complementthis manual:
■ An additional companion volume to the Tutorial, the Informix Guideto SQL: Reference, provides reference information on the types ofInformix databases you can create, the data types supported inInformix products, system catalog tables associated with the data-base, environment variables, and the SQL utilities. This guide alsoprovides a detailed description of the stores7 demonstration data-base and contains a glossary.
■ An additional companion volume to the Tutorial, the Informix Guideto SQL: Syntax, provides a detailed description of all the SQL state-ments supported by Informix products. This guide also provides adetailed description of Stored Procedure Language (SPL) statements.
■ The SQL Quick Syntax Guide contains syntax diagrams for allstatements and segments described in this manual.
■ You, or whoever installs your Informix products, should refer tothe UNIX Products Installation Guide for your particular release toensure that your Informix product is properly set up before youbegin to work with it. A matrix depicting possible client/serverconfigurations is included in the UNIX Products Installation Guide.
: Tutorial
How to Use This Manual
■ Depending on the database server you are using, you or your systemadministrator need either the INFORMIX-SE Administrator’s Guide orthe INFORMIX-OnLine Dynamic Server Administrator’s Guide.
■ The DB-Access User Manual describes how to invoke the utility toaccess, modify, and retrieve information from Informix databaseservers.
■ When errors occur, you can look them up by number and learn theircause and solution in the Informix Error Messages manual. If you pre-fer, you can look up the error messages in the on-line message filedescribed in the section “ASCII and PostScript Error Message Files”on page 8 later in this Introduction and in the Introduction to theInformix Error Messages manual.
How to Use This ManualThis manual assumes that you are using INFORMIX-OnLine Dynamic Serveras your database server. Features and behavior specific to INFORMIX-SE arenoted throughout the manual.
The following sections describe the conventions used in this manual fortypographical format, syntax, and example of code.
Typographical ConventionsInformix product manuals use a standard set of conventions to introducenew 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 areprinted in italics.
boldface Database names, table names, column names, filenames, utilities, and other similar terms are printed inboldface.
Introduction 5
6 Informix Guide to SQL
Typographical Conventions
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.
computer Information that OnLine displays and information thatyou enter is printed in a computer typeface.
KEYWORD All keywords appear in uppercase letters.
✦ The diamond symbol appears at the beginning and theend of product-specific information.
This symbol indicates a unique identifier (primary key)for each table.
This symbol indicates a warning. Warnings provide crit-ical information that, if ignored, could cause harm toyour database.
This symbol indicates important information that youshould consider when working with the product.
This symbol indicates a tip. It alerts you to useful infor-mation that, for instance, might indicate a shortcut ormake it easier to navigate in the product or manual.
: Tutorial
Example Code Conventions
Example Code ConventionsExamples of SQL code occur throughout this manual. Except where noted,the code is not specific to any single Informix application development tool.If only SQL statements are listed in the example, they are not delineated bysemicolons. To use this SQL code for a specific product, you must apply thesyntax rules for that product. For example, if you are using the Query-language option of DB-Access, you must delineate multiple statements withsemicolons. If you are using an SQL API, you must use EXEC SQL and a semi-colon (or other appropriate delimiters) at the start and end of each statement,respectively.
For instance, you might see the following example code:
CONNECT TO stores7...DELETE FROM customer
WHERE customer_num = 121...COMMIT WORKDISCONNECT CURRENT
For detailed directions on using SQL statements for a particular applicationdevelopment tool or SQL API, see the manual for your product.
Also note that dots in the example indicate that more code would be addedin a full application, but it is not necessary to show it to describe the conceptbeing discussed.
Introduction 7
8 Informix Guide to SQL
Useful On-Line Files
Useful On-Line FilesIn addition to the Informix set of manuals, the following on-line files, locatedin the $INFORMIXDIR/release directory, might supplement the informationin this manual:
Please read these files because they contain vital information aboutapplication and performance issues.
ASCII and PostScript Error Message FilesInformix software products provide ASCII files that contain all the Informixerror messages and their corrective actions. To access the error messages inthe ASCII file, Informix provides scripts that let you display error messageson the screen (finderr) or print formatted error messages (rofferr). See theIntroduction to the Informix Error Messages manual for a detailed descriptionof these scripts.
The optional Informix Messages and Corrections product providesPostScript files that contain the error messages and their corrective actions. Ifyou have installed this product, you can print the PostScript files on a
DocumentationNotes
describe features not covered in the manual or that havebeen modified since publication. The file containing theDocumentation Notes for this product is calledSQLTDOC_7.1.
Release Notes describe feature differences from earlier versions ofInformix products and how these differences mightaffect current products. The file containing the ReleaseNotes for Version 7.1 of Informix database server prod-ucts is called SERVERS_7.1.
Machine Notes describe any special actions required to configure anduse Informix products on your computer. MachineNotes are named for the product described, for exam-ple, the Machine Notes file for INFORMIX-OnLineDynamic Server is ONLINE_7.1.
: Tutorial
The Demonstration Database
PostScript printer. The PostScript error messages are distributed in a numberof files of the format errmsg1.ps, errmsg2.ps, and so on. These files arelocated in the $INFORMIXDIR/msg directory.
The Demonstration DatabaseThe DB-Access utility, which is provided with your Informix database serverproducts, includes a demonstration database called stores7 that containsinformation about a fictitious wholesale sporting-goods distributor. The sam-ple command files that make up a demonstration application are alsoincluded.
Most of the examples in this manual are based on the stores7 demonstrationdatabase. The stores7 database is described in detail and its contents arelisted in Appendix A of the Informix Guide to SQL: Reference.
The script that you use to install the demonstration database is calleddbaccessdemo7 and is located in the $INFORMIXDIR/bin directory. Thedatabase name that you supply is the name given to the demonstration data-base. If you do not supply a database name, the name defaults to stores7. Fol-low these rules for naming your database:
■ Names can be up to 18 characters long for INFORMIX-OnLineDynamic Server databases and up to 10 characters long forINFORMIX-SE databases.
■ The first character of a name must be a letter or an underscore (_).
■ You can use letters, characters, and underscores (_) for the rest of thename.
■ DB-Access makes no distinction between uppercase and lowercaseletters.
■ The database name should be unique.
Introduction 9
10 Informix Guide to SQ
Creating the Demonstration Database
When you run dbaccessdemo7, you are, as the creator of the database, theowner and Database Administrator (DBA) of that database.
If you installed your Informix database server according to the installationinstructions, the files that make up the demonstration database are protectedso you cannot make any changes to the original database.
You can run the dbaccessdemo7 script again whenever you want to workwith 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 thesample command files to the current directory. Enter N if you have madechanges to the sample files and do not want them replaced with the originalversions. Enter Y if you want to copy over the sample command files.
Creating the Demonstration DatabaseUse the following steps to create and populate the demonstration database:
1. Set the INFORMIXDIR environment variable so that it contains thename of the directory in which your Informix products are installed.Set INFORMIXSERVER to the name of the default database server.The name of the default database server must exist in the$INFORMIXDIR/etc/sqlhosts file. (For a full description of environ-ment variables, see Chapter 4 of the Informix Guide to SQL: Reference.)For more information about sqlhosts, see the INFORMIX-OnLineDynamic Server Administrator’s Guide or INFORMIX-SE Administrator’sGuide.
2. Create a new directory for the SQL command files. Create thedirectory by entering the following command:
mkdir dirname
3. Make the new directory the current directory by entering thefollowing command:
cd dirname
L: Tutorial
Creating the Demonstration Database
4. Create the demonstration database and copy over the sample com-mand files by entering the dbaccessdemo7 command:
To create the database without logging enter the followingcommand:
dbaccessdemo7 dbname
To create the demonstration database with logging enter the follow-ing command:
dbaccessdemo7 -log dbname
If you are using INFORMIX-OnLine Dynamic Server, by default thedata for the database is put into the root dbspace. If you wish, youcan specify a dbspace for the demonstration database.
To create a demonstration database in a particular dbspace enter thefollowing command:
dbaccessdemo7 dbname -dbspace dbspacename
You can specify all the options in one command as shown in the fol-lowing command:
dbaccessdemo7 -log dbname -dbspace dbspacename
If you are using INFORMIX-SE, a subdirectory called dbname.dbs iscreated in your current directory and the database files associatedwith stores7 are placed there. You will see both data (.dat) and index(.idx) files in the dbname.dbs directory. (If you specify a dbspacename, it will be ignored.)
To use the database and the command files that have been copied toyour directory, you must have UNIX read and execute permissionsfor each directory in the pathname of the directory from which youran the dbaccessdemo7 script. Check with your system administra-tor for more information about operating-system file and directorypermissions. UNIX permissions are discussed in theINFORMIX-OnLine Administrator’s Guide and the INFORMIX-SE Admin-istrator’s Guide.
5. To give someone else the permissions to access the command files inyour directory, use the UNIX chmod command.
6. To give someone else the access to the database that you have cre-ated, grant them the appropriate privileges using the GRANT state-ment. To remove privileges, use the REVOKE statement. The GRANTand REVOKE statements are described in Chapter 1 of the InformixGuide to SQL: Syntax.
Introduction 11
12 Informix Guide to SQ
Compliance with Industry Standards
Compliance with Industry StandardsThe American National Standards Institute (ANSI) has established a set ofindustry standards for SQL. Informix SQL-based products are fully compliantwith SQL-92 Entry Level (published as ANSI X3.L35-1992), which is identical toISO 9075:1992 on INFORMIX-OnLine Dynamic Server. In addition, many fea-tures of OnLine comply with the SQL-92 Intermediate and Full Level andX/Open CAE (common applications environment) standards.
Informix SQL-based products are compliant with ANSI SQL-92 EntryLevel (published as ANSI X3.135-1992) on INFORMIX-SE with the followingexceptions:
■ Effective checking of constraints
■ Serializable transactions
New Features in Informix Version 7.1 ProductsThat Use SQLThe Introduction to each Version 7.1 product manual contains a list of newfeatures for that product. The Introduction to each manual in the Version 7.1Informix Guide to SQL series contains a list of new SQL features.
A comprehensive listing of all the new features for Version 7.1 Informixproducts is found in the Release Notes file called SERVERS_7.1.
This section highlights the major new features implemented in Version 7.1 ofInformix products that use SQL.
■ New FRAGMENT BY clause in the CREATE TABLE statement
The CREATE TABLE statement contains a new FRAGMENT BY clausethat allows you to create fragmented tables. Fragmentation enablesyou to define groups of rows within a table based on a rule and tospecify a separate dbspace for each group.
L: Tutorial
New Features in Informix Version 7.1 Products That Use SQL
■ New FRAGMENT BY EXPRESSION clause in the CREATE INDEXstatement
The CREATE INDEX statement contains a new FRAGMENT BYEXPRESSION clause that allows you to create fragmented indexes.
■ New ALTER FRAGMENT statement
You can use the ALTER FRAGMENT statement to dynamically alter anexisting table or index-fragmentation strategy as well as to initiallycreate fragments.
■ New ADD ROWIDS and DROP ROWIDS clauses in the ALTER TABLEstatement
You can use the ADD ROWIDS clause to add the rowid column tofragmented tables. You can use the DROP ROWIDS clause to drop therowid column from a fragmented table that has a rowid column.
■ New FRAGMENTS keyword in INFO statement
The FRAGMENTS keyword allows you to display the dbspace nameswhere fragments are located for a specified table.
■ New SET DATASKIP statement
The SET DATASKIP statement allows you to control whetherINFORMIX-OnLine Dynamic Server skips any dbspaces in the frag-mentation list that are unavailable while a transaction is beingprocessed.
■ New sysfragments system catalog table
The sysfragments table stores fragmentation information for tablesand indexes.
■ New SET PDQPRIORITY statement
The SET PDQPRIORITY statement supports the parallel-data-query(PDQ) functionality. PDQ allows queries to be processed in parallel.The SET PDQPRIORITY statement allows an application to set thequery priority level dynamically within the application. The querypriority level refers to the degree of parallelism to be used forqueries.
■ New output in the SET EXPLAIN statement
The output of the SET EXPLAIN statement has been enhanced to sup-port the new fragmentation and PDQ features.
Introduction 13
14 Informix Guide to SQ
New Features in Informix Version 7.1 Products That Use SQL
■ Changes to the dbexport and dbschema utilities
The dbexport and dbschema utilities have been enhanced to supportthe new fragmentation and PDQ features.
■ New SET TRANSACTION statement
You can now use the ANSI isolation levels for transactions. In addi-tion, the SET TRANSACTION statement permits you to use read-onlyand read-write access modes.
■ New TRIM function
The TRIM function allows you to strip leading characters or blanks,trailing characters or blanks, or both from a character string.
■ Support for delimited identifiers
Delimited identifiers allow you to specify as identifiers characterstrings that are otherwise identical to SQL reserved keywords. Theyalso allow you to specify nonalphanumeric characters in databaseobject names and to use lowercase identifiers. This feature is onlyactivated when the DELIMIDENT environment variable is set.
■ WITH REOPTIMIZATION clause for the OPEN CURSOR statement
The WITH REOPTIMIZATION clause allows you to reoptimize a queryplan if that query plan becomes deoptimized.
■ INTO clause for the EXECUTE statement
The INTO clause allows you to execute a prepared singleton selectstatement or execute a prepared EXECUTE PROCEDURE statement. Inaddition, you can specify output variables using the INTO clause.
■ New environment variables
The following environment variables, described in Chapter 4, “Envi-ronment Variables,” of the Informix Guide to SQL: Reference are new inVersion 7.1:
❑ DBBLOBBUF
❑ DELIMIDENT
❑ BUF_FET_SIZE
❑ OPTCOMPIND
❑ PDQPRIORITY
L: Tutorial
New Features in Informix Version 7.1 Products That Use SQL
■ XPG4 SQL CAE compliance
❑ X/Open information schemas
The information schema consists of a set of read-only views fromwhich you can retrieve information about any tables, views, andcolumns to which you have access.
❑ Support for CHARACTER VARYING syntax
The CHARACTER VARYING data type syntax, which is compliantwith XPG4 and ANSI, performs like the Informix data typeVARCHAR. The data type supports both a maximum and mini-mum length.
❑ Specification of cursors as READ ONLY
You can specify cursors as READ ONLY with the DECLAREstatement.
❑ Optional specification of RESTRICT/CASCADE on the DROPTABLE, DROP VIEW, and REVOKE statements
You can now restrict drop and revoke actions with the RESTRICTkeyword. Previously, all drop requests to tables and views andrevoke requests cascaded to drop all related tables, views, andpermissions. Now you can specify the RESTRICT keyword onthese statements to disallow the drop or revoke.
■ Hexadecimal load/unload format
This feature allows the LOAD/UNLOAD statements, as well as thedbexport, dbimport, and dbload utilities, to format the nonprintableASCII characters in hexadecimal format. It affects the formats ofunload files if the CHAR/VARCHAR NCHAR/NVARCHAR data typescontain nonprintable ASCII characters. It also allows you to load thenonprintable characters from the file into the database after they areprepared in hex format.
Introduction 15
on I
Using Basic SQLSect
i
1Chapter
Informix Databases
Databases: What and Why? . . . . . . . . . . . . . . . . 1-3The Data Illustration of a Data Model . . . . . . . . . . . 1-4
Storing Data . . . . . . . . . . . . . . . . . . 1-6Querying Data. . . . . . . . . . . . . . . . . . 1-7Modifying Data . . . . . . . . . . . . . . . . . 1-8
Concurrent Use and Security . . . . . . . . . . . . . . 1-9Centralized Management . . . . . . . . . . . . . . . 1-10
Group and Private Databases . . . . . . . . . . . . 1-10Essential Databases . . . . . . . . . . . . . . . . 1-11
Important Database Terms . . . . . . . . . . . . . . . . 1-12The Relational Model. . . . . . . . . . . . . . . . . 1-12
Tables . . . . . . . . . . . . . . . . . . . . . 1-12Columns. . . . . . . . . . . . . . . . . . . . 1-13Rows . . . . . . . . . . . . . . . . . . . . . 1-13Tables, Rows, and Columns . . . . . . . . . . . . . 1-14Operations on Tables . . . . . . . . . . . . . . . 1-14
Structured Query Language. . . . . . . . . . . . . . . . 1-16Standard SQL . . . . . . . . . . . . . . . . . . . 1-17Informix SQL and ANSI SQL . . . . . . . . . . . . . . 1-17ANSI-Compliant Databases . . . . . . . . . . . . . . 1-18NLS Databases . . . . . . . . . . . . . . . . . . . 1-18
The Database Software . . . . . . . . . . . . . . . . . 1-19The Applications . . . . . . . . . . . . . . . . . . 1-19The Database Server . . . . . . . . . . . . . . . . . 1-19Interactive SQL . . . . . . . . . . . . . . . . . . . 1-20Reports and Forms . . . . . . . . . . . . . . . . . 1-20General Programming . . . . . . . . . . . . . . . . 1-21Applications and Database Servers . . . . . . . . . . . . 1-21
Summary . . . . . . . . . . . . . . . . . . . . . . 1-22
1-2 Infor
mix Guide to SQL: Tutorialnformix Databases
This is a book about databases and about how you can exploit themusing Informix software. Your real use of a database begins with the SELECTstatement, which is described in Chapter 2, “Composing Simple SELECTStatements.” If you are in a hurry, and if you know at least a little aboutdatabases, turn to it now.
This chapter covers the fundamental concepts of databases and defines someterms that are used throughout the book, emphasizing the following topics:
■ What makes a database different from a collection of files?
■ What terms are used to describe the main components of a database?
■ What language is used to create, query, and modify a database?
■ What are the main parts of the software that manages a database, andhow do these parts work with each other?
Databases: What and Why?A database is a collection of information—but so is a simple computer file. Whatmakes a database so special? There must be reasons; otherwise people wouldnot spend so much money, effort, and computer time on databases. Two fun-damental differences exist. First, a database comprises not only data but alsoa plan, or model, of the data. Second, a database can be a common resource,used concurrently by many people.
Informix Databases 1-3
1-4 Informix Guide to S
The Data Illustration of a Data Model
The Data Illustration of a Data ModelThe principal difference between information collected in a database andinformation in a file is in the way the data is organized. A flat file is organizedphysically; certain items precede or follow other items. But the contents of adatabase are organized according to a data model. A data model is a plan, ormap, that defines the units of data and specifies how each unit is related tothe others.
For example, a number can appear in either a file or a database. In a file, it issimply a number that occurs at a certain point in the file. A number in a data-base, however, has a role assigned to it by the data model. It may be a pricethat is associated with a product that was sold as one item of an order that wasplaced by a customer. Each of these things—prices, products, items, orders,and customers—are also roles specified by the data model. (See Figure 1-1 onpage 1-5.)
The data model is designed when the database is created; then units of dataare inserted according to the plan laid out in the model. In some books, theterm schema is used instead of data model.
QL: Tutorial
The Data Illustration of a Data Model
1
$19.8
Figure 1-1Illustration of a data model
1015 06/27/94 1 case baseball gloves $450.00
1014 06/25/94 1 case football $960.00
1013 06/22/94 1 each tennis racquet $19.80
1012 06/18/94 1 case volleyball $ 840.00
1011 06/18/94 5 each tennis racquet $99.00
010 06/17/94 1 case tennis ball $36.00
ORDERS
order1011
06/18/94
order1003
05/22/94order1001
05/20/94 customerAnthony Higgins
item2
volleyballnets
item1 casetennis
ball
order1013
06/22/94
itemtennis
racquet
0
Informix Databases 1-5
1-6 Informix Guide to S
The Data Illustration of a Data Model
Storing Data
Another difference between a database and a file is that the organization ofthe database is stored with the database.
A file may have a complex inner structure, but the definition of that structureis 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 containvery detailed structures describing the format of the document. However,only the word-processing program can decipher the contents of the filebecause the structure is defined within the program, not within the file.
A data model, however, is contained in the database it describes. It travelswith the database and is available to any program that uses the database. Themodel 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 canfind out that, in the current database, a price item is a decimal number witheight digits, two to the right of the decimal point; then it can allocate storagefor a number of that type. How programs work with databases is the subjectof Chapter 5, “Programming with SQL,” and Chapter 6, “Modifying DataThrough SQL Programs.”
QL: Tutorial
The Data Illustration of a Data Model
10
1011
1010 0
Querying Data
Another difference between a database and a file is the way you caninterrogate them. You can search a file sequentially, looking for particularvalues at particular physical locations in each line or record. That is, youmight ask a file, “What records have numbers under 20 in the fifth field?”Figure 1-2 illustrates this type of search.
In contrast, when you query a database you use the terms defined by itsmodel. To a database, you can pose questions such as, “What orders have beenplaced for products made by the Shimara Corporation, by customers in NewJersey, with ship dates in the third quarter?” Figure 1-3 on page 1-8 illustratesthis type of query.
In other words, when you interrogate data stored in a file, you must stateyour question in terms of the physical layout of the file. When you query adatabase, you can ignore the arcane details of computer storage and stateyour query in terms that reflect the real world—at least, to the extent that thedata model reflects the real world.
Figure 1-2Searching a file
sequentially1015 06/27/94 1 case baseball gloves$450.00
1014 06/25/94 1 case footballs 960.001013 06/22/94 1 each tennis racquet $19.8006/22/94 1 case tennis ball $36.0006/22/94 1 case tennis ball $48.0006/23/9412 06/18/94 1 case volleyball $840.00
06/18/94 5 each tennis racquet $99.00
6/17/94 1 case tennis ball $36.00
ORDERS
Informix Databases 1-7
1-8 Informix Guide to S
The Data Illustration of a Data Model
manS
order1019
07/16/94
RD
--
10
In this manual, Chapter 2 and Chapter 3 discuss the language you use formaking queries. Chapter 8 and Chapter 9 discuss designing an accurate,robust data model for other users to query.
Modifying Data
The model also makes it possible to modify the contents of the database withless chance for error. You can query the database with commands such as“Find every stock item with a manufacturer of Presta or Schraeder, and increaseits price by 13 percent.” You state changes in terms that reflect the meaning ofthe data. You do not have to waste time and effort thinking about details offields 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.”
Figure 1-3Querying a database
customerCathy
O’Brian
order1016
06/29/94
order1023
07/24/94
ufacturerhimara
stateNew Jersey
custome rBob
Shorter
un: Next Restart Exitisplay the next page of query results
------stores7-----------Press CTRL-W for Help------
19 Bob Shorter SHM swim cap 07/16/94
QL: Tutorial
Concurrent Use and Security
Concurrent Use and SecurityA database can be a common resource for many users. Multiple users canquery and modify a database simultaneously. The database server (the pro-gram that manages the contents of all databases) ensures that the queries andmodifications are done in sequence and without conflict.
Having concurrent users on a database provides great advantages but alsointroduces new problems of security and privacy. Some databases are pri-vate; individuals set them up for their own use. Other databases contain con-fidential material that must be shared but among only a select group ofpersons; still other databases provide public access.
Informix database software provides the means to control database use.When you design a database, you can perform any of the followingfunctions:
■ Keep the database completely private.
■ Open its entire contents to all users or to selected users.
■ Restrict the selection of data that some users can view. (In fact, youcan reveal entirely different selections of data to different groups ofusers.)
■ Allow specified users to view certain items but not modify them.
■ Allow specified users to add new data but not modify old data.
■ Allow specified users to modify all, or specified items of, existingdata.
■ Ensure that added or modified data conforms to the data model.
The facilities that make these and other things possible are discussed inChapter 10, “Granting and Limiting Access to Your Database.”
Informix Databases 1-9
1-10 Informix Guide to
Centralized Management
Centralized ManagementDatabases that are used by many people are highly valuable and must beprotected as important business assets. This creates two significant problems:protecting data and maintaining performance. The INFORMIX-OnLineDynamic Server database server lets you 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 fordamage. 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 databaseusers 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 mitigatethese 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 theapplication programs; someone must diagnose these and correct them. Ifrapid response is important, someone must study and analyze theperformance of the system and find the causes of slow responses.
Group and Private Databases
Some Informix database servers are designed to manage relatively smalldatabases that are used privately by individuals or that are shared among asmall group of users.
These database servers (for example, INFORMIX-SE for the UNIX operatingsystem) store databases in files managed by the host operating system. Thesedatabases can be archived using the same procedures for backing up files thatwork with other computer files; that is, copying the files to another mediumwhen they are not in use. The only difference is that when a database isarchived its transaction log file must be reset to empty. (The use of transactionlogs is discussed in Chapter 7, “Programming for a Multiuser Environment.”The INFORMIX-OnLine Dynamic Server Administrator’s Guide andINFORMIX-OnLine Dynamic Server Archive and Backup Guide have moreinformation on archiving.)
SQL: Tutorial
Centralized Management
Performance problems that arise in group and private databases are usuallyrelated to particular queries that take too long. The INFORMIX-OnLineDynamic Server Performance Guide deals in depth with the reasons why aquery takes more or less time. After you understand all the features of theSELECT statement and the alternative ways of stating a query, as covered inChapter 2, “Composing Simple SELECT Statements,” and Chapter 3,“Composing Advanced SELECT Statements” in this manual, you can use theinformation in the INFORMIX-OnLine Dynamic Server Performance Guide tounderstand the performance impact of queries.
Essential Databases
The INFORMIX-OnLine Dynamic Server database server is designed tomanage large databases with requirements for high reliability, high availabil-ity, and high performance. Although it supports private and group databasesvery well, it is at its best managing the databases that are essential for yourorganization to carry out its work.
INFORMIX-OnLine Dynamic Server gives you the ability to make archivalcopies 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 bywhich its operator (or any user) can monitor the activities within the databaseserver to see when bottlenecks are developing. It also comes with utilityprograms to analyze its use of disk storage. In addition, OnLine provides thesysmaster tables that contain information about an entire OnLine databaseserver, which might manage many databases. For more information aboutthe sysmaster tables, see the INFORMIX-OnLine Dynamic ServerAdministrator’s Guide.
The INFORMIX-OnLine Dynamic Server Performance Guide contains tips onoptimizing placement of tables on disk. All the details of using and managingOnLine are contained in the INFORMIX-OnLine Dynamic ServerAdministrator’s Guide.
Informix Databases 1-11
1-12 Informix Guide to
Important Database Terms
Important Database TermsYou should know two sets of terms before beginning the next chapter. Oneset of terms describes the database and the data model; the other set describesthe computer programs that manage the database.
The Relational ModelInformix databases are relational databases. In technical terms, that meansthat the data model by which an Informix database is organized is based onthe relational calculus devised by E.F. Codd. In practical terms, it means thatall data is presented in the form of tables comprising rows and columns.
Tables
A database is a collection of information grouped into one or more tables. Atable is an array of data items organized into rows and columns. A demon-stration database is distributed with every Informix product. A partial tablefrom the demonstration database is shown in Figure 1-4.
Figure 1-4The stock table from the demonstration database distributed with all Informix products
stock_num manu_code description unit_price unit unit_descr
1 HRO baseball gloves 250.00 case 10 gloves/case
1 HSK baseball gloves 800.00 case 10 gloves/case
1 SMT baseball gloves 450.00 case 10 gloves/case
2 HRO baseball 126.00 case 24/case
3 HSK baseball bat 240.00 case 12/case
4 HSK football 960.00 case 24/case
4 HRO football 480.00 case 24/case
(1 of 2)
SQL: Tutorial
The Relational Model
A table represents all that is known about one entity, one type of thing thatthe database describes. The example table, stock, represents all that is knownabout the merchandise that is stocked by a sporting-goods store. Other tablesin the demonstration database represent such entities as customer andorders.
A database can be thought of as a collection of tables. To create a database isto create a set of tables. The right to query or modify tables can be controlledon a table-by-table basis, so that some users can view or modify some tablesand 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, whichis, one particular example of that entity. Each row of the stock table stands forone item of merchandise that is sold by the sporting-goods store.
5 NRG tennis racquet 28.00 each each
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
313 ANZ swim cap 60.00 box 12/box
stock_num manu_code description unit_price unit unit_descr
(2 of 2)
Informix Databases 1-13
1-14 Informix Guide to
The Relational Model
Tables, Rows, and Columns
You now understand that the relational model of data is a very simple wayof organizing data to reflect the world using the following simplecoresponding relationships:
Some rules apply about how you choose entities and attributes, but they areimportant only when you are designing a new database. (Database design iscovered in Chapter 8 and Chapter 9.) The data model in an existing databasealready is set. To use the database, you need to know only the names of thetables and columns and how they correspond to the real world.
Operations on Tables
Because a database is really a collection of tables, database operations areoperations on tables. The relational model supports three fundamentaloperations, two of which are illustrated in Figure 1-5 on page 1-15. (All threeoperations are defined in more detail, with many examples, in Chapter 2,“Composing Simple SELECT Statements,” and Chapter 3, “ComposingAdvanced SELECT Statements.”)
To select from a table is to choose certain rows, leaving others aside. Oneselection that could be made on the stock table is “select all rows in which themanufacturer 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. Oneprojection that can be made from the stock table is “show me the stock_num,unit_descr, and unit_price columns only.”
table = entity A table represents all that the database knows aboutone subject or kind of thing.
column = attribute A column represents one feature, characteristic, orfact that is true of the table subject.
row = instance A row represents one individual instance of thetable subject.
SQL: Tutorial
The Relational Model
P R
A table contains information about only one entity; when you wantinformation about multiple entities, you must join their tables. You can jointables in many ways. (The join operation is the subject of Chapter 3, “Com-posing Advanced SELECT Statements.”)
Figure 1-5Illustration of selection of projection
O J E C T I O N
SELECT
stock Table
stock_num manu_code description unit_priceunitunit_descr
1 HRO baseball gloves 250.00case 10 gloves/case
1 HSK baseball gloves 800.00case 10 gloves/case
1 SMT baseball gloves 450.00case 10 gloves/case
2 HRO baseball 126.00case 24/case
Informix Databases 1-15
1-16 Informix Guide to
Structured Query Language
Structured Query LanguageMost computer software has not yet reached a point where you can literallyask a database, “what orders have been placed by customers in New Jerseywith ship dates in the second quarter?” You must still phrase questions in arestricted syntax that the software can easily parse. You can pose the samequestion to the demonstration database in the following terms:
SELECT * FROM customer, ordersWHERE customer.customer_num = orders.customer_num
AND customer.state = 'NJ'AND orders.ship_dateBETWEEN DATE('7/1/94') AND DATE('7/30/94')
This question is a sample of Structured Query Language (SQL). It is thelanguage that you use to direct all operations on the database. SQL is com-posed of statements, each of which begins with one or two keywords thatspecify a function. The Informix implementation of SQL includes about 76statements, from ALLOCATE DESCRIPTOR to WHENEVER.
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 ortuning a database. People generally use three or four statements to query orupdate databases.
One statement, SELECT, is in almost constant use. It is the only statement thatyou can use to retrieve data from the database. It is also the most complicatedstatement, and the next two chapters of this book are devoted to exploring itsmany uses.
SQL: Tutorial
Standard SQL
Standard SQLSQL and the relational model were invented and developed at IBM in theearly and middle 1970s. Once IBM proved that it was possible to implementpractical relational databases and that SQL was a usable language for manip-ulating them, other vendors began to provide similar products for non-IBMcomputers.
For reasons of performance or competitive advantage, or to take advantageof local hardware or software features, each SQL implementation differed insmall ways from the others and from the IBM version of the language. Toensure that the differences remained small, a standards committee wasformed in the early 1980s.
Committee X3H2, sponsored by the American National Standards Institute(ANSI), issued the SQL1 standard in 1986. This standard defines a core set ofSQL features and the syntax of statements such as SELECT.
Informix SQL and ANSI SQLThe SQL version that is supported by Informix products is highly compatiblewith standard SQL (it is also compatible with the IBM version of the lan-guage). However, it does contain extensions to the standard; that is, extraoptions or features for certain statements, and looser rules for others. Most ofthe differences occur in the statements that are not in everyday use. Forexample, few differences occur in the SELECT statement, which accounts for90 percent of the SQL use for a typical person.
However, the extensions do exist, and that creates a conflict. Thousands ofInformix customers have embedded Informix-style SQL in programs andstored queries. They rely on Informix to keep its language the same. Othercustomers require the ability to use databases in a way that conforms exactlyto the ANSI standard. They rely on Informix to change its language toconform.
Informix Databases 1-17
1-18 Informix Guide to
ANSI-Compliant Databases
Informix resolved the conflict with the following compromise:
■ The Informix version of SQL, with its extensions to the standard, isavailable by default.
■ You can ask any Informix SQL language processor to check your useof SQL and post a warning flag whenever you use an Informixextension.
This resolution is fair but makes the SQL documentation more complicated.Wherever a difference exists between Informix and ANSI SQL, the InformixGuide to SQL: Syntax describes both versions. Because you probably intend touse only one version, simply ignore the version you do not need.
ANSI-Compliant DatabasesYou can designate a database as ANSI-compliant by using the MODE ANSIkeywords when you create it. Within such a database, certain characteristicsof the ANSI standard apply. For example, all actions that modify data auto-matically take place within a transaction, which means that the changes aremade in their entirety or not at all. Differences in the behavior of ANSI-compliant databases are noted where appropriate in the Informix Guide toSQL: Syntax.
NLS DatabasesThe Version 6.0 and later Informix database servers provide Native LanguageSupport (NLS). This allows you to work in various European or Latin Amer-ican languages other than English and conform to the customs of a specificlocale (various money and date formats, foreign characters in data or identi-fier names, different collation order, and so on). You can activate the NLSfunctionality by setting the DBNLS environment variable as well as otherNLS-specific environment variables.
Chapter 4 of the Informix Guide to SQL: Reference describes how to set the NLSenvironment variables. For additional information on NLS databases, seeChapter 1 in the Informix Guide to SQL: Reference.
SQL: Tutorial
The Database Software
The Database SoftwareYou access your database through two layers of sophisticated software. Thetop layer, or application, sends commands or queries to the database server.The application calls on the bottom layer, or database server, and gets backinformation. You command both layers using SQL.
The ApplicationsA database application, or simply application, is a program that uses thedatabase. It does so by communicating with the database server. At itssimplest, the application sends SQL commands to the database server, andthe database server sends rows of data back to the application. Then theapplication 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 andpasses this command to the database server for execution.
Several types of applications exist. Some allow you to access the databaseinteractively using SQL; others present the stored data in different formsrelated to its use.
The Database ServerThe database server is the program that manages the contents of the databaseas they are stored on disk. The database server knows how tables, rows, andcolumns are actually organized in physical computer storage. The databaseserver also interprets and executes all SQL commands.
Informix Databases 1-19
1-20 Informix Guide to
Interactive SQL
Interactive SQLTo carry out the examples in this book, and to experiment with SQL anddatabase design for yourself, you need a program that lets you execute SQLstatements interactively. DB-Access and INFORMIX-SQL are two such pro-grams. They assist you in composing SQL statements; then they pass yourSQL to the database server for execution and display the results to you.
Reports and FormsAfter you perfect a query to return precisely the data in which you are inter-ested, you need to format the data for display as a report or form on the ter-minal screen. ACE is the report generator for INFORMIX-SQL. You provide toACE a SELECT statement that returns the rows of data and a report specifica-tion stating how the pages of the report are to be laid out. ACE compiles thisinformation into a program that you can run whenever you want to producethat report. With INFORMIX-4GL and INFORMIX-NewEra, you can use the 4GLreport language to create formatted display.
PERFORM is the module of INFORMIX-SQL that generates interactive screenforms. You prepare a form specification that relates display fields on thescreen to columns within tables in the database. PERFORM compiles this spec-ification into a program that you can run at any time. When run, the form pro-gram interrogates the database to display a row or rows of data on the screenin the format you specified. You can arrange the form so that the user cantype in sample values and have matching rows returned from the database(the query-by-example feature).
NewEra provides a Form Painter and a Visual Class Library for display ofdata in a graphical environment. INFORMIX-4GL also supports form specifi-cation files for screen display of data. For more information on theseproducts, refer to the manuals that come with them.
SQL: Tutorial
General Programming
General ProgrammingYou can write programs that incorporate SQL statements and exchange datawith the database server. That is, you can write a program to retrieve datafrom 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 itinto the database.
The most convenient programming languages for this kind of work are New-Era, with an object-oriented language, and INFORMIX-4GL with a procedurallanguage. Both are designed expressly for writing database applications.However, you can also communicate with an Informix database server fromprograms that contain embedded SQL written in C AND COBOL.
You also can write programs called stored procedures to work with databasedata and objects. The stored procedures that you write are stored directly ina database within tables. You can then execute a stored procedure fromDB-Access or an SQL API.
Chapter 5, “Programming with SQL,” and Chapter 6, “Modifying DataThrough SQL Programs,” present an overview of how SQL is used inprograms.
Applications and Database ServersEvery program that uses data from a database operates the same way.Regardless of whether it is a packaged program such as ViewPoint Pro, areport program compiled by ACE, or a program that you wrote usingINFORMIX-NewEra or an SQL API, you find the same two layers in every case:
1. An application that interacts with the user, prepares and formatsdata, and sets up SQL statements.
2. A database server that manages the database and interprets the SQL.
All the applications make requests of the database server, and only thedatabase server manipulates the database files on disk.
Informix Databases 1-21
1-22 Informix Guide to
Summary
SummaryA database contains a collection of related information but differs in afundamental way from other methods of storing data. The database containsnot only the data but also a data model that defines each data item andspecifies its meaning with respect to the other items and to the real world.
A database can be used and even modified by several computer usersworking concurrently. Different users can be given different views of the con-tents of a database, and their access to those contents can be restricted inseveral ways.
A database can be crucially important to the success of an organization andcan require central administration and monitoring. The OnLine databaseserver caters to the needs of essential applications; both OnLine andINFORMIX-SE support smaller databases for private or group use.
You manipulate and query a database using SQL, which was pioneered byIBM and standardized by ANSI. You can take advantage of the Informixextensions to the ANSI-defined language, and your Informix tools also makeit possible to maintain strict compliance with ANSI standards.
Two layers of software mediate all your work with databases. The bottomlayer is always a database server that executes SQL statements and managesthe data on disk and in computer memory. The top layer is one of many appli-cations, some from Informix and some written by you or written by othervendors or your colleagues.
SQL: Tutorial
2Chapter
Composing Simple SELECTStatements
Introducing the SELECT Statement . . . . . . . . . . . . . 2-4Some Basic Concepts . . . . . . . . . . . . . . . . . 2-5
Privileges . . . . . . . . . . . . . . . . . . . 2-5Relational Operations . . . . . . . . . . . . . . . 2-5Selection and Projection . . . . . . . . . . . . . . 2-6Joining . . . . . . . . . . . . . . . . . . . . 2-9
The Forms of SELECT . . . . . . . . . . . . . . . . 2-11Special Data Types. . . . . . . . . . . . . . . . . . 2-11
Single-Table SELECT Statements . . . . . . . . . . . . . . 2-12Selecting All Columns and Rows. . . . . . . . . . . . . 2-12
Using the Asterisk Symbol (*) . . . . . . . . . . . . 2-12Reordering the Columns . . . . . . . . . . . . . . 2-13Sorting the Rows . . . . . . . . . . . . . . . . . 2-14
Selecting Specific Columns . . . . . . . . . . . . . . . 2-18ORDER BY and Native Language Support . . . . . . . . 2-25Selecting Substrings . . . . . . . . . . . . . . . . 2-27
Using the WHERE Clause . . . . . . . . . . . . . . . 2-28Creating a Comparison Condition . . . . . . . . . . . . 2-29
Using Variable Text Searches . . . . . . . . . . . . . 2-38Using Exact Text Comparisons . . . . . . . . . . . . 2-39Using a Single-Character Wildcard. . . . . . . . . . . 2-40MATCHES and Native Language Support . . . . . . . . 2-43Comparing for Special Characters . . . . . . . . . . . 2-45
Expressions and Derived Values . . . . . . . . . . . . . 2-47Arithmetic Expressions. . . . . . . . . . . . . . . 2-47Sorting on Derived Columns . . . . . . . . . . . . . 2-52
Using Functions in SELECT Statements . . . . . . . . . . 2-53Aggregate Functions . . . . . . . . . . . . . . . 2-53Time Functions . . . . . . . . . . . . . . . . . 2-56Other Functions and Keywords . . . . . . . . . . . . 2-62
Using Stored Procedures in SELECT Statements . . . . . . . 2-67
2-2 Infor
Multiple-Table SELECT Statements . . . . . . . . . . . . . 2-69Creating a Cartesian Product . . . . . . . . . . . . . . 2-69Creating a Join . . . . . . . . . . . . . . . . . . . 2-71
Equi-Join. . . . . . . . . . . . . . . . . . . . 2-71Natural Join. . . . . . . . . . . . . . . . . . . 2-75Multiple-Table Join . . . . . . . . . . . . . . . . 2-78
Some Query Shortcuts . . . . . . . . . . . . . . . . 2-80Using Aliases . . . . . . . . . . . . . . . . . . 2-80The INTO TEMP Clause . . . . . . . . . . . . . . 2-83
Summary . . . . . . . . . . . . . . . . . . . . . . 2-84
mix Guide to SQL: Tutorial
SELECT is the most important and the most complex SQL statement.It is used, along with the SQL statements INSERT, UPDATE, and DELETE, tomanipulate data. You can use the SELECT statement in the following ways:
■ By itself to retrieve data from a database
■ As part of an INSERT statement to produce new rows
■ As part of an UPDATE statement to update information
The SELECT statement is the primary way to query on information in adatabase. It is your key to retrieving data in a program, report, screen form,or spreadsheet.
This chapter shows how you can use the SELECT statement to query on andretrieve data in a variety of ways from a relational database. It discusses howto tailor your statements to select columns or rows of information from oneor more tables, how to include expressions and functions in SELECT state-ments, and how to create various join conditions between relational databasetables.
This chapter introduces the basic methods for retrieving data from arelational database. More complex uses of SELECT statements, such as sub-queries, outer joins, and unions, are discussed in Chapter 3, “ComposingAdvanced SELECT Statements.” The syntax and usage for the SELECT state-ment are described in detail in Chapter 1 of the Informix Guide to SQL: Syntax.
Most examples in this chapter come from the tables in the stores7demonstration database, which is installed with the software for yourInformix SQL API or database utility. In the interest of brevity, the examplesmay show only part of the data that is retrieved for each SELECT statement.See Appendix A in the Informix Guide to SQL: Reference for information on thestructure and contents of the stores7 database. For emphasis, keywordsare shown in uppercase letters in the examples, although SQL is notcase-sensitive.
Composing Simple SELECT Statements 2-3
2-4 Informix Guide to S
Introducing the SELECT Statement
Introducing the SELECT StatementThe SELECT statement is constructed of clauses that let you look at data in arelational database. These clauses let you select columns and rows from oneor more database tables or views, specify one or more conditions, order andsummarize the data, and put the selected data in a temporary table.
This chapter shows how to use five SELECT statement clauses. You mustinclude these clauses in a SELECT statement in the following order:
1. SELECT clause
2. FROM clause
3. WHERE clause
4. ORDER BY clause
5. INTO TEMP clause
Only the SELECT and FROM clauses are required. These two clauses form thebasis for every database query because they specify the tables and columnsto be retrieved. Use one or more of the other clauses from the following list:
■ Add a WHERE clause to select specific rows or create a join condition.
■ Add an ORDER BY clause to change the order in which data is pro-duced.
■ Add an INTO TEMP clause to save the results as a table for furtherqueries.
Two additional SELECT statement clauses, GROUP BY and HAVING, enableyou to perform more complex data retrieval. They are introduced inChapter 3, “Composing Advanced SELECT Statements.” Another clause,INTO, is used to specify the program or host variable to receive data from aSELECT statement in the INFORMIX-NewEra, INFORMIX-4GL and SQL APIs.Complete syntax and rules for using the SELECT statement are shown inChapter 1 of the Informix Guide to SQL: Syntax.
QL: Tutorial
Some Basic Concepts
Some Basic ConceptsThe SELECT statement, unlike INSERT, UPDATE, and DELETE statements, doesnot modify the data in a database. It is used simply to query on the data.Whereas only one user at a time can modify data, multiple users can queryon or select the data concurrently. The statements that modify data are dis-cussed in Chapter 4, “Modifying Data.” The INSERT, UPDATE, and DELETEstatements appear in Chapter 1 of the Informix Guide to SQL: Syntax.
In a relational database, a column is a data element that contains a particulartype of information that occurs in every row in the table. A row is a group ofrelated items of information about a single entity across all columns in adatabase table.
You can select columns and rows from a database table; from a system catalogtable, a file that contains information on the database; or from a view, which isa virtual table created to contain a customized set of data. System catalogtables are shown in Chapter 2 of the Informix Guide to SQL: Reference. Viewsare discussed in Chapter 10, “Granting and Limiting Access to Your Data-base,” of this manual.
Privileges
Before you can query on data, you must have the Connect privilege to thedatabase and the Select privilege to the tables in it. These privileges arenormally granted to all users. Database access privileges are discussed inChapter 10, “Granting and Limiting Access to Your Database,” of thismanual and in the GRANT and REVOKE statements in Chapter 1 of theInformix Guide to SQL: Syntax.
Relational Operations
A relational operation involves manipulating one or more tables, or relations, toresult in another table. The three kinds of relational operation are selection,projection, and join. This chapter includes examples of selection, projection,and simple joining.
Composing Simple SELECT Statements 2-5
2-6 Informix Guide to S
Some Basic Concepts
customer_numfnamelnamecompanyaddress1address2citystatezipcodephone
customer_numfnamelnamecompanyaddress1address2citystatezipcodephone
Selection and Projection
In relational terminology, selection is defined as taking the horizontal subset ofrows of a single table that satisfies a particular condition. This kind of SELECTstatement returns some of the rows and all of the columns in a table. Selectionis implemented through the WHERE clause of A SELECT statement, as shownin Query 2-1:
Query 2-1SELECT * FROM customer
WHERE state = 'NJ'
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 doesnot fit on one line of the DB-Access or INFORMIX-SQL Interactive SchemaEditor (ISED) screen, the data is displayed vertically instead of horizontally.
Query Result 2-1119BobShorterThe Triathletes Club
2405 Kings Highway
Cherry HillNJ08002609-663-6079
122CathyO’BrianThe Sporting Life
543 Nassau Street
PrincetonNJ08540609-342-0054
QL: Tutorial
Some Basic Concepts
city
BartlesvilleBlue IslandBrightonCherry HillDenverJacksonvilleLos AltosMenlo ParkMountain ViewMountain ViewOaklandPalo AltoPalo AltoPhoenixPhoenixPrincetonRedwood CityRedwood CityRedwood CitySan FranciscoSunnyvaleSunnyvaleWilmington
In relational terminology, projection is defined as taking a vertical subset fromthe columns of a single table that retains the unique rows. This kind ofSELECT statement returns some of the columns and all of the rows in a table.
Projection is implemented through the select list in the SELECT clause of aSELECT statement, as shown in Query 2-2:
Query 2-2SELECT UNIQUE city, state, zipcode
FROM customer
Query Result 2-2 contains the same number of rows as the customer table,but it projects only a subset of the columns in the table:
Query Result 2-2state zipcode
OK 74006NY 60406MA 02135
NJ 08002CO 80219
FL 32256CA 94022CA 94025
CA 94040CA 94063CA 94609
CA 94303CA 94304AZ 85008AZ 85016
NJ 08540CA 94026CA 94062CA 94063
CA 94117CA 94085CA 94086
DE 19898
Composing Simple SELECT Statements 2-7
2-8 Informix Guide to S
Some Basic Concepts
city
Cherry HillPrinceton
The most common kind of SELECT statement uses both selection andprojection. A query of this kind, shown in Query 2-3, returns some of therows and some of the columns in a table:
Query 2-3SELECT UNIQUE city, state, zipcode
FROM customerWHERE state = 'NJ'
Query Result 2-3 contains a subset of the rows and a subset of the columns inthe customer table:
Query Result 2-3state zipcode
NJ 08002NJ 08540
QL: Tutorial
Some Basic Concepts
1 1001
1 1002
2 1002
3 1003
1 1005
3
1
item_num order_
items Table (e
1
1
item_num
Joining
A join occurs when two or more tables are connected by one or more columnsin common, creating a new table of results. The query in the example uses asubset of the items and stock tables to illustrate the concept of a join, asshown in Figure 2-1.
Figure 2-1Example of a join between two tables
1
4
3
5
5
4 HSK football
2 HRO baseball
1 HSK baseball gloves
1 HRO baseball gloves
5 NRG tennis racquet
1003
1005
num stock_num stock_num manu_code description
xample)
1002
1001
stock Table (example)
order_num stock_num description
SELECT unique item_num, order_num, stock.stock_num,description
FROM items, stockWHERE items.stock_num = stock.stock_num
5 tennis racquet
1 baseball gloves
4 football
5 tennis racquet
Composing Simple SELECT Statements 2-9
2-10 Informix Guide to
Some Basic Concepts
city
BartlesvilleBlue IslandBrightonCherry HillDenverJacksonvilleLos AltosMenlo ParkMountain ViewMountain ViewOaklandPalo AltoPalo AltoPhoenixPhoenixPrincetonRedwood CityRedwood CityRedwood CitySan FranciscoSunnyvaleSunnyvaleWilmington
Query 2-4 joins the customer and state tables:
Query 2-4SELECT UNIQUE city, state, zipcode, sname
FROM customer, stateWHERE customer.state = state.code
Query Result 2-4 is composed of specified rows and columns from both thecustomer and state tables:
Query Result 2-4state zipcode sname
OK 74006 OklahomaNY 60406 New YorkMA 02135 Massachusetts
NJ 08002 New JerseyCO 80219 Colorado
FL 32256 FloridaCA 94022 CaliforniaCA 94025 California
CA 94040 CaliforniaCA 94063 CaliforniaCA 94609 California
CA 94303 CaliforniaCA 94304 CaliforniaAZ 85008 ArizonaAZ 85016 Arizona
NJ 08540 New JerseyCA 94026 CaliforniaCA 94062 CaliforniaCA 94063 California
CA 94117 CaliforniaCA 94085 CaliforniaCA 94086 California
DE 19898 Delaware
SQL: Tutorial
The Forms of SELECT
The Forms of SELECTAlthough the syntax remains the same across all Informix products, the formof a SELECT statement and the location and formatting of the resulting outputdepends on the application. The examples in this chapter and in Chapter 3,“Composing Advanced SELECT Statements,” display the SELECT statementsand their output as they appear when you use the interactive Query-language option in DB-Access or INFORMIX-SQL.
You also can use SELECT statements to query on data noninteractivelythrough INFORMIX-SQL ACE reports, you can embed them in a language suchas INFORMIX-ESQL/C (where they are treated as executable code), you canincorporate them in INFORMIX-4GL as part of its fourth-generation language,or with INFORMIX-NewEra, you can either have them automaticallygenerated or embed them.
Special Data TypesThe examples in this chapter use the INFORMIX-OnLine Dynamic Server data-base server, which enables database applications to include the data typesVARCHAR, TEXT, and BYTE. These data types are not available to applicationsthat run on INFORMIX-SE.
With the DB-Access or INFORMIX-SQL Interactive Editor, when you issue aSELECT statement that includes one of these three data types, the results ofthe query are displayed differently.
■ If you execute a query on a VARCHAR column, the entire VARCHARvalue is displayed, just as CHARACTER values are displayed.
■ If you select a TEXT column, the contents of the TEXT column aredisplayed and you can scroll through them.
■ If you query on a BYTE column, the words <BYTE value> are dis-played instead of the actual value.
Differences specific to VARCHAR, TEXT, and BYTE are noted as appropriatethroughout this chapter.
When Native Language Support (NLS) is enabled, you can issue a SELECTstatement that queries on NCHAR or NVARCHAR columns instead of theirCHAR or VARCHAR counterparts. The NCHAR and NVARCHAR data typesallow foreign characters in character data.
Composing Simple SELECT Statements 2-11
2-12 Informix Guide to
Single-Table SELECT Statements
For additional information on these and other data types, see Chapter 9,“Implementing Your Data Model,” in this manual, and Chapter 3 in theInformix Guide to SQL: Reference.
Single-Table SELECT StatementsYou can query a single table in a database in many ways. You can tailor aSELECT statement to perform the following actions:
■ Retrieve all or specific columns
■ Retrieve all or specific rows
■ Perform computations or other functions on the retrieved data
■ Order the data in various ways
Selecting All Columns and RowsThe most basic SELECT statement contains only the two required clauses,SELECT and FROM.
Using the Asterisk Symbol (*)
Query 2-5a specifies all the columns in the manufact table in a select list. Aselect list is a list of the column names or expressions that you want to projectfrom a table.
Query 2-5aSELECT manu_code, manu_name, lead_time
FROM manufact
Query 2-5b uses the wildcard asterisk symbol (*), which is shorthand for theselect list. The * represents the names of all the columns in the table. You canuse the asterisk symbol (*) when you want all the columns, in their definedorder.
Query 2-5bSELECT * FROM manufact
SQL: Tutorial
Selecting All Columns and Rows
manu_code m
SMT ANZ NRG HSK HRO SHM KAR NKL PRC
manu_name
Smith Anza Norge Husky Hero Shimara Karsten Nikolus ProCycle
Query 2-5a and Query 2-5b are equivalent and display the same results; thatis, a list of every column and row in the manufact table. Query Result 2-5shows the results as they would appear on a DB-Access or INFORMIX-SQLISED screen.
Reordering the Columns
Query 2-6 shows how you can change the order in which the columns arelisted by changing their order in your select list:
Query 2-6SELECT manu_name, manu_code, lead_time
FROM manufact
Query Result 2-6 includes the same columns as the previous one, but becausethe columns are specified in a different order, the display is also different:
Query Result 2-5
Query Result 2-6
anu_name lead_time
Smith 3Anza 5Norge 7Husky 5Hero 4Shimara 30Karsten 21Nikolus 8ProCycle 9
manu_code lead_time
SMT 3ANZ 5NRG 7HSK 5HRO 4SHM 30KAR 21NKL 8PRC 9
Composing Simple SELECT Statements 2-13
2-14 Informix Guide to
Selecting All Columns and Rows
manu_code m
SMT HRO HSK ANZ NRG NKL PRC KAR SHM
Sorting the Rows
You can direct the system to sort the data in a specific order by adding anORDER BY clause to your SELECT statement. The columns you want to use inthe ORDER BY clause must be included in the select list either explicitly orimplicitly.
An explicit select list, shown in Query 2-7a, includes all the column namesthat you want to retrieve:
Query 2-7aSELECT manu_code, manu_name, lead_time
FROM manufactORDER BY lead_time
An implicit select list uses the asterisk symbol (*), as shown in Query 2-7b:
Query 2-7bSELECT * FROM manufact
ORDER BY lead_time
Query 2-7a and Query 2-7b produce the same display. Query Result 2-7shows a list of every column and row in the manufact table, in order oflead_time:
Query Result 2-7anu_name lead_time
Smith 3Hero 4Husky 5Anza 5Norge 7Nikolus 8ProCycle 9Karsten 21Shimara 30
SQL: Tutorial
Selecting All Columns and Rows
manu_code m
SHM KAR K PRC P NKL N NRG HSK H ANZ A HRO SMT S
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 DATETIMEtype data are sorted from earliest to latest, and INTERVAL data is orderedfrom shortest to longest span of time.
Descending Order
Descending order is the opposite of ascending order, from lowercase z touppercase A for character types and highest to lowest for numeric data types.DATE and DATETIME data are sorted from latest to earliest, and INTERVALdata is ordered from longest to shortest span of time. Query 2-8 shows anexample of descending order:
Query 2-8SELECT * FROM manufact
ORDER BY lead_time DESC
The keyword DESC following a column name causes the retrieved data to besorted in descending order, as shown in Query Result 2-8:
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 Result 2-8anu_name lead_time
Shimara 30arsten 21roCycle 9ikolus 8
Norge 7usky 5nza 5
Hero 4mith 3
Composing Simple SELECT Statements 2-15
2-16 Informix Guide to
Selecting All Columns and Rows
stock_num manu_c
5 ANZ9 ANZ6 ANZ
313 ANZ201 ANZ310 ANZ301 ANZ304 ANZ110 ANZ205 ANZ
8 ANZ302 HRO309 HRO...113 SHM
5 SMT6 SMT1 SMT
Sorting on Multiple Columns
You can also ORDER BY two or more columns, creating a nested sort. Thedefault is still ascending, and the column listed first in the ORDER BY clausetakes precedence.
Query 2-9 and Query 2-10 and corresponding query results show nestedsorts. The order in which selected data is displayed is modified by changingthe order of the two columns named in the ORDER BY clause.
Query 2-9SELECT * FROM stock
ORDER BY manu_code, unit_price
In Query Result 2-9, the manu_code column data appears in alphabeticalorder and, within each set of rows with the same manu_code (for example,ANZ, HRO), the unit_price is listed in ascending order:
Query Result 2-9ode description unit_price unit unit_descr
tennis racquet $19.80 each eachvolleyball net $20.00 each eachtennis ball $48.00 case 24 cans/caseswim cap $60.00 box 12/boxgolf shoes $75.00 each eachkick board $84.00 case 12/caserunning shoes $95.00 each eachwatch $170.00 box 10/boxhelmet $244.00 case 4/case3 golf balls $312.00 case 24/casevolleyball $840.00 case 24/caseice pack $4.50 each eachear drops $40.00 case 20/case
18-spd, assmbld $685.90 each eachtennis racquet $25.00 each eachtennis ball $36.00 case 24 cans/casebaseball gloves $450.00 case 10 gloves/case
SQL: Tutorial
Selecting All Columns and Rows
stock_num manu_c
302 HRO302 KAR
5 ANZ9 ANZ
103 PRC106 PRC
5 SMT...301 HRO204 KAR108 SHM
6 ANZ305 HRO303 PRC311 SHM...110 HSK205 ANZ205 HRO205 NKL
1 SMT4 HRO
102 PRC111 SHM112 SHM
7 HRO203 NKL113 SHM
1 HSK8 ANZ4 HSK
Query 2-10 shows the reversed order of the columns in the ORDER BY clause:
Query 2-10SELECT * FROM stock
ORDER BY unit_price, manu_code
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:
Query Result 2-10ode description unit_price unit unit_descr
ice pack $4.50 each eachice pack $5.00 each eachtennis racquet $19.80 each eachvolleyball net $20.00 each eachfrnt derailleur $20.00 each eachbicycle stem $23.00 each eachtennis racquet $25.00 each each
running shoes $42.50 each eachputter $45.00 each eachcrankset $45.00 each eachtennis ball $48.00 case 24 cans/casefirst-aid kit $48.00 case 4/casesocks $48.00 box 24 pairs/boxwater gloves $48.00 box 4 pairs/box
helmet $308.00 case 4/case3 golf balls $312.00 case 24/case3 golf balls $312.00 case 24/case3 golf balls $312.00 case 24/casebaseball gloves $450.00 case 10 gloves/casefootball $480.00 case 24/casebicycle brakes $480.00 case 4 sets/case10-spd, assmbld $499.99 each each12-spd, assmbld $549.00 each eachbasketball $600.00 case 24/case
irons/wedge $670.00 case 2 sets/case18-spd, assmbld $685.90 each eachbaseball gloves $800.00 case 10 gloves/casevolleyball $840.00 case 24/casefootball $960.00 case 24/case
Composing Simple SELECT Statements 2-17
2-18 Informix Guide to
Selecting Specific Columns
The order of the columns in the ORDER BY clause is important, and so is theposition of the DESC keyword. Although the statements in Query 2-11 con-tain the same components in the ORDER BY clause, each produces a differentresult (not shown):
Query 2-11SELECT * FROM stock
ORDER BY manu_code, unit_price DESC
SELECT * FROM stockORDER BY unit_price, manu_code DESC
SELECT * FROM stockORDER BY manu_code DESC, unit_price
SELECT * FROM stockORDER BY unit_price DESC, manu_code
Selecting Specific ColumnsThe previous section showed how to select and order all data from a table.However, often all you want to see is the data in one or more specific col-umns. Again, the formula is to use the SELECT and FROM clauses, specify thecolumns and table, and perhaps order the data in ascending or descendingorder with an ORDER BY clause.
SQL: Tutorial
Selecting Specific Columns
customer_num
1010101010101011111111111111111112121212121212
If you want to find all the customer numbers in the orders table, you woulduse a statement such as the one in Query 2-12:
Query 2-12SELECT customer_num FROM orders
Query Result 2-12 shows how the statement simply selects all data in thecustomer_num column in the orders table and lists the customer numbers onall the orders, including duplicates:
The output includes several duplicates because some customers have placedmore 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 ofteneach value appears.
Query Result 2-12
14444660012567790123467
Composing Simple SELECT Statements 2-19
2-20 Informix Guide to
Selecting Specific Columns
customer_num
1010101111111111111112121212121212
You can cause duplicate rows to be suppressed by including the keywordDISTINCT or its synonym UNIQUE at the start of the select list, as shown inQuery 2-13:
Query 2-13SELECT DISTINCT customer_num FROM orders
SELECT UNIQUE customer_num FROM orders
Query 2-13 limits the display to show each customer number in the orderstable only once, producing a more readable list, as shown in Query Result2-13:
Query Result 2-13
14601256790123467
SQL: Tutorial
Selecting Specific Columns
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
Suppose you are handling a customer call, and you want to locate purchaseorder number DM354331. You decide to list all the purchase order numbers inthe orders table, using a statement such as the one shown in Query 2-14:
Query 2-14SELECT po_num FROM orders
Query Result 2-14 shows how the statement retrieves data in the po_numcolumn in the orders table:
Query Result 2-14
Composing Simple SELECT Statements 2-21
2-22 Informix Guide to
Selecting Specific Columns
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
However, the list is not in a very useful order. You can add an ORDER BYclause to sort the column data in ascending order and make it easier to findthat particular po_num, as shown in Query Result 2-15:
Query 2-15SELECT po_num FROM orders
ORDER BY po_num
Query Result 2-15
SQL: Tutorial
Selecting Specific Columns
paid_date ship_da
05/30
06/0506/2907/1207/13
06/03/1994 05/26/106/14/1994 05/23/106/21/1994 06/09/107/10/1994 07/03/107/21/1994 07/06/107/22/1994 06/01/107/31/1994 07/10/108/06/1994 07/13/108/06/1994 07/16/108/21/1994 06/21/108/22/1994 06/29/108/22/1994 07/25/108/22/1994 07/30/108/29/1994 07/03/108/31/1994 07/16/109/02/1994 07/30/109/20/1994 07/16/1
To select multiple columns from a table, list them in the select list in theSELECT clause. Query 2-16 shows the order in which the columns are selectedis the order in which they are produced, from left to right:
Query 2-16SELECT paid_date, ship_date, order_date,
customer_num, order_num, po_numFROM ordersORDER BY paid_date, order_date, customer_num
As shown in “Sorting on Multiple Columns” on page 2-16, you can use theORDER BY clause to sort the data in ascending or descending order andperform nested sorts. Query Result 2-16 shows descending order:
Query Result 2-16te order_date customer_num order_num po_num
/1994 05/22/1994 106 1004 800605/30/1994 112 1006 Q13557
/1994 05/31/1994 117 1007 278693/1994 06/18/1994 117 1012 278701/1994 06/29/1994 119 1016 PC6782/1994 07/09/1994 120 1017 DM354331994 05/21/1994 101 1002 9270994 05/22/1994 104 1003 B77890994 05/24/1994 116 1005 2865994 06/25/1994 106 1014 8052994 06/07/1994 110 1008 LZ230994 05/20/1994 104 1001 B77836994 06/22/1994 104 1013 B77930994 07/10/1994 121 1018 S22942994 07/11/1994 122 1019 Z55709994 06/14/1994 111 1009 4745994 06/17/1994 115 1010 429Q994 07/23/1994 124 1021 C3288994 07/24/1994 127 1023 KF2961994 06/18/1994 104 1011 B77897994 06/27/1994 110 1015 MA003994 07/24/1994 126 1022 W9925994 07/11/1994 123 1020 W2286
Composing Simple SELECT Statements 2-23
2-24 Informix Guide to
Selecting Specific Columns
customer_num
104101104106116112117110111115104117104106110119120121122123124126127
When you use SELECT and ORDER BY on several columns in a table, youmight find it helpful to use integers to refer to the position of the columns inthe ORDER BY clause.The statements in Query 2-17 retrieve and display thesame data, shown in Query Result 2-17.
Query 2-17SELECT customer_num, order_num, po_num, order_date
FROM ordersORDER BY 4, 1
SELECT customer_num, order_num, po_num, order_dateFROM ordersORDER BY order_date, customer_num
Query Result 2-17order_num po_num order_date
1001 B77836 05/20/19941002 9270 05/21/19941003 B77890 05/22/19941004 8006 05/22/19941005 2865 05/24/19941006 Q13557 05/30/19941007 278693 05/31/19941008 LZ230 06/07/19941009 4745 06/14/19941010 429Q 06/17/19941011 B77897 06/18/19941012 278701 06/18/19941013 B77930 06/22/19941014 8052 06/25/19941015 MA003 06/27/19941016 PC6782 06/29/19941017 DM354331 07/09/19941018 S22942 07/10/19941019 Z55709 07/11/19941020 W2286 07/11/19941021 C3288 07/23/19941022 W9925 07/24/19941023 KF2961 07/24/1994
SQL: Tutorial
Selecting Specific Columns
You can include the DESC keyword in the ORDER BY clause when you assignintegers to column names, as shown in Query 2-18:
Query 2-18SELECT customer_num, order_num, po_num, order_date
FROM ordersORDER BY 4 DESC, 1
In this case, data is first sorted in descending order by order_date and inascending order by customer_num.
ORDER BY and Native Language Support
You can set the DBNLS environment variable to activate Native LanguageSupport (NLS) functionality. You can then specify a language environment(locale) by setting the LANG environment variable and can set theLC_COLLATE environment variable to further define the collation order.
Query 2-19 uses a SELECT statement with an ORDER BY clause on a columncontaining data of type NCHAR (the NLS equivalent of CHAR). This NLS table,abonnés, is provided separately from the demonstration database; thisSELECT statement example is provided as the sel_nls1.sql command file withNLS-enabled DB-Access.
Query 2-19SELECT numéro,nom,prénom
FROM abonnésORDER BY nom;
The collation order for the results of this query may vary, depending on thefollowing system variations:
■ Whether NLS is activated and the settings for the LANG andLC_COLLATE environment variables
■ How uppercase versus lowercase letters are handled by the particu-lar system.
Composing Simple SELECT Statements 2-25
2-26 Informix Guide to
Selecting Specific Columns
numéro n
13612 A13606 D13607 H13602 H13604 L13610 L13613 L13603 M13611 O13609 T13600 d13615 d13601 Å13608 É13605 Ö13614 Ø
numéro n
13601 Å13612 A13600 d13615 d13606 D13608 É13607 H13602 H13604 L13610 L13613 L13603 M13611 O13605 Ö13614 Ø13609 T
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 rankscapital letters before lowercase letters and moves the names that start with acapitalized foreign character (Ålesund, Étaix, Ötker, and Øverst) to the endof the list.
Query Result 2-19a
Query Result 2-19b
om prénom
zevedo Edouardo Freireupré Michèle Françoiseammer Gerhardämmerle GretaaForêt Jean-NoëleMaître Héloïselanero Gloria Doloresontaña José Antonioatfield Emilyiramisù Paolo Alfredoa Sousa João Lourenço Antunesi Girolamo Giuseppelesund Sverretaix Émiletker Hans-Jürgenverst Per-Anders
om prénom
lesund Sverrezevedo Edouardo Freirea Sousa João Lourenço Antunesi Girolamo Giuseppeupré Michèle Françoisetaix Émileammer Gerhardämmerle GretaaForêt Jean-NoëleMaître Héloïselanero Gloria Doloresontaña José Antonioatfield Emilytker Hans-Jürgenverst Per-Andersiramisù Paolo Alfredo
SQL: Tutorial
Selecting Specific Columns
Query Result 2-19b indicates that with the appropriate NLS environmentvariable settings, names starting with foreign characters (Ålesund, Étaix,Ötker, and Øverst) are collated differently than they are in the standard ASCIIorder so they are integrated in the list. It does not distinguish betweenuppercase and lowercase letters.
Selecting Substrings
You can select part of the value of a CHARACTER column by including asubstring in the select list. Suppose your marketing department is planning amailing to your customers and wants a rough idea of their geographicaldistribution based on zip codes. You could write a query similar to the oneshown in Query 2-20:
Query 2-20SELECT zipcode[1,3], customer_num
FROM customerORDER BY zipcode
Composing Simple SELECT Statements 2-27
2-28 Informix Guide to
Using the WHERE Clause
zipcode customer_n
021080085198322604740802850850940940940940940940940940940940940940940940941943943946
Query 2-20 uses a substring to select the first three characters of the zipcodecolumn (which identify the state) and the full customer_num, and lists themin ascending order by zip code, as shown in Query Result 2-20:
Using the WHERE ClausePerhaps you want to see only those orders placed by a particular customer orthe calls entered by a particular customer service representative. You can adda WHERE clause to a SELECT statement to retrieve these specific rows from atable.
You can use the WHERE clause to set up a comparison condition or a joincondition. This section demonstrates only the first use. Join conditions aredescribed in a later section and in the next chapter.
Query Result 2-20um
125119122121123127124126128120105112113115104116110114106108117111101109102103107118
SQL: Tutorial
Creating a Comparison Condition
The set of rows returned by a SELECT statement is the active set for thatstatement. A singleton SELECT statement returns a single row. InINFORMIX-4GL or an SQL API, the retrieval of multiple rows requires the useof a cursor. In NewEra, you use a SuperTable to handle multiple row retrieval.See Chapter 5, “Programming with SQL,” and Chapter 6, “Modifying DataThrough SQL Programs.”
Creating a Comparison ConditionThe WHERE clause of a SELECT statement specifies the rows you want to see.A comparison condition employs specific keywords and operators to define thesearch criteria.
For example, you might use one of the keywords BETWEEN, IN, LIKE, orMATCHES to test for equality, or the keywords IS NULL to test for null values.You can combine the keyword NOT with any of these keywords to specify theopposite condition.
Figure 2-2 lists the relational operators you can use in a WHERE clause in placeof a keyword to test for equality:
Figure 2-2Relational operators that test for equality
Operator Operation
= equals
!= or <> does not equal
> greater than
>= greater than or equal to
< less than
<= less than or equal to
Composing Simple SELECT Statements 2-29
2-30 Informix Guide to
Creating a Comparison Condition
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 toSQL: Syntax. For DATE and DATETIME expressions, “greater than” meanslater in time, and for INTERVAL expressions, it means of longer duration. Youcannot use TEXT or BYTE columns in string expressions, except when you testfor null values.
You can use the preceding keywords and operators in a WHERE clause tocreate comparison condition queries that perform the following actions:
■ Include values
■ Exclude values
■ Find a range of values
■ Find a subset of values
■ Identify null values
You can also use the preceding keywords and operators in a WHERE clauseto create comparison condition queries, which perform variable text searchesusing the following criteria:
■ Exact text comparison
■ Single-character wildcards
■ Restricted single-character wildcards
■ Variable-length wildcards
■ Subscripting
The following section contains examples that illustrate these types of queries.
SQL: Tutorial
Creating a Comparison Condition
customer_num
106121127
Including Rows
Use the relational operator = to include rows in a WHERE clause, as shown inQuery 2-21:
Query 2-21SELECT customer_num, call_code, call_dtime, res_dtime
FROM cust_callsWHERE user_id = 'maryj'
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 customertable. This qualifier is not required when the creator of the table is the currentuser, or when the database is not ANSI-compliant. However, it is not incorrectto include the qualifier in either case. For a complete discussion of ownernaming, see Chapter 1 in the Informix Guide to SQL: Syntax.
Query 2-22SELECT customer_num, company, city, state
FROM odin.customerWHERE state != 'CA'
SELECT customer_num, company, city, stateFROM odin.customerWHERE state <> 'CA'
Query Result 2-21call_code call_dtime res_dtime
D 1994-06-12 08:20 1994-06-12 08:25O 1994-07-10 14:05 1994-07-10 14:06I 1994-07-31 14:30
Composing Simple SELECT Statements 2-31
2-32 Informix Guide to
Creating a Comparison Condition
customer_num
11121212121212121212
Both statements in Query 2-22 exclude values by specifying that, in thecustomer table owned by the user odin, the value in the state column shouldnot be equal to CA, as shown in Query Result 2-22
Specifying Rows
Query 2-23 shows two ways to specify rows in a WHERE clause:
Query 2-23SELECT catalog_num, stock_num, manu_code, cat_advert
FROM catalogWHERE catalog_num BETWEEN 10005 AND 10008
SELECT catalog_num, stock_num, manu_code, cat_advertFROM catalogWHERE catalog_num >= 10005 AND catalog_num <= 10008
Query Result 2-22company city state
9 The Triathletes Club Cherry Hill NJ0 Century Pro Shop Phoenix AZ1 City Sports Wilmington DE2 The Sporting Life Princeton NJ3 Bay Sports Jacksonville FL4 Putnum’s Putters Bartlesville OK5 Total Fitness Sports Brighton MA6 Neelie’s Discount Sp Denver CO7 Big Blue Bike Shop Blue Island NY8 Phoenix College Phoenix AZ
SQL: Tutorial
Creating a Comparison Condition
catalog_numstock_nummanu_codecat_advert H
catalog_numstock_nummanu_codecat_advert Dte
catalog_numstock_nummanu_codecat_advert Q
catalog_numstock_nummanu_codecat_advert H
Each statement in Query 2-23 specifies a range for catalog_num from 10005through 10008, inclusive. The first statement uses keywords, and the seconduses relational operators to retrieve the rows shown in Query Result 2-23:
Note that although the catalog table includes a column with the BYTE datatype, that column is not included in this SELECT statement because theoutput would show only the words <BYTE value> by the column name. Youcan display TEXT and BYTE values by using the PROGRAM attribute whenusing forms in INFORMIX-SQL or INFORMIX-4GL or by writing a NewEra, 4GLor an SQL API application to do so.
Query Result 2-23100053HSK
igh-Technology Design Expands the Sweet Spot
100063SHM
urable Aluminum for High School and CollegiaAthletes
100074HSK
uality Pigskin with Joe Namath Signature
100084HRO
ighest Quality Football for High Schooland Collegiate Competitions
Composing Simple SELECT Statements 2-33
2-34 Informix Guide to
Creating a Comparison Condition
fname
FredFrankEileen NJasonMarvinJamesBobCathyKimChris
Excluding a Range of Rows
In Query 2-24, by using the keywords NOT BETWEEN, the condition excludesrows that have the character range 94000 through 94999 in the zipcodecolumn, as shown in Query Result 2-24:
Query 2-24SELECT fname, lname, company, city, state
FROM customerWHERE zipcode NOT BETWEEN '94000' AND '94999'ORDER BY state
Using a WHERE Clause to Find a Subset of Values
As shown in “Excluding Rows” on page 2-31, Query 2-25 also assumes theuse of an ANSI-compliant database. The owner qualifier is in quotation marksto preserve the case-sensitivity of the literal string.
Query 2-25SELECT lname, city, state, phone
FROM 'Aleta'.customerWHERE state = 'AZ' OR state = 'NJ'ORDER BY lname
SELECT lname, city, state, phoneFROM 'Aleta'.customerWHERE state IN ('AZ', 'NJ')ORDER BY lname
Query Result 2-24lname company city state
Jewell Century* Pro Shop Phoenix AZLessor Phoenix University Phoenix AZeelie Neelie’s Discount Sp Denver COWallack City Sports Wilmington DEHanlon Bay Sports Jacksonville FLHenry Total Fitness Sports Brighton MAShorter The Triathletes Club Cherry Hill NJ
O’Brian The Sporting Life Princeton NJSatifer Big Blue Bike Shop Blue Island NY
Putnum Putnum’s Putters Bartlesville OK
SQL: Tutorial
Creating a Comparison Condition
lname
Jewell Lessor O’Brian Shorter
Each statement in Query 2-25 retrieves rows that include the subset of AZ orNJ in the state column of the Aleta.customer table, as shown in Query Result2-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, noquotation marks exist around the table owner name. Whereas the two state-ments in Query 2-25 searched the Aleta.customer table, Query 2-26 searchesthe table ALETA.customer, which is a different table, because of the wayANSI-compliant databases look at owner names.
Query 2-26SELECT lname, city, state, phone
FROM Aleta.customerWHERE state NOT IN ('AZ', 'NJ')ORDER BY state
Query Result 2-25city state phone
Phoenix AZ 602-265-8754Phoenix AZ 602-533-1817Princeton NJ 609-342-0054Cherry Hill NJ 609-663-6079
Composing Simple SELECT Statements 2-35
2-36 Informix Guide to
Creating a Comparison Condition
lname
PauliSadlerCurrieHigginsVectorWatsonReamQuinnMillerJaegerKeyesLawsonBeattyAlbertsonGrantParmeleeSipesBaxterNeelieWallackHanlonHenrySatiferPutnum
In Query 2-26, by adding the keyword NOT IN, the subset changes to excludethe subsets AZ and NJ in the state column. Query Result 2-26 shows theresults in order of the state column:
Query Result 2-26city state phone
Sunnyvale CA 408-789-8075San Francisco CA 415-822-1289Palo Alto CA 415-328-4543Redwood City CA 415-368-1100Los Altos CA 415-776-3249Mountain View CA 415-389-8789Palo Alto CA 415-356-9876
Redwood City CA 415-544-8729Sunnyvale CA 408-723-8789
Redwood City CA 415-743-3611Sunnyvale CA 408-277-7245Los Altos CA 415-887-7235
Menlo Park CA 415-356-9982Redwood City CA 415-886-6677
Menlo Park CA 415-356-1123Mountain View CA 415-534-8822Redwood City CA 415-245-4578Oakland CA 415-655-0011Denver CO 303-936-7731Wilmington DE 302-366-7511Jacksonville FL 904-823-4239Brighton MA 617-232-4159
Blue Island NY 312-944-5691Bartlesville OK 918-355-2074
SQL: Tutorial
Creating a Comparison Condition
order_num
100410061007101210161017
Identifying Null Values
Use the IS NULL or IS NOT NULL option to check for null values. A nullrepresents either the absence of data or a value that is unknown or notapplicable. A null value is not the same as a zero or a blank.
Query 2-27 returns all rows that have a null paid_date, as shown in QueryResult 2-27:
Query 2-27SELECT order_num, customer_num, po_num, ship_date
FROM ordersWHERE paid_date IS NULLORDER BY customer_num
Forming Compound Conditions
You can connect two or more comparison conditions, or Boolean expressions,by using the logical operators AND, OR, and NOT. A Boolean expression eval-uates as true or false or, if null values are involved, as unknown. You can useTEXT or BYTE objects in a Boolean expression only when you test for a nullvalue.
In Query 2-28, the operator AND combines two comparison expressions inthe WHERE clause:
Query 2-28SELECT order_num, customer_num, po_num, ship_date
FROM ordersWHERE paid_date IS NULL
AND ship_date IS NOT NULLORDER BY customer_num
Query Result 2-27customer_num po_num ship_date
106 8006 05/30/1994112 Q13557117 278693 06/05/1994117 278701 06/29/1994119 PC6782 07/12/1994120 DM354331 07/13/1994
Composing Simple SELECT Statements 2-37
2-38 Informix Guide to
Creating a Comparison Condition
order_num c
10041007101210161017
The query returns all rows that have a null paid_date and the ones that do notalso have a null ship_date, as shown in Query Result 2-28:
Using Variable Text Searches
You can use the keywords LIKE and MATCHES for variable text queries basedon substring searches of CHARACTER fields. Include the keyword NOT toindicate the opposite condition. The keyword LIKE is the ANSI standard,whereas MATCHES is an Informix extension.
Variable text search strings can include the wildcards listed in Figure 2-3 withLIKE or MATCHES.
Figure 2-3Wildcards used with LIKE and MATCHES
You cannot test a TEXT or BYTE column with LIKE or MATCHES.
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
ustomer_num po_num ship_date
106 8006 05/30/1994117 278693 06/05/1994117 278701 06/29/1994119 PC6782 07/12/1994120 DM354331 07/13/1994
SQL: Tutorial
Creating a Comparison Condition
stock_no mfg_co
991 ANT991 BKE991 JSK991 PRM991 SHR
Using Exact Text Comparisons
The following examples include a WHERE clause that searches for exact textcomparisons by using the keyword LIKE or MATCHES or the equal sign (=)relational operator . Unlike earlier examples, these examples illustrate howto query on an external table in an ANSI-compliant database.
An external table is a table that is not in the current database. You can accessonly external tables that are part of an ANSI-compliant database.
Whereas the database used previously in this chapter was the demonstrationdatabase called stores7, the FROM clause in the following examples specifiesthe manatee table, created by the owner bubba, which resides in an ANSI-compliant database named syzygy. For more information on definingexternal tables, see Chapter 1 in the Informix Guide to SQL: Syntax.
Each statement in Query 2-29 retrieves all the rows that have the single wordhelmet in the description column as shown in Query Result 2-29:
Query 2-29SELECT * FROM syzygy:bubba.manatee
WHERE description = 'helmet'ORDER BY mfg_code
SELECT * FROM syzygy:bubba.manateeWHERE description LIKE 'helmet'ORDER BY mfg_code
SELECT * FROM syzygy:bubba.manateeWHERE description MATCHES 'helmet'ORDER BY mfg_code
Query Result 2-29de description unit_price unit unit_type
helmet $222.00 case 4/casehelmet $269.00 case 4/casehelmet $311.00 each 4/casehelmet $234.00 case 4/casehelmet $245.00 case 4/case
Composing Simple SELECT Statements 2-39
2-40 Informix Guide to
Creating a Comparison Condition
stock_num manu_co
205 HRO 3 g 2 HRO bas 1 HRO bas 7 HRO bas 102 PRC bic 114 PRC bic 4 HRO foot 110 PRC hel 110 HRO he 307 PRC infa 306 PRC tan 308 PRC twi 304 HRO wa
Using a Single-Character Wildcard
The statements in Query 2-30 illustrate the use of a single-character wildcardin a WHERE clause. Further, they demonstrate a query on an external table.The stock table is in the external database sloth, which, beside being outsidethe current stores7 database, is on a separate database server called meerkat.
For details on external tables, external databases, and networks, seeChapter 11, “Understanding Informix Networking,” in this manual andChapter 1 in the Informix Guide to SQL: Syntax.
Query 2-30SELECT * FROM sloth@meerkat:stock
WHERE manu_code LIKE '_R_'AND unit_price >= 100
ORDER BY description, unit_price
SELECT * FROM sloth@meerkat:stockWHERE manu_code MATCHES '?R?'
AND unit_price >= 100ORDER BY description, unit_price
Each statement in Query 2-30 retrieves only those rows for which the middleletter of the manu_code is R, as shown in Query Result 2-30:
Query Result 2-30de description unit_price unit unit_descr
olf balls $312.00 case 24/caseeball $126.00 case 24/caseeball gloves $250.00 case 10 gloves/caseketball $600.00 case 24/caseycle brakes $480.00 case 4 sets/caseycle gloves $120.00 case 10 pairs/caseball $480.00 case 24/casemet $236.00 case 4/caselmet $260.00 case 4/casent jogger $250.00 each eachdem adapter $160.00 each eachn jogger $280.00 each eachtch $280.00 box 10/box
SQL: Tutorial
Creating a Comparison Condition
stock_num manu_c
205 ANZ205 HRO
2 HRO3 HSK1 HRO1 HSK7 HRO
.
.
.110 ANZ110 HRO110 HSK...301 ANZ301 HRO313 ANZ
6 ANZ5 ANZ8 ANZ9 ANZ
304 ANZ304 HRO
The comparison '_R_' (for LIKE) or '?R?' (for MATCHES) specifies, from left toright, the following items:
■ Any single character
■ The letter R
■ Any single character
WHERE Clause with Restricted Single-Character Wildcard
Query 2-31 selects only those rows where the manu_code begins with Athrough H and returns the rows shown in Query Result 2-31. The class test'[A-H]' specifies any single letter from A through H, inclusive. No equivalentwildcard symbol exists for the LIKE keyword.
Query 2-31SELECT * FROM stock
WHERE manu_code MATCHES '[A-H]*'ORDER BY description, manu_code, unit_price
Query Result 2-31ode description unit_price unit unit_descr
3 golf balls $312.00 case 24/case3 golf balls $312.00 case 24/casebaseball $126.00 case 24/casebaseball bat $240.00 case 12/casebaseball gloves $250.00 case 10 gloves/casebaseball gloves $800.00 case 10 gloves/casebasketball $600.00 case 24/case
helmet $244.00 case 4/casehelmet $260.00 case 4/casehelmet $308.00 case 4/case
running shoes $95.00 each eachrunning shoes $42.50 each eachswim cap $60.00 box 12/boxtennis ball $48.00 case 24 cans/casetennis racquet $19.80 each eachvolleyball $840.00 case 24/casevolleyball net $20.00 each eachwatch $170.00 box 10/boxwatch $280.00 box 10/box
Composing Simple SELECT Statements 2-41
2-42 Informix Guide to
Creating a Comparison Condition
stock_num manu_
102 PRC102 SHM114 PRC107 PRC106 PRC101 PRC101 SHM105 PRC105 SHM
WHERE Clause with Variable-Length Wildcard
The statements in Query 2-32 use a wildcard at the end of a string to retrieveall the rows where the description begins with the characters bicycle:
Query 2-32SELECT * FROM stock
WHERE description LIKE 'bicycle%'ORDER BY description, manu_code
SELECT * FROM stockWHERE description MATCHES 'bicycle*'ORDER BY description, manu_code
Either statement returns the rows found in Query Result 2-32:
The comparison 'bicycle%' or 'bicycle*' specifies the characters bicyclefollowed by any sequence of zero or more characters. It matches bicyclestem with stem matched by the wildcard. It matches to the charactersbicycle alone, if a row exists with that description.
Query 2-33 narrows the search by adding another comparison condition thatexcludes a manu_code of PRC:
Query 2-33SELECT * FROM stock
WHERE description LIKE 'bicycle%'AND manu_code NOT LIKE 'PRC'
ORDER BY description, manu_code
Query Result 2-32code description unit_price unit unit_descr
bicycle brakes $480.00 case 4 sets/casebicycle brakes $220.00 case 4 sets/casebicycle gloves $120.00 case 10 pairs/casebicycle saddle $70.00 pair pairbicycle stem $23.00 each eachbicycle tires $88.00 box 4/boxbicycle tires $68.00 box 4/boxbicycle wheels $53.00 pair pairbicycle wheels $80.00 pair pair
SQL: Tutorial
Creating a Comparison Condition
stock_num manu_c
102 SHM101 SHM105 SHM
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 thecomparison string (such as '%cycle'), the query often takes longer to execute.This is because indexes cannot be used, so every row is searched.
MATCHES and Native Language Support
As indicated on page 2-25, you can set the DBNLS, LANG, and LC_COLLATEenvironment variables to influence NLS functionality regarding the collationorder of data returned by a query.
Query 2-34 uses an ORDER BY clause and a WHERE clause specifying amatching range on a column containing data of type NCHAR. This NLS table,abonnés, is provided separately from the demonstration database. Query2-34 is provided as the sel_nls2.sql command file with NLS-enabledDB-Access.
Query 2-34SELECT numéro,nom,prénom
FROM abonnésWHERE nom MATCHES '[E-P]*'ORDER BY nom;
Query Result 2-33ode description unit_price unit unit_descr
bicycle brakes $220.00 case 4 sets/casebicycle tires $68.00 box 4/boxbicycle wheels $80.00 pair pair
Composing Simple SELECT Statements 2-43
2-44 Informix Guide to
Creating a Comparison Condition
numéro n
13607 H13602 H13604 L13610 L13613 L13603 M13611 O
numéro n
13608 É13607 H13602 H13604 L13610 L13613 L13603 M13611 O13605 Ö13614 Ø
The output in Query Result 2-34a and Query Result 2-34b show differentrows selected for the MATCHES range by the same query, based on differentNLS environment variable settings:
In Query Result 2-34a, the rows for Étaix, Ötker, and Øverst are not selectedand listed because, with standard ASCII ordering, the accented first letter ofeach 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 inthe list because, with the appropriate NLS environment variable settings, theaccented first letter of each name is in the E-P MATCHES range for the nomcolumn.
Query Result 2-34a
Query Result 2-34b
om prénom
ammer Gerhardämmerle GretaaForêt Jean-NoëleMaître Héloïselanero Gloria Doloresontaña José Antonioatfield Emily
om prénom
taix Émileammer Gerhardämmerle GretaaForêt Jean-NoëleMaître Héloïselanero Gloria Doloresontaña José Antonioatfield Emilytker Hans-Jürgenverst Per-Anders
SQL: Tutorial
Creating a Comparison Condition
customer_num 1 call_dtime 19 user_id m call_code I call_descr Se
res_dtime 1 res_descr M
Comparing for Special Characters
Query 2-35 uses the keyword ESCAPE with LIKE or MATCHES so you canprotect a special character from misinterpretation as a wildcard symbol:
Query 2-35SELECT * FROM cust_calls
WHERE res_descr LIKE '%!%%' ESCAPE '!'
The ESCAPE keyword designates an escape character (it is an exclamation point(!) in this example), which protects the next character so it is interpreted asdata and not as a wildcard. In the example, the escape character causes themiddle percent sign (%) to be treated as data. By using the ESCAPE keyword,you can search for occurrences of a percent sign (%) in the res_descr columnusing the LIKE wildcard percent sign (%). The query retrieves the row shownin Query Result 2-35:
Using Subscripting in a WHERE Clause
You can use subscripting in the WHERE clause of a SELECT statement to specifya range of characters or numbers in a column, as shown in Query 2-36:
Query 2-36SELECT catalog_num, stock_num, manu_code, cat_advert,
cat_descrFROM catalogWHERE cat_advert[1,4] = 'High'
The subscript [1,4] causes Query 2-36 to retrieve all rows in which the firstfour letters of the cat_advert column are High, as shown in Query Result 2-36:
Query Result 2-3516
93-12-21 11:24annyn
cond complaint from this customer! Receivedtwo cases right-handed outfielder gloves(1 HRO) instead of one case lefties.
993-12-27 08:19emo to shipping (Ava Brown) to send case ofleft-handed gloves, pick up wrong case; memoto billing requesting 5% discount to placatecustomer due to second offense and latenessof resolution because of holiday
Composing Simple SELECT Statements 2-45
2-46 Informix Guide to
Creating a Comparison Condition
catalog_num 100 stock_num 2 manu_code HR cat_advert Highe
H cat_descrJackie Robinson sigNational League.
catalog_num 100 stock_num 3 manu_code HS cat_advert High- cat_descrPro-style wood. Av
catalog_num 100 stock_num 4 manu_code HR cat_advert Highe
C cat_descrNFL-style, pigskin.
catalog_num 100 stock_num 6 manu_code SM cat_advert High- cat_descrSoft yellow color foartificial light.
catalog_num 100 stock_num 202 manu_code KA cat_advert High-
C cat_descrFull set of woodspower performance
catalog_num 100 stock_num 204 manu_code KA cat_advert High-
A cat_descrIdeally balanced fo
catalog_num 100 stock_num 310 manu_code AN cat_advert High- cat_descrWhite. Standard siz
Query Result 2-3604
Ost Quality Ball Available, fromand-Stitching to the Robinson Signature
nature ball. Highest professional quality, used by
05
KTechnology Design Expands the Sweet Spot
ailable in sizes: 31, 32, 33, 34, 35.
08
Ost Quality Football for High School andollegiate Competitions
12
TVisibility Tennis, Day or Night
r easy visibility in sunlight or
43
RQuality Woods Appropriate for High Schoolompetitions or Serious Amateurs
designed for precision control and.
45
RQuality Beginning Set of Ironsppropriate for High School Competitions
r optimum control. Nylon covered shaft.
68
ZQuality Kickboard
e.
SQL: Tutorial
Expressions and Derived Values
Expressions and Derived ValuesYou are not limited to selecting columns by name. You can use the SELECTclause of a SELECT statement to perform computations on column data andto display information derived from the contents of one or more columns. Youdo this by listing an expression in the select list.
An expression consists of a column name, a constant, a quoted string, akeyword, or any combination of these items connected by operators. It alsocan include host variables (program data) when the SELECT statement isembedded in a program.
For more information, see the section “Expression,” in Chapter 1 of theInformix Guide to SQL: Syntax.
Arithmetic Expressions
An arithmetic expression contains at least one of the arithmetic operators listedin Figure 2-4 and produces a number. You cannot use TEXT or BYTE columnsin arithmetic expressions.
Figure 2-4Arithmetic operators used in arithmetic expressions
Operations of this nature enable you to see the results of proposedcomputations without actually altering the data in the database. You can addan INTO TEMP clause to save the altered data in a temporary table for further
Operator Operation
+ addition
- subtraction
* multiplication
/ division
Composing Simple SELECT Statements 2-47
2-48 Informix Guide to
Expressions and Derived Values
stock_num descrip
1 baseb1 baseb4 footba4 footba7 baske8 volley
102 bicycl111 10-sp112 12-sp113 18-sp203 irons/
reference, computations, or impromptu reports. Query 2-37 calculates a 7percent sales tax on the unit_price column when the unit_price is $400 ormore (but does not update it in the database).
Query 2-37SELECT stock_num, description, unit, unit_descr,
unit_price, unit_price * 1.07FROM stockWHERE unit_price >= 400
If you are using the DB-Access or INFORMIX-SQL ISED, the result is displayedin a column labeled expression, as shown in Query Result 2-37:
Query 2-38 calculates a surcharge of $6.50 on orders when the quantityordered is less than 5:
Query 2-38SELECT item_num, order_num, quantity,
total_price, total_price + 6.50FROM itemsWHERE quantity < 5
Query Result 2-37tion unit unit_descr unit_price (expression)
all gloves case 10 gloves/case $800.00 $856.0000all gloves case 10 gloves/case $450.00 $481.5000ll case 24/case $960.00 $1027.2000ll case 24/case $480.00 $513.6000tball case 24/case $600.00 $642.0000ball case 24/case $840.00 $898.8000e brakes case 4 sets/case $480.00 $513.6000d, assmbld each each $499.99 $534.9893d, assmbld each each $549.00 $587.4300d, assmbld each each $685.90 $733.9130wedge case 2 sets/case $670.00 $716.9000
SQL: Tutorial
Expressions and Derived Values
item_num or
112121234
.
.
.1234123123456
If you are using DB-Access or INFORMIX-SQL, the result appears in a columnlabeled expression, as shown in Query Result 2-38:
Query 2-39 calculates and displays in an expression column (if you are usingDB-Access or INFORMIX-SQL) the interval between when the customer callwas received (call_dtime) and when the call was resolved (res_dtime), indays, hours, and minutes.
Query 2-39SELECT customer_num, user_id, call_code,
call_dtime, res_dtime - call_dtimeFROM cust_callsORDER BY user_id
Query Result 2-38der_num quantity total_price (expression)
1001 1 $250.00 $256.501002 1 $960.00 $966.501002 1 $240.00 $246.501003 1 $20.00 $26.501003 1 $840.00 $846.501004 1 $250.00 $256.501004 1 $126.00 $132.501004 1 $240.00 $246.501004 1 $800.00 $806.50
1021 2 $75.00 $81.501021 3 $225.00 $231.501021 3 $690.00 $696.501021 2 $624.00 $630.501022 1 $40.00 $46.501022 2 $96.00 $102.501022 2 $96.00 $102.501023 2 $40.00 $46.501023 2 $116.00 $122.501023 1 $80.00 $86.501023 1 $228.00 $234.501023 1 $170.00 $176.501023 1 $190.00 $196.50
Composing Simple SELECT Statements 2-49
2-50 Informix Guide to
Expressions and Derived Values
customer_num us
116 m116 m106 m121 m127 m110 ri119 ri
stock_num descript
1 baseba1 baseba4 footbal4 footbal7 basket8 volleyb
102 bicycle111 10-spd112 12-spd113 18-spd203 irons/w
Using Display Labels
You can assign a display label to a computed or derived data column to replacethe default column header expression. In Query 2-40, Query 2-41, and Query2-42, the derived data is shown in a column called (expression). Query 2-40also presents derived values, but the column displaying the derived valuesnow has the descriptive header, taxed.
Query 2-40SELECT stock_num, description, unit, unit_descr,
unit_price, unit_price * 1.07 taxedFROM stockWHERE unit_price >= 400
Query Result 2-40 shows the label taxed is assigned to the expression in theselect list that displays the results of the operation unit_price * 1.07:
Query Result 2-39
Query Result 2-40
er_id call_code call_dtime (expression)
annyn I 1993-12-21 11:24 5 20:55annyn I 1993-11-28 13:34 0 03:13aryj D 1994-06-12 08:20 0 00:05aryj O 1994-07-10 14:05 0 00:01aryj I 1994-07-31 14:30chc L 1994-07-07 10:24 0 00:06chc B 1994-07-01 15:00 0 17:21
ion unit unit_descr unit_price taxed
ll gloves case 10 gloves/case $800.00 $856.0000ll gloves case 10 gloves/case $450.00 $481.5000
l case 24/case $960.00 $1027.2000l case 24/case $480.00 $513.6000ball case 24/case $600.00 $642.0000all case 24/case $840.00 $898.8000brakes case 4 sets/case $480.00 $513.6000
, assmbld each each $499.99 $534.9893, assmbld each each $549.00 $587.4300, assmbld each each $685.90 $733.9130edge case 2 sets/case $670.00 $716.9000
SQL: Tutorial
Expressions and Derived Values
item_num or...
234121123412...
In Query 2-41, the label surcharge is defined for the column that displays theresults of the operation total_price + 6.50:
Query 2-41SELECT item_num, order_num, quantity,
total_price, total_price + 6.50 surchargeFROM itemsWHERE quantity < 5
The surcharge column is labeled in the output, as shown in Query Result2-41:
Query 2-42 assigns the label span to the column that displays the results ofsubtracting the DATETIME column call_dtime from the DATETIME columnres_dtime.
Query 2-42SELECT customer_num, user_id, call_code,
call_dtime, res_dtime - call_dtime spanFROM cust_callsORDER BY user_id
Query Result 2-41der_num quantity total_price surcharge
1013 1 $36.00 $42.501013 1 $48.00 $54.501013 2 $40.00 $46.501014 1 $960.00 $966.501014 1 $480.00 $486.501015 1 $450.00 $456.501016 2 $136.00 $142.501016 3 $90.00 $96.501016 1 $308.00 $314.501016 1 $120.00 $126.501017 4 $150.00 $156.501017 1 $230.00 $236.50
Composing Simple SELECT Statements 2-51
2-52 Informix Guide to
Expressions and Derived Values
customer_num use
116 ma116 ma106 ma121 ma127 ma110 rich119 rich
customer_num use
127 ma121 ma106 ma110 ric116 ma119 ric116 ma
The span column is labeled in the output, as shown in Query Result 2-42:
Sorting on Derived Columns
When you want to use ORDER BY as an expression, you can use either thedisplay label assigned to the expression or an integer, as shown in Query2-43:
Query 2-43SELECT customer_num, user_id, call_code,
call_dtime, res_dtime - call_dtime spanFROM cust_callsORDER BY span
Query 2-43 retrieves the same data from the cust_calls table as Query 2-42. InQuery 2-43, the ORDER BY clause causes the data to be displayed in ascendingorder of the derived values in the span column, as shown in Query Result2-43:
Query Result 2-42
Query Result 2-43
r_id call_code call_dtime span
nnyn I 1993-12-21 11:24 5 20:55nnyn I 1993-11-28 13:34 0 03:13ryj D 1994-06-12 08:20 0 00:05ryj O 1994-07-10 14:05 0 00:01ryj I 1994-07-31 14:30c L 1994-07-07 10:24 0 00:06c B 1994-07-01 15:00 0 17:21
r_id call_code call_dtime span
ryj I 1994-07-31 14:30ryj O 1994-07-10 14:05 0 00:01ryj D 1994-06-12 08:20 0 00:05
hc L 1994-07-07 10:24 0 00:06nnyn I 1992-11-28 13:34 0 03:13
hc B 1994-07-01 15:00 0 17:21nnyn I 1992-12-21 11:24 5 20:55
SQL: Tutorial
Using Functions in SELECT Statements
Query 2-44 uses an integer to represent the result of the operationres_dtime - call_dtime and retrieves the same rows that appear in QueryResult 2-43.
Query 2-44SELECT customer_num, user_id, call_code,
call_dtime, res_dtime - call_dtime spanFROM cust_callsORDER BY 5
Using Functions in SELECT StatementsIn addition to column names and operators, an expression can also includeone or more functions.
Expressions supported include aggregate, function (which includearithmetic functions), constant, and column expressions. These expressionsare described in Chapter 1 of the Informix Guide to SQL: Syntax.
Aggregate Functions
The aggregate functions are COUNT, AVG, MAX, MIN, and SUM. They take onvalues that depend on all the rows selected and return information aboutrows, not the rows themselves. You cannot use these functions with TEXT orBYTE columns.
Aggregates are often used to summarize information about groups of rowsin a table. This use is discussed in Chapter 3, “Composing AdvancedSELECT Statements.” When you apply an aggregate function to an entiretable, the result contains a single row that summarizes all of the selectedrows.
Query 2-45 counts and displays the total number of rows in the stock table:
Query 2-45SELECT COUNT(*)
FROM stock
Composing Simple SELECT Statements 2-53
2-54 Informix Guide to
Using Functions in SELECT Statements
(count(*))
73
(count)
9
(avg)
$197.14
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-46SELECT COUNT (*)
FROM stockWHERE manu_code = 'SHM'
By including the keyword DISTINCT (or its synonym UNIQUE) and a columnname in Query 2-47, you can tally the number of different manufacturercodes in the stock table:
Query 2-47SELECT COUNT (DISTINCT manu_code)
FROM stock
Query 2-48 computes the average unit_price of all rows in the stock table:
Query 2-48SELECT AVG (unit_price)
FROM stock
Query Result 2-45
Query Result 2-47
Query Result 2-48
SQL: Tutorial
Using Functions in SELECT Statements
(avg)
$204.93
(max)
$25.20
Query 2-49 computes the average unit_price of just those rows in the stocktable that have a manu_code of SHM:
Query 2-49SELECT AVG (unit_price)
FROM stockWHERE manu_code = 'SHM'
You can combine aggregate functions as shown in Query 2-50:
Query 2-50SELECT MAX (ship_charge), MIN (ship_charge)
FROM orders
Query 2-50 finds and displays both the highest and lowest ship_charge in theorders table, as shown in Query Result 2-50:
You can apply functions to expressions, and you can supply display labels fortheir results, as shown in Query 2-51:
Query 2-51SELECT MAX (res_dtime - call_dtime) maximum,
MIN (res_dtime - call_dtime) minimum,AVG (res_dtime - call_dtime) averageFROM cust_calls
Query Result 2-49
Query Result 2-50(min)
$5.00
Composing Simple SELECT Statements 2-55
2-56 Informix Guide to
Using Functions in SELECT Statements
maximum
5 20:55
(sum)
130.5
Query 2-51 finds and displays the maximum, minimum, and averageamount of time (in days, hours, and minutes) between the reception and res-olution of a customer call and labels the derived values appropriately. Theseamounts of time are shown in Query Result 2-51:
Query 2-52 calculates the total ship_weight of orders shipped on July 13,1994:
Query 2-52SELECT SUM (ship_weight)
FROM ordersWHERE ship_date = '07/13/1994'
Time Functions
You can use the time functions DAY, MDY, MONTH, WEEKDAY, YEAR, andDATE 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 thatyou use to call the function. You also can use the CURRENT function to returna value with the current date and time, or the EXTEND function to adjust theprecision of a DATE or DATETIME value.
Using DAY and CURRENT
Query 2-53 returns the day of the month for the call_dtime and res_dtimecolumns in two expression columns, as shown in Query Result 2-53:
Query 2-53SELECT customer_num, DAY (call_dtime), DAY (res_dtime)
FROM cust_calls
Query Result 2-51
Query Result 2-52
minimum average
0 00:01 1 02:56
SQL: Tutorial
Using Functions in SELECT Statements
customer_num
10111112121111
customer_num
106110119121
Query 2-54 uses the DAY and CURRENT functions to compare column valuesto the current day of the month. It selects only those rows where the value isearlier than the current day.
Query 2-54SELECT customer_num, DAY (call_dtime), DAY (res_dtime)
FROM cust_callsWHERE DAY (call_dtime) < DAY (CURRENT)
Query 2-55 shows another use of the CURRENT function, selecting rowswhere the day is earlier than the current one:
Query 2-55SELECT customer_num, call_code, call_descr
FROM cust_callsWHERE call_dtime < CURRENT YEAR TO DAY
Query Result 2-53
Query Result 2-54
(expression) (expression)
6 12 120 7 79 1 21 10 107 316 28 286 21 27
(expression) (expression)
12 127 71 2
10 10
Composing Simple SELECT Statements 2-57
2-58 Informix Guide to
Using Functions in SELECT Statements
customer_num 10call_code Dcall_descr Orde
w
customer_num 11call_code Icall_descr Rece
te
customer_num 11call_code Icall_descr Seco
rile
customer_num
10111112121111
Using MONTH
Query 2-56 uses the MONTH function to extract and show what month thecustomer call was received and resolved and uses display labels for theresulting columns. However, it does not make a distinction between years.
Query 2-56SELECT customer_num,
MONTH (call_dtime) call_month,MONTH (res_dtime) res_monthFROM cust_calls
Query Result 2-55
Query Result 2-56
6
r was received, but two of the cans of ANZ tennis ballsithin the case were empty
6
ived plain white swim caps (313 ANZ) instead of navy witham logo (313 SHM)
6
nd complaint from this customer! Received two casesght-handed outfielder gloves (1 HRO) instead of one casefties.
call_month res_month
6 6 60 7 79 7 71 7 77 76 11 116 12 12
SQL: Tutorial
Using Functions in SELECT Statements
customer_num
101112
customer_num
12111112111011
Query 2-57 uses the MONTH function plus DAY and CURRENT to show whatmonth the customer call was received and resolved if DAY is earlier than thecurrent day:
Query 2-57SELECT customer_num,
MONTH (call_dtime) called,MONTH (res_dtime) resolvedFROM cust_callsWHERE DAY (res_dtime) < DAY (CURRENT)
Using WEEKDAY
In Query 2-58, the WEEKDAY function is used to indicate which day of theweek calls are received and resolved (0 represents Sunday, 1 is Monday, andso on), and the expression columns are labeled:
Query 2-58SELECT customer_num,
WEEKDAY (call_dtime) called,WEEKDAY (res_dtime) resolvedFROM cust_callsORDER BY resolved
Query Result 2-57
Query Result 2-58
called resolved
6 6 69 7 71 7 7
called resolved
7 30 0 09 1 21 3 36 3 36 3 36 5 4
Composing Simple SELECT Statements 2-59
2-60 Informix Guide to
Using Functions in SELECT Statements
(count(*))
4
customer_num
116116
Query 2-59 uses the COUNT and WEEKDAY functions to count how manycalls were received on a weekend. This kind of statement can give you anidea of customer call patterns or indicate whether overtime pay might berequired.
Query 2-59SELECT COUNT(*)
FROM cust_callsWHERE WEEKDAY (call_dtime) IN (0,6)
Query 2-60 retrieves rows where the call_dtime is earlier than the beginningof the current year.
Query 2-60SELECT customer_num, call_code,
YEAR (call_dtime) call_year,YEAR (res_dtime) res_yearFROM cust_callsWHERE YEAR (call_dtime) < YEAR (TODAY)
Formatting DATETIME Values
In Query 2-61, the EXTEND function restricts the two DATETIME values bydisplaying only the specified subfields:
Query 2-61SELECT customer_num,
EXTEND (call_dtime, month to minute) call_time,EXTEND (res_dtime, month to minute) res_timeFROM cust_callsORDER BY res_time
Query Result 2-59
Query Result 2-60call_code call_year res_year
I 1993 1993I 1993 1993
SQL: Tutorial
Using Functions in SELECT Statements
customer_num
127106119110121116116
customer_num
1011111212
Query Result 2-61 returns the month-to-minute range for the columnslabeled call_time and res_time and gives an indication of the workload:
Using the DATE Function
Query 2-62 retrieves DATETIME values only when call_dtime is later than thespecified DATE:
Query 2-62SELECT customer_num, call_dtime, res_dtime
FROM cust_callsWHERE call_dtime > DATE ('12/31/93')
Query Result 2-62 returns the following rows:
Query Result 2-61
Query Result 2-62
call_time res_time
07-31 14:3006-12 08:20 06-12 08:2507-01 15:00 07-02 08:2107-07 10:24 07-07 10:3007-10 14:05 07-10 14:0611-28 13:34 11-28 16:4712-21 11:24 12-27 08:19
call_dtime res_dtime
6 1994-06-12 08:20 1994-06-12 08:250 1994-07-07 10:24 1994-07-07 10:309 1994-07-01 15:00 1994-07-02 08:211 1994-07-10 14:05 1994-07-10 14:067 1994-07-31 14:30
Composing Simple SELECT Statements 2-61
2-62 Informix Guide to
Using Functions in SELECT Statements
customer_num
1011111212
Query 2-63 converts DATETIME values to DATE format and displays thevalues, with labels, only when call_dtime is greater than or equal to thespecified date.
Query 2-63SELECT customer_num,
DATE (call_dtime) called,DATE (res_dtime) resolvedFROM cust_callsWHERE call_dtime >= DATE ('1/1/94')
Other Functions and Keywords
You also can use the LENGTH, USER, CURRENT, and TODAY functionsanywhere in an SQL expression that you would use a constant. In addition,with INFORMIX-OnLine Dynamic Server, you can include the DBSERVER-NAME keyword in a SELECT statement to display the name of the databaseserver where the current database resides.
You can use these functions and keywords to select an expression thatconsists entirely of constant values or an expression that includes columndata. In the first instance, the result is the same for all rows of output.
In addition, you can use the HEX function to return the hexadecimal encodingof an expression, the ROUND function to return the rounded value of anexpression, and the TRUNC function to return the truncated value of anexpression.
Query Result 2-63called resolved
6 06/12/1994 06/12/19940 07/07/1994 07/07/19949 07/01/1994 07/02/19941 07/10/1994 07/10/19947 07/31/1994
SQL: Tutorial
Using Functions in SELECT Statements
customer_num
101105107112115118119120122124125126127128
In Query 2-64, the LENGTH function calculates the number of bytes in thecombined fname and lname columns for each row where the length ofcompany is greater than 15:
Query 2-64SELECT customer_num,
LENGTH (fname) + LENGTH (lname) namelengthFROM customerWHERE LENGTH (company) > 15
Although it might not be useful when you work with the DB-Access orINFORMIX-SQL ISED, the LENGTH function can be important to determine thestring length for programs and reports. LENGTH returns the clipped lengthof a CHARACTER or VARCHAR string and the full number of bytes in a TEXTor BYTE string.
The USER function can be handy when you want to define a restricted viewof a table that contains only your rows. For information on creating views, seeChapter 10, “Granting and Limiting Access to Your Database,” in thismanual and the GRANT and CREATE VIEW statements in Chapter 1 of theInformix Guide to SQL: Syntax.
Query Result 2-64namelength
1113111411101010121110121011
Composing Simple SELECT Statements 2-63
2-64 Informix Guide to
Using Functions in SELECT Statements
customer_num 11call_dtime 199user_id richcall_code Lcall_descr Ordres_dtime 199res_descr Ch
wd
customer_num 11call_dtime 199user_id richcall_code Bcall_descr Billres_dtime 199res_descr Sp
s
Query 2-65a specifies the USER function and the cust_calls table:
Query 2-65aSELECT USER from cust_calls
Query 2-65b returns the user name (login account name) of the user whoexecutes the query. It is repeated once for each row in the table.
Query 2-65bSELECT * FROM cust_calls
WHERE user_id = USER
If the user name of the current user is richc, Query 2-65b retrieves only thoserows in the cust_calls table that are owned by that user, as shown in QueryResult 2-65:
Query Result 2-650
4-07-07 10:24c
er placed one month ago (6/7) not received.4-07-07 10:30
ecked with shipping (Ed Smith). Order sent yesterday- weere waiting for goods from ANZ. Next time will call withelay if necessary
94-07-01 15:00c
does not reflect credit from previous order4-07-02 08:21
oke with Jane Akant in Finance. She found the error and isending new bill to customer
SQL: Tutorial
Using Functions in SELECT Statements
order_num order_date customer_num ship_instruct backlog po_num ship_date ship_weight ship_charge paid_date
server
montague montague montague montague
Query 2-66, if issued when the current system date is July 10, 1994, returnsthis one row:
Query 2-66SELECT * FROM orders
WHERE order_date = TODAY
You can include the keyword DBSERVERNAME (or its synonym, SITENAME)in a SELECT statement on INFORMIX-OnLine Dynamic Server to find the nameof the database server. You can query on the DBSERVERNAME for any tablethat has rows, including system catalog tables.
In Query 2-67, you assign the label server to the DBSERVERNAME expressionand also select the tabid column from the systables system catalog table. Thistable describes database tables, and tabid is the serial interval table identifier.
Query 2-67SELECT DBSERVERNAME server, tabid FROM systables
WHERE tabid <= 4
Query Result 2-66
Query Result 2-67
101807/10/1994
121SW corner of Biltmore Mall
nS22942
07/13/199470.50$20.0008/06/1994
tabid
1234
Composing Simple SELECT Statements 2-65
2-66 Informix Guide to
Using Functions in SELECT Statements
hexnum h
0x00000065 0x0x00000066 0x0x00000067 0x0x00000068 0x0x00000069 0x0x0000006A 0x0x0000006B 0x0x0000006C 0x0x0000006D 0x0x0000006E 0x0x0000006F 0x0x00000070 0x0x00000071 0x0x00000072 0x0x00000073 0x0x00000074 0x0x00000075 0x0x00000076 0x0x00000077 0x0x00000078 0x0x00000079 0x0x0000007A 0x0x0000007B 0x0x0000007C 0x0x0000007D 0x0x0000007E 0x0x0000007F 0x0x00000080 0x
Without the WHERE clause to restrict the values in the tabid, the databaseserver name would be repeated for each row of the systables table.
In Query 2-68, the HEX function returns the hexadecimal format of threespecified columns in the customer table:
Query 2-68SELECT HEX (customer_num) hexnum, HEX (zipcode) hexzip,
HEX (rowid) hexrowFROM customer
Query Result 2-68exzip hexrow
00016F86 0x0000000100016FA5 0x000000020001705F 0x0000000300016F4A 0x0000000400016F46 0x0000000500016F6F 0x0000000600017060 0x0000000700016F6F 0x0000000800016F86 0x0000000900016F6E 0x0000000A00016F85 0x0000000B00016F46 0x0000000C00016F49 0x0000000D00016F6E 0x0000000E00016F49 0x0000000F00016F58 0x0000001000016F6F 0x0000001100017191 0x0000001200001F42 0x0000001300014C18 0x0000001400004DBA 0x000000150000215C 0x0000001600007E00 0x0000001700012116 0x0000001800000857 0x000000190001395B 0x0000001A0000EBF6 0x0000001B00014C10 0x0000001C
SQL: Tutorial
Using Stored Procedures in SELECT Statements
Using Stored Procedures in SELECT StatementsWe have seen examples of SELECT statement expressions consisting ofcolumn names, operators, and functions. Another type of expression is onethat contains a stored procedure call.
Stored procedures are procedures that contain special Stored ProcedureLanguage (SPL) statements as well as SQL statements. For more informationon stored procedures, refer to Chapter 12, “Creating and Using StoredProcedures.”
Stored procedures provide a way to extend the range of functions available;you can perform a subquery on each row you select.
For example, suppose you want a listing of the customer number, thecustomer’s last name, and the number of orders the customer has made. Oneway to retrieve this information is shown in Query 2-69. The customer tablehas customer_num and lname columns but no record of the number oforders each customer has made. You could write a get_orders procedure,which queries the orders table for each customer_num and returns thenumber of corresponding orders (labeled n_orders).
Query 2-69SELECT customer_num, lname, get_orders(customer_num) n_orders
FROM customer
Composing Simple SELECT Statements 2-67
2-68 Informix Guide to
Using Stored Procedures in SELECT Statements
customer_num
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
The output from this stored-procedure query is shown in Query Result 2-69:
You can use stored procedures to encapsulate operations that you frequentlyperform in your queries. For example, the condition in Query 2-70 contains aprocedure, conv_price, that converts the unit price of a stock item to adifferent currency and adds any import tariffs:
Query 2-70SELECT stock_num, manu_code, description FROM stock
WHERE conv_price(unit_price, ex_rate = 1.50, tariff = 50.00) < 1000
Query Result 2-69lname n_orders
Pauli 1Sadler 0Currie 0Higgins 4Vector 0Watson 2Ream 0Quinn 0Miller 0Jaeger 2Keyes 1Lawson 1Beatty 0Albertson 0Grant 1Parmelee 1Sipes 2Baxter 0Shorter 1Jewell 1Wallack 1O’Brian 1Hanlon 1Putnum 1Henry 0Neelie 1Satifer 1Lessor 0
SQL: Tutorial
Multiple-Table SELECT Statements
Multiple-Table SELECT StatementsYou can select data from two or more tables by naming these tables in theFROM clause. Add a WHERE clause to create a join condition between at leastone related column in each table. This creates a temporary composite table inwhich each pair of rows that satisfies the join condition is linked to form asingle row.
A simple join combines information from two or more tables based on therelationship between one column in each table. A composite join is a joinbetween two or more tables based on the relationship between two or morecolumns in each table.
To create a join, you must specify a relationship, called a join condition,between at least one column from each table. Because the columns are beingcompared, they must have compatible data types. When you join large tables,performance improves when you index the columns in the join condition.
Data types are described in Chapter 3 of the Informix Guide to SQL: Reference;indexing is discussed in detail in the administrator’s guide for your databaseserver.
Creating a Cartesian ProductWhen you perform a multiple-table query that does not explicitly state a joincondition among the tables, you create a Cartesian product. A Cartesian prod-uct consists of every possible combination of rows from the tables. This isusually a very large, unwieldy result, and the data is inaccurate.
Query 2-71 selects from two tables and produces a Cartesian product:
Query 2-71SELECT * FROM customer, state
Composing Simple SELECT Statements 2-69
2-70 Informix Guide to
Creating a Cartesian Product
customer_num fname lname company address1 address2 city state zipcode phone code sname
customer_num fname lname company address1 address2 city state zipcode phone code sname
customer_num fname lname company address1 address2 city state zipcode phone code sname . . .
Although only 52 rows exist in the state table and 28 rows in the customertable, the effect of Query 2-71 is to multiply the rows of one table by the rowsof the other and retrieve an impractical 1,456 rows, as shown in Query 2-71:
Query Result 2-71101LudwigPauliAll Sports Supplies
213 Erstwild Court
SunnyvaleCA94086408-789-8075AKAlaska
101LudwigPauliAll Sports Supplies
213 Erstwild Court
SunnyvaleCA94086408-789-8075HIHawaii
101LudwigPauliAll Sports Supplies
213 Erstwild Court
SunnyvaleCA94086408-789-8075CACalifornia
SQL: Tutorial
Creating a Join
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 anaddress in California, the code and sname from the state table might be for adifferent state.
Creating a JoinConceptually, the first stage of any join is the creation of a Cartesian product.To refine or constrain this Cartesian product and eliminate meaningless rowsof data, include a WHERE clause with a valid join condition in your SELECTstatement.
This section illustrates equi-joins, natural joins, and multiple-table joins.Additional complex forms, such as self-joins and outer joins, are covered inChapter 3, “Composing Advanced SELECT Statements.”
Equi-Join
An equi-join is a join based on equality or matching values. This equality isindicated with an equal sign (=) in the comparison operation in the WHEREclause, as shown in Query 2-72:
Query 2-72SELECT * FROM manufact, stock
WHERE manufact.manu_code = stock.manu_code
Composing Simple SELECT Statements 2-71
2-72 Informix Guide to
Creating a Join
manu_code manu_name lead_time stock_num manu_code description b unit_price $ unit unit_descr 1
manu_code manu_name lead_time stock_num manu_code description te unit_price $ unit unit_descr e
manu_code manu_name lead_time stock_num manu_code description te unit_price $ unit unit_descr 2
manu_code manu_name lead_time stock_num manu_code description te unit_price $ unit unit_descr e . . .
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 areequal, as shown in Query Result 2-72:
Query Result 2-72SMTSmith
31SMT
aseball gloves450.00case0 gloves/case
SMTSmith
35SMT
nnis racquet25.00eachach
SMTSmith
36SMT
nnis ball36.00case4 cans/case
ANZAnza
55ANZ
nnis racquet19.80eachach
SQL: Tutorial
Creating a Join
Note that in this equi-join, Query Result 2-72 includes the manu_codecolumn from both the manufact and stock tables because the select listrequested every column.
You also can create an equi-join with additional constraints, one where thecomparison condition is based on the inequality of values in the joined col-umns. These joins use a relational operator other than the equal sign (=) inthe comparison condition specified in the WHERE clause.
When columns in the joined tables have the same name, the columns must bepreceded by the name of a specific table and a period, as shown in Query2-73:
Query 2-73SELECT order_num, order_date, ship_date, cust_calls.*
FROM orders, cust_callsWHERE call_dtime >= ship_date
AND cust_calls.customer_num = orders.customer_numORDER BY customer_num
Composing Simple SELECT Statements 2-73
2-74 Informix Guide to
Creating a Join
order_num 1 order_date 05 ship_date 05 customer_num 1 call_dtime 19 user_id m call_code D call_descr Or
res_dtime 1 res_descr A
order_num 1 order_date 06 ship_date 07 customer_num 1 call_dtime 19 user_id ri call_code L call_descr Or res_dtime 1 res_descr C
order_num 1 order_date 07 ship_date 07 customer_num 1 call_dtime 19 user_id m call_code I call_descr Re
res_dtime res_descr S
Query 2-73 joins on the customer_num column and then selects only thoserows where the call_dtime in the cust_calls table is greater than or equal tothe ship_date in the orders table. It returns the rows shown in Query Result2-73:
Query Result 2-73004/22/1994/30/199406
94-06-12 08:20aryj
der received okay, but two of the cans ofANZ tennis balls within the case were empty
994-06-12 08:25uthorized credit for two cans to customer,
issued apology. Called ANZ buyer to reportthe qa problem.
008/07/1994/06/199410
94-07-07 10:24chc
der placed one month ago (6/7) not received.994-07-07 10:30hecked with shipping (Ed Smith). Order out
yesterday-was waiting for goods from ANZ.Next time will call with delay if necessary.
023/24/1994/30/199427
94-07-31 14:30aryj
ceived Hero watches (item # 304) insteadof ANZ watches
ent memo to shipping to send ANZ item 304to customer and pickup HRO watches. Shouldbe done tomorrow, 8/1
SQL: Tutorial
Creating a Join
Natural Join
A natural join is structured so that the join column does not display dataredundantly, as shown in Query 2-74:
Query 2-74SELECT manu_name, lead_time, stock.*
FROM manufact, stockWHERE manufact.manu_code = stock.manu_code
Like the example for equi-join, Query 2-74 joins the manufact and stocktables on the manu_code column. Because the select list is more closelydefined, the manu_code is listed only once for each row retrieved, as shownin Query Result 2-74.
Composing Simple SELECT Statements 2-75
2-76 Informix Guide to
Creating a Join
manu_name lead_time stock_num manu_code description b unit_price $ unit unit_descr 1
manu_name lead_time stock_num manu_code description te unit_price $ unit unit_descr e
manu_name lead_time stock_num manu_code description te unit_price $ unit unit_descr 2
manu_name lead_time stock_num manu_code description te unit_price $ unit unit_descr e . . .
All joins are associative, that is, the order of the joining terms in the WHEREclause does not affect the meaning of the join.
Query Result 2-74Smith
31SMT
aseball gloves450.00case0 gloves/case
Smith3
5SMT
nnis racquet25.00eachach
Smith3
6SMT
nnis ball36.00case4 cans/case
Anza5
5ANZ
nnis racquet19.80eachach
SQL: Tutorial
Creating a Join
catalog_num stock_num manu_code cat_descr Reinforced, ha Effective again and road grip. cat_picture <
cat_advert U
description b unit_price $ unit unit_descr 4
Both of the statements in Query 2-75 create the same natural join:
Query 2-75SELECT catalog.*, description, unit_price, unit, unit_descr
FROM catalog, stockWHERE catalog.stock_num = stock.stock_num
AND catalog.manu_code = stock.manu_codeAND catalog_num = 10017
SELECT catalog.*, description, unit_price, unit, unit_descrFROM catalog, stockWHERE catalog_num = 10017
AND catalog.manu_code = stock.manu_codeAND catalog.stock_num = stock.stock_num
Each statement retrieves the row shown in Query Result 2-75:
Note that Query 2-75 includes a TEXT column, cat_descr; a BYTE column,cat_picture; and a VARCHAR column, cat_advert.
Query Result 2-7510017101PRC
nd-finished tubular. Polyurethane belted.st punctures. Mixed tread for super wear
BYTE value>
ltimate in Puncture Protection, TiresDesigned for In-City Riding
icycle tires88.00box/box
Composing Simple SELECT Statements 2-77
2-78 Informix Guide to
Creating a Join
catalog_num 100 stock_num 106 manu_code PR cat_descr Hard anodized allo Available in length cat_picture <BYT
cat_advert ProC stock_num 106 manu_code PR description bicycle unit_price $23.0 unit eac unit_descr each manu_code PR manu_name P lead_time 9
Multiple-Table Join
A multiple-table join connects more than two tables on one or moreassociated columns; it can be an equi-join or a natural join.
Query 2-76 creates an equi-join on the catalog, stock, and manufact tablesand retrieves the following row:
Query 2-76SELECT * FROM catalog, stock, manufact
WHERE catalog.stock_num = stock.stock_numAND stock.manu_code = manufact.manu_codeAND catalog_num = 10025
Query 2-76 retrieves the rows shown in Query Result 2-76:
Note that the manu_code is repeated three times, once for each table, andstock_num is repeated twice.
Query Result 2-7625
C
y with pearl finish; 6mm hex bolt hardware.s of 90-140mm in 10mm increments.E value>
ycle Stem with Pearl Finish
Cstem
0h
CroCycle
SQL: Tutorial
Creating a Join
catalog_num 100 stock_num 106 manu_code PR cat_descr Hard anodized allo Available in length cat_picture <BYT
cat_advert ProC description bicycle unit_price $23.0 unit eac unit_descr each manu_name P lead_time 9
Because of the considerable duplication of a multiple-table query in Query2-76, it is wise to more closely define the SELECT statement by includingspecific columns in the select list, as shown in Query 2-77:
Query 2-77SELECT catalog.*, description, unit_price, unit,
unit_descr, manu_name, lead_timeFROM catalog, stock, manufactWHERE catalog.stock_num = stock.stock_num
AND stock.manu_code = manufact.manu_codeAND catalog_num = 10025
Query 2-77 uses a wildcard to select all columns from the table having themost 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 sameinformation as the previous example, but without duplication:
Query Result 2-7725
C
y with pearl finish. 6mm hex bolt hardware.s of 90-140mm in 10mm increments.E value>
ycle Stem with Pearl Finishstem
0h
roCycle
Composing Simple SELECT Statements 2-79
2-80 Informix Guide to
Some Query Shortcuts
Some Query ShortcutsYou can use aliases, the INTO TEMP clause, and display labels to speed yourway through joins and multiple-table queries and to produce output forother uses.
Using Aliases
You can make multiple-table queries shorter and more readable by assigningaliases to the tables in a SELECT statement. An alias is a word that immedi-ately follows the name of a table in the FROM clause. You can use it whereverthe table name would be used, for instance, as a prefix to the column namesin the other clauses.
Query 2-78aSELECT s.stock_num, s.manu_code, s.description,
s.unit_price, s.unit, c.catalog_num,c.cat_descr, c.cat_advert, m.lead_time
FROM stock s, catalog c, manufact mWHERE s.stock_num = c.stock_num
AND s.manu_code = c.manu_codeAND s.manu_code = m.manu_codeAND s.manu_code IN ('HRO', 'HSK')AND s.stock_num BETWEEN 100 AND 301
ORDER BY catalog_num
The associative nature of the SELECT statement allows you to use an aliasbefore you define it. In Query 2-78a, the aliases s for the stock table, c for thecatalog table, and m for the manufact table are specified in the FROM clauseand used throughout the SELECT and WHERE clauses as column prefixes.
Compare the length of Query 2-78a with Query 2-78b, which does not usealiases:
Query 2-78bSELECT stock.stock_num, stock.manu_code, stock.description,
stock.unit_price, stock.unit, catalog.catalog_num, catalog.cat_descr, catalog.cat_advert, manufact.lead_time
FROM stock, catalog, manufactWHERE stock.stock_num = catalog.stock_num
AND stock.manu_code = catalog.manu_codeAND stock.manu_code = manufact.manu_codeAND stock.manu_code IN ('HRO', 'HSK')AND stock.stock_num BETWEEN 100 AND 301
ORDER BY catalog_num
SQL: Tutorial
Some Query Shortcuts
stock_num 11 manu_code H description helme unit_price $260 unit cas catalog_num 100 cat_descr Newest ultralight channels of any h cat_advert Ligh
C lead_time
stock_num 11 manu_code H description helme unit_price $308 unit eac catalog_num 100 cat_descr Aerodynamic (tear
Credited with sha Tour de France t cat_advert Tear
Y lead_time
stock_num 20 manu_code H description 3 go unit_price $312 unit eac catalog_num 100 cat_descr Combination fluore cat_advert HiFli
Y lead_time
stock_num 30 manu_code H description runnin unit_price $42.5 unit eac catalog_num 100 cat_descr Engineered for se Fabulous shock a
mens/womens, si cat_advert Pron
T lead_time
Query 2-78a and Query 2-78b are equivalent and retrieve the data shown inQuery Result 2-78:
Query Result 2-780ROt
.00e33
helmet uses plastic shell. Largest ventilationelmet on the market. 8.5 oz.
tweight Plastic Slatted with Vents Assures Coolomfort Without Sacrificing Protection
4
0SKt
.00h34
drop) helmet covered with anti-drag fabric.ving 2 seconds/mile from winner’s time in
ime-trial. 7.5 oz.drop Design Endorsed by Yellow Jerseys,ou Can Time the Difference5
5ROlf balls.00h48
scent yellow and standard white.er Golf Balls: Case Includes Fluorescentellow and Standard White4
1ROg shoes0h50
rious training with exceptional stability.bsorption. Great durability. Specifyze.ators and Supinators Take Heart: A Seriousraining Shoe For Runners Who Need Motion Control4
Composing Simple SELECT Statements 2-81
2-82 Informix Guide to
Some Query Shortcuts
order_num
1001100210031004100510061007100810091010
Note that you cannot ORDER BY the TEXT column cat_descr or the BYTEcolumn cat_picture.
You also can use aliases to shorten your queries on external tables residing inexternal databases.
Query 2-79 joins columns from two tables that reside in different databasesand systems, neither of which is the current database or system:
Query 2-79SELECT order_num, lname, fname, phoneFROM masterdb@central:customer c, sales@western:orders o
WHERE c.customer_num = o.customer_numAND order_num <= 1010
By assigning the aliases c and o to the long database@system:table names,masterdb@central:customer and sales@western:orders, respectively, youcan use the aliases to shorten the expression in the WHERE clause and retrievethe data shown in Query Result 2-79:
For more information on external tables and external databases, seeChapter 11, “Understanding Informix Networking,” in this manual andChapter 1 in the Informix Guide to SQL: Syntax.
You also can use synonyms as shorthand references to the long names ofexternal and current tables and views. For details on how to create and usesynonyms, see Chapter 11, “Understanding Informix Networking,” in thismanual and the CREATE SYNONYM statement in Chapter 1 of the InformixGuide to SQL: Syntax.
Query Result 2-79lname fname phone
Higgins Anthony 415-368-1100Pauli Ludwig 408-789-8075Higgins Anthony 415-368-1100Watson George 415-389-8789Parmelee Jean 415-534-8822Lawson Margaret 415-887-7235Sipes Arnold 415-245-4578Jaeger Roy 415-743-3611Keyes Frances 408-277-7245Grant Alfred 415-356-1123
SQL: Tutorial
Some Query Shortcuts
stock_num manu_
1 Hero1 Husk1 Smith2 Hero3 Husk4 Hero4 Husk...
306 Shima307 ProCy308 ProCy309 Hero309 Shima310 Anza310 Shima311 Shima312 Hero312 Shima313 Anza313 Shima
The INTO TEMP Clause
By adding an INTO TEMP clause to your SELECT statement, you cantemporarily save the results of a multiple-table query in a separate table thatcan be queried or manipulated without modifying the database. Temporarytables are dropped when you end your SQL session or when your program orreport terminates.
Query 2-80 creates a temporary table called stockman and stores the resultsof the query in it. Because all columns in a temporary table must have names,the alias adj_price is required.
Query 2-80SELECT DISTINCT stock_num, manu_name, description,
unit_price, unit_price * 1.05 adj_priceFROM stock, manufactWHERE manufact.manu_code = stock.manu_codeINTO TEMP stockman
You can query on this table and join it with other tables, which avoids amultiple sort and lets you move more quickly through the database. Tempo-rary tables are discussed at greater length in the INFORMIX-OnLine DynamicServer Administrator’s Guide.
Query Result 2-80name description unit_price adj_price
baseball gloves $250.00 $262.5000y baseball gloves $800.00 $840.0000
baseball gloves $450.00 $472.5000baseball $126.00 $132.3000
y baseball bat $240.00 $252.0000football $480.00 $504.0000
y football $960.00 $1008.0000
ra tandem adapter $190.00 $199.5000cle infant jogger $250.00 $262.5000cle twin jogger $280.00 $294.0000
ear drops $40.00 $42.0000ra ear drops $40.00 $42.0000
kick board $84.00 $88.2000ra kick board $80.00 $84.0000ra water gloves $48.00 $50.4000
racer goggles $72.00 $75.6000ra racer goggles $96.00 $100.8000
swim cap $60.00 $63.0000ra swim cap $72.00 $75.6000
Composing Simple SELECT Statements 2-83
2-84 Informix Guide to
Summary
SummaryThis chapter introduced sample syntax and results for basic kinds of SELECTstatements that are used to query on a relational database. Earlier sections ofthe chapter showed how to perform the following activities:
■ Select all columns and rows from a table with the SELECT and FROMclauses
■ Select specific columns from a table with the SELECT and FROMclauses
■ Select specific rows from a table with the SELECT, FROM, and WHEREclauses
■ Use the DISTINCT or UNIQUE keyword in the SELECT clause toeliminate 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 variousrelational operators in the WHERE clause to create a comparisoncondition
■ Create comparison conditions that include values, exclude values,find a range of values (with keywords, relational operators, andsubscripting), 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 searchconditions 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 keywordsin the WHERE clause
■ Use arithmetic operators in the SELECT clause to performcomputations 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 forreports
SQL: Tutorial
Summary
■ Use the aggregate functions COUNT, AVG, MAX, MIN, and SUM in theSELECT 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 USERfunctions in your SELECT statements
■ Include stored procedures in your SELECT statements
This chapter also introduced simple join conditions that enable you to selectand display data from two or more tables. The section “Multiple-TableSELECT Statements” on page 2-69 described how to perform the followingactions:
■ Create a Cartesian product
■ Constrain a Cartesian product by including a WHERE clause with avalid join condition in your query
■ Define and create a natural join and an equi-join
■ Join two or more tables on one or mxore columns
■ Use aliases as a shortcut in multiple-table queries
■ Retrieve selected data into a separate, temporary table with the INTOTEMP clause to perform computations outside the database.
The next chapter explains more complex queries and subqueries; self-joinsand outer joins; the GROUP BY and HAVING clauses; and the UNION,INTERSECTION, and DIFFERENCE set operations.
Composing Simple SELECT Statements 2-85
3Chapter
Composing Advanced SELECTStatements
Using the GROUP BY and HAVING Clauses . . . . . . . . . . 3-4Using the GROUP BY Clause . . . . . . . . . . . . . . 3-4Using the HAVING Clause . . . . . . . . . . . . . . . 3-8
Creating Advanced Joins . . . . . . . . . . . . . . . . . 3-11Self-Joins . . . . . . . . . . . . . . . . . . . . . 3-11Outer Joins . . . . . . . . . . . . . . . . . . . . 3-21
Simple Join . . . . . . . . . . . . . . . . . . . 3-22Simple Outer Join on Two Tables . . . . . . . . . . . 3-24Outer Join for a Simple Join to a Third Table . . . . . . . 3-26Outer Join for an Outer Join to a Third Table . . . . . . . 3-27Outer Join of Two Tables to a Third Table . . . . . . . . 3-29
Subqueries in SELECT Statements . . . . . . . . . . . . . 3-31Using ALL . . . . . . . . . . . . . . . . . . . . 3-33Using ANY . . . . . . . . . . . . . . . . . . . . 3-34Single-Valued Subqueries . . . . . . . . . . . . . . . 3-35Correlated Subqueries . . . . . . . . . . . . . . . . 3-36Using EXISTS . . . . . . . . . . . . . . . . . . . 3-37
Set Operations . . . . . . . . . . . . . . . . . . . . 3-41Union . . . . . . . . . . . . . . . . . . . . . . 3-42Intersection . . . . . . . . . . . . . . . . . . . . 3-50Difference. . . . . . . . . . . . . . . . . . . . . 3-52
Summary . . . . . . . . . . . . . . . . . . . . . . 3-54
3-2 Infor
mix Guide to SQL: TutorialThe previous chapter “Composing Simple SELECT Statements,”demonstrated some basic ways to retrieve data from a relational databasewith the SELECT statement. This chapter increases the scope of what you cando with this powerful SQL statement and enables you to perform morecomplex database queries and data manipulation.
Whereas the previous chapter focused on five of the clauses in SELECTstatement syntax, this chapter adds two more. You can use the GROUP BYclause with aggregate functions to organize rows returned by the FROMclause. You can include a HAVING clause to place conditions on the valuesreturned 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, whereyou 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 SELECTstatement clauses in your queries. The clauses must appear in the followingorder:
1. SELECT
2. FROM
3. WHERE
4. GROUP BY
5. HAVING
6. ORDER BY
7. INTO TEMP
Composing Advanced SELECT Statements 3-3
3-4 Informix Guide to S
Using the GROUP BY and HAVING Clauses
An additional SELECT statement clause, INTO, which you can use to specifyprogram and host variables in INFORMIX-4GL and SQL APIs is described inChapter 5, “Programming with SQL,” as well as in the manuals that comewith the product.
Using the GROUP BY and HAVING ClausesThe optional GROUP BY and HAVING clauses add functionality to yourSELECT statement. You can include one or both in a basic SELECT statementto increase your ability to manipulate aggregates.
The GROUP BY clause combines similar rows, producing a single result rowfor each group of rows that have the same values for each column listed in theselect list. The HAVING clause sets conditions on those groups after you formthem. You can use a GROUP BY clause without a HAVING clause, or a HAVINGclause without a GROUP BY clause.
Using the GROUP BY ClauseThe GROUP BY clause divides a table into sets. It is most often combined withaggregate functions that produce summary values for each of those sets.Some examples in Chapter 2, “Composing Simple SELECT Statements”show the use of aggregate functions applied to a whole table. This chapterillustrates aggregate functions applied to groups of rows.
Using the GROUP BY clause without aggregates is much like using theDISTINCT (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 DISTINCT customer_num FROM orders
You also could write the statement as shown in Query 3-1b:
Query 3-1bSELECT customer_num
FROM ordersGROUP BY customer_num
QL: Tutorial
Using the GROUP BY Clause
customer_nu
11111111111111111
Query 3-1a and Query 3-1b return the rows shown in Query Result 3-1:
The GROUP BY clause collects the rows into sets so that each row in each sethas equal customer numbers. With no other columns selected, the result is alist of the unique customer_num values.
The power of the GROUP BY clause is more apparent when you use it withaggregate functions.
Query 3-2 retrieves the number of items and the total price of all items foreach order:
Query 3-2SELECT order_num, COUNT (*) number, SUM (total_price) price
FROM itemsGROUP BY order_num
The GROUP BY clause causes the rows of the items table to be collected intogroups, each group composed of rows that have identical order_num values(that is, the items of each order are grouped together). After you form thegroups, the aggregate functions COUNT and SUM are applied within eachgroup.
Query Result 3-1
m
0104061011121516171920212223242627
Composing Advanced SELECT Statements 3-5
3-6 Informix Guide to S
Using the GROUP BY Clause
order_num
10011002100310041005100610071008...101510161017101810191020102110221023
Query 3-2 returns one row for each group. It uses labels to give names to theresults of the COUNT and SUM expressions, as shown in Query Result 3-2:
Query Result 3-2 collects the rows of the items table into groups that haveidentical order numbers and computes the COUNT of rows in each group andthe sum of the prices.
Note that you cannot include a column having a TEXT or BYTE data type in aGROUP BY clause. To group, you must be able to sort, and no natural sort orderexists 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 sortdata in a particular order or to sort on an aggregate in the select list.
Query Result 3-2
number price
1 $250.002 $1200.003 $959.004 $1416.004 $562.005 $448.005 $1696.002 $940.00
1 $450.004 $654.003 $584.005 $1131.001 $1499.972 $438.004 $1614.003 $232.006 $824.00
QL: Tutorial
Using the GROUP BY Clause
order_num
101010111013102210011020100610151009...1018100210041014101910211007
Query 3-3 is the same as Query 3-2 but includes an ORDER BY clause to sortthe retrieved rows in ascending order of price, as shown in Query Result 3-3:
Query 3-3SELECT order_num, COUNT(*) number, SUM (total_price) price
FROM itemsGROUP BY order_numORDER BY price
As stated in Chapter 2, “Composing Simple SELECT Statements,” you canuse an integer in an ORDER BY clause to indicate the position of a column inthe select list. You also can use an integer in a GROUP BY clause to indicate theposition of column names or display labels in the group list.
Query 3-4 returns the same rows as Query 3-3, as shown in Query Result 3-3.
Query 3-4SELECT order_num, COUNT(*) number, SUM (total_price) price
FROM itemsGROUP BY 1ORDER BY 3
Query Result 3-3number price
2 $84.001 $99.004 $143.803 $232.001 $250.002 $438.005 $448.001 $450.001 $450.00
5 $1131.002 $1200.004 $1416.002 $1440.001 $1499.974 $1614.005 $1696.00
Composing Advanced SELECT Statements 3-7
3-8 Informix Guide to S
Using the HAVING Clause
order_num
10081015
When you build a query, remember that all nonaggregate columns that are inthe select list in the SELECT clause must also be included in the group list inthe GROUP BY clause. The reason for this is that a SELECT with GROUP BYmust return only one row per group. Columns that are listed after GROUP BYare certain to reflect only one distinct value within a group, and that valuecan be returned. However, a column not listed after GROUP BY might containdifferent 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 SELECTstatement that joins tables:
Query 3-5SELECT o.order_num, SUM (i.total_price)
FROM orders o, items iWHERE o.order_date > '01/01/93'
AND o.customer_num = 110AND o.order_num = i.order_num
GROUP BY o.order_num
Query 3-5 joins the orders and items tables, assigns table aliases to them, andreturns the rows shown in Query Result 3-5:
Using the HAVING ClauseThe HAVING clause usually complements a GROUP BY clause by applyingone or more qualifying conditions to groups after they are formed, which issimilar to the way the WHERE clause qualifies individual rows. Oneadvantage to using a HAVING clause is that you can include aggregates in thesearch condition, whereas you cannot include aggregates in the searchcondition of a WHERE clause.
Each HAVING condition compares one column or aggregate expression of thegroup with another aggregate expression of the group or with a constant. Youcan use HAVING to place conditions on both column values and aggregatevalues in the group list.
Query Result 3-5
(sum)
$940.00$450.00
QL: Tutorial
Using the HAVING Clause
order_num
100310041005100610071013101610171018102110221023
ave
$27
Query 3-6 returns the average total price per item on all orders that havemore than two items. The HAVING clause tests each group as it is formed andselects those composed of two or more rows.
Query 3-6SELECT order_num, COUNT(*) number, AVG (total_price) average
FROM itemsGROUP BY order_numHAVING COUNT(*) > 2
If you use a HAVING clause without a GROUP BY clause, the HAVINGcondition applies to all rows that satisfy the search condition. In other words,all rows that satisfy the search condition make up a single group.
Query 3-7, a modified version of Query 3-6, returns just one row, the averageof all total_price values in the table:
Query 3-7SELECT AVG (total_price) average
FROM itemsHAVING count(*) > 2
Query Result 3-6
Query Result 3-7
number average
3 $319.674 $354.004 $140.505 $89.605 $339.204 $35.954 $163.503 $194.675 $226.204 $403.503 $77.336 $137.33
rage
0.97
Composing Advanced SELECT Statements 3-9
3-10 Informix Guide to
Using the HAVING Clause
order_num
1017101610121019100510211022101010091020
If Query 3-7, like Query 3-6, had included the nonaggregate columnorder_ num in the select list, you would have to include a GROUP BY clausewith that column in the group list. In addition, if the condition in the HAVINGclause was not satisfied, the output would show the column heading and amessage would indicate that no rows were found.
Query 3-8 contains all the SELECT statement clauses that you can use in theInformix version of interactive SQL (the INTO clause naming program or hostvariables is available only in an INFORMIX-4GL or an SQL API):
Query 3-8SELECT o.order_num, SUM (i.total_price) price,
paid_date - order_date spanFROM orders o, items iWHERE o.order_date > '01/01/93'
AND o.customer_num > 110AND o.order_num = i.order_num
GROUP BY 1, 3HAVING COUNT (*) < 5ORDER BY 3INTO TEMP temptab1
Query 3-8 joins the orders and items tables; employs display labels, tablealiases, and integers used as column indicators; groups and orders the data;and puts the following results in a temporary table, as shown in Query Result3-8:
Query Result 3-8price span
$584.00$654.00
$1040.00$1499.97 26
$562.00 28$1614.00 30
$232.00 40$84.00 66
$450.00 68$438.00 71
SQL: Tutorial
Creating Advanced Joins
Creating Advanced JoinsChapter 2, “Composing Simple SELECT Statements,” showed how toinclude a WHERE clause in a SELECT statement to join two or more tables onone or more columns. It illustrated natural joins and equi-joins.
This chapter discusses the uses of two more complex kinds of joins: self-joinsand outer joins. As described for simple joins, you can define aliases fortables and assign display labels to expressions to shorten your multiple-tablequeries. You can also sort data with an ORDER BY clause and SELECT queryresults into a temporary table.
Self-JoinsA join does not always have to involve two different tables. You can join atable to itself, creating a self-join. This can be useful when you want tocompare 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 adifferent alias each time. Use the aliases to refer to the table in the SELECT andWHERE clauses as if it were two separate tables. (Aliases in SELECT state-ments are shown in Chapter 2, “Composing Simple SELECT Statements,” inthis manual and discussed in Chapter 1 of the Informix Guide to SQL: Syntax.)
Just as in joins between tables, you can use arithmetic expressions inself-joins. You can test for null values, and you can ORDER BY a specifiedcolumn in ascending or descending order.
Query 3-9 finds pairs of orders where the ship_weight differs by a factor offive or more, and the ship_date is not null and orders the data byship_date:
Query 3-9SELECT x.order_num, x.ship_weight, x.ship_date,
y.order_num, y.ship_weight, y.ship_dateFROM orders x, orders yWHERE x.ship_weight >= 5 * y.ship_weight
AND x.ship_date IS NOT NULLAND y.ship_date IS NOT NULL
ORDER BY x.ship_date
Composing Advanced SELECT Statements 3-11
3-12 Informix Guide to
Self-Joins
order_num ship_w
10041004100410071007100710071007100710051005100510121012101310171018
.
.
.
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 mustrename 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 theorders table and puts them in a temporary table called shipping:
Query 3-10SELECT x.order_num orders1, x.po_num purch1,
x.ship_date ship1, y.order_num orders2,y.po_num purch2, y.ship_date ship2
FROM orders x, orders yWHERE x.ship_weight >= 5 * y.ship_weight
AND x.ship_date IS NOT NULLAND y.ship_date IS NOT NULL
ORDER BY orders1, orders2INTO TEMP shipping
If you SELECT * from that table, you see the rows in Query Result 3-10:
Query Result 3-9eight ship_date order_num ship_weight ship_date
95.80 05/30/1994 1011 10.40 07/03/199495.80 05/30/1994 1020 14.00 07/16/199495.80 05/30/1994 1022 15.00 07/30/1994
125.90 06/05/1994 1015 20.60 07/16/1994125.90 06/05/1994 1020 14.00 07/16/1994125.90 06/05/1994 1022 15.00 07/30/1994125.90 06/05/1994 1011 10.40 07/03/1994125.90 06/05/1994 1001 20.40 06/01/1994125.90 06/05/1994 1009 20.40 06/21/1994
80.80 06/09/1994 1011 10.40 07/03/199480.80 06/09/1994 1020 14.00 07/16/199480.80 06/09/1994 1022 15.00 07/30/199470.80 06/29/1994 1011 10.40 07/03/199470.80 06/29/1994 1020 14.00 07/16/199460.80 07/10/1994 1011 10.40 07/03/199460.00 07/13/1994 1011 10.40 07/03/199470.50 07/13/1994 1011 10.40 07/03/1994
SQL: Tutorial
Self-Joins
orders1 purch
1004 80061004 80061004 80061005 28651005 28651005 28651007 27861007 27861007 27861007 27861007 27861007 27861012 27871012 27871013 B7791017 DM31018 S2291018 S2291019 Z5571019 Z5571019 Z5571023 KF2
You can join a table to itself more than once. The maximum number ofself-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 thatare supplied by three manufacturers. By including the last two conditions inthe WHERE clause, it eliminates duplicate manufacturer codes in rowsretrieved.
Query 3-11SELECT s1.manu_code, s2.manu_code, s3.manu_code,
s1.stock_num, s1.descriptionFROM stock s1, stock s2, stock s3WHERE s1.stock_num = s2.stock_num
AND s2.stock_num = s3.stock_numAND s1.manu_code < s2.manu_codeAND s2.manu_code < s3.manu_code
ORDER BY stock_num
Query Result 3-101 ship1 orders2 purch2 ship2
05/30/1994 1011 B77897 07/03/199405/30/1994 1020 W2286 07/16/199405/30/1994 1022 W9925 07/30/199406/09/1994 1011 B77897 07/03/199406/09/1994 1020 W2286 07/16/199406/09/1994 1022 W9925 07/30/1994
93 06/05/1994 1001 B77836 06/01/199493 06/05/1994 1009 4745 06/21/199493 06/05/1994 1011 B77897 07/03/199493 06/05/1994 1015 MA003 07/16/199493 06/05/1994 1020 W2286 07/16/199493 06/05/1994 1022 W9925 07/30/199401 06/29/1994 1011 B77897 07/03/199401 06/29/1994 1020 W2286 07/16/199430 07/10/1994 1011 B77897 07/03/199454331 07/13/1994 1011 B77897 07/03/199442 07/13/1994 1011 B77897 07/03/199442 07/13/1994 1020 W2286 07/16/199409 07/16/1994 1011 B77897 07/03/199409 07/16/1994 1020 W2286 07/16/199409 07/16/1994 1022 W9925 07/30/1994
961 07/30/1994 1011 B77897 07/03/1994
Composing Advanced SELECT Statements 3-13
3-14 Informix Guide to
Self-Joins
manu_code ma
HRO HANZ NANZ HANZ HANZ HANZ HANZ HANZ PHRO HHRO HHRO PHSK PANZ KANZ HANZ H . . .HRO PKAR NKAR NKAR PNKL PR
Say you want to select rows from a payroll table to determine whichemployees earn more than their manager. You can construct the self-joinshown in Query 3-12a:
Query 3-12a
SELECT emp.employee_num, emp.gross_pay, emp.level,emp.dept_num, mgr.employee_num, mgr.gross_pay,mgr.dept_num, mgr.level
FROM payroll emp, payroll mgrWHERE emp.gross_pay > mgr.gross_pay
AND emp.level < mgr.levelAND emp.dept_num = mgr.dept_num
ORDER BY 4
Query Result 3-11
nu_code manu_code stock_num description
SK SMT 1 baseball glovesRG SMT 5 tennis racquetRO HSK 110 helmetRO PRC 110 helmetRO SHM 110 helmetSK PRC 110 helmetSK SHM 110 helmetRC SHM 110 helmetSK PRC 110 helmetSK SHM 110 helmetRC SHM 110 helmetRC SHM 110 helmetAR NKL 201 golf shoesRO NKL 205 3 golf ballsRO KAR 301 running shoes
RC SHM 301 running shoesKL PRC 301 running shoesKL SHM 301 running shoesRC SHM 301 running shoes
C SHM 301 running shoes
SQL: Tutorial
Self-Joins
order_num t
1018101310031005100610131010101310221023
Query 3-12b uses a correlated subquery to retrieve and list the 10 highest-priced items ordered:
Query 3-12bSELECT order_num, total_price
FROM items aWHERE 10 >
(SELECT COUNT (*)FROM items bWHERE b.total_price < a.total_price)
ORDER BY total_price
Query 3-12b returns the 10 rows shown in Query Result 3-12:
You can create a similar query to find and list the 10 employees in thecompany who have the most seniority.
Correlated and uncorrelated subqueries are described later in “Subqueries inSELECT Statements” on page 3-31.
Using Rowid ValuesImportant: OnLine assigns a unique rowid to rows in nonfragmented tables. Rowsin fragmented tables do not contain the rowid column. Informix recommends thatyou use primary keys as a method of access in your applications rather than rowids.Because primary keys are defined in the ANSI specification of SQL, using them toaccess data makes your applications more portable. In addition, the time required byOnLine to access data in a fragmented table using a primary key is less than the timerequired to access the same data using rowid. For additional information about row-ids and tables, see “Accessing Data Stored in Fragmented Tables” on page 9-41.
Query Result 3-12otal_price
$15.00$19.80$20.00$36.00$36.00$36.00$36.00$40.00$40.00$40.00
Composing Advanced SELECT Statements 3-15
3-16 Informix Guide to
Self-Joins
rowid c
515769
You can use the hidden rowid column in a self-join to locate duplicate valuesin a table. In the following example, the condition x.rowid != y.rowid isequivalent to saying “row x is not the same row as row y.”
Query 3-13 selects data twice from the cust_calls table, assigning it the tablealiases x and y:
Query 3-13SELECT x.rowid, x.customer_num
FROM cust_calls x, cust_calls yWHERE x.customer_num = y.customer_num
AND x.rowid != y.rowid
Query 3-13 searches for duplicate values in the customer_num column, andfor their rowids, finding the pair shown in Query Result 3-13:
You can write the last condition in Query 3-13 as shown in the followingexample:
AND x.rowid != y.rowid
AND NOT x.rowid = y.rowid
Another way to locate duplicate values is with a correlated subquery, asshown in Query 3-14:
Query 3-14SELECT x.customer_num, x.call_dtime
FROM cust_calls xWHERE 1 <
(SELECT COUNT (*) FROM cust_calls yWHERE x.customer_num = y.customer_num)
Query Result 3-13ustomer_num
116116
SQL: Tutorial
Self-Joins
customer_num
116116
rowid m
257258259260261262263264265
Query 3-14 locates the same two duplicate customer_num values as Query3-13 and returns the rows shown in Query Result 3-14:
You can use the rowid, shown earlier in a self-join, to locate the internalrecord number associated with a row in a database table. The rowid is, ineffect, a hidden column in every table. The sequential values of rowid haveno 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. Theuse of rowid is discussed in detail in the INFORMIX-OnLine Dynamic ServerAdministrator’s Guide.
Query 3-15 uses the rowid and the wildcard asterisk symbol (*) in the SELECTclause to retrieve every row in the manufact table and their correspondingrowids:
Query 3-15SELECT rowid, * FROM manufact
Query Result 3-14
Query Result 3-15
call_dtime
1993-11-28 13:341993-12-21 11:24
anu_code manu_name lead_time
SMT Smith 3ANZ Anza 5NRG Norge 7HSK Husky 5HRO Hero 4SHM Shimara 30KAR Karsten 21NKL Nikolus 8PRC ProCycle 9
Composing Advanced SELECT Statements 3-17
3-18 Informix Guide to
Self-Joins
rowid m
258261260263264259265262257
manu_code m
KAR
You also can use the rowid when you select a specific column, as shown inQuery 3-16:
Query 3-16SELECT rowid, manu_code FROM manufact
You can use the rowid in the WHERE clause to retrieve rows based on theirinternal record number. This method is handy when no other unique columnexists in a table. Query 3-17 uses a rowid from Query 3-16:
Query 3-17SELECT * FROM manufact WHERE rowid = 263
Query 3-17 returns the row shown in Query Result 3-17:
Query Result 3-16
Query Result 3-17
anu_code
ANZHROHSKKARNKLNRGPRCSHMSMT
anu_name lead_time
Karsten 21
SQL: Tutorial
Self-Joins
username
zendazendazendazendazendazendazenda
rowid
258259
Using the USER Function
To obtain additional information about a table, you can combine the rowidwith the USER function.
Query 3-18 assigns the label username to the USER expression column andreturns this information about the cust_calls table:
Query 3-18SELECT USER username, rowid FROM cust_calls
You also can use the USER function in a WHERE clause when you select therowid.
Query 3-19 returns the rowid for only those rows inserted or updated by theuser who performs the query:
Query 3-19SELECT rowid FROM cust_calls WHERE user_id = USER
For example, if the user richc used Query 3-19, the output would be as shownin Query Result 3-19:
Query Result 3-18
Query Result 3-19
rowid
257258259513514515769
Composing Advanced SELECT Statements 3-19
3-20 Informix Guide to
Self-Joins
server
manatee manatee manatee manatee manatee manatee manatee manatee manatee manatee
Using the DBSERVERNAME Function
With INFORMIX-OnLine Dynamic Server, you can add the DBSERVERNAMEkeyword (or its synonym, SITENAME) to a query to find out where thecurrent database resides.
Query 3-20 finds the database server name and the user name as well as therowid and the tabid, which is the serial interval table identifier for systemcatalog tables:
Query 3-20SELECT DBSERVERNAME server, tabid, rowid, USER username
FROM systablesWHERE tabid >= 105 OR rowid <= 260ORDER BY rowid
Query 3-20 assigns display labels to the DBSERVERNAME and USERexpressions and returns the 10 rows from the systables system catalog table,as shown in Query Result 3-20:
Note that you should never store a rowid in a permanent table or attempt touse it as a foreign key because the rowid can change. For example, if a tableis dropped and then reloaded from external data, all the rowids are different.
USER and DBSERVERNAME were discussed in Chapter 2, “ComposingSimple SELECT Statements.”
Query Result 3-20tabid rowid username
1 257 zenda2 258 zenda3 259 zenda4 260 zenda
105 274 zenda106 1025 zenda107 1026 zenda108 1027 zenda109 1028 zenda110 1029 zenda
SQL: Tutorial
Outer Joins
Outer JoinsChapter 2, “Composing Simple SELECT Statements,” showed how to createand use some simple joins. Whereas a simple join treats two or more joinedtables equally, an outer join treats two or more joined tables unsymmetrically.It makes one of the tables dominant (also called “preserved”) over the othersubservient 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 outerjoins in Chapter 1 of the Informix Guide to SQL: Syntax for full information ontheir syntax, use, and logic.
In a simple join, the result contains only the combinations of rows from thetables that satisfy the join conditions. Rows that do not satisfy the join conditionsare discarded.
In an outer join, the result contains the combinations of rows from the tablesthat satisfy the join conditions. Rows from the dominant table that wouldotherwise be discarded are preserved, even though no matching row was found in thesubservient table. The dominant-table rows that do not have a matchingsubservient-table row receive a row of nulls before the selected columns areprojected.
An outer join applies conditions to the subservient table while sequentiallyapplying the join conditions to the rows of the dominant table. Theconditions are expressed in a WHERE clause.
An outer join must have a SELECT clause, a FROM clause, and a WHEREclause. 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 FROMclause. As shown later in this section, you can include the OUTER keywordmore than once in your query.
Composing Advanced SELECT Statements 3-21
3-22 Informix Guide to
Outer Joins
Before you use outer joins heavily, you should determine whether one ormore simple joins can work. You often can get by with a simple join when youdo not need supplemental information from other tables.
The examples in this section use table aliases for brevity. Table aliases arediscussed in Chapter 2, “Composing Simple SELECT Statements.”
Simple Join
Query 3-21 is an example of the type of simple join on the customer andcust_calls tables that is shown in Chapter 2, “Composing Simple SELECTStatements.”
Query 3-21SELECT c.customer_num, c.lname, c.company,
c.phone, u.call_dtime, u.call_descrFROM customer c, cust_calls uWHERE c.customer_num = u.customer_num
Query 3-21 returns only those rows where the customer has made a call tocustomer service, as shown in Query Result 3-21:
SQL: Tutorial
Outer Joins
customer_num 10lname Wcompany Wphone 41call_dtime 1994call_descr Orde
A
customer_num 11lname Jacompany Aphone 41call_dtime 1994call_descr Orde
customer_num 11lname Shcompany Tphone 60call_dtime 1994call_descr Bill
customer_num 12lname Wcompany Cphone 30call_dtime 1994call_descr Cust
sto
customer_num 12lname Sacompany Bphone 31call_dtime 1994call_descr Rece
A
customer_num 11lname Pacompany Ophone 41call_dtime 1993call_descr Rece
o
customer_num 11lname Pacompany Ophone 41call_dtime 1993call_descr Seco
twin
Query Result 3-21
6atsonatson & Son5-389-8789-06-12 08:20r was received, but two of the cans ofNZ tennis balls within the case were empty
0egerA Athletics5-743-3611-07-07 10:24r placed one month ago (6/7) not received.
9orter
he Triathletes Club9-663-6079-07-01 15:00
does not reflect credit from previous order
1allackity Sports2-366-7511-07-10 14:05omer likes our merchandise. Requests that wetock more types of infant joggers. Will call back
place order.
7tifer
ig Blue Bike Shop2-944-5691-07-31 14:30ived Hero watches (item # 304) instead ofNZ watches
6rmelee
lympic City5-534-8822-11-28 13:34ived plain white swim caps (313 ANZ) instead
f navy with team logo (313 SHM)
6rmelee
lympic City5-534-8822-12-21 11:24nd complaint from this customer! Receivedo cases right-handed outfielder gloves (1 HRO)stead of one case lefties.
Composing Advanced SELECT Statements 3-23
3-24 Informix Guide to
Outer Joins
Simple Outer Join on Two Tables
Query 3-22 uses the same select list, tables, and comparison condition as thepreceding example, but this time it creates a simple outer join:
Query 3-22SELECT c.customer_num, c.lname, c.company,
c.phone, u.call_dtime, u.call_descrFROM customer c, OUTER cust_calls uWHERE c.customer_num = u.customer_num
The addition of the keyword OUTER in front of the cust_calls table makes itthe subservient table. An outer join causes the query to return information onall customers, whether or not they have made calls to customer service. Allrows from the dominant customer table are retrieved, and null values areassigned to corresponding rows from the subservient cust_calls table, asshown in Query Result 3-22:
SQL: Tutorial
Outer Joins
customer_num 10lname Pacompany Aphone 40call_dtimecall_descr
customer_num 10lname Sacompany Sphone 41call_dtimecall_descr
customer_num 10lname Ccompany Pphone 41call_dtimecall_descr
customer_num 10lname Hcompany Pphone 41call_dtimecall_descr
customer_num 10lname Vecompany Lophone 41call_dtimecall_descr
customer_num 10lname Wcompany Wphone 41call_dtime 1994call_descr Orde
A
customer_num 10lname Rcompany Aphone 41call_dtimecall_descr
customer_num 10lname Qcompany Qphone 41call_dtimecall_descr
.
.
Query Result 3-221uli
ll Sports Supplies8-789-8075
2dler
ports Spot5-822-1289
3urriehil’s Sports5-328-4543
4igginslay Ball!5-368-1100
5ctors Altos Sports5-776-3249
6atsonatson & Son5-389-8789-06-12 08:20r was received, but two of the cans ofNZ tennis balls within the case were empty
7eamthletic Supplies5-356-9876
8uinnuinn’s Sports5-544-8729
Composing Advanced SELECT Statements 3-25
3-26 Informix Guide to
Outer Joins
Outer Join for a Simple Join to a Third Table
Query 3-23 shows an outer join that is the result of a simple join to a thirdtable. This second type of outer join is known as a nested simple join.
Query 3-23SELECT c.customer_num, c.lname, o.order_num,
i.stock_num, i.manu_code, i.quantityFROM customer c, OUTER (orders o, items i)WHERE c.customer_num = o.customer_num
AND o.order_num = i.order_numAND manu_code IN ('KAR', 'SHM')
ORDER BY lname
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 orSHM. It then performs an outer join to combine this information with datafrom the dominant customer table. An optional ORDER BY clause reorganizesthe data into the form shown in Query Result 3-23:
SQL: Tutorial
Outer Joins
customer_num lnam
114 Alb118 Ba113 Be103 Cu115 Gra123 Ha123 Ha125 He104 Hig110 Jae120 Jew120 Jew111 Ke112 Law128 Les109 Mil126 Ne122 O’B116 Pa101 Pa124 Pu108 Qu107 Re102 Sa127 Sa127 Sa127 Sa119 Sh117 Sip105 Ve121 Wa106 Wa
Outer Join for an Outer Join to a Third Table
Query 3-24 creates an outer join that is the result of an outer join to a thirdtable. This third type is known as a nested outer join.
Query 3-24SELECT c.customer_num, lname, o.order_num,
stock_num, manu_code, quantityFROM customer c, OUTER (orders o, OUTER items i)WHERE c.customer_num = o.customer_num
AND o.order_num = i.order_numAND manu_code IN ('KAR', 'SHM')
ORDER BY lname
Query Result 3-23e order_num stock_num manu_code quantity
ertsonxterattyrrient
nlon 1020 301 KAR 4nlon 1020 204 KAR 2nryginsgerell 1017 202 KAR 1ell 1017 301 SHM 2
yessonsor
lerelierian 1019 111 SHM 3
rmeleeulitnum 1021 202 KAR 3innamdlertifer 1023 306 SHM 1tifer 1023 105 SHM 1tifer 1023 110 SHM 1orter 1016 101 SHM 2esctorllack 1018 302 KAR 3tson
Composing Advanced SELECT Statements 3-27
3-28 Informix Guide to
Outer Joins
customer_num lnam
114 Alb118 Ba113 Be103 Cu115 Gra123 Ha123 Ha125 He104 Hig104 Hig104 Hig104 Hig110 Jae110 Jae120 Jew120 Jew111 Ke112 Law128 Les109 Mil126 Ne122 O’B116 Pa101 Pa124 Pu108 Qu107 Re102 Sa127 Sa127 Sa127 Sa119 Sh117 Sip117 Sip105 Ve121 Wa106 Wa106 Wa
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 orSHM. It then performs an outer join, which combines this information withdata from the dominant customer table. Query 3-24 preserves order numbersthat the previous example eliminated, returning rows for orders that do notcontain items with either manufacturer code. An optional ORDER BY clausereorganizes the data, as shown in Query Result 3-24:
Query Result 3-24e order_num stock_num manu_code quantity
ertsonxterattyrrient 1010
nlon 1020 204 KAR 2nlon 1020 301 KAR 4nrygins 1011gins 1001gins 1013gins 1003ger 1008ger 1015ell 1017 301 SHM 2ell 1017 202 KAR 1
yes 1009son 1006sor
lerelie 1022rian 1019 111 SHM 3
rmelee 1005uli 1002tnum 1021 202 KAR 3innamdlertifer 1023 110 SHM 1tifer 1023 105 SHM 1tifer 1023 306 SHM 1orter 1016 101 SHM 2es 1012es 1007ctorllack 1018 302 KAR 3tson 1014tson 1004
SQL: Tutorial
Outer Joins
You can state the join conditions in two ways when you apply an outer jointo the result of an outer join to a third table. The two subservient tables arejoined, but you can join the dominant table to either subservient table with-out affecting the results if the dominant table and the subservient table sharea common column.
Outer Join of Two Tables to a Third Table
Query 3-25 shows an outer join that is the result of an outer join of each of twotables to a third table. In this fourth type of outer join, join relationships arepossible only between the dominant table and the subservient tables.
Query 3-25SELECT c.customer_num, lname, o.order_num,
order_date, call_dtimeFROM customer c, OUTER orders o, OUTER cust_calls xWHERE c.customer_num = o.customer_num
AND c.customer_num = x.customer_numORDER BY lnameINTO TEMP service
Query 3-25 individually joins the subservient tables orders and cust_calls tothe dominant customer table; it does not join the two subservient tables. AnINTO TEMP clause selects the results into a temporary table for furthermanipulation or queries, as shown in Query Result 3-25.
Composing Advanced SELECT Statements 3-29
3-30 Informix Guide to
Outer Joins
customer_num lnam
114 Alb118 Ba113 Be103 Cu115 Gra123 Ha125 He104 Hig104 Hig104 Hig104 Hig110 Jae110 Jae120 Jew111 Ke112 Law109 Mil128 Mo126 Ne122 O’B116 Pa116 Pa101 Pa124 Pu108 Qu107 Re102 Sa127 Sa119 Sh117 Sip117 Sip105 Ve121 Wa106 Wa106 Wa
Note that if Query 3-25 had tried to create a join condition between the twosubservient tables o and x, as shown in Query 3-26, an error message wouldhave indicated the creation of a two-sided outer join:
Query 3-26WHERE o.customer_num = x.customer_num
Query Result 3-25e order_num order_date call_dtime
ertsonxterattyrrient 1010 06/17/1994
nlon 1020 07/11/1994nrygins 1003 05/22/1994gins 1001 05/20/1994gins 1013 06/22/1994gins 1011 06/18/1994ger 1015 06/27/1994 1994-07-07 10:24ger 1008 06/07/1994 1994-07-07 10:24ell 1017 07/09/1994
yes 1009 06/14/1994son 1006 05/30/1994
leroreelie 1022 07/24/1994rian 1019 07/11/1994
rmelee 1005 05/24/1994 1993-12-21 11:24rmelee 1005 05/24/1994 1993-11-28 13:34uli 1002 05/21/1994tnum 1021 07/23/1994innamdlertifer 1023 07/24/1994 1994-07-31 14:30orter 1016 06/29/1994 1994-07-01 15:00es 1007 05/31/1994es 1012 06/18/1994ctorllack 1018 07/10/1994 1994-07-10 14:05tson 1004 05/22/1994 1994-06-12 08:20tson 1014 06/25/1994 1994-06-12 08:20
SQL: Tutorial
Subqueries in SELECT Statements
Subqueries in SELECT StatementsA SELECT statement nested in the WHERE clause of another SELECT statement(or in an INSERT, DELETE, or UPDATE statement) is called a subquery. Eachsubquery must contain a SELECT clause and a FROM clause, and it must beenclosed in parentheses, which tells the database server to perform thatoperation first.
Subqueries can be correlated or uncorrelated. A subquery (or inner SELECTstatement) is correlated when the value it produces depends on a value pro-duced by the outer SELECT statement that contains it. Any other kind ofsubquery is considered uncorrelated.
The important feature of a correlated subquery is that, because it depends ona value from the outer SELECT, it must be executed repeatedly, once for everyvalue produced by the outer SELECT. An uncorrelated subquery is executedonly once.
You can construct a SELECT statement with a subquery to replace twoseparate SELECT statements.
Subqueries in SELECT statements allow you to perform the following actions:
■ Compare an expression to the result of another SELECT statement
■ Determine whether an expression is included in the results ofanother SELECT statement
■ Determine whether any rows are selected by another SELECTstatement
An optional WHERE clause in a subquery often is used to narrow the searchcondition.
Composing Advanced SELECT Statements 3-31
3-32 Informix Guide to
Subqueries in SELECT Statements
A subquery selects and returns values to the first or outer SELECT statement.A subquery can return no value, a single value, or a set of values.
■ If it returns no value, the query does not return any rows. Such asubquery is equivalent to a null value.
■ If it returns one value, the subquery returns either one aggregateexpression or else selects exactly one row and one column. Such asubquery is equivalent to a single number or character value.
■ If it returns a list or set of values, the subquery returns either one rowor one column.
The following keywords introduce a subquery in the WHERE clause of aSELECT statement:
■ ALL
■ ANY
■ IN
■ EXISTS
You can use any relational operator with ALL and ANY to compare somethingto every one of (ALL), or to any one of (ANY), the values that the subqueryproduces. You can use the keyword SOME in place of ANY. The operator IN isequivalent to =ANY. To create the opposite search condition, use the keywordNOT or a different relational operator.
The EXISTS operator tests a subquery to see if it found any values; that is, itasks if the result of the subquery is not null.
See Chapter 1 in the Informix Guide to SQL: Syntax for the complete syntaxused in creating a condition with a subquery.
SQL: Tutorial
Using ALL
order_num s
1003100510061010101310131018
Using ALLUse the keyword ALL preceding a subquery to determine whether acomparison 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 trueof all the zero values.)
Query 3-27 lists the following information for all orders that contain an itemfor which the total price is less than the total price on every item in ordernumber 1023:
Query 3-27SELECT order_num, stock_num, manu_code, total_price
FROM itemsWHERE total_price < ALL
(SELECT total_price FROM itemsWHERE order_num = 1023)
Query Result 3-27tock_num manu_code total_price
9 ANZ $20.006 SMT $36.006 SMT $36.006 SMT $36.005 ANZ $19.806 SMT $36.00
302 KAR $15.00
Composing Advanced SELECT Statements 3-33
3-34 Informix Guide to
Using ANY
order_num
10011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
Using ANYUse the keyword ANY (or its synonym SOME) preceding a subquery todetermine whether a comparison is true for at least one of the valuesreturned. 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 forwhich the total price is greater than the total price of any one of the items inorder number 1005.
Query 3-28SELECT DISTINCT order_num
FROM itemsWHERE total_price > ANY
(SELECT total_priceFROM itemsWHERE order_num = 1005)
Query Result 3-28
SQL: Tutorial
Single-Valued Subqueries
order_num
1012
order_num s
1003101810181018
Single-Valued SubqueriesYou do not need to include the keyword ALL or ANY if you know thesubquery can return exactly one value to the outer-level query. A subquery thatreturns exactly one value can be treated like a function. This kind of subqueryoften uses an aggregate function because aggregate functions always returnsingle values
Query 3-29 uses the aggregate function MAX in a subquery to find theorder_num for orders that include the maximum number of volleyball nets.
Query 3-29SELECT order_num FROM items
WHERE stock_num = 9AND quantity =
(SELECT MAX (quantity)FROM itemsWHERE stock_num = 9)
Query 3-30 uses the aggregate function MIN in the subquery to select itemsfor which the total price is higher than 10 times the minimum price:
Query 3-30SELECT order_num, stock_num, manu_code, total_price
FROM items xWHERE total_price >
(SELECT 10 * MIN (total_price)FROM itemsWHERE order_num = x.order_num)
Query Result 3-29
Query Result 3-30tock_num manu_code total_price
8 ANZ $840.00307 PRC $500.00110 PRC $236.00304 HRO $280.00
Composing Advanced SELECT Statements 3-35
3-36 Informix Guide to
Correlated Subqueries
po_num s
4745 0278701 0429Q 08052 0B77897 0LZ230 0B77930 0PC6782 0DM354331 0S22942 0MA003 0W2286 0Z55709 0C3288 0KF2961 0W9925 0
Correlated SubqueriesQuery 3-31 is an example of a correlated subquery, which returns a list of the10 earliest shipping dates in the orders table. It includes an ORDER BY clauseafter the subquery to order the results because you cannot include ORDER BYwithin a subquery.
Query 3-31SELECT po_num, ship_date FROM orders main
WHERE 10 >(SELECT COUNT (DISTINCT ship_date)
FROM orders subWHERE sub.ship_date > main.ship_date)AND ship_date IS NOT NULL
ORDER BY ship_date, po_num
The subquery is correlated because the number it produces depends onmain.ship_date, a value produced by the outer SELECT. Thus, the subquerymust be executed anew for every row that the outer query considers.
Query 3-31 uses the COUNT function to return a value to the main query. TheORDER BY clause then orders the data. The query locates and returns the 13rows that have the 10 latest shipping dates, as shown in Query Result 3-31:
Query Result 3-31hip_date
6/21/19946/29/19946/29/19947/03/19947/03/19947/06/19947/10/19947/12/19947/13/19947/13/19947/16/19947/16/1994
7/16/19947/25/19947/30/19947/30/1994
SQL: Tutorial
Using EXISTS
manu_name
AnzaHeroKarstenNikolusProCycleShimara
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 itexecutes the subquery once for every row of the table. Indexing andperformance issues are discussed in the administrator’s guide for yourdatabase server.
Using EXISTSThe keyword EXISTS is known as an existential qualifier because the subqueryis true only if the outer SELECT, shown in Query 3-32a, finds at least one row:
Query 3-32a
SELECT UNIQUE manu_name, lead_timeFROM manufactWHERE EXISTS
(SELECT * FROM stockWHERE description MATCHES '*shoe*'
AND manufact.manu_code = stock.manu_code)
You often can construct a query with EXISTS that is equivalent to one that usesIN. You also can substitute =ANY for IN, as shown in Query 3-32b:
Query 3-32bSELECT UNIQUE manu_name, lead_time
FROM stock, manufactWHERE manufact.manu_code IN
(SELECT manu_code FROM stockWHERE description MATCHES '*shoe*')
AND stock.manu_code = manufact.manu_code
Query 3-32a and Query 3-32b return rows for the manufacturers that producea kind of shoe as well as the lead time for ordering the product. These resultsare shown in Query Result 3-32:
Query Result 3-32lead_time
54
2189
30
Composing Advanced SELECT Statements 3-37
3-38 Informix Guide to
Using EXISTS
customer_num
102103105107108109113114118125128
Note that you cannot use the predicate IN for a subquery that contains acolumn with a TEXT or BYTE data type.
Add the keyword NOT to IN or to EXISTS to create a search condition that isthe 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 thedatabase server to do less work than the other, depending on the design ofthe database and the size of the tables. To find out which query might bebetter, you can use the SET EXPLAIN command to get a listing of the queryplan. SET EXPLAIN is discussed in the INFORMIX-OnLine Dynamic ServerPerformance Guide and in Chapter 1 of the Informix Guide to SQL: Syntax.
Query 3-33SELECT customer_num, company FROM customer
WHERE customer_num NOT IN(SELECT customer_num FROM orders
WHERE customer.customer_num = orders.customer_num)
SELECT customer_num, company FROM customerWHERE NOT EXISTS
(SELECT * FROM ordersWHERE customer.customer_num = orders.customer_num)
Each statement in Query 3-33 returns the rows shown in Query Result 3-33,which identify customers who have not placed orders:
Query Result 3-33company
Sports SpotPhil’s SportsLos Altos SportsAthletic SuppliesQuinn’s SportsSport StuffSportstownSporting PlaceBlue Ribbon SportsTotal Fitness SportsPhoenix University
SQL: Tutorial
Using EXISTS
Note that the keywords EXISTS and IN are used for the set operation knownas intersection, and the keywords NOT EXISTS and NOT IN are used for the setoperation known as difference. These concepts are discussed in “Set Opera-tions” on page 3-41.
Query 3-34 identifies all the items in the stock table that have not beenordered yet by performing a subquery on the items table:
Query 3-34SELECT stock.* FROM stock
WHERE NOT EXISTS(SELECT * FROM items
WHERE stock.stock_num = items.stock_numAND stock.manu_code = items.manu_code)
Composing Advanced SELECT Statements 3-39
3-40 Informix Guide to
Using EXISTS
stock_num manu_c
101 PRC102 SHM102 PRC105 PRC106 PRC107 PRC108 SHM109 SHM110 ANZ110 HRO112 SHM113 SHM201 KAR202 NKL203 NKL205 NKL205 HRO301 NKL301 HRO301 PRC301 ANZ302 HRO303 KAR305 HRO306 PRC308 PRC309 SHM310 SHM310 ANZ311 SHM312 SHM312 HRO313 SHM313 ANZ
It returns the rows shown in Query Result 3-34:
Note that no logical limit exists to the number of subqueries a SELECTstatement can have, but the size of any statement is physically limited whenconsidered as a character string. However, this limit is probably larger thanany practical statement you are likely to compose.
Query Result 3-34ode description unit_price unit unit_descr
bicycle tires $88.00 box 4/boxbicycle brakes $220.00 case 4 sets/casebicycle brakes $480.00 case 4 sets/casebicycle wheels $53.00 pair pairbicycle stem $23.00 each eachbicycle saddle $70.00 pair paircrankset $45.00 each eachpedal binding $200.00 case 4 pairs/casehelmet $244.00 case 4/casehelmet $260.00 case 4/case12-spd, assmbld $549.00 each each18-spd, assmbld $685.90 each eachgolf shoes $90.00 each eachmetal woods $174.00 case 2 sets/caseirons/wedge $670.00 case 2 sets/case3 golf balls $312.00 case 24/case3 golf balls $312.00 case 24/caserunning shoes $97.00 each eachrunning shoes $42.50 each eachrunning shoes $75.00 each eachrunning shoes $95.00 each eachice pack $4.50 each eachsocks $36.00 box 24 pairs/boxfirst-aid kit $48.00 case 4/casetandem adapter $160.00 each eachtwin jogger $280.00 each eachear drops $40.00 case 20/casekick board $80.00 case 10/casekick board $84.00 case 12/casewater gloves $48.00 box 4 pairs/boxracer goggles $96.00 box 12/boxracer goggles $72.00 box 12/boxswim cap $72.00 box 12/boxswim cap $60.00 box 12/box
SQL: Tutorial
Set Operations
item_num order
12
Perhaps you want to check whether information has been entered correctlyin the databaes. One way to find errors in a database is to write a query thatreturns output only when errors exist. A subquery of this type serves as akind of audit query, as shown in Query 3-35:
Query 3-35SELECT * FROM items
WHERE total_price != quantity *(SELECT unit_price FROM stock
WHERE stock.stock_num = items.stock_numAND stock.manu_code = items.manu_code)
Query 3-35 returns only those rows for which the total price of an item on anorder is not equal to the stock unit price times the order quantity. Assumingthat no discount has been applied, such rows must have been entered incor-rectly in the database. The query returns rows only when errors occur. Ifinformation is correctly inserted into the database, no rows are returned.
Set OperationsThe standard set operations union, intersection, and difference let youmanipulate database information. These three operations enable you to useSELECT statements to check the integrity of your database after you performan update, insert, or delete. They can be useful when you transfer data to ahistory table, for example, and want to verify that the correct data is in thehistory table before you delete it from the original table.
Query Result 3-35_num stock_num manu_code quantity total_price
1004 1 HRO 1 $960.001006 5 NRG 5 $190.00
Composing Advanced SELECT Statements 3-41
3-42 Informix Guide to
Union
SELECT DISTINCFROM stockWHERE unit_pr
UNION
SELECT stock_nuFROM itemsWHERE quantit
UnionThe union operation uses the UNION keyword, or operator, to combine twoqueries into a single compound query. You can use the UNION keywordbetween two or more SELECT statements to unite them and produce atemporary 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 thedefinition of a view.) Figure 3-1 illustrates the union set operation.
The UNION keyword selects all rows from the two queries, removesduplicates, and returns what is left. Because the results of the queries arecombined into a single result, the select list in each query must have the samenumber of columns. Also, the corresponding columns selected from eachtable must be of the same data type (CHARACTER type columns must be thesame length), and these corresponding columns must either all allow or alldisallow nulls.
Figure 3-1The union set operation
quantity > 3
unit_price < 25.00
unit_price
quantity
qualifies
less thanor equal
to 3
greater thanor equal to
25.00
less than25.00
qualifies
qualifies
greaterthan 3
T stock_num, manu_code
ice < 25.00
m, manu_code
y > 3
SQL: Tutorial
Union
stock_num man
5 AN5 NR5 SM9 AN
103 PR106 PR201 NK301 KA302 HR302 KA
Query 3-36 performs a union on the stock_num and manu_code columns inthe stock and items tables:
Query 3-36SELECT DISTINCT stock_num, manu_code
FROM stockWHERE unit_price < 25.00
UNION
SELECT stock_num, manu_codeFROM itemsWHERE quantity > 3
Query 3-36 selects those items that have a unit price of less than $25.00 or thathave been ordered in quantities greater than three and lists their stock_numand manu_code, as shown in Query Result 3-36:
If you include an ORDER BY clause, it must follow Query 3-36 and use aninteger, not an identifier, to refer to the ordering column. Ordering takesplace after the set operation is complete.
Query Result 3-36
u_code
ZGTZCCLROR
Composing Advanced SELECT Statements 3-43
3-44 Informix Guide to
Union
stock_num man
5 AN9 AN
302 HR301 KA302 KA201 NK
5 NR103 PR106 PR
5 SM
Query 3-37SELECT DISTINCT stock_num, manu_code
FROM stockWHERE unit_price < 25.00
UNION
SELECT stock_num, manu_codeFROM itemsWHERE quantity > 3ORDER BY 2
The compound query in Query 3-37 selects the same rows as Query 3-36 butdisplays them in order of the manufacturer code, as shown in Query Result3-37:
By default, the UNION keyword excludes duplicate rows. Add the optionalkeyword ALL, as shown in Query 3-38, to retain the duplicate values:
Query 3-38SELECT stock_num, manu_code
FROM stockWHERE unit_price < 25.00
UNION ALL
SELECT stock_num, manu_codeFROM itemsWHERE quantity > 3ORDER BY 2INTO TEMP stockitem
Query Result 3-37u_code
ZZORRLGCCT
SQL: Tutorial
Union
stock_num man
9 AN5 AN9 AN5 AN9 AN5 AN5 AN5 AN
302 HR302 KA301 KA201 NK
5 NR5 NR
103 PR106 PR
5 SM5 SM
Query 3-38 uses the UNION ALL keywords to unite two SELECT statementsand puts the results into a temporary table by adding an INTO TEMP clauseafter the final SELECT. It returns the same rows as Query 3-37 but alsoincludes duplicate values.
Corresponding columns in the select lists for the combined queries musthave identical data types, but the columns do not need to use the sameidentifier.
Query 3-39 selects the state column from the customer table and thecorresponding code column from the state table:
Query 3-39SELECT DISTINCT state
FROM customerWHERE customer_num BETWEEN 120 AND 125
UNION
SELECT DISTINCT codeFROM stateWHERE sname MATCHES '*a'
Query Result 3-38u_code
ZZZZZZZZORRLGGCCTT
Composing Advanced SELECT Statements 3-45
3-46 Informix Guide to
Union
state
AKALAZCADEFLGAIAINLAMAMNMTNCNDNENJNVOKPASCSDVAWV
Query Result 3-39 returns state code abbreviations for customer numbers 120through 125, or for states whose sname ends in A or a:
In compound queries, the column names or display labels in the first SELECTstatement are the ones that appear in the results. Thus, in Query 3-40, thecolumn name state from the first SELECT statement is used instead of thecolumn name code from the second.
Query 3-40 performs a union on three tables. The maximum number ofunions depends on the practicality of the application and any memorylimitations.
Query Result 3-39
SQL: Tutorial
Union
stock_num man
5 AN9 AN8 AN4 HS1 HS
203 NK5 NR
106 PR113 SH
Query 3-40SELECT stock_num, manu_code
FROM stockWHERE unit_price > 600.00
UNION ALL
SELECT stock_num, manu_codeFROM catalogWHERE catalog_num = 10025
UNION ALL
SELECT stock_num, manu_codeFROM itemsWHERE quantity = 10ORDER BY 2
Query 3-40 selects items where the unit_price in the stock table is greaterthan $600, the catalog_num in the catalog table is 10025, or the quantity inthe items table is 10; and the query orders the data by manu_code. Theresults are shown in Query Result 3-40:
See Chapter 1 of the Informix Guide to SQL: Syntax for the complete syntax ofthe SELECT statement and the UNION operator. See also Chapter 5, “Pro-gramming with SQL,”and Chapter 6, “Modifying Data Through SQLPrograms,”as well as the product manuals for information specific to theINFORMIX-4GL and INFORMIX-ESQL/C products and any limitationsinvolving the INTO clause and compound queries.
Query 3-41 uses a combined query to select data into a temporary table andthen adds a simple query to order and display it. You must separate thecombined and simple queries with a semicolon.
Query Result 3-40u_code
ZZZKKLGCM
Composing Advanced SELECT Statements 3-47
3-48 Informix Guide to
Union
The combined query uses a literal in the select list to tag the output of part ofa union so it can be distinguished later. The tag is given the label sortkey. Thesimple query uses that tag as a sort key for ordering the retrieved rows.
Query 3-41SELECT '1' sortkey, lname, fname, company,
city, state, phoneFROM customer xWHERE state = 'CA'
UNION
SELECT '2' sortkey, lname, fname, company,city, state, phone
FROM customer yWHERE state <> 'CA'INTO TEMP calcust;
SELECT * FROM calcustORDER BY 1
Query 3-41 creates a list where the California customers, the ones called mostfrequently, appear first, as shown in Query Result 3-41:
SQL: Tutorial
Union
sortkey 1lname Baxterfname Dickcompany Blue Ribcity Oaklandstate CAphone 415-655
sortkey 1lname Beattyfname Lanacompany Sportstocity Menlo Pastate CAphone 415-356
sortkey 1lname Curriefname Philipcompany Phil’s Scity Palo Altostate CAphone 415-328
sortkey 1lname Grantfname Alfredcompany Gold Mecity Menlo Pastate CAphone 415-356...sortkey 2lname Satiferfname Kimcompany Big Bluecity Blue Islanstate NYphone 312-944
sortkey 2lname Shorterfname Bobcompany The Triacity Cherry Hstate NJphone 609-663
sortkey 2lname Wallackfname Jasoncompany City Spocity Wilmingtostate DEphone 302-366
Query Result 3-41
bon Sports
-0011
wnrk
-9982
ports
-4543
dal Sportsrk
-1123
Bike Shopd
-5691
thletes Clubill
-6079
rtsn
-7511
Composing Advanced SELECT Statements 3-49
3-50 Informix Guide to
Intersection
SELECT stock_nuFROM stockWHERE stock_(SELECT stock
ORDER BY sto
IntersectionThe intersection of two sets of rows produces a table containing rows that existin both the original tables. Use the keyword EXISTS or IN to introduce sub-queries that show the intersection of two sets. Figure 3-2 illustrates theintersection set operation.
Query 3-42 is an example of a nested SELECT statement that shows theintersection of the stock and items tables:
Query 3-42SELECT stock_num, manu_code, unit_price
FROM stockWHERE stock_num IN
(SELECT stock_num FROM items)ORDER BY stock_num
Query Result 3-42 contains all the elements from both sets, returning thefollowing 57 rows:
Figure 3-2The intersection set operation
stock_num
stock_num
qualifies
not initems table
not in stocktable
exists instock table
exists initems table
m, manu_code, unit_price
num IN_num FROM items)
ck_numstock table
items table
SQL: Tutorial
Intersection
stock_num manu_c
1 HRO1 HSK1 SMT2 HRO3 HSK3 SHM4 HRO4 HSK5 ANZ5 NRG5 SMT6 ANZ6 SMT7 HRO8 ANZ9 ANZ
101 PRC101 SHM103 PRC104 PRC105 PRC105 SHM109 PRC109 SHM110 ANZ110 HRO110 HSK110 PRC110 SHM111 SHM114 PRC201 ANZ201 KAR201 NKL202 KAR202 NKL204 KAR205 ANZ205 HRO205 NKL301 ANZ301 HRO301 KAR301 NKL301 PRC301 SHM302 HRO302 KAR303 KAR303 PRC304 ANZ304 HRO306 PRC306 SHM307 PRC309 HRO
Query Result 3-42ode unit_price
$250.00z$800.00$450.00$126.00$240.00$280.00$480.00$960.00$19.80$28.00$25.00$48.00$36.00
$600.00$840.00
$20.00$88.00$68.00$20.00$58.00$53.00$80.00$30.00
$200.00$244.00$260.00$308.00$236.00$228.00$499.99$120.00$75.00$90.00$37.50
$230.00$174.00
$45.00$312.00$312.00$312.00
$95.00$42.50$87.00$97.00$75.00
$102.00$4.50$5.00
$36.00$48.00
$170.00$280.00$160.00$190.00$250.00
$40.00
Composing Advanced SELECT Statements 3-51
3-52 Informix Guide to
Difference
SELECT stock_nuFROM stockWHERE stock_(SELECT stock
ORDER BY sto
DifferenceThe difference between two sets of rows produces a table containing rows inthe first set that are not also in the second set. Use the keywords NOT EXISTSor NOT IN to introduce subqueries that show the difference between two sets.Figure 3-3 illustrates the difference set operation.
Figure 3-3The difference set operation
stock_num
stock_num
qualifies
not initems table
not in stocktable
exists instock table
exists initems table
m, manu_code, unit_price
num NOT IN_num FROM items)
ck_numstock table
items table
SQL: Tutorial
stock_num man
102 PR102 SH106 PR107 PR108 SH112 SH113 SH203 NK305 HR308 PR310 AN310 SH311 SH312 HR312 SH313 AN313 SH
Query 3-43 is an example of a nested SELECT statement that shows thedifference between the stock and items tables:
Query 3-43SELECT stock_num, manu_code, unit_price
FROM stockWHERE stock_num NOT IN
(SELECT stock_num FROM items)ORDER BY stock_num
Query Result 3-43 contains all the elements from only the first set, returning17 rows:
Query Result 3-43u_code unit_price
C $480.00M $220.00C $23.00C $70.00M $45.00M $549.00M $685.90L $670.00O $48.00C $280.00Z $84.00M $80.00M $48.00O $72.00M $96.00Z $60.00M $72.00
3-54 Informix Guide to
Summary
SummaryThis chapter was built on concepts introduced in Chapter 2, “ComposingSimple SELECT Statements.” It provided sample syntax and results for moreadvanced kinds of SELECT statements, which are used to perform a query ona relational database. This chapter has presented the following material.
■ Introduced the GROUP BY and HAVING clauses, which can be usedwith aggregates to return groups of rows and apply conditions tothose groups
■ Described how to use the rowid to retrieve internal record numbersfrom tables and system catalog tables and discussed the serial iternaltable identifier or tabid
■ Showed how to join a table to itself with a self-join to compare valuesin a column with other values in the same column and to identifyduplicates
■ Introduced the keyword OUTER, explained how an outer join treatstwo or more tables asymmetrically, and provided examples of thefour kinds of outer join
■ Described how to create correlated and uncorrelated subqueries bynesting a SELECT statement in the WHERE clause of another SELECTstatement and showed the use of aggregate functions in subqueries
■ Demonstrated the use of the keywords ALL, ANY, EXISTS, IN, andSOME in creating subqueries, and the effect of adding the keywordNOT or a relational operator
■ Discussed the set operations union, intersection, and difference
■ Showed how to use the UNION and UNION ALL keywords to createcompound queries consisting of two or more SELECT statements
SQL: Tutorial
4Chapter
Modifying Data
Statements That Modify Data . . . . . . . . . . . . . . . 4-4Deleting Rows . . . . . . . . . . . . . . . . . . . 4-4
Deleting All Rows of a Table . . . . . . . . . . . . . 4-4Deleting a Known Number of Rows . . . . . . . . . . . 4-5
Deleting an Unknown Number of Rows . . . . . . . . . 4-5Complicated Delete Conditions . . . . . . . . . . . . 4-6
Inserting Rows . . . . . . . . . . . . . . . . . . . 4-7Single Rows . . . . . . . . . . . . . . . . . . 4-7Multiple Rows and Expressions . . . . . . . . . . . . 4-10Restrictions on the Insert-Selection. . . . . . . . . . . 4-11
Updating Rows. . . . . . . . . . . . . . . . . . . 4-12Selecting Rows to Update . . . . . . . . . . . . . . 4-13Updating with Uniform Values . . . . . . . . . . . . 4-14Impossible Updates . . . . . . . . . . . . . . . . 4-15Updating with Selected Values . . . . . . . . . . . . 4-15
Database Privileges. . . . . . . . . . . . . . . . . . . 4-16Displaying Table Privileges . . . . . . . . . . . . . . 4-18
Data Integrity. . . . . . . . . . . . . . . . . . . . . 4-19Entity Integrity . . . . . . . . . . . . . . . . . . . 4-19Semantic Integrity . . . . . . . . . . . . . . . . . . 4-20Referential Integrity . . . . . . . . . . . . . . . . . 4-21
Using the ON DELETE CASCADE Option . . . . . . . . 4-23
Interrupted Modifications . . . . . . . . . . . . . . . . 4-25The Transaction. . . . . . . . . . . . . . . . . . . 4-26Transaction Logging . . . . . . . . . . . . . . . . . 4-26
Logging and Cascading Deletes . . . . . . . . . . . . 4-27Specifying Transactions . . . . . . . . . . . . . . . . 4-27
4-2 Infor
Archives and Logs . . . . . . . . . . . . . . . . . . . 4-28Archiving with INFORMIX-SE . . . . . . . . . . . . . 4-28Archiving with INFORMIX-OnLine Dynamic Server . . . . . . 4-29
Concurrency and Locks . . . . . . . . . . . . . . . . . 4-30
Data Replication . . . . . . . . . . . . . . . . . . . . 4-31INFORMIX-OnLine Dynamic Server Data Replication . . . . . 4-32
Summary . . . . . . . . . . . . . . . . . . . . . . 4-32
mix Guide to SQL: Tutorial
Modifying data is fundamentally different from queryingdata. Querying data involves examining the contents of tables. Modifyingdata involves changing the contents of tables.
Think about what happens if the system hardware or software fails during aquery. In this case, the effect on the application can be severe but the databaseitself is unharmed. However, if the system fails while a modification is underway, the state of the database is in doubt. Obviously, this can have far-reaching implications. Before you delete, insert, or update rows in a database,ask yourself the following questions:
■ Is user access to the database and its tables secure; that is, are specificusers given limited database and table-level privileges?
■ Does the modified data preserve the existing integrity of thedatabase?
■ Are systems in place that make the database relatively immune toexternal events that might cause system or hardware failures?
If you are unable to answer yes to each of these questions, do not panic.Solutions to all these problems are built in to the Informix database servers.After an introduction to the statements that modify data, this chapter dis-cusses these solutions. Chapters 8 through 10 talk about these topics ingreater detail.
Modifying Data 4-3
4-4 Informix Guide to S
Statements That Modify Data
Statements That Modify DataThe following statements modify data:
■ DELETE
■ INSERT
■ UPDATE
Although these SQL statements are relatively simple when compared withthe more advanced SELECT statements, use them carefully because theychange the contents of the database.
Deleting RowsThe 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-25. Fornow, 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 othertables whose values depend on the deleted row. If, however, your databaseenforces referential constraints, you can use the ON DELETE CASCADE optionof the CREATE TABLE or ALTER TABLE statements to allow deletes to cascadefrom one table in a relationship to another. For more information on referen-tial constraints and the ON DELETE CASCADE option, refer to “ReferentialIntegrity” on page 4-21.
Deleting All Rows of a Table
The DELETE statement specifies a table and usually contains a WHERE clausethat designates the row or rows that are to be removed from the table. If theWHERE clause is left out, all rows are deleted. Do not execute the followingstatement:
DELETE FROM customer
QL: Tutorial
Deleting a Known Number of Rows
Because this DELETE statement does not contain a WHERE clause, all rowsfrom the customer table are deleted. If you attempt an unconditional deleteusing the DB-Access or INFORMIX-SQL menu options, the program warns youand asks for confirmation. However, an unconditional delete from within aprogram can occur without warning.
Deleting a Known Number of RowsThe WHERE clause in a DELETE statement has the same form as the WHEREclause in a SELECT Statement. You can use it to designate exactly which rowor rows should be deleted. You can delete a customer with a specific cus-tomer number, as shown in the following example:
DELETE FROM customer WHERE customer_num = 175
In this example, because the customer_num column has a unique constraint,you are sure that no more than one row is deleted.
Deleting an Unknown Number of Rows
You can also choose rows based on nonindexed columns, as shown in thefollowing example:
DELETE FROM customer WHERE company = 'Druid Cyclery'
Because the column tested does not have a unique constraint, this statementmight delete more than one row. (Druid Cyclery may have two stores, bothwith the same name but different customer numbers.)
You can find out how many rows might be affected by a DELETE statementby selecting the count of qualifying rows from the customer table for DruidCyclery.
SELECT COUNT(*) FROM customer WHERE company = 'Druid Cyclery'
You can also select the rows and display them, to be sure they are the onesyou want to delete.
Modifying Data 4-5
4-6 Informix Guide to S
Deleting a Known Number of Rows
Using a SELECT statement as a test is only an approximation, however, whenthe database is available to multiple users concurrently. Between the timeyou execute the SELECT statement and the subsequent DELETE statement,other users could have modified the table and changed the result. In thisexample, 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, orupdate some other customer to have the name Druid Cyclery
Although it is not likely that other users would do these things in that briefinterval, the possibility does exist. This same problem affects the UPDATEstatement. Ways of addressing this problem are discussed under “Concur-rency and Locks” on page 4-30, and in greater detail in Chapter 7, “Program-ming for a Multiuser Environment.”
Another problem you may encounter is a hardware or software failure beforethe 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, whichis undesirable. You can prevent this situation by using transaction logging, asdiscussed in “Interrupted Modifications” on page 4-25.
Complicated Delete Conditions
The WHERE clause in a DELETE statement can be almost as complicated as theone in a SELECT statement. It can contain multiple conditions connected byAND and OR, and it may contain subqueries.
Suppose you discover that some rows of the stock table contain incorrectmanufacturer codes. Rather than update them, you want to delete them sothey 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 aDELETE statement such as the one shown in the following example:
DELETE FROM stockWHERE 0 = (SELECT COUNT(*) FROM manufact
WHERE manufact.manu_code = stock.manu_code)
The subquery counts the number of rows of manufact that match; the countis 1 for a correct row of stock and 0 for an incorrect one. The latter rows arechosen for deletion.
QL: Tutorial
Inserting Rows
One way to develop a DELETE statement with a complicated condition isto first develop a SELECT statement that returns precisely the rows to bedeleted. Write it as SELECT *; when it returns the desired set of rows, changeSELECT * to read DELETE and execute it once more.
The WHERE clause of a DELETE statement cannot use a subquery that teststhe same table. That is, when you delete from stock, you cannot use asubquery 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 FROMclause of a DELETE statement, it cannot also appear in the FROM clause of asubquery of the DELETE statement.
Inserting RowsThe INSERT statement adds a new row, or rows, to a table. The statement hastwo basic functions: It can create a single new row using column values yousupply, or it can create a group of new rows using data selected from othertables.
Single Rows
In its simplest form, the INSERT statement creates one new row from a list ofcolumn values, and puts that row in the table. The following statement showsan example of adding a row to the stock table:
INSERT INTO stockVALUES (115, 'PRC', 'tire pump', 108, 'box', '6/box')
The stock table has the following columns:
■ stock_num (a number identifying the type of merchandise)
■ manu_code (a foreign key to the manufact table)
■ description (a description of the merchandise)
■ unit_price (the unit price of the merchandise)
■ unit (of measure)
■ unit_descr (characterizing the unit of measure)
Modifying Data 4-7
4-8 Informix Guide to S
Inserting Rows
Notice that the values listed in the VALUES clause in the preceding examplehave a one-to-one correspondence with the columns of this table. To write aVALUES clause, you must know the columns of the tables as well as theirsequence from first to last.
Possible Column Values
The VALUES clause accepts only constant values, not expressions. You cansupply the following values:
■ Literal numbers
■ Literal datetime values
■ Literal interval values
■ Quoted strings of characters
■ The word NULL for a null value
■ The word TODAY for the current date
■ The word CURRENT for the current date and time
■ The word USER for your user name
■ The word DBSERVERNAME (or SITENAME) for the name of thecomputer where the database server is running
Some columns of a table might not allow null values. If you attempt to insertNULL in such a column, the statement is rejected. Or a column in the tablemay not permit duplicate values. If you specify a value that is a duplicate ofone already in such a column, the statement is rejected. Some columns mayeven restrict the possible column values allowed. These restrictions areplaced on columns using data integrity constraints. For more information ondata restrictions, see “Database Privileges” on page 4-16.
Only one column in a table can have the SERIAL data type. The databaseserver generates values for a serial column. To make this happen when youinsert values, specify the value zero for the serial column. The databaseserver generates the next actual value in sequence. Serial columns do notallow null values.
QL: Tutorial
Inserting Rows
You can specify a nonzero value for a serial column (as long as it does notduplicate any existing value in that column) and the database server uses thevalue. However, that nonzero value may set a new starting point for valuesthat the database server generates. The next value the database servergenerates 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 thevalue of a numeric column. The database server converts the numeric stringto 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. Thedatabase server converts that value to a character string. For example, if youspecify TODAY as the value for a character column, a character string repre-senting the current date is used. (The format used is specified by the DBDATEenvironment variable.)
Listing Specific Column Names
You do not have to specify values for every column. Instead, you can list thecolumn names after the table name and then supply values for only those col-umns you named. The following example shows a statement that inserts anew row into the stock table:
INSERT INTO stock (stock_num,description,unit_price,manu_code)VALUES (115,'tyre pump',114,'SHM')
Notice that only the data for the stock number, description, unit price, andmanufacturer code is provided. The database server supplies the followingvalues 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 asso-ciated with it.
■ It generates a null value for any column that allows nulls but doesnot specify a default value for any column that specifies null as thedefault value.
Modifying Data 4-9
4-10 Informix Guide to
Inserting Rows
This means that you must list and supply values for all columns that do notspecify 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 thesame order. For information about setting a default value for a column, seeChapter 9, “Implementing Your Data Model.”
After the INSERT statement is executed, the following new row is insertedinto the stock table:
stock_num manu_code description unit_price unit unit_descr
115 SHM tyre pump 114
Both the unit and unit_descr are blank, indicating that null values are inthose two columns. Because the unit column permits nulls, one can onlyguess the number of tire pumps that were purchased for $114. Of course, if adefault value of “box” was specified for this column, then “box” would be theunit of measure. In any case, when inserting values into specific columns ofa table, pay attention to what data is needed for that row.
Multiple Rows and Expressions
The other major form of the INSERT statement replaces the VALUES clausewith a SELECT statement. This feature allows you to insert the following data:
■ Multiple rows with only one statement (a row is inserted for eachrow returned by the SELECT statement)
■ Calculated values (the VALUES clause only permits constants)because the select list can contain expressions
For example, suppose a follow-up call is required for every order that hasbeen paid for but not shipped. The INSERT statement in the followingexample finds those orders and inserts a row in cust_calls for each order:
INSERT INTO cust_calls (customer_num, call_descr)SELECT customer_num, order_num FROM orders
WHERE paid_date IS NOT NULLAND ship_date IS NULL
SQL: Tutorial
Inserting Rows
This SELECT statement returns two columns. The data from these columns (ineach 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 thecall description, which is a character column. Remember that the databaseserver allows you to insert integer values into a character column. Itautomatically converts the serial number to a character string of decimaldigits.
Restrictions on the Insert-Selection
The following list contains the restrictions on the SELECT statement forinserting rows:
■ It cannot contain an INTO clause.
■ It cannot contain an INTO TEMP clause.
■ It cannot contain an ORDER BY clause.
■ It cannot refer to the table into which you are inserting rows.
The INTO, INTO TEMP, and ORDER BY clause restrictions are minor. The INTOclause is not useful in this context. (It is discussed in Chapter 5, “Program-ming with SQL.”) You can work around the INTO TEMP clause restriction byfirst selecting the data you want to insert into a temporary table and theninserting the data from the temporary table with the INSERT statement. Like-wise, the lack of an ORDER BY clause is not important. If you need to ensurethat the new rows are physically ordered in the table, you can first select theminto a temporary table and order it, and then insert from the temporary table.You can also apply a physical order to the table using a clustered index afterall insertions are done.
The last restriction is more serious because it prevents you from naming thesame table in both the INTO clause of the INSERT statement and the FROMclause of the SELECT statement. (This saves the database server from gettinginto an endless loop in which each inserted row is reselected and reinserted.)In some cases, however, you may want to do this. For example, suppose thatyou have learned that the Nikolus company supplies the same products asthe Anza company, but at half the price. You want to add rows to the stocktable to reflect this. Optimally, you want to select data from all the Anza stockrows and reinsert it with the Nikolus manufacturer code. However, youcannot select from the same table into which you are inserting.
Modifying Data 4-11
4-12 Informix Guide to
Updating Rows
You can get around this restriction by selecting the data you want to insertinto a temporary table. Then, select from that table in the INSERT statement.The following statements are required to accomplish this:
SELECT stock_num, 'HSK' temp_manu, description, unit_price/2half_price, unit, unit_descr FROM stock
WHERE manu_code = 'ANZ'AND stock_num < 110
INTO TEMP anzrows;
INSERT INTO stock SELECT * FROM anzrows;
DROP TABLE anzrows;
This SELECT statement takes existing rows from stock and substitutes aliteral value for the manufacturer code and a computed value for the unitprice. These rows are then saved in a temporary table, anzrows, which isimmediately inserted into the stock table.
When you insert multiple rows, a risk exists that one of the rows containsinvalid data that might cause the database server to report an error. Whenthis happens, the statement terminates early. Even if no error occurs, a verysmall risk exists that there might be a hardware or software failure while thestatement is executing (for example, the disk might fill up).
In either event, you cannot easily tell how many new rows were inserted. Ifyou repeat the statement in its entirety, you might create duplicate rows—oryou might not. Because the database is in an unknown state, you cannotknow what to do. The answer lies in using transactions, as discussed in“Interrupted Modifications” on page 4-25.
Updating RowsYou use the UPDATE statement to change the contents of one or morecolumns in one or more existing rows of a table. This statement takes twofundamentally different forms. One lets you assign specific values to col-umns by name; the other lets you assign a list of values (that might bereturned by a SELECT statement) to a list of columns. In either case, if you areupdating rows and some of the columns have data integrity constraints, thedata you change must be within the constraints placed on those columns. Formore information, refer to “Database Privileges” on page 4-16.
SQL: Tutorial
Updating Rows
Selecting Rows to Update
Either form of the UPDATE statement can end with a WHERE clause thatdetermines which rows are modified. If you omit it, all rows are modified.The WHERE clause can be quite complicated to select the precise set of rowsthat need changing. The only restriction on it is that the table that you areupdating cannot be named in the FROM clause of a subquery.
The first form of an UPDATE statement uses a series of assignment clauses tospecify new column values, as shown in the following example:
UPDATE customerSET fname = 'Barnaby', lname = 'Dorfler'WHERE customer_num = 103
The WHERE clause selects the row to be updated. In the stores7 database, thecustomer.customer_num column is the primary key for that table, so thisstatement can update no more than one row.
You can also use subqueries in the WHERE clause. Suppose that the AnzaCorporation issues a safety recall of their tennis balls. As a result, anyunshipped orders that include stock number 6 from manufacturer ANZ mustbe put on back order, as shown in the following example:
UPDATE ordersSET backlog = 'y'WHERE ship_date IS NULLAND order_num IN
(SELECT DISTINCT items.order_num FROM itemsWHERE items.stock_num = 6AND items.manu_code = 'ANZ')
This subquery returns a column of order numbers (zero or more). TheUPDATE operation then tests each row of orders against the list and performsthe update if that row matches.
Modifying Data 4-13
4-14 Informix Guide to
Updating Rows
Updating with Uniform Values
Each assignment after the keyword SET specifies a new value for a column.That value is applied uniformly to every row that you update. In the exam-ples in the previous section, the new values were constants, but you canassign any expression, including one based on the column value itself. Sup-pose the manufacturer code HRO has raised all prices by 5 percent, and youmust update the stock table to reflect this. You would use a statement such asthe one shown in the following example:
UPDATE stockSET unit_price = unit_price * 1.05WHERE manu_code = 'HRO'
You can also use a subquery as part of the assigned value. When a subqueryis used as an element of an expression, it must return exactly one value (onecolumn and one row). Suppose that you decide that for any stock number,you must charge a higher price than any manufacturer of that product. Youneed to update the prices of all unshipped orders. The SELECT statements inthe following example specify the criteria:
UPDATE itemsSET total_price = quantity *
(SELECT MAX (unit_price) FROM stockWHERE 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 thestock table for a particular product. This is a correlated subquery; becausewhen a value from items appears in its WHERE clause, you must execute itfor every row that you update.
The second SELECT statement produces a list of the order numbers ofunshipped orders. It is an uncorrelated subquery that is executed once.
SQL: Tutorial
Updating Rows
Impossible Updates
Restrictions exist on the use of subqueries when you modify data. Inparticular, you cannot query the table that is being modified. You can refer tothe present value of a column in an expression, as in the example in whichthe unit_price column was incremented by 5 percent. You can refer to a valueof a column in a WHERE clause in a subquery, as in the example that updatedthe stock table, in which the items table is updated and items.stock_num isused in a join expression.
The need to update and query a table at the same time does not occur oftenin a well-designed database. (Database design is covered in Chapter 8 andChapter 9.) However, you may want to update and query at the same timewhen a database is first being developed, before its design has been carefullythought through. A typical problem arises when a table inadvertently andincorrectly contains a few rows with duplicate values in a column that shouldbe unique. You might want to delete the duplicate rows or update only theduplicate rows. Either way, a test for duplicate rows inevitably requires asubquery, which is not allowed in an UPDATE statement or DELETE state-ment. Chapter 6, “Modifying Data Through SQL Programs,” discusses howto use an update cursor to perform this kind of modification.
Updating with Selected Values
The second form of UPDATE statement replaces the list of assignments witha single bulk assignment, in which a list of columns is set equal to a list of val-ues. When the values are simple constants, this form is nothing more than theform of the previous example with its parts rearranged, as shown in thefollowing example:
UPDATE customerSET (fname, lname) = ('Barnaby', 'Dorfler')WHERE customer_num = 103
No advantage exists to writing the statement this way. In fact, it is harder toread because it is not obvious which values are assigned to which columns.
Modifying Data 4-15
4-16 Informix Guide to
Database Privileges
However, when the values to be assigned come from a single SELECTstatement, this form makes sense. Suppose that changes of address are to beapplied to several customers. Instead of updating the customer table eachtime a change is reported, the new addresses are collected in a single tempo-rary table named newaddr. It contains columns for the customer number andthe address-related fields of the customer table. Now the time comes to applyall the new addresses at once.
UPDATE customerSET (address1, address2, city, state, zipcode) =
((SELECT address1, address2, city, state, zipcodeFROM newaddrWHERE 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 SELECTstatement. If you rewrite this example in the other form, with an assignmentfor each updated column, you must write five SELECT statements, one foreach column to be updated. Not only is such a statement harder to write butit also takes much longer to execute.
Tip: In NewEra, INFORMIX-4GL, and the SQL API programs, you can use record orhost variables to update values. For more information, refer to Chapter 5, “Program-ming with SQL.”
Database PrivilegesTwo levels of privileges exist in a database: database-level privileges andtable-level privileges. When you create a database, you are the only one whocan access it until you, as the owner (or Database Administrator [DBA]) of thedatabase, grant database-level privileges to others. When you create a tablein a database that is not ANSI-compliant, all users have access privileges tothe table until you, as the owner of the table, revoke table-level privilegesfrom specific users.
SQL: Tutorial
Database Privileges
The following list contains database-level privileges:
Seven table-level privileges exist. However, only the first four are coveredhere:
The people who create databases and tables often grant the Connect andSelect privileges to public so that all users have them. If you can query atable, you have at least the Connect and Select privileges for that databaseand table. For more information about public, see “The Users and the Public”on page 10-7.
You need the other table-level privileges to modify data. The owners of tablesoften withhold these privileges or grant them only to specific users. As aresult, you may not be able to modify some tables that you can query freely.
Because these privileges are granted on a table-by-table basis, you can haveonly Insert privileges on one table and only Update privileges on another, forexample. The Update privileges can be restricted even further to specificcolumns in a table.
Chapter 10, “Granting and Limiting Access to Your Database,” discussesgranting privileges from the standpoint of the DBA. A complete list of privi-leges and a summary of the GRANT and REVOKE statements can be found inChapter 1 of the Informix Guide to SQL: Syntax.
Connect privilege allows you to open a database, issue queries, andcreate 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.
Select privilege is granted on a table-by-table basis and allows you toselect rows from a table (This privilege can be limitedby specific columns in a table.)
Delete privilege allows you to delete rows.Insert privilege allows you to insert rows.Update privilege allows you to update existing rows (that is, to change
their content).
Modifying Data 4-17
4-18 Informix Guide to
Displaying Table Privileges
Displaying Table PrivilegesIf you are the owner of a table (that is, if you created it), you have allprivileges on that table. Otherwise, you can determine the privileges youhave for a certain table by querying the system catalog. The system catalogconsists of system tables that describe the database structure. The privilegesgranted on each table are recorded in the systabauth system table. To displaythese privileges, you must also know the unique identifier number of thetable. This number is specified in the systables system table. So, to displayprivileges granted on the orders table, you might enter the following SELECTstatement:
SELECT * FROM systabauthWHERE tabid = (SELECT tabid FROM systables
WHERE tabname = 'orders')
The output of the query resembles the following display:
The grantor is the user who grants the privilege. The grantor is usually theowner of the table but can be another user empowered by the grantor. Thegrantee is the user to whom the privilege is granted, and the grantee publicmeans “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 rowof this column are the initial letters of the privilege names except that i meansInsert and x means Index. In this example, public has Select, Insert, andIndex privileges. Only the user mutator has Update privileges, and only theuser procrustes has Delete privileges.
Before the database server performs any action for you (for example, executea DELETE statement), it performs a query similar to the preceding one. If youare not the owner of the table, and if it cannot find the necessary privilege onthe table for your user name or for public, it refuses to perform the operation.
grantor grantee tabid tabauth
tfecit mutator 101 su-i-x--tfecit procrustes 101 s--idx--tfecit public 101 s--i-x--
SQL: Tutorial
Data Integrity
Data IntegrityThe INSERT, UPDATE, and DELETE statements modify data in an existingdatabase. Whenever you modify existing data, the integrity of the data can beaffected. For example, an order for a nonexistent product could be enteredinto the orders table, a customer with outstanding orders could be deletedfrom the customer table, or the order number could be updated in the orderstable and not in the items table. In each of these cases, the integrity of thestored data is lost.
Data integrity is actually made up of the following parts:
■ Entity integrity
Each row of a table has a unique identifier.
■ Semantic integrity
The data in the columns properly reflects the types of informationthe column was designed to hold.
■ Referential integrity
The relationships between tables are enforced.
Well-designed databases incorporate these principles so that when youmodify data, the database itself prevents you from doing anything that mightharm the data integrity.
Entity IntegrityAn entity is any person, place, or thing to be recorded in a database. Eachentity represents a table, and each row of a table represents an instance of thatentity. For example, if order is an entity, the orders table represents the idea oforder and each row in the table represents a specific order.
To identify each row in a table, the table must have a primary key. Theprimary key is a unique value that identifies each row. This requirement iscalled the entity integrity constraint.
Modifying Data 4-19
4-20 Informix Guide to
Semantic Integrity
For example, the orders table primary key is order_num. The order_numcolumn holds a unique system-generated order number for each row in thetable. To access a row of data in the orders table, you can use the followingSELECT statement:
SELECT * FROM orders WHERE order_num = 1001
Using the order number in the WHERE clause of this statement enables youto access a row easily because the order number uniquely identifies that row.If the table allowed duplicate order numbers, it would be almost impossibleto access one single row, because all other columns of this table allowduplicate values.
Refer to Chapter 8, “Building Your Data Model,” for more information onprimary keys and entity integrity.
Semantic IntegritySemantic integrity ensures that data entered into a row reflects an allowablevalue for that row. This means that the value must be within the domain, orallowable set of values, for that column. For example, the quantity column ofthe items table permits only numbers. If a value outside the domain can beentered into a column, the semantic integrity of the data is violated.
Semantic integrity is enforced using the following constraints:
■ Data type
The data type defines the types of values that you can store in acolumn. For example, the data type SMALLINT allows you to entervalues from -32,767 to 32,767 into a column.
■ Default value
The default value is the value inserted into the column when anexplicit value is not specified. For example, the user_id column of thecust_calls table defaults to the login name of the user if no name isentered.
SQL: Tutorial
Referential Integrity
■ Check constraint
The check constraint specifies conditions on data inserted into acolumn. Each row inserted into a table must meet these conditions.For example, the quantity column of the items table may check forquantities greater than or equal to one.
For more information on using semantic integrity constraints indatabase design, refer to “Defining the Domains” on page 9-3.
Referential IntegrityReferential integrity refers to the relationship between tables. Because eachtable in a database must have a primary key, it is possible that this primarykey appears in other tables because of its relationship to data within thosetables. When a primary key from one table appears in another table, it iscalled a foreign key.
Foreign keys join tables and establish dependencies between tables. Tablescan form a hierarchy of dependencies in such a way that if you change ordelete a row in one table, you destroy the meaning of rows in other tables. Forexample, Figure 4-1 on page 4-22 shows that the customer_num column ofthe customer table is a primary key for that table and a foreign key in theorders and cust_call tables. Customer number 106, George Watson, is refer-enced in both the orders and cust_calls tables. If customer 106 is deleted fromthe customer table, the link between the three tables and this particular cus-tomer is destroyed.
When you delete a row containing a primary key or update it with a differentprimary key, you destroy the meaning of any rows that contain that value asa foreign key. Referential integrity is the logical dependency of a foreign keyon a primary key. The integrity of a row that contains a foreign key dependson the integrity of the row that it references—the row that contains thematching primary key.
Modifying Data 4-21
4-22 Informix Guide to
Referential Integrity
1003
1004
1002
order_num
orders Table(detail)
By default, INFORMIX-OnLine Dynamic Server does not allow you to violatereferential integrity and gives you an error message if you attempt to deleterows from the parent table before you delete rows from the child table. Youcan, however, use the ON DELETE CASCADE option to cause deletes from aparent table to trip deletes on child tables. See “Using the ON DELETE CAS-CADE Option” on page 4-23.
Figure 4-1Referential integrity in the stores7 database
106 George Watson
103 Philip Currie
customer_num fname lname
05/22/1994 104
05/22/1994 106
05/21/1994 101
order_date customer_num
customer Table(detail)
cust_calls Table(detail)
110 1994-07-07 10:24 richc
119 1994-07-01 15:00 richc
106 1994-06-12 8:20 maryj
customer_num call_dtime user_id
SQL: Tutorial
Referential Integrity
You can define primary and foreign keys, and the relationship between them,using the CREATE TABLE and ALTER TABLE statements. For more informationon these statements, see Chapter 1 of the Informix Guide to SQL: Syntax. Forinformation on building data models using primary and foreign keys, referto Chapter 8, “Building Your Data Model.”
Using the ON DELETE CASCADE Option
You can maintain referential integrity when deleting rows from a primarykey for a table by using the ON DELETE CASCADE option in the REFERENCESclause of the CREATE TABLE and ALTER TABLE statements. This option allowsyou to delete a row from a parent table and its corresponding rows in match-ing child tables with a single delete command.
Locking During Cascading Deletes
During deletes, locks are held on all qualifying rows of the parent and childtables. When you specify a delete, the delete requested from the parent tableoccurs before any referential actions are performed.
What Happens to Multiple Children Tables
If you have a parent table with two child constraints, one child withcascading deletes specified and one child without cascading deletes, and youattempt to delete a row from the parent table that applies to both child tables,then the DELETE statement fails and no rows are deleted from either theparent or child tables.
Logging Must Be Turned On
You must turn logging on in your current database for cascading deletes towork. Logging and cascading deletes are discussed in “Transaction Logging”on page 4-26.
Modifying Data 4-23
4-24 Informix Guide to
Referential Integrity
Example
Say you have two tables with referential integrity rules applied, a parenttable, accounts, and a child table, sub_accounts. The following CREATETABLE statements define the referential constraints:
CREATE TABLE accounts ( acc_num SERIAL primary key, acc_type INT, acc_descr CHAR(20));
CREATE TABLE sub_accounts ( sub_acc INTEGER primary key, ref_num INTEGER REFERENCES references accounts (acc_num) ON DELETE CASCADE, sub_descr CHAR(20));
Notice that the primary key of the accounts table, the acc_num column, usesa SERIAL data type, and the foreign key of the sub_accounts table, theref_num column, uses an INTEGER data type. Combining the SERIAL datatype on the primary key and the INTEGER data type on the foreign key isallowed. 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 CHARmust match a foreign key defined as CHAR.
To delete a row from the accounts table that will cascade a delete to thesub_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 thefollowing example:
DELETE FROM accounts WHERE acc_num = 2
Restrictions on Cascading Deletes
You can use cascading deletes for most deletes, including deletes on self-referencing and cyclic queries. The only exception is correlated subqueries. Incorrelated subqueries, the subquery (or inner SELECT) is correlated when thevalue it produces depends on a value produced by the outer SELECT state-ment that contains it. If you have implemented cascading deletes, you cannotwrite deletes that use a child table in the correlated subquery. You receive anerror when you attempt to delete from a correlated subquery.
SQL: Tutorial
Interrupted Modifications
Interrupted ModificationsEven 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 tostrike the building, interrupting the electrical supply and stopping the com-puter in the middle of your UPDATE statement. It is more likely, however, thata disk fills up or a user supplies incorrect data, causing your multirow insertto stop early with an error. In any case, as you are modifying data, you mustassume that some unforeseen event can interrupt the modification.
When a modification is interrupted by an external cause, you cannot be surehow much of the operation was completed. Even in a single-row operation,you cannot know whether the data reached the disk or the indexes wereproperly updated.
If multirow modifications are a problem, multistatement ones are worse. Itdoes not help that they are usually embedded in programs so that you do notsee the individual SQL statements being executed. For example, the job ofentering a new order in the stores7 database requires you to perform thefollowing steps:
■ Insert a row in the orders table. (This generates an order number.)
■ For each item ordered, insert a row in the items table.
Two ways to program an order-entry application exist. One way is to make itcompletely interactive so that the program inserts the first row immediately,and then inserts each item as the user enters data. This is the wrong approachbecause it exposes the operation to the possibility of many more unforeseenevents: the customer’s telephone disconnecting, the user pressing the wrongkey, the user’s terminal or computer losing power, and so on.
The right way to build an order-entry application is described in thefollowing list:
■ Accept all the data interactively
■ Validate the data and expand it (by looking up codes in stock andmanufact, for example)
■ Display the information on the screen for inspection
■ Wait for the operator to make a final commitment
■ Perform the insertions quickly
Modifying Data 4-25
4-26 Informix Guide to
The Transaction
Even when this is done, sometimes an unforeseen circumstance can halt theprogram after it inserts the order but before it finishes inserting the items. Ifthat happens, the database is in an unpredictable condition: its data integrityis compromised.
The TransactionThe solution to all these potential problems is called the transaction. Atransaction is a sequence of modifications that either must be accomplishedcompletely or not at all. The database server guarantees that operationsperformed within the bounds of a transaction are either completely and per-fectly committed to disk, or the database is restored to the state it was inbefore the transaction started.
The transaction is not merely protection against unforeseen failures; it alsooffers a program a way to escape when the program detects a logical error.(This is discussed further in Chapter 6, “Modifying Data Through SQLPrograms.”)
Transaction LoggingThe database server can keep a record of each change that it makes to thedatabase during a transaction. If something happens to cancel the transac-tion, the database server automatically uses the records to reverse thechanges. Many things can make a transaction fail. The program that issuesthe SQL statements can crash or be terminated, or there might be a hardwareor 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 afterthe computer and the database server are restarted, it returns the database tothe state it was in before the transaction began using the records from thetransaction.
The process of keeping records of transactions is called transaction logging, orsimply logging. The records of the transactions, called log records, are stored ina portion of disk space separate from the database. In INFORMIX-OnLineDynamic Server, this space is called the logical log (because the log recordsrepresent logical units of the transactions). In INFORMIX-SE, the space usedto store log records is called the transaction log file.
SQL: Tutorial
Specifying Transactions
Databases do not generate transaction records automatically. The databaseadministrator decides whether to make a database use transaction logging.Without transaction logging, you cannot roll back transactions.
Logging and Cascading Deletes
Logging must be turned on in your database for cascading deletes to workbecause when you specify a cascading delete, the delete is first performed onthe primary key of the parent table. If the system crashes after the rows of theprimary key of the parent table are performed but before the rows of theforeign key of the child table are deleted, referential integrity is violated. Iflogging is turned off, even temporarily, deletes do not cascade. After loggingis turned back on, however, deletes can cascade again. Turn logging on withthe CREATE DATABASE statement for OnLine database servers.
Specifying TransactionsThe boundaries of transactions are specified with SQL statements. You can dothis in two ways. In the most common style, you specify the start of a multi-statement transaction by executing the BEGIN WORK statement. In databasesthat are created with the MODE ANSI option, no need exists to mark thebeginning of a transaction. One is always in effect; you indicate only the endof each transaction.
In both styles, you specify the end of a successful transaction by executing theCOMMIT WORK statement. This statement tells the database server that youreached the end of a series of statements that must succeed together. Thedatabase server does whatever is necessary to make sure that allmodifications are properly completed and committed to disk.
It is also possible for a program to cancel a transaction deliberately. It does soby executing the ROLLBACK WORK statement. This statement asks thedatabase server to cancel the current transaction and undo any changes.
For example, an order-entry application can use a transaction when creatinga new order in the following ways:
■ Accept all data interactively
■ Validate and expand it
■ Wait for the operator to make a final commitment
Modifying Data 4-27
4-28 Informix Guide to
Archives and Logs
■ Execute BEGIN WORK
■ Insert rows in the orders and items tables, checking the error codereturned by the database server
■ If there were no errors, execute COMMIT WORK, otherwise executeROLLBACK WORK
If any external failure prevents the transaction from being completed, thepartial 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 itis not entered at all.
Archives and LogsBy using transactions, you can ensure that the database is always in aconsistent state and that your modifications are properly recorded on disk.But the disk itself is not perfectly safe. It is vulnerable to mechanical failuresand to flood, fire, and earthquake. The only safeguard is to keep multiplecopies of the data. These redundant copies are called archive copies.
The transaction log (also called the logical log) complements the archive copyof a database. Its contents are a history of all modifications that occurred sincethe last time the database was archived. If it should ever be necessary torestore the database from the archive copy, the transaction log can be used toroll the database forward to its most recent state.
Archiving with INFORMIX-SEIf a database is stored in operating system files (INFORMIX-SE), archive copiesare made using the normal methods for making backup copies in your oper-ating system. Only two special considerations exist for databases.
The first is a practical consideration: A database can grow to great size. It maybecome the largest file or set of files in the system. It can also be awkward orvery time consuming to make a copy of it. You may need a special procedurefor copying the database, separate from the usual backup procedures, andthe job may not be done too frequently.
SQL: Tutorial
Archiving with INFORMIX-OnLine Dynamic Server
The second consideration is the special relationship between the databaseand the transaction log file. An archive copy is an image of the database atone instant. The log file contains the history of modifications that were madeduring that instant. It is important that those two instants are identical; inother words, it is important to start a new transaction log file immediatelyupon making an archive copy of the database. Then, if you must restore thedatabase from the archive tape, the transaction log contains exactly thehistory needed to bring it forward in time from that instant to the latestupdate.
The statement that applies a log to a restored database is ROLLFORWARDDATABASE. You start a new log file by using whatever operating system com-mands are needed to delete the file and re-create it empty or simply to set thelength of the file to zero.
A transaction log file can grow to extreme size. If you update a row ten times,just one row exists in the database—but ten update events are recorded in thelog file. If the size of the log file is a problem, you can start a fresh log. Choosea time when the database is not being updated (so no transactions are active),and copy the existing log to another medium. That copy represents all mod-ifications for some period of time; preserve it carefully. Then start a new logfile. If you ever have to restore the database, you must apply all the log filesin their correct sequence.
Archiving with INFORMIX-OnLine Dynamic ServerThe OnLine database server contains elaborate features to support archivingand logging. They are described in the INFORMIX-OnLine Dynamic ServerArchive and Backup Guide.
Conceptually, the facilities of OnLine are similar to those already describedfor INFORMIX-SE, but they are more elaborate for the following reasons:
■ OnLine has very stringent requirements for performance and reli-ability (for example, it supports making archive copies while data-bases are in use).
■ OnLine manages its own disk space, which is devoted to logging.
■ It performs logging concurrently for all databases using a limited setof log files. The log files can be copied to another medium (backedup) while transactions are active.
Modifying Data 4-29
4-30 Informix Guide to
Concurrency and Locks
These facilities are usually managed from a central location by the OnLineadministrator, so database users never have to be concerned with them.
If you want to make a personal archive copy of a single database or table thatis held by OnLine, you can do it with the onunload utility. This programcopies a table or a database to tape. Its output consists of binary images of thedisk pages as they were stored in OnLine. As a result, the copy can be madevery quickly, and the corresponding onload program can restore the file veryquickly. However, the data format is not meaningful to any other programs.
If your OnLine administrator is using ON-Archive to create archives and backup logical logs, you may also be able to create your own backup copies usingON-Archive. See your INFORMIX-OnLine Dynamic Server Archive and BackupGuide for more information.
Concurrency and LocksIf your database is contained in a single-user workstation, without a networkconnecting it to other computers, concurrency is unimportant. In all othercases, you must allow for the possibility that, while your program is modify-ing data, another program is also reading or modifying the same data. This isconcurrency: two or more independent uses of the same data at the same time.
A high level of concurrency is crucial to good performance in a multiuserdatabase system. Unless controls exist on the use of data, however, concur-rency can lead to a variety of negative effects. Programs could read obsoletedata; modifications could be lost even though it seems they were enteredsuccessfully.
The database server prevents errors of this kind by imposing a system oflocks. A lock is a claim, or reservation, that a program can place on a piece ofdata. The database server guarantees that, as long as the data is locked, noother program can modify it. When another program requests the data, thedatabase server either makes the program wait or turns it back with an error.
SQL: Tutorial
Data Replication
You use a combination of SQL statements to control the effect that locks haveon your data access: SET LOCK MODE and either SET ISOLATION or SETTRANSACTION. You can understand the details of these statements afterreading a discussion on the use of cursors from within programs. Cursors arecovered in Chapter 5, “Programming with SQL,” and Chapter 6, “ModifyingData Through SQL Programs.” Also see Chapter 7, “Programming for a Mul-tiuser Environment,” for more information about locking and concurrency.
Data ReplicationData replication, in the broadest sense of the term, is when database objectshave 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 computer—so that reports can be run against the data without disturbing client applica-tions 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 datathat is not replicated—experience improved performance becausethey do not have to use network services.
■ Clients at all sites experience improved availability with replicateddata, because if local replicated data is unavailable, a copy of the datais still available, albeit remotely.
These advantages do not come without a cost. Data replication obviouslyrequires more storage for replicated data than for unreplicated data, andupdating replicated data can take more processing time than updating asingle object.
Data replication can actually be implemented in the logic of clientapplications, by explicitly specifying where data should be found orupdated. However, this way of achieving data replication is costly, error-prone, and difficult to maintain. Instead, the concept of data replication isoften coupled with replication transparency. Replication transparency is func-tionality built into a database server (instead of client applications) toautomatically handle the details of locating and maintaining data replicas.
Modifying Data 4-31
4-32 Informix Guide to
INFORMIX-OnLine Dynamic Server Data Replication
INFORMIX-OnLine Dynamic Server Data ReplicationWithin the broad framework of data replication, OnLine implements nearlytransparent data replication of entire database servers. All the data managedby one OnLine database server is replicated and dynamically updated onanother OnLine database server, usually at a remote site. OnLine data repli-cation is sometimes called hot site backup, because it provides a means ofmaintaining a backup copy of the entire database server that can be usedquickly in the event of a catastrophic failure.
Because OnLine provides replication transparency, you generally do notneed to be concerned with or aware of data replication; the OnLine adminis-trator takes care of it. However, if your organization decides to use datareplication, you should be aware that special connectivity considerationsexist for client applications in a data replication environment. Theseconsiderations are described in the INFORMIX-OnLine Dynamic ServerAdministrator’s Guide.
SummaryDatabase access is regulated by the privileges that the database owner grantsto you. The privileges that let you query data are often granted automatically,but the ability to modify data is regulated by specific Insert, Delete, andUpdate privileges that are granted on a table-by-table basis.
If data integrity constraints are imposed on the database, your ability tomodify data is restricted by those constraints. Your database- and table-levelprivileges, along with any data constraints, control how and when you canmodify data.
You can delete one or more rows from a table with the DELETE statement. ItsWHERE clause selects the rows; use a SELECT statement with the same clauseto preview the deletes.
Rows are added to a table with the INSERT statement. You can insert a singlerow containing specified column values, or you can insert a block of rowsgenerated by a SELECT statement.
SQL: Tutorial
Summary
You use the UPDATE statement to modify the contents of existing rows. Youspecify the new contents with expressions that can include subqueries, sothat you can use data based on other tables or the updated table itself. Thestatement has two forms: in the first form you specify new values column bycolumn; you use the other form when the new values are generated as a setfrom a SELECT statement or a record variable.
You use the REFERENCES clause of the CREATE TABLE and ALTER TABLEstatements to create relationships between tables. The ON DELETE CASCADEoption of the REFERENCES clause allows you to delete rows from parent andassociated child tables with one DELETE statement.
You use transactions to prevent unforeseen interruptions in a modificationfrom leaving the database in an indeterminate state. When modifications areperformed within a transaction, they are rolled back following an error. Thetransaction 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 itsmost recent state.
Data replication, which is transparent to users, offers another type ofprotection from catastrophic failures.
Modifying Data 4-33
5Chapter
Programming with SQL
SQL in Programs . . . . . . . . . . . . . . . . . . . 5-4SQL in SQL APIs . . . . . . . . . . . . . . . . . . 5-4SQL in Application Languages . . . . . . . . . . . . . 5-5Static Embedding . . . . . . . . . . . . . . . . . . 5-5Dynamic Statements . . . . . . . . . . . . . . . . . 5-5Program Variables and Host Variables . . . . . . . . . . . 5-6
Calling the Database Server . . . . . . . . . . . . . . . . 5-8The SQL Communications Area . . . . . . . . . . . . . 5-9The SQLCODE Field . . . . . . . . . . . . . . . . . 5-12
End of Data . . . . . . . . . . . . . . . . . . . 5-12Negative Codes . . . . . . . . . . . . . . . . . 5-13
The SQLERRD Array . . . . . . . . . . . . . . . . . 5-13The SQLWARN Array . . . . . . . . . . . . . . . . 5-13The SQLSTATE Value . . . . . . . . . . . . . . . . 5-14
Retrieving Single Rows . . . . . . . . . . . . . . . . . 5-14Data Type Conversion . . . . . . . . . . . . . . . . 5-16Dealing with Null Data . . . . . . . . . . . . . . . . 5-17Dealing with Errors . . . . . . . . . . . . . . . . . 5-18
End of Data . . . . . . . . . . . . . . . . . . . 5-18End of Data with Databases that Are Not ANSI-Compliant . . 5-18Serious Errors . . . . . . . . . . . . . . . . . . 5-18Interpreting End of Data with Aggregate Functions . . . . . 5-19Using Default Values . . . . . . . . . . . . . . . 5-19
Retrieving Multiple Rows . . . . . . . . . . . . . . . . 5-21Declaring a Cursor . . . . . . . . . . . . . . . . . 5-21Opening a Cursor . . . . . . . . . . . . . . . . . . 5-22Fetching Rows . . . . . . . . . . . . . . . . . . . 5-23
Detecting End of Data . . . . . . . . . . . . . . . 5-23Locating the INTO Clause. . . . . . . . . . . . . . 5-24
5-2 Infor
Cursor Input Modes . . . . . . . . . . . . . . . . . 5-24The Active Set of a Cursor . . . . . . . . . . . . . . . 5-25
Creating the Active Set . . . . . . . . . . . . . . . 5-25The Active Set for a Sequential Cursor . . . . . . . . . 5-26The Active Set for a Scroll Cursor . . . . . . . . . . . 5-26The Active Set and Concurrency . . . . . . . . . . . 5-27
Using a Cursor: A Parts Explosion . . . . . . . . . . . . 5-28
Dynamic SQL . . . . . . . . . . . . . . . . . . . . . 5-30Preparing a Statement . . . . . . . . . . . . . . . . 5-31Executing Prepared SQL. . . . . . . . . . . . . . . . 5-33
Using Prepared SELECT Statements . . . . . . . . . . 5-34Dynamic Host Variables . . . . . . . . . . . . . . . . 5-35Freeing Prepared Statements . . . . . . . . . . . . . . 5-36Quick Execution . . . . . . . . . . . . . . . . . . 5-36
Embedding Data Definition Statements . . . . . . . . . . . . 5-36Embedding Grant and Revoke Privileges . . . . . . . . . . 5-37
Summary . . . . . . . . . . . . . . . . . . . . . . 5-40
mix Guide to SQL: Tutorial
In the examples in the previous chapters, SQL is treated as if it were aninteractive computer language; that is, as if you could type a SELECTstatement directly into the database server and see rows of data rolling backto you.
Of course, that is not how things are. Many layers of software stand betweenyou and the database server. The database server retains data in a binaryform that must be formatted before it can be displayed. It does not return amass of data at once; it returns one row at a time, as a program requests it.
You can access information in your database in two ways: through interactiveaccess using DB-Access or INFORMIX-SQL or through application programswritten using an SQL API, or through an application language such asNewEra or INFORMIX-4GL.
Almost any program can contain SQL statements, execute them, and retrievedata from a database server. This chapter explains how these activities areperformed and indicates how you can write programs that perform them.
This chapter is only an introduction to the concepts that are common to SQLprogramming in any language. Before you can write a successful program ina particular programming language, you must first become fluent in that lan-guage. Then, because the details of the process are slightly different in everylanguage, you must become familiar with the manual for the Informix SQLAPI specific to that language or your NewEra OR INFORMIX-4GLdocumentation.
Programming with SQL 5-3
5-4 Informix Guide to S
SQL in Programs
ESQL sourceprogram
SQL in ProgramsYou can write a program in any of several languages and mix SQL statementsin among the other statements of the program, just as if they were ordinarystatements of that programming language. The SQL statements are said to beembedded in the program, and the program is said to contain embedded SQL,often abbreviated by Informix as ESQL.
SQL in SQL APIsESQL products are Informix SQL APIs.Informix produces SQL APIs for the fol-lowing programming languages:
■ C
■ COBOL
■ FORTRAN (pre-Version 6.0)
■ Ada (Version 4.0 only)
All SQL API products work in a similar way, as shown in Figure 5-1. You writea source program in which you treat SQL statements as executable code. Yoursource program is processed by an embedded SQL preprocessor, a programthat locates the embedded SQL statements and converts them into a series ofprocedure calls and special data structures.
Figure 5-1Overview of processing a program with embedded SQL statements
ESQLpreprocessor
Source programwith procedure calls
Languagecompiler
Executableprogram
QL: Tutorial
SQL in Application Languages
The converted source program then passes through the programminglanguage compiler. The compiler output becomes an executable programafter it is linked with a library of SQL API procedures. When the programruns, the SQL API library procedures are called; they set up communicationswith the database server to carry out the SQL operations.
SQL in Application LanguagesWhereas SQL API products allow you to embed SQL in the host language,some languages have SQL as a natural part of their statement set.INFORMIX-4GL incorporates the SQL language as a natural part of the fourth-generation language it supports. The NewEra product provides support forembedded SQL, and it also provides a mechanism called a SuperTable forautomatically generating SQL statements needed to access a table being dis-played. Informix Stored Procedure Language (SPL) also uses SQL as a naturalpart of its statement set. You use INFORMIX-4GL or an SQL API product towrite application programs. You use SPL to write procedures that are storedwith a database and are called from an application program.
Static EmbeddingYou can introduce SQL statements into a program in two ways. The simplerand more common way is by static embedding, which means that the SQLstatements are written as part of the source program text. The statements arestatic because they are a fixed part of the source text.
Dynamic StatementsSome applications require the ability to compose SQL statements in responseto user input. For example, a program might have to select different columnsor apply different criteria to rows, depending on what the user wants.
This can be done with dynamic SQL, in which the program composes an SQLstatement as a string of characters in memory and passes it to the databaseserver to be executed. Dynamic statements are not part of the program sourcetext; they are constructed in memory during execution. In NewEra, much ofthe database interation is done with dynamically executed SQL statements.
Programming with SQL 5-5
5-6 Informix Guide to S
Program Variables and Host Variables
MAIN...DEFINE dropLET drop_nuDELETE FROM...
CREATE PROC...DELETE FROM...
Program Variables and Host VariablesApplication programs can use program variables within SQL statements. InNewEra, INFORMIX-4GL and SPL, you put the program variable in the SQLstatement as syntax allows. For example, a DELETE statement can use a pro-gram variable in its WHERE clause. Figure 5-2 shows a program variable inINFORMIX-4GL.
Figure 5-3 shows a program variable in SPL.
In applications that use embedded SQL statements, the SQL statements canrefer to the contents of program variables. A program variable that is namedin an embedded SQL statement is called a host variable because the SQLstatement is thought of as being a “guest” in the program.
Figure 5-2Using a program
variable inINFORMIX-4GL
Figure 5-3Using a program
variable in SPL
_number INTmber = 108 items WHERE order_num = drop_number
EDURE delete_item (drop_number INT)
items WHERE order_num = drop_number
QL: Tutorial
Program Variables and Host Variables
The following example is a DELETE statement as it might appear whenembedded in a COBOL source program:
EXEC SQLDELETE FROM items
WHERE order_num = :o-numEND-EXEC.
The first and last lines mark off embedded SQL from the normal COBOLstatements. Between them you see an ordinary DELETE statement, asdescribed in Chapter 4, “Modifying Data.” When this part of the COBOLprogram is executed, a row of the items table is deleted; multiple rows canalso be deleted.
The statement contains one new feature. It compares the order_num columnto 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 hostvariables 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 numberequals the current contents of the host variable named :o-num. This is anumeric variable that has been declared and assigned a value earlier in theprogram.
The same DELETE statement embedded in a FORTRAN program looks like thefollowing example:
EXEC SQLDELETE FROM items
WHERE order_num = :onum
The same statement embedded in an Ada program looks like the followingexample:
EXEC SQLDELETE FROM items
WHERE order_num = $onum;
In INFORMIX-ESQL/Ada, a host variable is indicated by a leading dollar sign,and statements end with a semicolon. In INFORMIX-ESQL/C a host variablecan be introduced with either a dollar sign ($) or a colon (:). The colon (:) isthe ANSI-compatible format. The corresponding DELETE statement is writtenin INFORMIX-ESQL/C as shown in the following example:
EXEC SQL delete FROM itemsWHERE order_num = :onum;
Programming with SQL 5-7
5-8 Informix Guide to S
Calling the Database Server
In INFORMIX-ESQL/C, an SQL statement can be introduced with either aleading dollar sign ($) or the words EXEC SQL.
These differences of syntax are trivial; the essential points in all languages (anSQL API, NewEra, INFORMIX-4GL, or SPL) are described in the following list:
■ You can embed SQL statements in a source program as if they wereexecutable statements of the host language.
■ You can use program variables in SQL expressions the way literalvalues are used.
If you have programming experience, you can immediately see thepossibilities. In the example, the order number to be deleted is passed in thevariable onum. That value comes from any source that a program can use: Itcan be read from a file, the program can prompt a user to enter it, or it can beread from the database. The DELETE statement itself can be part of a subrou-tine (in which case onum can be a parameter of the subroutine); thesubroutine can be called once or repetitively.
In short, when you embed SQL statements in a program, you can apply all thepower of the host language to them. You can hide the SQL under a multitudeof interfaces, and you can embellish its functions in a multitude of ways.
Calling the Database ServerExecuting an SQL statement is essentially calling the database server as asubroutine. Information must pass from the program to the database serverand information must be returned.
Some of this communication is done through host variables. You can think ofthe host variables named in an SQL statement as the parameters of the proce-dure call to the database server. In the preceding example, a host variable actsas a parameter of the WHERE clause. Also, as described in “Retrieving Multi-ple Rows” on page 5-21, host variables receive data that is returned by thedatabase server.
QL: Tutorial
The SQL Communications Area
The SQL Communications AreaThe database server always returns a result code, and possibly otherinformation about the effect of an operation, in a data structure known as theSQL Communications Area (SQLCA). If the database server executes an SQLstatement in a stored procedure, the SQLCA of the calling applicationcontains the values triggered by the SQL statement in the procedure.
The principal fields of the SQLCA are listed in Figure 5-4 on page 5-10 andFigure 5-5 on page 5-11. The syntax you use to describe a data structure suchas the SQLCA as well as the syntax you use to refer to a field in it, differsamong programming languages. See your NewEra, INFORMIX-4GL, or SQLAPI manual for details.
You can also use the SQLSTATE variable of the GET DIAGNOSTICS statementto detect, handle, and diagnose errors. See “The SQLSTATE Value” onpage 5-14.
Programming with SQL 5-9
5-10 Informix Guide to
The SQL Communications Area
Follstataffe
Wherro
Afteope
If anapp
Follgen
Follthe
Follfield
FollstatweiINF
FollSQLdete
Follope
array of 6integers
first
second
third
fourth
fifth
sixth
SQ
Succ
No m
Erro
integer
0
100
negative
SQL
Inte
character(8) SQ
Figure 5-4The uses of SQLCODE, SQLERRD, and SQLERRP
owing successful PREPARE statement for a SELECT, UPDATE, INSERT, or DELETEement, or after a select cursor is opened, this field contains the estimated number ofcted rows. It is not used in INFORMIX-ESQL/Ada.
en SQLCODE contains an error code, this field contains either zero or an additionalr code, called the ISAM error code, that explains the cause of the main error.
r a failed CONNECT or DATABASE statement, this field contains the ISAM,rating system, or network-specific protocol error code.
application connects to an INFORMIX-Gateway with DRDA, this field contains thelication server error code. In this case, sqlca.sqlcode is -29000.
owing a successful insert operation of a single row, this field contains the value of aerated serial number for that row.
owing a successful multirow insert, update, or delete operation, this field containsnumber of processed rows.
owing a multirow insert, update, or delete operation that ends with an error, this contains the number of rows successfully processed before the error was detected.
owing successful PREPARE statement for a SELECT, UPDATE, INSERT, or DELETEement, or after a select cursor has been opened, this field contains the estimatedghted sum of disk accesses and total rows processed. It is not used inORMIX-ESQL/Ada.
owing a syntax error in a PREPARE, EXECUTE IMMEDIATE, DECLARE, or static statement, this field contains the offset in the statement text where the error wascted.
owing a successful fetch of a selected row or a successful insert, update, or deleteration, this field contains the rowid (physical address) of the last row processed.
LERRD
ess.
ore data/not found.
r code.
CODE
rnal use only.
LERRP
SQL: Tutorial
The SQL Communications Area
character(71)
All
Set
Set
Set
Onis n
Set clau
Set (pro
Set INF
No
first
second
third
fourth
fifth
sixth
seventh
eighth
Wh
Set
Set
Set
Set
Set(DO
No
Setdatdat
No
array of 8characters
first
second
third
fourth
fifth
sixth
seventh
eighth
SQ
Connet
SQ
Figure 5-5The uses of SQLWARN and SQLERRM
Other Operations:
to W when any other field is set to W.
to W when a column value is truncated as it is fetched into a host variable.
to W when an aggregate function encounters a null value.
a SELECT or on opening a cursor, set to W when the number of items in the select listot the same as the number of host variables given in the INTO clause to receive them.
to W if a prepared statement contains a DELETE or an UPDATE without a WHEREse.
to W following execution of a statement that does not use ANSI-standard SQL syntaxvided that the DBANSIWARN environment variable is set).
to W when a data fragment (a dbspace) is skipped during query processing (whenORMIX-OnLine Dynamic Server DATASKIP feature is on).
t used.
en Opening or Connecting to a Database:
to W when any field is set to W. If this field is blank, the others need not be checked.
to W when the database now open uses a transaction log.
to W when the database now open is ANSI-compliant.
to W when the database server is INFORMIX-OnLine Dynamic Server.
to W when the database server stores the FLOAT data type in DECIMAL FORMNE WHEN THE HOST SYSTEM LACKS SUPPORT FOR FLOAT TYPES).
t used.
to W when the application is connected to an INFORMIX-OnLine Dynamic Serverabase server, which is a secondary server in a data replication pair (that is, theabase server is available only for read operations).
t used.
LWARN
tains the variable, such as table name, that is placed in the error message. For someworked applications, contains an error message generated by networking software.
LERRM
Programming with SQL 5-11
5-12 Informix Guide to
The SQLCODE Field
In particular, the subscript by which you name one element of the SQLERRDand SQLAWARN arrays differs: Array elements are numbered starting withzero in INFORMIX-ESQL/C, but starting with one in the other languages. Inthis discussion, the fields are named using specific words such as third, andyou must translate into the syntax of your programming language.
The SQLCODE FieldThe SQLCODE field is the primary return code of the database server. Afterevery SQL statement, SQLCODE is set to an integer value as shown inFigure 5-4 on page 5-10. When that value is zero, the statement is performedwithout error. In particular, when a statement is supposed to return data intoa host variable, a code of zero means that the data has been returned and canbe used. Any nonzero code means the opposite: No useful data was returnedto host variables.
In INFORMIX-4GL and NewEra, SQLCODE is also accessible under the nameSTATUS. NewEra also supports access to SQLCODE through ODBC libraries.
End of Data
The database server sets SQLCODE to 100 when the statement is performedcorrectly but no rows are found. Two situations exist where this can occur.
The first situation involves a query that uses a cursor. (Queries using cursorsare described under “Retrieving Multiple Rows” on page 5-21.) In thesequeries the FETCH statement retrieves each value from the active set intomemory. After the last row is retrieved, a subsequent FETCH statementcannot return any data. When this occurs the database server sets SQLCODEto 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 database server sets SQLCODE to 100 when no rows satisfy the query con-dition. In ANSI-compliant databases, SELECT, DELETE, UPDATE, and INSERTstatements all set SQLCODE to 100 if no rows are returned. In databases thatare not ANSI-compliant, only a SELECT statement that returns no rows causesSQLCODE to be set to 100.
SQL: Tutorial
The SQLERRD Array
Negative Codes
When something unexpected goes wrong during a statement, the databaseserver returns a negative number in SQLCODE to explain the problem. Themeanings of these codes are documented in the Informix Error Messagesmanual and in the on-line error message file.
The SQLERRD ArraySome error codes that can be reported in SQLCODE reflect general problems,and the database server can set a more detailed code in the second field ofSQLERRD. This second code (referred to as the ISAM error) reveals the low-level error encountered by the database server I/O routines or by theunderlying operating system.
The integers in the array named SQLERRD are set to different valuesfollowing different statements. The first and fourth elements of the array areused only in INFORMIX-4GL, INFORMIX-ESQL/C, INFORMIX-ESQL/COBOL,and NewEra (Informix CCL only). The fields are used as shown in Figure 5-4on page 5-10.
These additional details can be very useful. For example, you can use thevalue in the third field to report how many rows were deleted or updated.When your program prepares an SQL statement entered by the user and anerror is found, the value in the fifth field enables you to display the exactpoint of error to the user. (DB-Access and INFORMIX-SQL use this feature toposition the cursor when you ask to modify a statement after an error.)
The SQLWARN ArrayThe eight character fields in the SQLWARN array are set to either a blank or aW to indicate a variety of special conditions. Their meanings depend on thestatement just executed.
A set of warning flags appear when a database opens, that is, following aCONNECT, DATABASE or CREATE DATABASE statement. These flags tell yousome characteristics of the database as a whole.
Programming with SQL 5-13
5-14 Informix Guide to
The SQLSTATE Value
A second set of flags appear following any other statement. These flags reflectunusual events that occur during the statement, which are usually notserious enough to be reflected by SQLCODE.
Important: NewEra and INFORMIX-4GL call this array SQLWARN.
Both sets of SQLWARN values are summarized in Figure 5-5 on page 5-11.
The SQLSTATE ValueCertain Informix products, such as INFORMIX-ESQL/COBOL andINFORMIX-ESQL/C, support the SQLSTATE value in compliance with X/Openand ANSI SQL standards. The GET DIAGNOSTICS statement reads theSQLSTATE value in order to diagnose errors after you run an SQL statement.The database server returns a result code in a five-character string that isstored in a variable called SQLSTATE. The SQLSTATE error code, or value, tellsyou the following information about the most recently executed SQLstatement:
■ 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 themeanings of the SQLSTATE return codes, see “GET DIAGNOSTICS” in Chapter1 of the Informix Guide to SQL: Syntax. If your Informix product supports GETDIAGNOSTICS and SQLSTATE, Informix recommends that you use them asthe primary structure to detect, handle, and diagnose errors. Using SQLSTATEallows you to detect multiple errors and it is ANSI-compliant.
Retrieving Single RowsYou can use embedded SELECT statements to retrieve single rows from thedatabase into host variables. When a SELECT statement returns more thanone row of data, however, a program must use a more complicated methodto fetch the rows one at a time. Multiple-row select operations are discussedin “Retrieving Multiple Rows” on page 5-21.
SQL: Tutorial
Retrieving Single Rows
To retrieve a single row of data, simply embed a SELECT statement in yourprogram. The following example shows how it can be written usingINFORMIX-ESQL/C:
EXEC SQL select avg (total_price)into :avg_pricefrom itemswhere order_num in
(select order_num from orderswhere order_date < date('6/1/94') );
The INTO clause is the only detail that distinguishes this statement from anyexample in Chapter 2, “Composing Simple SELECT Statements,” orChapter 3, “Composing Advanced SELECT Statements.” This clausespecifies the host variables that are to receive the data that is produced.
When the program executes an embedded SELECT statement, the databaseserver performs the query. The example statement selects an aggregate value,so that it produces exactly one row of data. The row has only a single column,and its value is deposited in the host variable named avg_price. Subsequentlines of the program can use that variable.
You can use statements of this kind to retrieve single rows of data into hostvariables. The single row can have as many columns as desired. In the follow-ing INFORMIX-4GL example, host variables are used in two ways, as receiversof data and in the WHERE clause:
DEFINE cfname, clname, ccompany CHAR(20)DEFINE cnumbr INTEGERLET cnumbr = 104SELECT fname, lname, company
INTO cfname, clname, ccompanyFROM customerWHERE customer_num = cnumbr
Because the customer_num column has a unique index (implementedthrough a constraint), this query returns only one row. If a query producesmore than one row of data, the database server cannot return any data. Itreturns an error code instead.
You should list as many host variables in the INTO clause as there are itemsin the select list. If, by accident, these lists are of different lengths, the data-base server returns as many values as it can and sets the warning flag in thefourth field of SQLWARN.
Programming with SQL 5-15
5-16 Informix Guide to
Data Type Conversion
Data Type ConversionThe following example retrieves the average of a DECIMAL column, which isitself a DECIMAL value. However, the host variable into which it is placed isnot required to have that data type.
EXEC SQL select avg (total_price) into :avg_pricefrom items;
The declaration of the receiving variable avg_price in the previous exampleof ESQL/C code is not shown. It could be any one of the following definitions:
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 passedto the database server along with the statement. The database server does itsbest to convert column data into the form used by the receiving variables.Almost any conversion is allowed, although some conversions cause a loss ofprecision. The results of the preceding example differ, depending on the datatype 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 maximummagnitude of the FLOAT format, an error is returned.
INTEGER The database server converts the result to integer, truncat-ing fractional digits if necessary.
If the integer part of the converted number does not fit thereceiving variable, an error occurs.
CHARACTER The database server converts the decimal value to acharacter string.
If the string is too long for the receiving variable, it istruncated. The second field of SQLWARN is set to W and thevalue in the SQLSTATE variable is 01004.
SQL: Tutorial
Dealing with Null Data
Dealing with Null DataWhat if the program retrieves a null value? Null values can be stored in thedatabase, but the data types supported by programming languages do notrecognize a null state. A program must have some way of recognizing a nullitem to avoid processing it as data.
Indicator variables meet this need in SQL APIs. An indicator variable is anadditional variable that is associated with a host variable that might receivea null item. When the database server puts data in the main variable, it alsoputs 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 asingle value is retrieved into the host variable op_date:
EXEC SQL select paid_dateinto :op_date:op_d_indfrom orderswhere order_num = $the_order;
if (op_d_ind < 0) /* data was null */rstrdate ('01/01/1900', :op_date);
Because the value might be null, an indicator variable named op_d_ind isassociated with the host variable. (It must be declared as a short integerelsewhere in the program.)
Following execution of the SELECT statement, the program tests the indicatorvariable for a negative value. A negative number (usually -1) means that thevalue retrieved into the main variable is null. If that is the case, this programuses an ESQL/C library function to assign a default value to the host variable.(The function rstrdate is part of the INFORMIX-ESQL/C product.)
The syntax you use to associate an indicator variable differs with thelanguage you are using, but the principle is the same in all. However, indica-tor variables are not used explicitly in INFORMIX-4GL, NewEra, or in SPLbecause in those languages, null values are supported for variables. In 4GL,the preceding example is written as shown in the following example:
SELECT paid_dateINTO op_dateFROM ordersWHERE order_num = the_order
IF op_date IS NULL THENLET op_date = date ('01/01/1900')
END IF
Programming with SQL 5-17
5-18 Informix Guide to
Dealing with Errors
Dealing with ErrorsAlthough the database server handles conversion between data typesautomatically, several things still can go wrong with a SELECT statement. InSQL programming, as in any kind of programming, you must anticipateerrors and provide for them at every point.
End of Data
One common event is that no rows satisfy a query. This is signalled by anSQLSTATE code of 02000 and by a code of 100 in SQLCODE following aSELECT statement. This code indicates an error or a normal event, dependingentirely on your application. If you are sure that there ought to be a row orrows—for example, if you are reading a row using a key value that you justread from a row of another table—then the end-of-data code represents aserious failure in the logic of the program. On the other hand, if you select arow based on a key supplied by a user or some other source that is lessreliable than a program, a lack of data can be a normal event.
End of Data with Databases that Are Not ANSI-Compliant
If your database is not ANSI-compliant, the end-of-data return code, 100, isset in SQLCODE only following SELECT statements. In addition, the SQLSTATEvalue is set to 02000. (Other statements, such as INSERT, UPDATE, andDELETE, set the third element of SQLERRD to show how many rows theyaffected; this topic is covered in Chapter 6, “Modifying Data Through SQLPrograms.”)
Serious Errors
Errors that set SQLCODE to a negative value or SQLSTATE to a valuebeginning with anything other than 00, 01, or 02 are usually serious.Programs that you have developed and are in production should rarelyreport these errors. Nevertheless, it is difficult to anticipate every problematicsituation, so your program must be able to deal with them.
For example, a query can return error -206, which means table name isnot in the database. This happens if someone dropped the table since theprogram was written or if, through some error of logic or mistake in input,the program opened the wrong database.
SQL: Tutorial
Dealing with Errors
Interpreting End of Data with Aggregate Functions
A SELECT statement that uses an aggregate function such as SUM, MIN, orAVG always succeeds in returning at least one row of data. This is true evenwhen no rows satisfy the WHERE clause; an aggregate value based on anempty set of rows is null, but it exists nonetheless.
However, an aggregate value is also null if it is based on one or more rowsthat all contain null values. If you must be able to detect the differencebetween an aggregate value based on no rows and one based on some rowsthat are all null, you must include a COUNT function in the statement and anindicator variable on the aggregate value. You can then work out thefollowing cases:
Using Default Values
You can handle these inevitable errors in many ways. In some applications,more lines of code to handle errors are used than for normal situations. In theexamples in this section, however, one of the simplest methods, the defaultvalue, should work, as shown in the following example:
avg_price = 0; /* set default for errors */EXEC SQL select avg (total_price)
into :avg_price:null_flagfrom items;
if (null_flag < 0) /* probably no rows */avg_price = 0; /* set default for 0 rows */
Count Value Indicator Case
0 -1 zero rows selected
>0 -1 some rows selected; all were null
>0 0 some non-null rows selected
Programming with SQL 5-19
5-20 Informix Guide to
Dealing with Errors
The previous example deals with the following considerations:
■ If the query selects some non-null rows, the correct value is returnedand used. This is the expected and most frequent result.
■ If the query selects no rows, or in the much less likely event that itselects only rows that have null values in the total_price column (acolumn that should never be null), the indicator variable is set andthe default value is assigned.
■ If any serious error occurs, the host variable is left unchanged; itcontains the default value initially set. At this point in the program,the programmer sees no need to trap such errors and report them.
The following example is an expansion of an earlier INFORMIX-4GL examplethat displays default values if it cannot find the company that the userrequests:
DEFINE cfname, clname, ccompany CHAR(20)DEFINE cnumbr INTEGERPROMPT 'Enter the customer number: ' FOR cnumbrLET cfname = 'unknown'LET clname = 'person'LET ccompany = 'noplace'SELECT fname, lname, company
INTO cfname, clname, ccompanyWHERE customer_num = cnumbr
DISPLAY cfname,' ', clname,' at ', ccompany
This query does not use aggregates, so if no row matches the user-specifiedcustomer number, SQLCODE is set to 100 and SQLSTATE is 02000 and the hostvariables remain unchanged.
SQL: Tutorial
Retrieving Multiple Rows
Retrieving Multiple RowsWhen any chance exists that a query could return more than one row, theprogram must execute the query differently. Multirow queries are handled intwo stages. First, the program starts the query. (No data is returnedimmediately.) Then, the program requests the rows of data one at a time.
These operations are performed using a special data object called a cursor. Acursor is a data structure that represents the current state of a query. Thefollowing list is the general sequence of program operations:
1. The program declares the cursor and its associated SELECT statement,which merely allocates storage to hold the cursor.
2. The program opens the cursor, which starts the execution of theassociated SELECT statement and detects any errors in it.
3. The program fetches a row of data into host variables and processes it.
4. The program closes the cursor after the last row is fetched.
5. When the cursor is no longer needed, the program frees the cursor todeallocate the resources it uses.
These operations are performed with SQL statements named DECLARE,OPEN, FETCH, CLOSE, and FREE.
Declaring a CursorYou declare a cursor using the DECLARE statement. This statement gives thecursor a name, specifies its use, and associates it with a statement. Thefollowing example is written in INFORMIX-4GL:
DECLARE the_item CURSOR FORSELECT order_num, item_num, stock_numINTO o_num, i_num, s_numFROM items
The declaration gives the cursor a name (the_item in this case) and associatesit with a SELECT statement. (Chapter 6, “Modifying Data Through SQLPrograms,” discusses how a cursor also can be associated with an INSERTstatement.)
Programming with SQL 5-21
5-22 Informix Guide to
Opening a Cursor
The SELECT statement in this example contains an INTO clause. That is one oftwo ways in which you can specify the variables that receive data. The otherway, using the FETCH statement, is discussed in “Locating the INTO Clause”on page 5-24.
The DECLARE statement is not an active statement; it merely establishes thefeatures of the cursor and allocates storage for it. You can use the cursordeclared in the preceding example to read once through the items table.Cursors can be declared to read backward and forward (see “Cursor InputModes” on page 5-24). This cursor, because it lacks a FOR UPDATE clause,probably is used only to read data, not to modify it. (The use of cursors tomodify data is covered in Chapter 6, “Modifying Data Through SQLPrograms.”)
Opening a CursorThe program opens the cursor when it is ready to use it. The OPEN statementactivates the cursor. It passes the associated SELECT statement to the databaseserver, which begins the search for matching rows. The database serverprocesses the query to the point of locating or constructing the first row ofoutput. It does not actually return that row of data, but it does set a returncode in SQLSTATE for SQL APIs and SQLCODE for INFORMIX-4GL and SQLAPIs. 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 isthe time when many errors are detected. After opening the cursor, theprogram should test SQLSTATE or SQLCODE. If the SQLSTATE value is greaterthan 02000 or the SQLCODE contains a negative number, the cursor is notusable. There may be an error in the SELECT statement, or some otherproblem may be preventing the database server from executing thestatement.
If SQLSTATE is equal to 00000 or SQLCODE contains a zero, the SELECTstatement 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.
SQL: Tutorial
Fetching Rows
Fetching RowsThe program uses the FETCH statement to retrieve each row of output. Thisstatement names a cursor and can also name the host variables to receive thedata. The following example shows the completed INFORMIX-4GL code:
DECLARE the_item CURSOR FORSELECT order_num, item_num, stock_num
INTO o_num, i_num, s_numFROM items
OPEN the_itemWHILE SQLCA.SQLCODE = 0
FETCH the_itemIF SQLCA.SQLCODE = 0 THEN
DISPLAY o_num, i_num, s_numEND IF
END WHILE
Detecting End of Data
In the previous example, the WHILE condition prevents execution of the loopin case the OPEN statement returns an error. The same condition terminatesthe loop when SQLCODE is set to 100 to signal the end of data. However, theloop contains a test of SQLCODE. This test is necessary because, if the SELECTstatement is valid yet finds no matching rows, the OPEN statement returns azero but the first fetch returns 100, end of data, and no data. The followingexample shows another way to write the same loop:
DECLARE the_item CURSOR FORSELECT order_num, item_num, stock_num
INTO o_num, i_num, s_numFROM items
OPEN the_itemIF SQLCA.SQLCODE = 0 THEN
FETCH the_item -- fetch first rowEND IFWHILE SQLCA.SQLCODE = 0
DISPLAY o_num, i_num, s_numFETCH the_item
END WHILE
In this version, the case of zero returned rows is handled early, so no secondtest of SQLCA.SQLCODE exists within the loop. These versions have nomeasurable difference in performance because the time cost of a test ofSQLCA.SQLCODE is a tiny fraction of the cost of a fetch.
Programming with SQL 5-23
5-24 Informix Guide to
Cursor Input Modes
Locating the INTO Clause
The INTO clause names the host variables that are to receive the data returnedby the database server. It must appear in either the SELECT or the FETCHstatement but not both. The following example is reworked to specify hostvariables in the FETCH statement:
DECLARE the_item CURSOR FORSELECT order_num, item_num, stock_num
FROM itemsOPEN the_itemWHILE status = 0
FETCH the_item INTO o_num, i_num, s_numIF status = 0 THEN
DISPLAY o_num, i_num, s_numEND IF
END WHILE
The second form has the advantage that different rows can be fetched intodifferent variables. For example, you can use this form to fetch successiverows into successive elements of an array.
Cursor Input ModesFor purposes of input, a cursor operates in one of two modes, sequential orscrolling. A sequential cursor can fetch only the next row in sequence so it canread through a table only once each time it is opened. A scroll cursor can fetchthe next row or any prior row, so it can read rows multiple times. Thefollowing example shows a sequential cursor declared in INFORMIX-ESQL/C:
EXEC SQL declare pcurs cursor forselect customer_num, lname, city
from customer;
After it is opened, the cursor can be used only with a sequential fetch thatretrieves the next row of data, as shown in the following example:
EXEC SQL fetch p_curs into:cnum, :clname, :ccity;
Each sequential fetch returns a new row.
A scroll cursor is declared with the keyword SCROLL, as shown in thefollowing example from INFORMIX-ESQL/FORTRAN:
EXEC SQL DECLARE s_curs SCROLL CURSOR FOR+ SELECT order_num, order_date FROM orders+ WHERE customer_num > 104
SQL: Tutorial
The Active Set of a Cursor
A scroll cursor can be used with a variety of fetch options. The ABSOLUTEoption specifies the rank number of the row to fetch.
EXEC SQL FETCH ABSOLUTE :numrow s_curs+ INTO :nordr, :nodat
This statement fetches the row whose position is given in the host variablenumrow. It is also possible to fetch the current row again or to fetch the firstrow and then scan through the entire list again. However, these features areobtained at a price, as described in the next section.
The Active Set of a CursorOnce a cursor is opened, it stands for some selection of rows. The set of allrows that the query produces is called the active set of the cursor. It is easy tothink of the active set as a well-defined collection of rows and to think of thecursor as pointing to one row of the collection. This situation is true as longas no other programs are modifying the same data concurrently.
Creating the Active Set
When a cursor is opened, the database server does whatever is necessary tolocate the first row of selected data. Depending on how the query is phrased,this can be very easy to do, or it can require a great deal of work and time.Consider the following declaration of a cursor:
DECLARE easy CURSOR FORSELECT fname, lname FROM customer
WHERE state = 'NJ'
Because this cursor queries only a single table in a simple way, the databaseserver can very quickly discover whether any rows satisfy the query and findthe first one. The first row is the only row it finds at this time. The rest of therows in the active set remain unknown. As a contrast, consider the followingdeclaration of a cursor:
DECLARE hard CURSOR FORSELECT C.customer_num, O.order_num, sum (items.total_price)
FROM customer C, orders O, items IWHERE C.customer_num = O.customer_num
AND O.order_num = I.order_numAND O.paid_date is null
GROUP BY C.customer_num, O.order_num
Programming with SQL 5-25
5-26 Informix Guide to
The Active Set of a Cursor
The active set of this cursor is generated by joining three tables and groupingthe output rows. The optimizer might be able to use indexes to produce therows in the correct order, but in general the use of ORDER BY or GROUP BYclauses requires the database server to generate all the rows, copy them to atemporary table, and sort the table, before it can know which row to presentfirst.
In cases where the active set is entirely generated and saved in a temporarytable, 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 cannever be sure which method the optimizer uses. If it can avoid sorts andtemporary tables, it does; but very small changes in the query, in the sizes ofthe tables, or in the available indexes can change its methods.
The Active Set for a Sequential Cursor
The database server wants to tie up as few resources as possible inmaintaining the active set of a cursor. If it can do so, the database server neverretains more than the single row that is fetched next. It can do this for mostsequential cursors. On each fetch, it returns the contents of the current rowand locates the next one.
The Active Set for a Scroll Cursor
All the rows in the active set for a scroll cursor must be retained until thecursor closes because the database server cannot be sure which row theprogram will ask for next.
Most frequently, the database server implements the active set of a scrollcursor as a temporary table. The database server might not fill this tableimmediately, however (unless it created a temporary table to process thequery). Usually it creates the temporary table when the cursor is opened.Then, the first time a row is fetched, the database server copies it into the tem-porary table and returns it to the program. When a row is fetched for a secondtime, it can be taken from the temporary table. This scheme uses the fewestresources in the event that the program abandons the query before it fetchesall the rows. Rows that are never fetched are not created or saved.
SQL: Tutorial
The Active Set of a Cursor
The Active Set and Concurrency
When only one program is using a database, the members of the active setcannot change. This is the situation in most personal computers, and it is theeasiest situation to think about. But some programs must be designed for usein a multiprogramming system, where two, three, or dozens of different pro-grams can work on the same tables simultaneously.
When other programs can update the tables while your cursor is open, theidea of the active set becomes less useful. Your program can see only one rowof data at a time, but all other rows in the table can be changing.
In the case of a simple query, when the database server holds only one row ofthe active set, any other row can change. The instant after your programfetches a row, another program can delete the same row or update it so thatif it is examined again, it is no longer part of the active set.
When the active set, or part of it, is saved in a temporary table, stale data canpresent a problem. That is, the rows in the actual tables, from which theactive-set rows are derived, can change. If they do, some of the active-setrows no longer reflect the current table contents.
These ideas may seem unsettling at first, but as long as your program onlyreads the data, there is no such thing as stale data, or rather, all data is equallystale. No matter when it is taken, the active set is a snapshot of the data as itis at one moment in time. A row is different the next day; it does not matterif it is also different in the next millisecond. To put it another way, no practicaldifference exists between changes that occur while the program is runningand changes that are saved and applied the instant the program terminates.
The only time that stale data can cause a problem is when the programintends to use the input data to modify the same database; for example, whena banking application must read an account balance, change it, and write itback. Chapter 6, “Modifying Data Through SQL Programs,” discussesprograms that modify data.
Programming with SQL 5-27
5-28 Informix Guide to
Using a Cursor: A Parts Explosion
Using a Cursor: A Parts ExplosionWhen you use a cursor, supplemented by program logic, you can solve prob-lems that plain SQL cannot solve. One of these is the parts-explosion problem,sometimes called Bill of Materials processing. At the heart of this problem isa recursive relationship among objects; one object contains other objects,which contain yet others.
The problem is usually stated in terms of a manufacturing inventory. Acompany makes a variety of parts, for example. Some parts are discrete, butsome are assemblages of other parts.
These relationships are documented in a single table, which might be calledcontains.The column contains.parent holds the part numbers of parts thatare assemblages. The column contains.child has the part number of a partthat is a component of the parent. If part #123400 is an assembly of nine parts,nine rows exist with 123400 in the first column and other part numbers in thesecond. Figure 5-6 shows one of the rows which describe part #123400.
Figure 5-6Parts-explosion
problem
PARENT
FK NN
CONTAINS
432100765899
FK NN
CHILD
123400432100
SQL: Tutorial
Using a Cursor: A Parts Explosion
DEFINE partFUNCTION bo
DEFINE DEFINE DECLARE
SEL
LET nexLET parLET nex
WHILE nthiFOR
ENDLET
END WHIRETURN
END FUNCTIO
The parts-explosion problem is this: given a part number, produce a list of allparts that are components of that part. A sketch of one solution, asimplemented in INFORMIX-4GL, is shown in Figure 5-7.
Technically speaking, each row of the contains table is the head node of adirected acyclic graph, or tree. The function in Figure 5-7 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 theINFORMIX-4GL statement FOREACH, which opens a cursor, iterates once foreach row in the selection set, and closes the cursor.
This is the heart of the parts-explosion problem, but it is not a completesolution. For example, the program in Figure 5-7 does not allow for compo-nents that appear at more than one level in the tree. Furthermore, a practicalcontains table would also have a column count, giving the count of childparts used in each parent. A program that returns a total count of eachcomponent part is much more complicated.
Figure 5-7A breadth-first
algorithm togenerate a parts
explosion
_list ARRAY[200] OF INTEGERom (top_part)this_part, child_part INTEGERnext_to_do, next_free SMALLINT part_scan CURSOR FORECT child INTO child_part FROM containsWHERE parent = this_part
t_to_do = 1t_list[next_to_do] = top_partt_free = 2
ext_to_do < next_frees_part = part_list[next_to_do]EACH part_scanLET part_list[next_free] = child_partLET next_free = next_free + 1
FOREACH next_to_do = next_to_do + 1LEnext_free - 1N
Programming with SQL 5-29
5-30 Informix Guide to
Dynamic SQL
The iterative approach described earlier is not the only way to approach theparts-explosion problem. If the number of generations has a fixed limit, youcan solve the problem with a single SELECT statement using nested, outerself-joins.
If there can be up to four generations of parts contained within one top-levelpart, the following SELECT statement returns all of them:
SELECT a.parent, a.child, b.child, c.child, d.childFROM contains a
OUTER (contains b,OUTER (contains c, outer contains d) )
WHERE a.parent = top_part_numberAND a.child = b.parentAND b.child = c.parentAND c.child = d.parent
This SELECT statement returns one row for each line of descent rooted in thepart given as top_part_number. Null values are returned for levels that donot exist. (Use indicator variables to detect them.) You can extend this solu-tion to more levels by selecting additional nested outer joins of the containstable.You also can revise this solution to return counts of the number of partsat each level.
Dynamic SQLAlthough static SQL is extremely useful, it requires that you know the exactcontent 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 clauseand 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 inadvance. In particular, a program that must respond to an interactive usermight need the ability to compose SQL statements in response to what theuser enters.
SQL: Tutorial
Preparing a Statement
Dynamic SQL allows a program to form an SQL statement during execution,so that the contents of the statement can be determined by user input. This isdone in the following steps:
1. The program assembles the text of an SQL statement as a characterstring, which is stored in a program variable.
2. It executes a PREPARE statement, which asks the database server toexamine the statement text and prepare it for execution.
3. It uses the EXECUTE statement to execute the prepared statement.
In this way, a program can construct and then use any SQL statement, basedon user input of any kind. For example, it can read a file of SQL statementsand prepare and execute each one.
DB-Access, the utility that you use to explore SQL interactively, is anINFORMIX-ESQL/C program that constructs, prepares, and executes SQLstatements dynamically. For example, it enables users to specify the columnsof a table using simple, interactive menus. When the user is finished,DB-Access builds the necessary CREATE TABLE or ALTER TABLE statementdynamically and prepares and executes it.
Preparing a StatementIn form, a dynamic SQL statement is like any other SQL statement that iswritten into a program, except that it cannot contain the names of any hostvariables.
This leads to two restrictions. First, if it is a SELECT statement, it cannotinclude the INTO clause. The INTO clause names host variables into whichcolumn 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 anexpression, a question mark (?) is written as a placeholder.
You can prepare a statement in this form for execution with the PREPAREstatement. The following example is written in INFORMIX-ESQL/C:
EXEC SQL prepare query_2 from'select * from orders
where customer_num = ? andorder_date > ?';
Programming with SQL 5-31
5-32 Informix Guide to
Preparing a Statement
MOVE
TO BIG-
EXEC SQLPREPARE
END-EXEC.
Notice the two question marks in this example; they indicate that when thestatement is executed, the values of host variables are used at those twopoints.
You can prepare almost any SQL statement dynamically. The only ones thatcannot be prepared are the ones directly concerned with dynamic SQL andcursor management, such as the PREPARE and OPEN statements. After youprepare an UPDATE or DELETE statement, it is a good idea to test the fifth fieldof SQLWARN to see if you used a WHERE clause (see“The SQLWARN Array” on page 5-13).
The result of preparing a statement is a data structure that represents thestatement. This data structure is not the same as the string of characters thatproduced 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 theprepared 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-8shows a fairly complex example in INFORMIX-ESQL/COBOL:
When this list of statements is executed, host variables must provide valuesfor six place-holding question marks. Although it is more complicated to setup a multistatement list, the performance is often better because fewerexchanges take place between the program and the database server.
Figure 5-8Preparing a string
containing five SQLstatements
'BEGIN WORK;UPDATE account
SET balance = balance + ?WHERE acct_number = ?;
UPDATE tellerSET balance = balance + ?
WHERE teller_number = ?;UPDATE branch
SET balance = balance + ?WHERE branch_number = ?;
INSERT INTO history VALUES(timestamp, values);'
QUERY.
BIG-Q FROM :BIG-QUERY
SQL: Tutorial
Executing Prepared SQL
EXEC SQL BEGIN Dchar bigquery[27EXEC SQL END DECstcat ("update astcat ("acct_numstcat ("update tstcat ("teller_nstcat ("update bstcat ("branch_nstcat ("insert i
EXEC SQL prepare
EXEC SQL execute:teller_numb
EXEC SQL commit
Executing Prepared SQLOnce a statement is prepared, it can be executed multiple times. Statementsother than SELECT statements, and SELECT statements that return only asingle row, are executed with the EXECUTE statement.
Figure 5-9 shows how INFORMIX-ESQL/C prepares and executes amultistatement update of a bank account:
The USING clause of the EXECUTE statement supplies a list of host variableswhose values are to take the place of the question marks in the preparedstatement. If a SELECT (or an EXECUTE PROCEDURE) returns only one row,you can use the INTO clause of EXECUTE to specify the host variables thatreceive the values.
Figure 5-9Preparing and
executing amultistatement
operation in ESQL/C
ECLARE SECTION;0] = "begin work;";LARE SECTION;ccount set balance = balance + ? where ", bigquery);ber = ?;', bigquery);eller set balance = balance + ? where ", bigquery);umber = ?;', bigquery);ranch set balance = balance + ? where ", bigquery);umber = ?;', bigquery);nto history values(timestamp, values);", bigquery);
bigq from :bigquery;
bigq using :delta, :acct_number, :delta,er, :delta, :branch_number;
work;
Programming with SQL 5-33
5-34 Informix Guide to
Executing Prepared SQL
Using Prepared SELECT Statements
A dynamically prepared SELECT statement cannot simply be executed; itmight produce more than one row of data, and the database server, notknowing which row to return, produces an error code.
Instead, a dynamic SELECT statement is attached to a cursor. Then, the cursoris opened and used in the usual way. The cursor to be used with a preparedstatement is declared for that statement name. The following example is writ-ten in INFORMIX-4GL:
LET select_2 = 'select order_num, order_date from orders ','where customer_num = ? and order_date > ?'
PREPARE q_orders FROM select_2
DECLARE cu_orders CURSOR FOR q_orders
OPEN cu_orders USING q_c_number, q_o_date
FETCH cu_orders INTO f_o_num, f_o_date
The following list identifies the stages of processing in the 4GL example:
1. A character string expressing a SELECT statement is placed in a pro-gram variable. It employs two place-holding question marks.
2. The PREPARE statement converts the string into a data structure thatcan be executed. The data structure is associated with a name,q_orders.
3. A cursor named cu_orders is declared and associated with the nameof the prepared statement.
4. When the cursor is opened, the prepared statement is executed. TheUSING clause in the OPEN statement provides the names of two hostvariables whose contents are substituted for the question marks inthe original statement.
5. The first row of data is fetched from the open cursor. The INTO clauseof the FETCH statement specifies the host variables that are to receivethe fetched column values.
Later, the cursor can be closed and reopened. While the cursor is closed, adifferent SELECT statement can be prepared under the name q_orders. In thisway, a single cursor can be used to fetch from different SELECT statements.
SQL: Tutorial
Dynamic Host Variables
Dynamic Host VariablesIn SQL APIs, which support dynamically allocated data objects, it is possibleto take dynamic statements one step further. It is possible to dynamicallyallocate the host variables that receive column data.
This makes it possible to take an arbitrary SELECT statement from programinput, determine how many values it produces and their data types, andallocate the host variables of the appropriate types to hold them.
The key to this ability is the DESCRIBE statement. It takes the name of aprepared SQL statement and returns information about the statement and itscontents. It sets SQLCODE to specify the type of statement; that is, the verbwith which it begins. If the prepared statement is a SELECT, the DESCRIBEstatement also returns information about the selected output data. If the pre-pared statement is an INSERT, the DESCRIBE statement returns informationabout the input parameters. The data structure is a predefined data structureallocated for this purpose and is known as a system-descriptor area. If youare using INFORMIX-ESQL/C, you can use a system-descriptor area or, as analternative, an sqlda structure.
The data structure that A DESCRIBE statement returns or references for aSELECT statement includes an array of structures. Each structure describesthe data that is returned for one item in the select list. The program can exam-ine the array and discover that a row of data includes a decimal value, acharacter value of a certain length, and an integer.
Using this information, the program can allocate memory to hold theretrieved values and put the necessary pointers in the data structure for thedatabase server to use.
Programming with SQL 5-35
5-36 Informix Guide to
Freeing Prepared Statements
Freeing Prepared StatementsA prepared SQL statement occupies space in memory. With some databaseservers, it can consume space owned by the database server as well as spacebelonging to the program. This space is released when the programterminates, but in general, you should free this space when you finish with it.
You can use the FREE statement to release this space. It takes either the nameof a statement or the name of a cursor that was declared for a statement name,and releases the space allocated to the prepared statement. If more than onecursor is defined on the statement, freeing the statement does not free thecursor.
Quick ExecutionFor simple statements that do not require a cursor or host variables, you cancombine the actions of the PREPARE, EXECUTE, and FREE statements into asingle operation. The EXECUTE IMMEDIATE statement, shown in the follow-ing example, takes a character string, prepares it, executes it, and frees thestorage in one operation.
exec sql execute immediate 'drop index my_temp_index';
This makes it easy to write simple SQL operations. However, because noUSING clause is allowed, the EXECUTE IMMEDIATE statement cannot be usedfor SELECT statements.
Embedding Data Definition StatementsData definition statements, the SQL statements that create databases andmodify the definitions of tables, are not usually put into programs. Thereason is that they are rarely performed—a database is created once, but isqueried and updated many times.
The creation of a database and its tables is generally done interactively, usingDB-Access or INFORMIX-SQL. These tools can also be driven from a file ofstatements, so that the creation of a database can be done with one operatingsystem command.
SQL: Tutorial
Embedding Grant and Revoke Privileges
Embedding Grant and Revoke PrivilegesOne task related to data definition is done repeatedly: the granting andrevoking of privileges. The reasons for this are discussed in Chapter 10,“Granting and Limiting Access to Your Database.” Because privileges mustbe granted and revoked frequently, and because this might be done by per-sons who are not skilled in SQL, it can be useful to package the GRANT andREVOKE statements in programs to give them a simpler, more convenientuser interface.
The GRANT and REVOKE statements are especially good candidates fordynamic 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 programinput (from the user, command-line parameters, or a file) but none can besupplied in the form of a host variable. The syntax of these statements doesnot allow host variables at any point.
The only alternative is to assemble the parts of a statement into a characterstring, and prepare and execute the assembled statement. Program input canbe incorporated into the prepared statement as characters.
Programming with SQL 5-37
5-38 Informix Guide to
Embedding Grant and Revoke Privileges
FUNCTION taDEFINE
LET gra
WHENEVEPREPAREIF stat
EXEEND IFIF stat DISPLA DISPLAEND IFWHENEVEFREE th
END FUNCTIO
Figure 5-10 shows a function in INFORMIX-4GL that assembles a GRANTstatement from the function parameters, and then prepares and executes it.
The opening statement, shown in the following example, defines the name ofthe function and the names of its three parameters:
FUNCTION table_grant (priv_to_grant, table_name, user_id)
The DEFINE statement, shown in the following example, defines theparameters and one additional variable local to the function. All four arecharacter strings of various lengths.
DEFINE priv_to_grant char(100),table_name char(20),user_id char(20),grant_stmt char(200)
The variable grant_stmt holds the assembled GRANT statement, which iscreated by concatenating the parameters and some constants. This is shownin the following example:
LET grant_stmt ='GRANT ', priv_to_grant,' ON ', table_name,' TO ', user_id
Figure 5-10A 4GL function that
builds, prepares,and executes a
GRANT statement
ble_grant (priv_to_grant, table_name, user_id)priv_to_grant char(100),table_name char(20),user_id char(20),grant_stmt char(200)
nt_stmt =' GRANT ', priv_to_grant,' ON ', table_name,' TO ', user_id
R ERROR CONTINUE the_grant FROM grant_stmtus = 0 THENCUTE the_grant
us <> 0 THENY 'Sorry, got error #', status, 'attempting:'Y ' ',grant_stmt
R ERROR STOPe_grantN
SQL: Tutorial
Embedding Grant and Revoke Privileges
This assignment statement uses the comma as a list delimiter to concatenatethe following six character strings:
■ 'GRANT'
■ The parameter specifying the privileges to be granted
■ 'ON'
■ The parameter specifying the table name
■ 'TO'
■ The parameter specifying the user.
The result is a complete GRANT statement composed partly of programinput. The same feat can be accomplished in other host languages usingdifferent syntax, as shown in the following figure:
WHENEVER ERROR CONTINUEPREPARE the_grant FROM grant_stmt
If the database server returns an error code in SQLCODE, the default action ofan INFORMIX-4GL program is to terminate. However, errors are quite likelywhen you prepare an SQL statement composed of user-supplied parts, andprogram termination is a poor way to diagnose the error. In the precedingcode, the WHENEVER statement prevents termination. Then the PREPAREstatement passes the assembled statement text to the database server forparsing.
If the database server approves the form of the statement, it sets a zero returncode. This does not guarantee that the statement is executed properly; itmeans only that the statement has correct syntax. It might refer to a nonexist-ent table or contain many other kinds of errors that can be detected onlyduring execution. The following portion of the example in Figure 5-10 checksthat the_grant was prepared successfully before executing it.
IF status = 0 THENEXECUTE the_grant
END IF
If the preparation is successful, the next step is to execute the preparedstatement. The function in Figure 5-10 on page 5-38 displays an error mes-sage if anything goes wrong. As written, it makes no distinction between anerror from the PREPARE operation and one from the EXECUTE operation. Itdoes not attempt to interpret the numeric error code, leaving it to the user tointerpret.
Programming with SQL 5-39
5-40 Informix Guide to
Summary
SummarySQL statements can be written into programs as if they were normalstatements of the programming language. Program variables can be used inWHERE clauses, and data from the database can be fetched into them. Apreprocessor translates the SQL code into procedure calls and data structures.
Statements that do not return data, or queries that return only one row ofdata, 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 fetcheach row of data as it is needed.
Static SQL statements are written into the text of the program. However, theprogram can form new SQL statements dynamically, as it runs, and executethem also. In the most advanced cases, the program can obtain informationabout the number and types of columns that a query returns anddynamically allocate the memory space to hold them.
SQL: Tutorial
6Chapter
Modifying Data Through SQLPrograms
Using DELETE . . . . . . . . . . . . . . . . . . . . 6- 3Direct Deletions . . . . . . . . . . . . . . . . . . 6- 4
Errors During Direct Deletions . . . . . . . . . . . . 6- 4Using Transaction Logging . . . . . . . . . . . . . 6- 5Coordinated Deletions . . . . . . . . . . . . . . . 6- 6
Deleting with a Cursor . . . . . . . . . . . . . . . . 6- 7
Using INSERT . . . . . . . . . . . . . . . . . . . . 6- 9Using an Insert Cursor . . . . . . . . . . . . . . . . 6- 9
Declaring an Insert Cursor . . . . . . . . . . . . . 6- 9Inserting with a Cursor. . . . . . . . . . . . . . . 6- 10Status Codes After PUT and FLUSH . . . . . . . . . . 6- 11
Rows of Constants. . . . . . . . . . . . . . . . . . 6- 12An Insert Example. . . . . . . . . . . . . . . . . . 6- 12
Using UPDATE . . . . . . . . . . . . . . . . . . . . 6- 15Using an Update Cursor . . . . . . . . . . . . . . . 6- 15
The Purpose of the Keyword UPDATE . . . . . . . . . 6- 16Updating Specific Columns . . . . . . . . . . . . . 6- 16UPDATE Keyword Not Always Needed. . . . . . . . . 6- 16
Cleaning up a Table . . . . . . . . . . . . . . . . . 6- 17
Summary . . . . . . . . . . . . . . . . . . . . . . 6- 18
6-2 Infor
mix Guide to SQL: TutorialThe 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 thedatabase by deleting, inserting, or updating rows. As in Chapter 5, “Pro-gramming with SQL,” this chapter aims to prepare you for reading themanual for your Informix ESQL, NewEra, or 4GL product.
The general use of the INSERT, UPDATE, and DELETE statements is covered inChapter 4, “Modifying Data.” This chapter examines their use from within aprogram. It is quite easy to put the statements in a program, but it can bequite difficult to handle errors and to deal with concurrent modificationsfrom multiple programs.
Using DELETEA program deletes rows from a table by executing a DELETE statement. TheDELETE 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 tablesdepend on the deleted rows. This problem of coordinated deletions is cov-ered in Chapter 4, “Modifying Data.” The problem is the same whendeletions are made from within a program.
Modifying Data Through SQL Programs 6-3
6-4 Informix Guide to S
Direct Deletions
Direct DeletionsYou can embed a DELETE statement in a program. The following exampleuses INFORMIX-ESQL/C:
EXEC SQL delete from itemswhere order_num = :onum;
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 ormore rows.
The WHERE clause in the example uses the value of a host variable namedonum. Following the operation, results are posted in the SQLSTATE and inSQLCA, as usual. The third element of the SQLERRD array contains the countof rows deleted even if an error occurs. The value in SQLCODE shows theoverall success of the operation. If it is not negative, no errors occurred andthe third element of SQLERRD is the count of all rows that satisfied theWHERE clause and were deleted.
Errors During Direct Deletions
When an error occurs, the statement ends prematurely. The values inSQLSTATE and in SQLCODE and the second element of SQLERRD explain itscause, and the count of rows reveals how many rows were deleted. For manyerrors, that count is zero because they prevented the database server frombeginning the operation. For example, if the named table does not exist or ifa column tested in the WHERE clause is renamed, no deletions are attempted.
However, certain errors can be discovered after the operation begins andsome rows are processed. The most common of these errors is a lock conflict.The database server must obtain an exclusive lock on a row before it candelete that row. Other programs might be using the rows from the table, pre-venting the database server from locking a row. Because the issue of lockingaffects all types of modifications, it is discussed Chapter 7, “Programming fora Multiuser Environment.”
Other, rarer types of errors can strike after deletions begin, for example,hardware errors that occur while the database is being updated.
QL: Tutorial
Direct Deletions
Using Transaction Logging
The best way to prepare for any kind of error during a modification is to usetransaction logging. In the event of an error, you can tell the database serverto put the database back the way it was. The following example is based onthe example in “Direct Deletions” on page 6-4, which is extended to usetransactions:
EXEC SQL begin work;/* start the transaction*/EXEC SQL delete from items
where order_num = :onum;del_result = sqlca.sqlcode;/* save two error */del_isamno = sqlca.sqlerrd[1];/* ...code numbers */del_rowcnt = sqlca.sqlerrd[2];/* ...and count of rows */if (del_result < 0)/* some problem, */
EXEC SQL rollback work;/* ...put everything back */else /* everything worked OK, */
EXEC SQL commit work;/* ...finish transaction */
An important point in this example is that the program saves the importantreturn values in the sqlca structure before it ends the transaction. The reasonis that both the ROLLBACK WORK and COMMIT WORK statements, as withall SQL statements, set return codes in the sqlca structure. Executing aROLLBACK WORK statement after an error wipes out the error code; unless itwas saved, it cannot be reported to the user.
The advantage of using transactions is that the database is left in a known,predictable state no matter what goes wrong. No question remains abouthow much of the modification is completed; either all of it is or none of it is.
Modifying Data Through SQL Programs 6-5
6-6 Informix Guide to S
Direct Deletions
WHENEVER EBEGIN WORKDELETE FRO
WHERE IF (status
DELETEWH
END IFIF (status
COMMITELSE
DISPLAROLLBA
END IF
Coordinated Deletions
The usefulness of transaction logging is particularly clear when you mustmodify more than one table. For example, consider the problem of deletingan 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 theINFORMIX-4GL example in Figure 6-1.
The logic of this program is much the same regardless if transactions areused. If they are not used, the person who sees the error message has a muchmore difficult set of decisions to make. Depending on when the erroroccurred, one of the following situations applies:
■ No deletions were performed; all rows with this order numberremain in the database.
■ Some, but not all, item rows were deleted; an order record with onlysome 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; itcontains partial information that can cause some queries to produce wronganswers. You must take careful action to restore consistency to theinformation. When transactions are used, all these uncertainties areprevented.
Figure 6-1A fragment of 4GL
that deletes fromtwo tables
RROR CONTINUE{do not terminate on error}{start transaction}
M itemsorder_num = o_num >= 0) THEN {no error on first delete} FROM ordersERE order_num = o_num
>= 0) THEN {no error on either delete} WORK
{problem on some delete}Y 'Error ', status,' deleting.'CK WORK
QL: Tutorial
Deleting with a Cursor
int delDupO{
int ordint dup
EXEC SQsel
EXEC SQif (sql
retexec sqfor(;;){
EXEif dupEXE
if {
}}ret_codif (ret
EXEelse
EXEreturn
}
Deleting with a CursorYou can also write a DELETE statement through a cursor to delete the row thatwas last fetched. This lets you program deletions based on conditions thatcannot be tested in a WHERE clause, as shown in Figure 6-2.
Warning: The design of the ESQL/C function in Figure 6-2 is unsafe. It depends onthe current isolation level for correct operation. Depending on isolation level is laterin the chapter. Even when it works as intended, its effects depend on the physicalorder of rows in the table, which is not generally a good idea.
Figure 6-2An unsafe ESQL/C
function that deletesthrough a cursor
rder()
_num;_cnt, ret_code;
L declare scan_ord cursor forect order_num, order_dateinto :ord_num, :ord_datefrom orders for update;
L open scan_ord;ca.sqlcode != 0)urn (sqlca.sqlcode);l begin work;
C SQL fetch next scan_ord;(sqlca.sqlcode != 0) break;_cnt = 0; /* default in case of error */C SQL select count(*) into dup_cnt from orderswhere order_num = :ord_num;
(dup_cnt > 1)
EXEC SQL delete where current of scan_ord;if (sqlca.sqlcode != 0)
break;
e = sqlca.sqlcode;_code == 100) /* merely end of data */C SQL commit work;/* error on fetch or on delete */
C SQL rollback work;(ret_code);
Modifying Data Through SQL Programs 6-7
6-8 Informix Guide to S
Deleting with a Cursor
The purpose of the function is to delete rows containing duplicate ordernumbers. In fact, in the demonstration database, the orders.order_numcolumn has a unique index, so duplicate rows cannot occur in it. However, asimilar function can be written for another database; this one uses familiarcolumn names.
The function declares scan_ord, a cursor to scan all rows in the orders table.It is declared with the FOR UPDATE clause, which states that the cursor canmodify data. If the cursor opens properly, the function begins a transactionand then loops over rows of the table. For each row, it uses an embeddedSELECT statement to determine how many rows of the table have the ordernumber of the current row. (This step fails without the correct isolation level,as described in Chapter 7, “Programming for a Multiuser Environment.”)
In the demonstration database, with its unique index on this table, the countreturned to dup_cnt is always one. However, if it is greater, the functiondeletes the current row of the table, reducing the count of duplicates by one.
Clean-up functions of this sort are sometimes needed, but they generallyneed more sophisticated design. This one deletes all duplicate rows exceptthe last one delivered by the database server. That ordering has nothing to dowith the contents of the rows or their meanings. You can improve the func-tion in Figure 6-2 on page 6-7 by adding, perhaps, an ORDER BY clause to thecursor declaration. However, you cannot use ORDER BY and FOR UPDATEtogether. A better approach is sketched in “An Insert Example” on page 6-12.
QL: Tutorial
Using INSERT
DEFINE the_the_fnathe_lna
DECLARE newINSERT
VAL
Using INSERTYou can embed the INSERT statement in programs. Its form and use in aprogram are the same as described in Chapter 4, “Modifying Data,” with theadditional feature that you can use host variables in expressions, both in theVALUES and WHERE clauses. Moreover, a program has the additional abilityto insert rows using a cursor.
Using an Insert CursorThe DECLARE CURSOR statement has many variations. Most are used tocreate cursors for different kinds of scans over data, but one variation createsa special kind of cursor called an insert cursor. You use an insert cursor withthe PUT and FLUSH statements to efficiently insert rows into a table in bulk.
Declaring an Insert Cursor
You create an insert cursor by declaring a cursor to be for an INSERTstatement instead of a SELECT statement. You cannot use such a cursor tofetch rows of data; you can use it only to insert them. An example of thedeclaration of an insert cursor is shown in Figure 6-3.
When you open an insert cursor, a buffer is created in memory to hold a blockof rows. The buffer receives rows of data as the program produces them; thenthey are passed to the database server in a block when the buffer is full. Thisreduces 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.
Figure 6-3A 4GL fragment that
declares an insertcursor
company LIKE customer.company,me LIKE customer.fname,me LIKE customer.lname_custs CURSOR FORINTO customer (company, fname, lname)UES (the_company, the_fname, the_lname)
Modifying Data Through SQL Programs 6-9
6-10 Informix Guide to
Using an Insert Cursor
WHENEVER ERROR BEGIN WORKOPEN new_custsWHILE status =
CALL next_cuIF the_comp
EXIT WHIEND IFPUT new_cus
END WHILEIF status = 0 T
FLUSH new_cEND IFIF status = 0 T
COMMIT WORKELSE
ROLLBACK WOEND IF
The minimum size of the insert buffer is set for any implementation ofembedded 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 insertedvalues. It is large enough to hold more than two rows when the rows areshorter than the minimum buffer size.
Inserting with a Cursor
The code in Figure 6-3 on page 6-9 prepares an insert cursor for use. Thecontinuation, shown in Figure 6-4, shows how the cursor can be used. Forsimplicity, this example assumes that a function named next_cust returnseither information about a new customer or null data to signal the end ofinput.
The code in Figure 6-4 calls next_cust repeatedly. When it returns non-nulldata, the PUT statement sends the returned data to the row buffer. When thebuffer 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 theFLUSH statement writes any rows that remain in the buffer, after which thetransaction terminates.
Figure 6-4Continuing , the 4GL
code that uses theinsert cursor
CONTINUE{do not terminate on error}
0st() RETURNING the_company,the_fname,the_lnameany IS NULL THENLE
ts
HEN {no problem in a PUT}usts {write any last rows}
HEN {no problem writing} {..make it permanent}
RK {retract any changes}
SQL: Tutorial
Using an Insert Cursor
Examine the INSERT statement in Figure 6-3 on page 6-9 once more. Thestatement by itself, not part of a cursor definition, inserts a single row into thecustomer table. In fact, the whole apparatus of the insert cursor can bedropped from the example code, and the INSERT statement can be writteninto Figure 6-4 on page 6-10 where the PUT statement now stands. The differ-ence is that an insert cursor causes a program to run somewhat faster.
Status Codes After PUT and FLUSH
When a program executes a PUT statement, the program should test whetherthe row is placed in the buffer successfully. If the new row fits in the buffer,the only action of PUT is to copy the row to the buffer. No errors can occur inthis case. However, if the row does not fit, the entire buffer load is passed tothe database server for insertion, and an error can occur.
The values returned into the SQL Communications Area ( SQLCA) give theprogram the information it needs to sort out each case. SQLCODE andSQLSTATE are set after every PUT statement—to zero if no error occurs and toa negative error code if an error occurs.
The third element of SQLERRD is set to the number of rows actually insertedinto the table: It is set to zero if the new row is merely moved to the buffer; tothe count of rows that are in the buffer, if the buffer load is inserted withouterror; or to the count of rows inserted before an error occurs, if one doesoccur.
Read the code once again to see how SQLCODE is used (see Figure 6-4 onpage 6-10). First, if the OPEN statement yields an error, the loop is not exe-cuted because the WHILE condition fails, the FLUSH operation is notperformed, and the transaction rolls back.
Second, if the PUT statement returns an error, the loop ends because of theWHILE condition, the FLUSH operation is not performed, and the transactionrolls back. This can occur only if the loop generates enough rows to fill thebuffer at least once; otherwise, the PUT statement cannot generate an error.
The program might end the loop with rows still in the buffer, possiblywithout inserting any rows. At this point, the SQL status is zero, and theFLUSH operation occurs. If the FLUSH operation produces an error code, thetransaction rolls back. Only when all inserts are successfully performed is thetransaction committed.
Modifying Data Through SQL Programs 6-11
6-12 Informix Guide to
Rows of Constants
Rows of ConstantsThe insert cursor mechanism supports one special case where highperformance is easy to obtain. This is the case in which all the values listed inthe INSERT statement are constants—no expressions and no host variables,just literal numbers and strings of characters. No matter how many timessuch an INSERT operation occurs, the rows it produces are identical. In thatcase, there is no point in copying, buffering, and transmitting each identicalrow.
Instead, for this kind of INSERT operation, the PUT statement does nothingexcept 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 databaseserver. The database server creates and inserts that many rows in oneoperation.
It is not common to insert a quantity of identical rows. You can do it whenyou 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 DELETEstatement 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 ofdeleting the undesired ones. The code in Figure 6-5 on page 6-13 shows oneway to do this. The example is written in INFORMIX-4GL to take advantage ofsome features that make SQL programming easy.
SQL: Tutorial
An Insert Example
BEGIN WORKINSERT INTO new_
SELECT * FROWHERE 1 =
COMMIT WORK
DEFINE ord_row Rlast_ord LIK
DECLARE dup_row SELECT * FRO
WHERE 1 <
ORDER BY DECLARE ins_row
INSERT INTO
BEGIN WORKOPEN ins_rowLET last_ord = -FOREACH dup_row
IF ord_row.oPUT ins_rLET last_
END IFEND FOREACHCLOSE ins_rowCOMMIT WORK
This example begins with an ordinary INSERT statement, which finds all thenonduplicated 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 uniqueindex and cannot have duplicate rows. This example deals with some otherdatabase.)
In NewEra and INFORMIX-4GL, you can define a data structure like a table; thestructure is automatically given one element for each column in the table. Theord_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 usethe ORDER BY clause to impose some order on the duplicates other than thephysical record order used in Figure 6-2 on page 6-7. In this example, theduplicate rows are ordered by their dates (the oldest one remains), but youcan use any other order based on the data.
Figure 6-5A 4GL program that
re-creates a tablewithout duplicates
ordersM ORDERS main (SELECT COUNT(*) FROM ORDERS minor
WHERE main.order_num = minor.order_num)
ECORD LIKE orders,E orders.order_numCURSOR FORM ORDERS main INTO ord_row.* (SELECT COUNT(*) FROM ORDERS minor
WHERE main.order_num = minor.order_num)order_dateCURSOR FORnew_orders VALUES (ord_row.*)
1
rder_num <> last_ord THENoword = ord_row.order_num
Modifying Data Through SQL Programs 6-13
6-14 Informix Guide to
An Insert Example
The second cursor is an insert cursor. It is written to take advantage of theasterisk (*) notation of INFORMIX-4GL; you can supply values for all columnssimply by naming a record with an asterisk to indicate all fields.
The remainder of the code examines the rows returned through dup_row. Itinserts the first one from each group of duplicates into the new table anddisregards the rest.
This example uses the simplest kind of error handling. Unless told otherwise,an INFORMIX-4GL program automatically terminates when an error code isset in SQLCODE. In this event, the active transaction rolls back. This programrelies on that behavior; it assumes that if it reaches the end, no errors exist andthe transaction can be committed. This kind of error handling is acceptablewhen errors are unlikely, and the program is used by people who do not needto know why the program terminates.
How Many Rows Were Affected?
When your program uses a cursor to select rows, it can test SQLCODE for 100(or SQLSTATE for 02000), the end-of-data return code. This is set to indicatethat no rows, or no more rows, satisfy the query conditions. For databasesthat are not ANSI-compliant, the end-of-data return code is set in SQLCODEor SQLSTATE only following SELECT statements; it is not used followingDELETE, INSERT, or UPDATE statements. For ANSI-compliant databases,SQLCODE is also set to 100 for updates, deletes, and inserts that affect zerorows.
A query that finds no data is not a success. However, an UPDATE or DELETEstatement that happens to update or delete no rows is still considered asuccess: It updated or deleted the set of rows that its WHERE clause said itshould; however, the set was empty.
In the same way, the INSERT statement does not set the end-of-data returncode even when the source of the inserted rows is a SELECT statement and itselected no rows. The INSERT statement is a success because it inserted asmany rows as it was asked to do (that is, zero).
To find out how many rows are inserted, updated, or deleted, a program cantest the third element of SQLERRD. The count of rows is there, regardless ofthe value (zero or negative) in SQLCODE.
SQL: Tutorial
Using UPDATE
Using UPDATEYou can embed the UPDATE statement in a program in any of the formsdescribed in Chapter 4, “Modifying Data,” with the additional feature thatyou can name host variables in expressions, both in the SET and WHEREclauses. Moreover, a program can update the row addressed by a cursor.
Using an Update CursorAn update cursor permits you to delete or update the current row; that is, themost recently fetched row. The following example (inINFORMIX-ESQL/COBOL) shows the declaration of an update cursor:
EXEC SQLDECLARE names CURSOR FOR
SELECT fname, lname, companyFROM customer
FOR UPDATEEND-EXEC.
The program that uses this cursor can fetch rows in the usual way.
EXEC SQLFETCH names INTO :FNAME, :LNAME, :COMPANY
END-EXEC.
If the program then decides that the row needs to be changed, it can do so.
IF COMPANY IS EQUAL TO 'SONY'EXEC SQL
UPDATE customerSET fname = 'Midori', lname = 'Tokugawa'WHERE CURRENT OF names
END-EXEC.
The words CURRENT OF names take the place of the usual test expressions inthe WHERE clause. In other respects, the UPDATE statement is the same asusual—even including the specification of the table name, which is implicitin the cursor name but still required.
Modifying Data Through SQL Programs 6-15
6-16 Informix Guide to
Using an Update Cursor
The Purpose of the Keyword UPDATE
The purpose of the keyword UPDATE in a cursor is to let the database serverknow that the program can update (or delete) any row that it fetches. Thedatabase server places a more demanding lock on rows that are fetchedthrough an update cursor and a less demanding lock when fetching a row fora cursor that is not declared with that keyword. This results in better perfor-mance for ordinary cursors and a higher level of concurrent use in amultiprocessing system. (Levels of locks and concurrent use are discussed inChapter 7, “Programming for a Multiuser Environment.”)
Updating Specific Columns
The following example has updated specific columns of the preceedingexample of an update cursor:
EXEC SQLDECLARE names CURSOR FOR
SELECT fname, lname, company, phoneINTO :FNAME,:LNAME,:COMPANY,:PHONE FROM customer
FOR UPDATE OF fname, lnameEND-EXEC.
Only the fname and lname columns can be updated through this cursor. Astatement such as the following one is rejected as an error:
EXEC SQLUPDATE customer
SET company = 'Siemens'WHERE CURRENT OF names
END-EXEC.
If the program attempts such an update, an error code is returned and noupdate occurs. An attempt to delete using WHERE CURRENT OF is alsorejected because deletion affects all columns.
UPDATE Keyword Not Always Needed
The ANSI standard for SQL does not provide for the FOR UPDATE clause in acursor definition. When a program uses an ANSI-compliant database, it canupdate or delete using any cursor.
SQL: Tutorial
Cleaning up a Table
EXEC SQL BEchar dcol[8short dcoliint sequencEXEC SQL EN
EXEC SQL DESELECT
INTFRO
FOR UPDEXEC SQL BEEXEC SQL OPif (sqlca.sfor(sequenc{
if (dcoEXE
elseEXE
}if (sqlca.s
EXEC SQLelse EXEC S
Cleaning up a TableA final, hypothetical example of using an update cursor presents a problemthat should never arise with an established database but could arise in theinitial design phases of an application.
A large table, named target, for example, is created and populated. Acharacter column, datcol, inadvertently acquires some null values. Theserows should be deleted. Furthermore, a new column, serials, is added to thetable with the ALTER TABLE statement. This column is to have unique integervalues installed. Figure 6-6 shows the INFORMIX-ESQL/C code needed toaccomplish these things.
Figure 6-6Cleaning up a table
using an updatecursor
GIN DECLARE SECTION;0];nt;e;D DECLARE SECTION;
CLARE target_row CURSOR FORdatcolO :dcol:dcolintM targetATE OF serials;GIN WORK;EN target_row;qlcode == 0) EXEC SQL FETCH NEXT target_row;e = 1; sqlca.sqlcode == 0; ++sequence)
lint < 0) /* null datcol */C SQL DELETE WHERE CURRENT OF target_row;
C SQL UPDATE target SET serials = :sequenceWHERE CURRENT OF target_row;
qlcode >= 0) COMMIT WORK;QL ROLLBACK WORK;
Modifying Data Through SQL Programs 6-17
6-18 Informix Guide to
Summary
SummaryA program can execute the INSERT, DELETE, and UPDATE statements asdescribed in Chapter 4, “Modifying Data.” A program also can scan througha table with a cursor, updating or deleting selected rows. It also can use acursor to insert rows, with the benefit that the rows are buffered and sent tothe database server in blocks.
In all these activities, you must make sure that the program detects errors andreturns the database to a known state when an error occurs. The most impor-tant tool for doing this is the transaction. Without transaction logging, it ismore difficult to write the program so that it can recover from errors.
SQL: Tutorial
7Chapter
Programming for a MultiuserEnvironment
Concurrency and Performance . . . . . . . . . . . . . . . 7-3
Locking and Integrity . . . . . . . . . . . . . . . . . . 7-3
Locking and Performance . . . . . . . . . . . . . . . . 7-4
Concurrency Issues. . . . . . . . . . . . . . . . . . . 7-4
How Locks Work . . . . . . . . . . . . . . . . . . . 7-6Kinds of Locks . . . . . . . . . . . . . . . . . . . 7-6Lock Scope . . . . . . . . . . . . . . . . . . . . 7-7
Database Locks . . . . . . . . . . . . . . . . . 7-7Table Locks . . . . . . . . . . . . . . . . . . . 7-8Page, Row, and Key Locks. . . . . . . . . . . . . . 7-9
The Duration of a Lock . . . . . . . . . . . . . . . . 7-9Locks While Modifying . . . . . . . . . . . . . . . . 7-10
Setting the Isolation Level . . . . . . . . . . . . . . . . 7-11Comparing SET TRANSACTION with SET ISOLATION . . . . 7-11ANSI Read Uncommitted and Informix Dirty Read Isolation . . . 7-12ANSI Read Committed and Informix Committed Read Isolation. . 7-13Informix Cursor Stability Isolation . . . . . . . . . . . . 7-13ANSI Serializable, ANSI Repeatable Read and Informix Repeatable Read
Isolation . . . . . . . . . . . . . . . . . . . . 7-15
Controlling Data Modification with Access Modes . . . . . . . . 7-16
Setting the Lock Mode. . . . . . . . . . . . . . . . . . 7-17Waiting for Locks . . . . . . . . . . . . . . . . . . 7-17Not Waiting for Locks . . . . . . . . . . . . . . . . 7-17Waiting a Limited Time . . . . . . . . . . . . . . . . 7-18Handling a Deadlock . . . . . . . . . . . . . . . . . 7-18Handling External Deadlock . . . . . . . . . . . . . . 7-19
7-2 Infor
Simple Concurrency . . . . . . . . . . . . . . . . . . 7-19
Locking with Other Database Servers . . . . . . . . . . . . 7-20Isolation While Reading . . . . . . . . . . . . . . . . 7-21Locking Updated Rows . . . . . . . . . . . . . . . . 7-21
Hold Cursors . . . . . . . . . . . . . . . . . . . . . 7-22
Summary . . . . . . . . . . . . . . . . . . . . . . 7-23
mix Guide to SQL: Tutorial
If your database is contained in a single-user workstation and is notconnected on a network to other computers, your programs can modify datafreely. But in all other cases, you must allow for the possibility that, whileyour program is modifying data, another program is reading or modifyingthe same data. This is concurrency: two or more independent uses of the samedata at the same time. This chapter addresses concurrency, locking, andisolation levels.
Concurrency and PerformanceConcurrency is crucial to good performance in a multiprogramming system.When access to the data is serialized so that only one program at a time canuse it, processing slows dramatically.
Locking and IntegrityUnless controls are placed on the use of data, concurrency can lead to avariety of negative effects. Programs can read obsolete data or modificationscan be lost even though they were apparently completed.
The database server prevents errors of this kind by imposing a system oflocks. A lock is a claim, or reservation, that a program can place on a piece ofdata. The database server guarantees that, as long as the data is locked, noother program can modify it. When another program requests the data, thedatabase server either makes the program wait or turns it back with an error.
Programming for a Multiuser Environment 7-3
7-4 Informix Guide to S
Locking and Performance
Locking and PerformanceBecause a lock serializes access to one piece of data, it reduces concurrency;any other programs that want access to that data must wait. The databaseserver can place a lock on a single row, a disk page (which holds multiplerows), a whole table, or an entire database. The more locks it places and thelarger the objects it locks, the more concurrency is reduced. The fewer thelocks and the smaller the locked objects, the greater concurrency and perfor-mance can be.
This section discusses how a program can achieve the following goals:
■ To place all the locks needed to ensure data integrity
■ To lock the fewest, smallest pieces of data possible consistent withthe preceding goal
Concurrency IssuesTo understand the hazards of concurrency, you must think in terms ofmultiple programs, each executing at its own speed. Suppose that yourprogram is fetching rows through the following cursor:
DECLARE sto_curse CURSOR FORSELECT * FROM stock
WHERE manu_code = 'ANZ'
The transfer of each row from the database server to the program takes time.During and between transfers, other programs can perform other databaseoperations. Say that at about the same time your program fetches the rowsproduced by that query, another user’s program executes the followingupdate:
UPDATE stockSET unit_price = 1.15 * unit_price
WHERE manu_code = 'ANZ'
QL: Tutorial
Concurrency Issues
In other words, both programs are reading through the same table, onefetching certain rows and the other changing the same rows. The followingpossibilities are concerned with what happens next:
1. The other program finishes its update before your program fetchesits first row.
Your program shows you only updated rows.
2. Your program fetches every row before the other program has achance to update it.
Your program shows you only original rows.
3. After your program fetches some original rows, the other programcatches up and goes on to update some rows that your program hasyet to read; then it executes the COMMIT WORK statement.
Your program might return a mixture of original rows and updatedrows.
4. Same as number 3, except that after updating the table, the other pro-gram issues a ROLLBACK WORK statement.
Your program can show you a mixture of original rows and updatedrows that no longer exist in the database.
The first two possibilities are harmless. In number 1, the update is completebefore your query begins. It makes no difference whether it finished amicrosecond or a week ago.
In number 2, your query is, in effect, complete before the update begins. Theother program might have been working just one row behind yours, or itmight not start until tomorrow night; it does not matter.
The second pair of chances, however, can be very important to the design ofsome 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, forinstance, 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.
Programming for a Multiuser Environment 7-5
7-6 Informix Guide to S
How Locks Work
Another concern arises when your program uses a cursor to update or deletethe last-fetched row. Erroneous results occur with the following sequence ofevents:
■ 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 isolationlevel features of the database server.
How Locks WorkThe INFORMIX-OnLine Dynamic Server database server supports a complex,flexible set of locking features that is described in this section. Some of theselocking features work differently on an INFORMIX-SE database server. (SeeChapter 1 of the Informix Guide to SQL: Reference for a summary of thedifferences between locking in SE and OnLine database servers.)
Kinds of LocksINFORMIX-OnLine Dynamic Server supports the following kinds of locks,which it uses in different situations:
shared A shared lock reserves its object for reading only. It pre-vents the object from changing while the lock remains.More than one program can place a shared lock on thesame object.
exclusive An exclusive lock reserves its object for the use of a singleprogram. It is used when the program intends to changethe object.
An exclusive lock cannot be placed where any other kindof lock exists. Once one has been placed, no other lock canbe placed on the same object.
QL: Tutorial
Lock Scope
promotable A promotable lock establishes the intent to update. It canonly be placed where no other promotable or exclusivelock exists. Promotable locks can be placed on recordsthat already have shared locks. When the program isabout to change the locked object, the promotable lockcan be ‘promoted’ to an exclusive lock, but only if thereare no other locks, including shared locks on the record atthe time the lock would change from promotable to exclu-sive. If a shared lock was on the record when the promot-able lock was set, the shared lock must be dropped beforethe promotable lock can be promoted to an exclusive lock.
Lock ScopeYou 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 thescope of the lock (also called the lock granularity). In general, the larger thescope of a lock, the more concurrency is reduced but the simplerprogramming becomes.
Database Locks
You can lock an entire database. The act of opening a database places a sharedlock on the name of the database. A database is opened with the CONNECT,DATABASE, or CREATE DATABASE statements. As long as a program has adatabase open, the shared lock on the name prevents any other program fromdropping the database or putting an exclusive lock on it.
You can lock an entire database exclusively with the following statement:
DATABASE database name EXCLUSIVE
This statement succeeds if no other program has opened that database. Oncethe lock is placed, no other program can open the database, even for readingbecause 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 doneexplicitly with the DISCONNECT or CLOSE DATABASE statements orimplicitly by executing another DATABASE statement.
Programming for a Multiuser Environment 7-7
7-8 Informix Guide to S
Lock Scope
Because locking a database reduces concurrency in that database to zero, itmakes 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 dataduring 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 itperforms 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. Thisstatement allows you to place either a shared lock or an exclusive lock on anentire table.
A shared table lock prevents any concurrent updating of that table whileyour program is reading from it. INFORMIX-OnLine Dynamic Server achievesthe same degree of protection by setting the isolation level, as described in thenext section, which allows greater concurrency than using a shared tablelock. However, all Informix database servers support the LOCK TABLEstatement.
An exclusive table lock prevents any concurrent use of the table. This has aserious effect on performance if many other programs are contending for theuse of the table. As with an exclusive database lock, an exclusive table lock isoften used when massive updates are applied during off-peak hours. Forexample, some applications do not update tables during the hours of peakuse. Instead, they write updates to an update journal. During off-peak hours,that journal is read and all updates are applied in a batch.
QL: Tutorial
The Duration of a Lock
Page, Row, and Key Locks
One row of a table is the smallest object that can be locked. A program canlock one row or a selection of rows while other programs continue to workon other rows of the same table.
INFORMIX-OnLine Dynamic Server stores data in units called disk pages. (Itsdisk-storage methods are described in detail in the INFORMIX-OnLineDynamic Server Administrator’s Guide. Tips for optimizing tables on disk stor-age can be found in the INFORMIX-OnLine Dynamic Server PerformanceGuide.) A disk page contains one or more rows. In some cases, it is better tolock a disk page than to lock individual rows on it.
You choose between locking by rows or locking by pages when you create thetable. INFORMIX-OnLine Dynamic Server supports a clause, LOCK MODE, tospecify either page or row locking. You can specify lock mode in the CREATETABLE statement and later change it with the ALTER TABLE statement. (OtherInformix database servers do not offer the choice; they lock by row or bypage, whichever makes the better implementation.)
Page and row locking are used identically. Whenever INFORMIX-OnLineDynamic Server needs to lock a row, it locks either the row itself or the pageit is on, depending on the lock mode established for the table.
In certain cases, the database server has to lock a row that does not exist—ineffect, it locks the place in the table where the row would be if it did exist. Thedatabase server does this by placing a lock on an index-key value. Key locksare used identically to row locks. When the table uses row locking, key locksare implemented as locks on imaginary rows. When it uses page locking, akey lock is placed on the index page that contains the key or that wouldcontain the key if it existed.
The Duration of a LockThe program controls the duration of a database lock. A database lock isreleased when the database closes.
The duration of a table lock depends on whether the database usestransactions. If it does not (that is, if no transaction log exists and the COMMITWORK statement is not used), a table lock remains until it is removed by theexecution of the UNLOCK TABLE statement.
Programming for a Multiuser Environment 7-9
7-10 Informix Guide to
Locks While Modifying
The duration of table, row, and index locks depends on what SQL statementsare used and on whether transactions are in use.
When transactions are used, the end of a transaction releases all table, row,page, and index locks. This is an important point: When a transaction ends,all locks are released.
Locks While ModifyingWhen the database server fetches a row through an update cursor, it places apromotable lock on the fetched row. If this succeeds, the database serverknows that no other program can alter that row. Because a promotable lockis not exclusive, other programs can continue to read the row. This helps per-formance because the program that fetched the row can take some timebefore it issues the UPDATE or DELETE statement, or it can simply fetch thenext row.
When it is time to modify a row, the database server obtains an exclusive lockon the row. If it already had a promotable lock, it changes it to exclusivestatus.
The duration of an exclusive row lock depends on whether transactions arein use. If they are not in use, the lock is released as soon as the modified rowis written to disk. When transactions are in use, all such locks are held untilthe end of the transaction. This prevents other programs from using rowsthat might be rolled back to their original state.
When transactions are in use, a key lock is used whenever a row is deleted.This prevents the following error from occurring:
■ Program A deletes a row.
■ Program B inserts a row having the same key.
■ Program A rolls back its transaction, forcing the database server torestore its deleted row. What is to be done with the row inserted byprogram B?
By locking the index, the database server prevents a second program frominserting a row until the first program commits its transaction.
The locks placed while reading a row are controlled by the current isolationlevel, which is discussed in the next section.
SQL: Tutorial
Setting the Isolation Level
Setting the Isolation LevelThe isolation level is the degree to which your program is isolated from theconcurrent actions of other programs. INFORMIX-OnLine Dynamic Serveroffers a choice of isolation levels. It implements them by setting differentrules for how a program uses locks when it is reading. (This does not applyto reads performed on update cursors.)
You set the isolation level using either the SET ISOLATION or SETTRANSACTION statement. Isolation levels can only be set with theINFORMIX-OnLine Dynamic Server database servers. The SET TRANSACTIONstatement also provides the ability to set access modes in eitherINFORMIX-OnLine Dynamic Server or INFORMIX-SE. For more informationabout access modes, see “Controlling Data Modification with Access Modes”on page 7-16.
Comparing SET TRANSACTION with SET ISOLATIONThe SET TRANSACTION statement complies with ANSI SQL-92. This statementis similar to the Informix SET ISOLATION statement; however, the SETISOLATION statement is not ANSI-compliant and does not provide accessmodes.
The isolation levels that you can set with the SET TRANSACTION statementare comparable to the isolation levels that you can set with the SETISOLATION statement, as shown in the following table:
SET TRANSACTION Correlates to SET ISOLATION
Read Uncommitted Dirty Read
Read Committed Committed Read
Not Supported Cursor Stability
(ANSI) Repeatable ReadSerializable
(Informix) Repeatable Read(Informix) Repeatable Read
Programming for a Multiuser Environment 7-11
7-12 Informix Guide to
ANSI Read Uncommitted and Informix Dirty Read Isolation
The major difference between the SET TRANSACTION and SET ISOLATIONstatements is the behavior of the isolation levels within transactions. The SETTRANSACTION statement can be issued only once for a transaction. Anycursors opened during that transaction are guaranteed to get that isolationlevel (or access mode if you are defining an access mode). With the SET ISO-LATION statement, after a transaction is started, you can change the isolationlevel more than once within the transaction. The following examples showboth the SET ISOLATION and SET TRANSACTION statements:
SET ISOLATION
EXEC SQL BEGIN WORK;EXEC SQL SET ISOLATION TO DIRTY READ;EXEC SQL SELECT ... ;EXEC SQL SET ISOLATION TO REPEATABLE READ;EXEC SQL INSERT ... ;EXEC SQL COMMIT WORK;
-- Executes without error
SET TRANSACTION
EXEC SQL BEGIN WORK;EXEC SQL SET TRANSACTION ISOLATION LEVEL TO SERIALIZABLE;EXEC SQL SELECT ... ;EXEC SQL SET TRANSACTION ISOLATION LEVEL TO READ COMMITTED;Error 876: Cannot issue SET TRANSACTION more than once in anactive transaction.
ANSI Read Uncommitted and Informix Dirty Read IsolationThe simplest isolation level, ANSI Read Uncommitted and Informix DirtyRead, amounts to virtually no isolation. When a program fetches a row, itplaces no locks and it respects none; it simply copies rows from the databasewithout regard for what other programs are doing.
A program always receives complete rows of data; even under ANSI ReadUncommitted or Informix Dirty Read isolation, a program never sees a rowin which some columns have been updated and some have not. However, aprogram using ANSI Read Uncommitted or Informix Dirty Read isolationsometimes reads updated rows before the updating program ends its trans-action. If the updating program later rolls back its transaction, the readingprogram processed data that never really existed (number 4 in the list ofconcurrency issues on page 7-5).
SQL: Tutorial
ANSI Read Committed and Informix Committed Read Isolation
ANSI Read Uncommitted or Informix Dirty Read is the most efficientisolation level. The reading program never waits and never makes anotherprogram wait. It is the preferred level in any of the following cases:
■ All tables are static; that is, concurrent programs only read and nevermodify data.
■ The database is held in an exclusive lock.
■ It is certain that only one program is using the database.
ANSI Read Committed and Informix Committed ReadIsolationWhen a program requests the ANSI Read Committed or Informix CommittedRead isolation level, INFORMIX-OnLine Dynamic Server guarantees that itnever returns a row that is not committed to the database. This prevents read-ing data that is not committed and that is subsequently rolled back.
ANSI Read Committed or Informix Committed Read is implemented verysimply. Before fetching a row, the database server tests to determine whetheran updating process placed a lock on the row; if not, it returns the row.Because rows that are updated but not committed have locks on them, thistest ensures that the program does not read uncommitted data.
ANSI Read Committed or Informix Committed Read does not actually placea lock on the fetched row; hence, it is almost as efficient as ANSI Read Uncom-mitted or Informix Dirty Read. It is appropriate for use when each row ofdata is processed as an independent unit, without reference to other rows inthe same or other tables.
Informix Cursor Stability IsolationThe next level, Cursor Stability, is available only with the Informix SQLstatement SET ISOLATION. When it is in effect, the database server places alock on the latest row fetched. It places a shared lock for an ordinary cursoror a promotable lock for an update cursor. Only one row is locked at a time;that is, each time a row is fetched, the lock on the previous row is released(unless that row is updated, in which case the lock holds until the end of thetransaction).
Programming for a Multiuser Environment 7-13
7-14 Informix Guide to
Informix Cursor Stability Isolation
Cursor Stability ensures that a row does not change while the programexamines it. This is important when the program updates some other tablebased on the data it reads from this row. Because of Cursor Stability, the pro-gram is assured that the update is based on current information. It preventsthe use of stale data.
Here is an example to illustrate this point. In terms of the demonstrationdatabase, Program A wants to insert a new stock item for manufacturer Hero(HRO). Concurrently, program B wants to delete manufacturer HRO and allstock associated with it. The following sequence of events can occur:
1. Program A, operating under Cursor Stability, fetches the HRO rowfrom the manufact table to learn the manufacturer code: This placesa shared lock on the row.
2. Program B issues a DELETE statement for that row. Because of thelock, the database server makes the program wait.
3. Program A inserts a new row in the stock table using the manufac-turer code it obtained from the manufact table.
4. Program A closes its cursor on the manufact table or reads a differentrow of it, releasing its lock.
5. Program B, released from its wait, completes the deletion of the rowand goes on to delete the rows of stock that use manufacturer codeHRO, including the row just inserted by Program A.
If Program A used a lesser level of isolation, the following sequence couldhave happened:
1. Program A reads the HRO row of the manufact table to learn themanufacturer code. No lock is placed.
2. Program B issues a DELETE statement for that row. It succeeds.
3. Program B deletes all rows of stock that use manufacturer code HRO.
4. Program B ends.
5. Program A, not aware that its copy of the HRO row is now invalid,inserts a new row of stock using the manufacturer code HRO.
6. Program A ends.
SQL: Tutorial
ANSI Serializable, ANSI Repeatable Read and Informix Repeatable Read Isolation
At the end, a row occurs in stock that has no matching manufacturer code inmanufact. Furthermore, Program B apparently has a bug; it did not delete therows it was supposed to delete. The use of the Cursor Stability isolation levelprevents these effects.
(It is possible to rearrange the preceding scenario so that it fails even withCursor Stability. All that is required is for Program B to operate on tables inthe reverse sequence to Program A. If Program B deletes from stock before itremoves the row of manufact, no degree of isolation can prevent an error.Whenever this kind of error is possible, it is essential that all programsinvolved use the same sequence of access.)
Because Cursor Stability locks only one row at a time, it restricts concurrencyless than does a table lock or database lock.
ANSI Serializable, ANSI Repeatable Read and InformixRepeatable Read IsolationThe definitions for ANSI Serializable, ANSI Repeatable Read, and InformixRepeatable Read isolation levels are all the same.
The Repeatable Read isolation level asks the database server to put a lock onevery row the program examines and fetches. The locks that are placed areshareable for an ordinary cursor and promotable for an update cursor. Thelocks are placed individually as each row is examined. They are not releaseduntil the cursor closes or a transaction ends.
Repeatable Read allows a program that uses a scroll cursor to read selectedrows more than once and to be sure that they are not modified or deletedbetween readings. (Scroll cursors are described in Chapter 5, “Programmingwith SQL.”) No lower isolation level guarantees that rows still exist and areunchanged the second time they are read.
Repeatable Read isolation places the largest number of locks and holds themthe longest. Therefore, it is the level that reduces concurrency the most. Ifyour program uses this level of isolation, you must think carefully about howmany locks it places, how long they are held, and what the effect can be onother programs.
Programming for a Multiuser Environment 7-15
7-16 Informix Guide to
Controlling Data Modification with Access Modes
In addition to the effect on concurrency, the large number of locks can be aproblem. The database server records the number of locks by each programin a lock table. If the maximum number of locks is exceeded, the lock tablefills up and the database server cannot place a lock. An error code is returned.The person who administers an INFORMIX-OnLine Dynamic Server systemcan monitor the lock table and tell you when it is heavily used.
Serializable is automatically used as the isolation level in an ANSI-compliantdatabase. Serializable is required to ensure operations behave in accordancewith the ANSI standard for SQL.
Controlling Data Modification with Access ModesBoth INFORMIX-OnLine Dynamic Server and INFORMIX-SE support accessmodes. Access modes affect read and write concurrency for rows withintransactions and are set with the SET TRANSACTION statement. You can useaccess modes to control data modification among shared files.
Transactions are read-write by default. If you specify that a transaction isread-only, that transaction cannot do the following tasks:
■ Insert, delete, or update table rows
■ Enable or disable constraints, triggers, or indexes
■ Create, alter, or drop any database object such as schemas, tables,temporary tables, indexes, or stored procedures
■ Grant or revoke privileges
■ Update statistics
■ Rename columns or tables
Read-only access mode prohibits updates.
You can execute stored procedures in a read-only transaction as long as theprocedure does not try to perform any restricted statements.
SQL: Tutorial
Setting the Lock Mode
Setting the Lock ModeThe lock mode determines what happens when your program encounterslocked data. One of the following situations occur when a program attemptsto fetch or modify a locked row:
■ The program receives an immediate return from the database serverwith an error code in SQLCODE or SQLSTATE.
■ The program is suspended until the lock is removed by the programthat placed it.
■ The program is suspended for a time and then, if the lock is notremoved, it receives an error-return code from the database server.
You choose among these results with the SET LOCK MODE command.
Waiting for LocksIf you prefer to wait (and this is the best choice for many applications),execute the following command:
SET LOCK MODE TO WAIT
When this lock mode is set, your program usually ignores the existence ofother concurrent programs. When it needs to access a row that another pro-gram has locked, your program waits until the lock is removed, thenproceeds. The delays are usually imperceptible.
Not Waiting for LocksThe disadvantage of waiting for locks is that the wait might become verylong (although properly designed applications should hold their locks verybriefly). When the possibility of a long delay is not acceptable, a program canexecute the following command:
SET LOCK MODE TO NOT WAIT
When the program requests a locked row, it immediately receives an errorcode (for example, error -107, Record is locked), and the current SQL state-ment terminates. It is up to the program to roll back its current transactionand try again.
Programming for a Multiuser Environment 7-17
7-18 Informix Guide to
Waiting a Limited Time
The initial setting is not waiting when a program starts up. If you are usingSQL interactively and see an error related to locking, set the lock mode towait. If you are writing a program, consider making that one of the firstembedded SQL commands that the program executes.
Waiting a Limited TimeWhen you use INFORMIX-OnLine Dynamic Server, you have an additionalchoice: You can ask the database server to set an upper limit on a wait. Youcan issue the following command:
SET LOCK MODE TO WAIT 17
This places an upper limit of 17 seconds on the length of any wait. If a lock isnot removed in that time, the error code is returned.
Handling a DeadlockA deadlock is a situation in which a pair of programs block the progress of eachother. Each program has a lock on some object that the other program wantsto access. A deadlock arises only when all programs concerned set their lockmodes to wait for locks.
INFORMIX-OnLine Dynamic Server detects deadlocks immediatelywhen they involve only data at a single network server. It preventsthe deadlock from occurring by returning an error code (error -143ISAM error: deadlock detected) to the second program to request alock. The error code is the one the program receives if it sets its lockmode to not wait for locks. Thus, if your program receives an errorcode related to locks even after it sets lock mode to wait, you know thecause is an impending deadlock.
SQL: Tutorial
Handling External Deadlock
Handling External DeadlockA deadlock can also occur between programs on different database servers.In this case, INFORMIX-OnLine Dynamic Server cannot instantly detect thedeadlock. (Perfect deadlock detection requires excessive communicationstraffic among all database servers in a network.) Instead, each databaseserver sets an upper limit on the amount of time that a program can wait toobtain a lock on data at a different database server. If the time expires, thedatabase server assumes that a deadlock was the cause and returns a lock-related error code.
In other words, when external databases are involved, every program runswith a maximum lock-waiting time. The maximum is set for the databaseserver and can be changed by the database administrator.
Simple ConcurrencyIf you are not sure which choice to make concerning locking and concurrency,and if your application is straightforward, have your program execute thefollowing commands when it starts up (immediately after the first DATABASEstatement):
SET LOCK MODE TO WAITSET ISOLATION TO REPEATABLE READ
Ignore the return codes from both statements. Proceed as if no otherprograms exist. If no performance problems arise, you do not need to readthis section again.
Programming for a Multiuser Environment 7-19
7-20 Informix Guide to
Locking with Other Database Servers
Locking with Other Database ServersINFORMIX-OnLine Dynamic Server manages its own locking so that it canprovide the different kinds of locks and levels of isolation described in thepreceding topics. Other Informix database servers implement locks using thefacilities of the host operating system and cannot provide the sameconveniences.
Some host operating systems provide locking functions as operating systemservices. In these systems, database servers support the SET LOCK MODEstatement.
Some host operating systems do not provide kernel-locking facilities. In thesesystems, the database server performs its own locking based on small filesthat it creates in the database directory. These files have the suffix .lok.
You can tell the kind of system in which your database server is running byexecuting the SET LOCK MODE statement and testing the error code, asshown in the following fragment of INFORMIX-ESQL/C code:
#define LOCK_ONLINE 1#define LOCK_KERNEL 2#define LOCK_FILES 3int 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, yourprogram is effectively always in NOT WAIT mode; that is, whenever it tries tolock a row that is locked by another program, it receives an error codeimmediately.
SQL: Tutorial
Isolation While Reading
Isolation While ReadingInformix database servers other than INFORMIX-OnLine Dynamic Server donot normally place locks when fetching rows. Nothing comparable exists tothe shared locks used by OnLine to implement the Cursor Stability isolationlevel.
If your program fetches a row with a singleton SELECT statement or througha cursor that is not declared FOR UPDATE, the row is fetched immediately,regardless of whether it is locked or modified by an unfinished transaction.
This design produces the best performance, especially when locks areimplemented by writing notes in disk files, but you must be aware that theprogram can read rows that are modified by uncommitted transactions.
You can obtain the effect of Cursor Stability isolation by declaring a cursorFOR UPDATE, and then using it for input. Whenever the database serverfetches a row through an update cursor, it places a lock on the fetched row. (Ifthe row is already locked, the program waits or receives an error, dependingon the lock mode.) When the program fetches another row without updatingthe current one, the lock on the current row is released and the new row islocked.
You can be sure by fetching through an update cursor, that the fetched row islocked as long as you use it. (The row cannot become stale.) You are alsoassured of fetching only committed data because locks on rows that areupdated are held until the end of the transaction. Depending on the hostoperating system and the database server, you might experience aperformance penalty for using an update cursor this way.
Locking Updated RowsWhen a cursor is declared FOR UPDATE, locks are handled as follows: Beforea row is fetched, it is locked; if it cannot be locked, the program waits orreturns an error.
The next time a fetch is requested, the database server notes whether thecurrent row is modified (using either the UPDATE or DELETE statement withWHERE CURRENT OF) and whether a transaction is in progress. If both thesethings are true, the lock on the row is retained. Otherwise, the lock is released.
Programming for a Multiuser Environment 7-21
7-22 Informix Guide to
Hold Cursors
DECLARE masDECLARE detOPEN masterLOOP:
FETCH mIF (the
BEGOPEFETUPDCOM
END IFEND LOOPCLOSE MASTE
So if you perform updates within a transaction, all updated rows remainlocked until the transaction ends. Rows that are not updated are locked onlywhile they are current. Rows updated outside a transaction or in a databasethat does not use transaction logging, are also unlocked as soon as anotherrow is fetched.
Hold CursorsWhen transaction logging is used, the database server guarantees thatanything done within a transaction can be rolled back at the end of it. To dothis 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 withouttransactions. However, when transactions are added, closing the cursorconflicts with using two cursors simultaneously.
Figure 7-1A pseudocodesketch of one
common form ofdatabase application
ter CURSOR FOR ...ail CURSOR FOR ... FOR UPDATE
aster INTO ... fetched data is appropriate) THENIN WORKN detail USING data read from masterCH detail ...ATE ... WHERE CURRENT OF detailMIT WORK
R
SQL: Tutorial
Summary
In this design, one cursor is used to scan a table. Selected records are used asthe basis for updating a different table. The problem is that when each updateis treated as a separate transaction (as shown in the pseudocode in Figure 7-1on page 7-22), the COMMIT WORK statement following the UPDATE closes allcursors, including the master cursor.
The simplest alternative is to move the COMMIT WORK and BEGIN WORKstatements to be the last and first ones, respectively, so that the entire scanover the master table is one large transaction. This is sometimes possible, butit may become impractical if many rows need to be updated. The number oflocks can be too large, and they are held for the duration of the program.
A solution supported by Informix database servers is to add the keywordsWITH HOLD to the declaration of the master cursor. Such a cursor is referredto as a hold cursor and is not closed at the end of a transaction. The databaseserver still closes all other cursors, and it still releases all locks, but the holdcursor remains open until it is explicitly closed.
Before you attempt to use a hold cursor, you must be sure that youunderstand the locking mechanism described here, and you must also under-stand the programs that are running concurrently. The reason is that when-ever COMMIT WORK is executed, all locks are released, including any locksplaced on rows fetched through the hold cursor.
This has little importance if the cursor is used as intended, for a singleforward scan over a table. However, you are allowed to specify WITH HOLDfor any cursor, including update cursors and scroll cursors. Before you dothis, you must understand the implications of the fact that all locks (includinglocks on entire tables) are released at the end of a transaction.
SummaryWhenever multiple programs have access to a database concurrently (andwhen at least one of them can modify data), all programs must allow for thepossibility that another program can change the data even as they read it. Thedatabase server provides a mechanism of locks and isolation levels thatusually allow programs to run as if they were alone with the data.
Programming for a Multiuser Environment 7-23
n II
Designing and ManagingDatabases
Sect
io
8Chapter
Building Your Data Model
Why Build a Data Model . . . . . . . . . . . . . . . . . 8-3Entity-Relationship Data Model Overview . . . . . . . . . 8-4
Identifying and Defining Your Principal Data Objects . . . . . . . 8-5Discovering Entities . . . . . . . . . . . . . . . . . 8-5
Choosing Possible Entities . . . . . . . . . . . . . 8-5Pruning Your List of Entities . . . . . . . . . . . . . 8-6The Telephone-Directory Example . . . . . . . . . . . 8-7Diagramming Your Entities . . . . . . . . . . . . . 8-9
Defining the Relationships . . . . . . . . . . . . . . . 8-9Connectivity . . . . . . . . . . . . . . . . . . 8-10Existence Dependency . . . . . . . . . . . . . . . 8-10Cardinality . . . . . . . . . . . . . . . . . . . 8-11Discover the Relationships . . . . . . . . . . . . . 8-11Diagramming Your Relationships . . . . . . . . . . . 8-16
Identifying Attributes . . . . . . . . . . . . . . . . 8-17How to Identify an Attribute . . . . . . . . . . . . . 8-17Selecting Attributes for Your Entities . . . . . . . . . . 8-17Listing Your Attributes . . . . . . . . . . . . . . . 8-18About Entity Occurrences . . . . . . . . . . . . . . 8-19
Diagramming Your Data Objects . . . . . . . . . . . . . . 8-19How You Read Entity-Relationship Diagrams . . . . . . . 8-21The Telephone-Directory Example . . . . . . . . . . . 8-21
Translating E-R Data Objects Into Relational Constructs . . . . . . 8-23Rules for Defining Tables, Rows, and Columns . . . . . . . . 8-24
Placing Constraints on Columns . . . . . . . . . . . 8-25Determining Keys for Tables . . . . . . . . . . . . . . 8-26
Primary Keys . . . . . . . . . . . . . . . . . . 8-26Foreign Keys (Join Columns) . . . . . . . . . . . . . 8-28Adding Keys to the Telephone-Directory Diagram . . . . . 8-29
8-2 Infor
Resolving Your Relationships . . . . . . . . . . . . . . . 8-30Resolving m:n Relationships . . . . . . . . . . . . . 8-30Resolving Other Special Relationships . . . . . . . . . 8-32
Normalizing Your Data Model . . . . . . . . . . . . . . . 8-33First Normal Form . . . . . . . . . . . . . . . . 8-34Second Normal Form . . . . . . . . . . . . . . . 8-36Third Normal Form . . . . . . . . . . . . . . . . 8-36Summary of Normalization Rules . . . . . . . . . . . 8-37
Summary . . . . . . . . . . . . . . . . . . . . . . 8-38
mix Guide to SQL: Tutorial
The first step in creating a database is to construct a data model—aprecise, complete definition of the data to be stored. This chapter contains acursory overview of one method of doing this. The following chaptersdescribe how to implement a data model once you design it.
To understand the material in this chapter, you should have a basicunderstanding of SQL and relational database theory.
Why Build a Data ModelYou may already have an idea of a database. If you use some type of formalnotation to build your data model, you can help your design in two ways:
■ It makes you think through the data model completely.
A mental model often contains unexamined assumptions;formalizing the design reveals these points.
■ It is easier to communicate your design to other people.
A formal statement makes the model explicit, so that others canreturn comments and suggestions in the same form.
Building Your Data Model 8-3
8-4 Informix Guide to S
Entity-Relationship Data Model Overview
Entity-Relationship Data Model OverviewDifferent books present different formal methods of modeling data. Mostmethods force you to be thorough and precise. If you have already learned amethod, by all means use it.
This chapter presents a summary of the entity-relationship (E-R ) data model,a modeling method taught in training courses presented by Informix. TheE-R modeling method is carried out in the following steps:
1. Identify and define the principal data objects (entities, relationships,and attributes).
2. Diagram the data objects using the entity-relationship approach.
3. Translate your entity-relationship data objects into relationalconstructs.
4. Resolve the logical data model.
5. Normalize the logical data model.
Steps 1-5 are discussed in this chapter. Chapter 9, “Implementing Your DataModel,” discusses a final step—converting your logical data model to aphysical schema.
The end product of data modeling is a fully defined database design encodedin a diagram similar to the one shown in Figure 8-16 on page 8-28, whichshows the final set of tables for a personal telephone directory. The personaltelephone directory is an example developed in this chapter. It is used ratherthan the stores7 database used in the rest of this book because it is smallenough to be developed completely in one chapter but large enough to showthe entire method.
QL: Tutorial
Identifying and Defining Your Principal Data Objects
Identifying and Defining Your Principal DataObjectsThe first step in building an entity-relationship data model is to identify anddefine your principal data objects. The principal data objects are entities,relationships, and attributes.
Discovering EntitiesAn entity is a principal data object that is of significant interest to the user. Itis usually a person, place, thing, or event to be recorded in the database. If thedata model were a language, entities would be its nouns. The stores7database 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 theentities that you choose will become tables in the model.
Choosing Possible Entities
If you have an idea for your database, you can probably list several entitiesimmediately. However, if other people use the database, you should pollthem for their understanding of what fundamental things the databaseshould contain. Make a preliminary list of all the entities you can identify.Interview the potential users of the database for their opinions about whatmust be recorded in the database. Determine basic characteristics for eachentity, such as “there must be at least one address associated with a name.”All the decisions you make in determining your entities become yourbusiness rules. “The Telephone-Directory Example” on page 8-7 providessome of the business rules for the example shown in this chapter.
Later, when you normalize your data model, some of the entities may expandor become other data objects. See “Normalizing Your Data Model” onpage 8-33 for additional information.
Building Your Data Model 8-5
8-6 Informix Guide to S
Discovering Entities
Pruning Your List of Entities
When the list of entities seems complete, prune it by making sure that eachone has the following qualities:
■ It is significant.
List only entities that are important to the users of the database andworth the trouble and expense of computer tabulation.
■ It is generic.
List only types of things, not individual instances. For instance,symphony might be an entity, but Beethoven’s Fifth would be an entityinstance or entity occurrence.
■ It is fundamental.
List only entities that exist independently, without needingsomething else to explain them. Anything you could call a trait, a fea-ture, or a description is not an entity. For example, a part number is afeature of the fundamental entity called part. Also, do not list thingsthat you can derive from other entities; for example, avoid any sum,average, or other quantity that you can calculate in a SELECTexpression.
■ It is unitary.
Be sure that each entity you name represents a single class—that itcannot be broken down into subcategories, each with its own fea-tures. In planning the telephone-directory model (see “TheTelephone-Directory Example” on page 8-7) an apparently simpleentity, the telephone number, turns out to consist of three categories,each with different features.
These choices are neither simple nor automatic. To discover the best choice ofentities, 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. Thefollowing section describes the example shown in this chapter in furtherdetail.
QL: Tutorial
Discovering Entities
NAME PThomas MorrisonADDRESS866 Gage Rd.Klamath FallsOR 97601
NAME PThomas MorrisonADDRESS866 Gage Rd.Klamath FallsOR 97601
NAME PThomas Morrison 503-7ADDRESS866 Gage Rd.Klamath FallsOR 97601
The Telephone-Directory Example
Suppose that you create a database that computerizes a personal telephonedirectory. The database model must record the names, addresses, andtelephone numbers of people and organizations that its user deals with forbusiness and pleasure.
The first step is to define the entities, and the first thing you might do is lookcarefully at a page from a telephone directory to see what entities are there.
Figure 8-1Part of a page from atelephone directory
HONE
HONE
NOPQRSTUVWXYZ
HONE76-3428
NAME PHONECatherine Morgan 206-789-5396
ADDRESS429 Bridge Way
Seattle, WA 98103
NAME PHONEThomas Morrison 503-256-6031
ADDRESS866 Gage Rd.
Klamath Falls, OR 97601
NAME PHONENorman Dearborn (206)598-8189ADDRESSMorganthaler Industries
12558 E. 10th Ave. Seattle, WA98102 FAX: 206 598-6872
Building Your Data Model 8-7
8-8 Informix Guide to S
Discovering Entities
The physical form of the existing data can be misleading. Do not let thelayout of pages and entries in the telephone directory mislead you into tryingto specify an entity that represents one entry in the book—some kind ofalphabetized record with fields for name, number, and address. Remember itis not the medium you want to model, it is the data.
At first glance, the entities recorded in a telephone directory include thefollowing items:
■ Names (of persons and organizations)
■ Addresses
■ Telephone numbers
Do these entities meet the earlier criteria? They are clearly significant to themodel and are generic.
Are they fundamental? A good test is to ask if an entity can vary in numberindependently of any other entity. After thinking about it, you realize that atelephone directory sometimes lists people who have no number or currentaddress (people who move or change jobs). A telephone directory also canlist both addresses and numbers that are used by more than one person. Allthree of these entities can vary in number independently; that stronglysuggests they are fundamental, not dependent.
Are they unitary? Names can be split into personal names and corporatenames. After thinking about it, you decide that all names should have thesame 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, youdecide only one kind of address exists; no need exists to treat home addressesdifferently from business ones.
However, you also realize that more than one kind of telephone numberexists, three. Voice numbers are answered by a person, fax numbers connectto a fax machine, and modem numbers connect to a computer. You decide thatyou want to record different information about each kind of number, so thesethree are different entities.
QL: Tutorial
Defining the Relationships
name
For the personal telephone-directory example, you decide that you want tokeep track of the following entities:
■ Name
■ Address (mailing)
■ Telephone number (voice)
■ Telephone number (fax)
■ Telephone number (modem)
Diagramming Your Entities
A section in this chapter will teach you how to use the entity-relationshipdiagrams. For now, create a separate, rectangular box for each entity in thetelephone-directory example. You will learn how to put the entities togetherwith relationships in “Diagramming Your Data Objects” on page 8-19.
Defining the RelationshipsAfter you choose your entities, you need to consider the relationshipsbetween them. Relationships are not always obvious, but all the ones worthrecording must be found. The only way to ensure that all the relationships arefound is to exhaustively list all possible relationships. You must considerevery pair of entities A and B and ask, “What is the relationship between anA and a B?”
A relationship is an association between two entities. Usually, a verb orpreposition connecting two entities implies a relationship. A relationshipbetween entities is described in terms of connectivity, existence dependency, andcardinality.
Figure 8-2Entities in the
personal telephone-directory example
address voice fax modem
Building Your Data Model 8-9
8-10 Informix Guide to
Defining the Relationships
one-to-one
Connectivity
Connectivity refers to the number of entity instances. An entity instance is aparticular 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 (writtenm:n) shown in Figure 8-3.
For example, in the telephone-directory example, an address can beassociated with more than one name. The connectivity for the relationshipbetween the name and address entities is one-to-many (1:n).
Existence Dependency
Existence dependency describes whether an entity in a relationship isoptional or mandatory. Analyze your business rules to identify whether anentity 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 theexistence dependency for the relationship between the name and addressentities mandatory. An example of an optional existence dependency couldbe a business rule that said a person may or may not have children.
Figure 8-3Connectivity in
relationships
one-to-many many-to-many
SQL: Tutorial
Defining the Relationships
nam
name
address
number(voice)
number(fax)
number(modem)
Cardinality
Cardinality places a constraint on the number of times an entity can appearin a relationship. The cardinality of a 1:1 relationship is always one. But thecardinality of a 1:n relationship is open; n could be any number. If you needto 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 ofsale items that a customer can purchase at one time. You usually placecardinality constraints through your application program or through storedprocedures.
For additional information about cardinality, see any entity-relationship datamodeling text. References to two data modeling books are included in the“Summary” on page 8-38.
Discover the Relationships
A compact way to discover the relationships is to prepare a matrix that namesall the entities on the rows and again on the columns. Figure 8-4 is a matrixthat reflects the entities for the personal telephone directory.
Figure 8-4A matrix that
reflects the entitiesfor a personal
telephone directory
e number(voice)
address number(fax)
number(modem)
Building Your Data Model 8-11
8-12 Informix Guide to
Defining the Relationships
nam
name no
address
number(voice)
number(fax)
number(modem)
You can ignore the lower triangle of the matrix, as indicated by the shadedarea. 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, theanswer is always none. No relationship exists between a name and a name oran 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 arecursive relationship. (See “Resolving Other Special Relationships” onpage 8-32.)
For all cells for which the answer is clearly none, write none in the matrix.Now the matrix looks like Figure 8-5.
Although no entities relate to themselves in this model, this is not alwaystrue in other models . A typical example is an employee who is the managerof another employee. Another example occurs in manufacturing, when a partentity is a component of another part.
Figure 8-5A matrix with initial
relationshipsincluded: No entitiesrelate to themselves
e number(voice)
ne
address number(fax)
number(modem)
none
none
none
none
SQL: Tutorial
Defining the Relationships
In the remaining cells, you write the connectivity relationship that existsbetween the entity on the row and the entity on the column. The followingkinds of relationships are possible:
■ One-to-one (1:1), in which never more than one entity A exists for oneentity B and never more than one B for one A.
■ One-to-many (1:n), in which never more than one entity A exists, butthere can be several entities B related to it (or vice versa).
■ Many-to-many (m:n), in which several entities A can be related to oneB and several entities B can be related to one A.
One-to-many relationships are the most common. Examples of one-to-manyand many-to-many relationships are shown in the telephone-directorymodel.
As Figure 8-5 on page 8-12 shows, the first unfilled cell represents the rela-tionship between names and addresses. What connectivity lies between theseentities? You can ask yourself, “How many names can be associated with anaddress?” A name (you decide) can have zero or one address but no more thanone. You write 0-1 opposite name and below address, as shown inFigure 8-6:
Ask yourself how many addresses can be associated with a name. You decidethat an address can be associated with more than one name. For example, youcan know several people at one company or more than two people who liveat the same address.
Figure 8-6Relationship
between name andaddress
name
name
address
none0-1
Building Your Data Model 8-13
8-14 Informix Guide to
Defining the Relationships
na
Can an address be associated with zero names? That is, should it be possiblefor 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 Figure 8-7:
If you decide that an address could not exist without being associated withat 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:nrelationship. In this case, the relationship between names and addresses is a1:n relationship.
Now consider the next cell, the relationship between a name and a voicenumber. How many voice numbers can a name be associated with, one ormore than one? Glancing at your telephone directory, you see that you mayoften have noted more than one telephone number for a person—for somebusy salesman you have a home number, an office number, a paging number,and a car phone number. But there also can be names without associatednumbers. You write 0-n opposite name and below number (voice), as shownin Figure 8-8:
Figure 8-7Relationship
between addressand name
Figure 8-8Relationship
between name andnumber
name
name
address
none 0-n0-1
name
me
address
none
number(voice)
0-n 0-n 0-1
SQL: Tutorial
Defining the Relationships
na
What is the other side of this relationship? How many names can beassociated 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 bysomeone. You write 1 under number (voice) and opposite name.
Fill out the rest of the matrix in the same fashion, using the followingdecisions:
■ A name can be associated with more than one fax number; forexample, a company can have several fax machines. Going the otherway, a fax number can be associated with more than one name; forexample, several people can use the same fax number.
■ A modem number must be associated with exactly one name. (Thisis an arbitrary decree to complicate the example; pretend it is arequirement of the design.) However, a name can have more thanone associated modem number; for example, a company computercan have several dial-up lines.
Figure 8-9Relationship
between numberand name
name
me
address
none 0-n 0-1
number(voice)
1 0-n
Building Your Data Model 8-15
8-16 Informix Guide to
Defining the Relationships
na
name n
address
number(voice)
number(fax)
number(modem)
■ Although some relationship exists between a voice number and anaddress, a modem number and an address, and a fax number and anaddress in the real world, none needs to be recorded in this model.There already is an indirect relationship through name.
Other decisions reflected in the matrix is that no relationship exists betweena fax number and a modem number, between a voice number and a fax, orbetween a voice number and a modem number.
You might disagree with some of these decisions (for example, why arelationship between voice numbers and modem numbers is not supported).For the sake of this example, these are our business rules.
Diagramming Your Relationships
For now, save the matrix that you created in this section. You will learn howto create an entity-relationship diagram in “Diagramming Your DataObjects” on page 8-19.
Figure 8-10A completed matrix
for a telephonedirectory
me number(voice)
one
address number(fax)
number(modem)
none
none
none
none
none
0-n0-1
10-n
1-n0-n
10-n
none
none none
none none
SQL: Tutorial
Identifying Attributes
Identifying AttributesEntities contain attributes, which are characteristics or modifiers, qualities,amounts, or features. An attribute is a fact or nondecomposable piece ofinformation about an entity. Later, when you represent an entity as a table, itsattributes are added to the model as new columns.
How to Identify an Attribute
Before you can identify your attributes, you must identify your entities. Afteryou determine your entities, ask yourself, “what characteristics do you needto know about each entity?” For example, in an address entity, you probablyneed information about street, city, and zipcode. Each of these characteristicsof the address entity become attributes.
Selecting Attributes for Your Entities
In selecting attributes, choose ones that have the following qualities:
■ They are significant.
Include only attributes that are useful to the database users.
■ They are direct, not derived.
An attribute that can be derived from existing attributes—forinstance, through an expression in a SELECT statement—should notbe made part of the model. The presence of derived data greatly com-plicates the maintenance of a database.
At a later stage of the design, you can consider adding derivedattributes to improve performance, but at this stage you shouldexclude them. Performance improvements are discussed in theINFORMIX-OnLine Dynamic Server Performance Guide.
■ They are nondecomposable.
An attribute can contain only single values, never lists or repeatinggroups. Composite values must be broken into separate attributes.
■ They contain data of the same type.
For example, you would want to enter only date values in a birthdayattribute, not names or telephone numbers.
Building Your Data Model 8-17
8-18 Informix Guide to
Identifying Attributes
name
fnamelnamebdateannivemailchild1child2child3
The rules for defining attributes are the same as those for defining columns.For more information about defining columns, see “Placing Constraints onColumns” on page 8-25.
The following attributes are added to the telephone-directory example toproduce the diagram shown in Figure 8-15 on page 8-22:
■ Street, city, state, and zip code are added to the address entity.
■ Birth date is added to the name entity. Also added to the name entityare e-mail address, anniversary date, and children’s first names.
■ Type is added to the voice entity to distinguish car phones, homephones, and office phones. A voice number can be associated withonly one voice type.
■ The hours that a fax machine is attended is added to the fax entity.
■ Whether a modem supports 300-, 1,200-, or 2,400-baud rates is addedto the modem entity.
Listing Your Attributes
For now, simply list the attributes for the telephone-directory example withthe entities with which you think they belong. Your list should looksomething like Figure 8-11:
Figure 8-11Attributes for the
telephone-directoryexample
address voice fax modem
streetcity
statezipcode
vce_numvce_type
fax_numoper_fromoper_till
mdm_numb300
b1200b2400
SQL: Tutorial
Diagramming Your Data Objects
About Entity Occurrences
An additional data object that you need to know about is the entityoccurrence. Each row in a table represents a specific, single occurrence of theentity. For example, if customer is an entity, a customer table represents theidea of customer; in it, each row represents one specific customer, such as SueSmith. Keep in mind that entities will become tables, attributes will becomecolumns, and rows will become entity occurrences.
Diagramming Your Data ObjectsAt this point, you have already discovered and understood the entities andrelationships in your database. That is the most important part of the rela-tional database design process. Once you have determined the entities andrelationships, you might find it helpful to have a method for displaying yourthought process during database design.
Most data modeling methods provide some form of graphically displayingyour entities and relationships. Informix uses the E-R diagram approachoriginally developed by C. R. Bachman. E-R diagrams serve the followingpurposes:
■ They model the information needs of an organization.
■ They identify entities and their relationships.
■ They provide a starting point for data definition (data flowdiagrams).
■ They provide an excellent source of documentation for applicationdevelopers as well as database and system administrators.
■ They create a logical design of the database which can be translatedinto a physical schema.
Building Your Data Model 8-19
8-20 Informix Guide to
Diagramming Your Data Objects
entity
name
ames
Several different styles of documenting E-R , diagrams exist. If you alreadyhave a style that you prefer, use it. A sample E-R diagram is shown inFigure 8-12:
Entities are represented by a box. Relationships are represented by a lineconnecting the entities. In addition, you use several graphical items todisplay the following features of relationships, as shown in Figure 8-13:
■ A circle across a relationship link indicates optionality in therelationship (zero instances).
■ A small bar across a relationship link indicates that exactly oneinstance of the entity is associated with another entity (consider thebar as a “1”).
■ The “crow’s feet” represents many in your relationship.
Figure 8-12Symbols of an
entity-relationshipdiagram
Figure 8-13The parts of a
relationship in anentity-relationship
diagram
relationship
entity
address
Addr
many exactlyone
optionality optionality
SQL: Tutorial
Diagramming Your Data Objects
name
How You Read Entity-Relationship Diagrams
You read the diagrams first from left to right and then from right to left. In thecase of the name-address relationship diagrammed in Figure 8-14, you read therelationships as follows: Names can be associated with zero or exactly oneaddress; addresses can be associated with zero, one, or many names.
The Telephone-Directory Example
Figure 8-15 on page 8-22 shows the telephone-directory example andincludes the entities, relationships, and attributes. This diagram includes therelationships that were established with the matrix. After studying the dia-gram symbols, compare the E-R diagram in Figure 8-15 with the matrix inFigure 8-10 on page 8-16. Verify for yourself that the relationships are thesame in both figures.
Figure 8-14Reading an entity-
relationshipdiagramaddress
can have zero ormany
can have zero orexactly 1
Building Your Data Model 8-21
8-22 Informix Guide to
Diagramming Your Data Objects
voice
vce_numvce_type
A matrix such as Figure 8-10 on page 8-16 is a useful tool when you are firstdesigning your model because, in filling it out, you are forced to think ofevery possible relationship. However, the same relationships appear in adiagram such as Figure 8-15, and this type of diagram may be easier to readwhen you are reviewing an existing model.
After the Diagram is Complete
The rest of the chapter describes the following tasks:
■ How to translate the entities, relationships, and attributes intorelational constructs
■ How to resolve the E-R data model
■ How to normalize the E-R data model
Chapter 9, “Implementing Your Data Model,” shows you how to create adatabase from the E-R data model.
Figure 8-15Preliminary entity-
relationshipdiagram of the
telephone-directoryexample
modem
mdm_numb300
b1200b2400
fax
fax_numoper_fromoper_till
lnamefnamebdateannivemailchild1child2child3
address
streetcity
statezipcode
SQL: Tutorial
Translating E-R Data Objects Into Relational Constructs
Translating E-R Data Objects Into RelationalConstructsAll the data objects you have learned about so far—entities, relationships,attributes, and entity occurrences—will be translated into SQL tables, joinsbetween tables, columns, and rows. The tables, columns, and rows of yourdatabase must fit the rules found in “Rules for Defining Tables, Rows, andColumns” on page 8-24.
Your data objects should fit these rules before you normalize your dataobjects. Normalizing your data objects is accomplished by analyzing thedependencies between your entities, relationships, and attributes.Normalizing is discussed in “Normalizing Your Data Model” on page 8-33.
After you normalize the data model, you can use SQL statements to create adatabase based on your data model. Chapter 9, “Implementing Your DataModel,” describes how to create your database and provides the databaseschema for the telephone-directory example.
Each entity you choose is represented as a table in the model. The table standsfor the entity as an abstract concept, and each row represents a specific, indi-vidual occurrence of the entity. In addition, each attribute of an entity isrepresented by a column in the table.
The following ideas are fundamental to most relational data model methods,including the E-R data model. By following these rules while you designyour data model, you will save time and effort when you normalize yourmodel.
Building Your Data Model 8-23
8-24 Informix Guide to
Rules for Defining Tables, Rows, and Columns
Rules for Defining Tables, Rows, and ColumnsYou are already familiar with the idea of a table composed of rows andcolumns. But you must respect the following rules while you define the tablesof a formal data model:
■ Rows must stand alone.
Each row of a table is independent and does not depend on any otherrow of the same table. As a consequence, the order of the rows in atable is not significant in the model. The model should still be correcteven if all the rows of a table are shuffled into random order.
After the database is implemented, you can tell the database serverto store rows in a certain order for the sake of efficiency, but that doesnot affect the model.
■ Rows must be unique.
In every row, some column must contain a unique value. If no singlecolumn has this property, the values of some group of columns takenas a whole must be different in every row.
■ Columns must stand alone.
The order of columns within a table has no meaning in the model.The model should still be correct even if the columns are rearranged.
After the database is implemented, programs and stored queries thatuse an asterisk to mean all columns are dependent on the final orderof columns, but that does not affect the model.
■ Column values must be unitary.
A column can contain only single values, never lists or repeatinggroups. Composite values must be broken into separate columns.For example, if you decide to treat a person’s first and last names asseparate values, as shown in the examples in this chapter, they mustbe in separate columns, not in a single name column.
■ Each column must have a unique name.
Two columns within the same table cannot share the same name.However, you may have columns that contain similar information.For example, the name table in the telephone-directory example con-tains columns for children’s names. You can name each column,child1, child2, and so on.
SQL: Tutorial
Rules for Defining Tables, Rows, and Columns
■ Each column must contain data of a single type.
A column must contain information of the same data type. For exam-ple, a column identified as an integer must contain only numericinformation, not characters from a name.
If your previous experience is only with data organized as arrays orsequential files, these rules might seem unnatural. However, relational data-base theory shows that you can represent all types of data using only tables,rows, and columns that follow these rules. With a little practice, these rulesbecome automatic.
Placing Constraints on Columns
When you define your table and columns with the CREATE TABLE statement,you constrain each column. These constraints specify whether you want thecolumn to contain characters or numbers, the form that you want dates touse, and other constraints. A domain describes the constraints on andidentifies the set of valid values that attributes may assume. The domaincharacteristics of a column can consist of the following items:
■ Data type (INTEGER, CHAR, DATE, and so on)
■ Format (for example, yy/mm/dd)
■ Range (for example, 1,000-5,400)
■ Meaning (for example, personnel number)
■ Allowable values (for example, only grades S or U)
■ Uniqueness
■ Null support
■ Default value
■ Referential constraints
You define the domain characteristics when you create your tables. Definingdomains and creating your tables and database are discussed in Chapter 9,“Implementing Your Data Model.”
Building Your Data Model 8-25
8-26 Informix Guide to
Determining Keys for Tables
Determining Keys for TablesThe columns of a table are either key columns or descriptor columns. A keycolumn is one that uniquely identifies a particular row in the table. For exam-ple, a social-security number is unique for each employee. A descriptorcolumn specifies the nonunique characteristics of a particular row in thetable. For example, two employees may have the same first name, Sue. Thefirst name Sue is a nonunique characteristic of an employee. The main typesof keys in a table are primary keys and foreign keys.
You designate primary and foreign keys when you create your tables.Primary and foreign keys are used to relate tables physically. Your next taskis to specify a primary key for each table. That is, you must identify somequantifiable characteristic of the table that distinguishes each row from everyother.
Primary Keys
The primary key of a table is the column whose values are different in everyrow. Because they are different, they make each row unique. If no one suchcolumn exists, the primary key is a composite of two or more columns whosevalues, taken together, are different in every row.
Every table in the model must have a primary key. This follows automaticallyfrom the rule that all rows must be unique. If necessary, the primary key iscomposed of all the columns taken together.
The primary key should be a numeric data type (INT or SMALLINT), SERIALdata type, or a short character string (as used for codes). It is recommendedthat you avoid using long character strings as primary keys.
Null values are never allowed in a primary-key column. Null values are notcomparable; that is, they cannot be said to be alike or different. Hence, theycannot make a row unique from other rows. If a column permits null values,it cannot be part of a primary key.
Some entities have ready-made primary keys such as catalog codes oridentity numbers, which are defined outside the model. These areuser-assigned keys.
SQL: Tutorial
Determining Keys for Tables
Sometimes more than one column or group of columns can be used as theprimary key. All columns or groups that qualify to be primary keys are calledcandidate keys. All candidate keys are worth noting because their property ofuniqueness makes them predictable in a SELECT operation. When you selectthe columns of a candidate key, you know the result can contain no duplicaterows. Sometimes that allows you to predict the uniqueness of the rowsreturned. It always means that the result of a SELECT operation can be a tablein its own right, with the selected candidate key as its primary key.
Composite Keys
Some entities lack features that are reliably unique. Different people can haveidentical names; different books can have identical titles. You can usually finda composite of attributes that work as a primary key. For example, it is rarefor people to have identical names and identical addresses or for differentbooks to have identical titles, authors, and publication dates.
System-Assigned Keys
A system-assigned primary key is usually preferable to a composite key. Asystem-assigned key is a number or code that is attached to each instance ofan entity when it is first entered into the database. The easiest system-assigned keys to implement are serial numbers because the database servercan generate them automatically. Informix offers the SERIAL data type forserial numbers. However, the people who use the database might not like aplain numeric code. Other codes can be based on actual data; for example, anemployee identification code could be based on a person’s initials combinedwith the digits of the date they were hired. In the telephone-directoryexample, a system-assigned primary key is used for the name table.
Building Your Data Model 8-27
8-28 Informix Guide to
Determining Keys for Tables
cust
customer_num
primary key
Foreign Keys (Join Columns)
A foreign key is simply a column or group of columns in one table thatcontains values that match the primary key in another table. Foreign keys areused to join tables; in fact, most of the join columns referred to earlier in thisbook are foreign-key columns. Figure 8-16 shows the primary and foreignkeys of the customer and order tables from the stores7 database.
Foreign keys are noted wherever they appear in the model because theirpresence can restrict your ability to delete rows from tables. Before you candelete a row safely, either you must delete all rows that refer to it throughforeign keys or you must define the relationship using special syntax thatallows you to delete rows from primary-key and foreign-key columns with asingle delete command. The database server disallows deletes that violatereferential integrity.
You can always preserve referential integrity by deleting all foreign-key rowsbefore you delete the primary key to which they refer. If you are imposing ref-erential constraints on your database, the database server does not permityou to delete primary keys with matching foreign keys. It also does notpermit you to add a foreign-key value that does not reference an existingprimary-key value. Referential integrity is discussed in Chapter 4,“Modifying Data.”
Figure 8-16Primary and foreign
keys in thecustomer-order
relationships
omer orders
order_num customer_num
foreign key
SQL: Tutorial
Determining Keys for Tables
Adding Keys to the Telephone-Directory Diagram
The initial choices of primary and foreign keys is shown in Figure 8-17 onpage 8-30. This diagram reflects some important decisions.
For the name table, the primary key rec_num is chosen. Note that the datatype for rec_num is SERIAL. The values for rec_num are system-generated. Ifyou look at the other columns (or attributes) in the name table, you see thatthe data types associated with the columns are mostly character- based. Noneof these columns alone are good candidates for a primary key. If you combineelements of the table into a composite key, you create an exceedingly cumber-some key. By using a SERIAL data type, you have a key that you can also useto join other tables to the name table.
For the voice, fax, and modem tables, the telephone numbers are shown asprimary keys. These tables are joined to the name table through the rec_numkey.
The address table also uses a system-generated primary key, id_num. Theaddress table must have a primary key because the business rules state that anaddress can exist when no names use it. If the business rules prevent anaddress from existing unless a name is associated with it, then the addresstable could be joined to the name table with the foreign key rec_num only.
Building Your Data Model 8-29
8-30 Informix Guide to
Resolving Your Relationships
voice
vce_num PKrec_num FK
vce_type
Resolving Your RelationshipsThe aim of a good data model is to create a structure that provides thedatabase server with quick access. The telephone-directory data model canbe further refined by resolving the relationships and normalizing the datamodel. This section addresses the hows and whys of resolving yourrelationships. Normalizing your data model is discussed in “NormalizingYour Data Model” on page 8-33.
Resolving m:n Relationships
Many-to-many (m:n) relationships add complexity and confusion to yourmodel and to the application development process. The key to resolving m:nrelationships is to separate the two entities and create two one-to-many (1:n)relationships between them with a third intersect entity. The intersect entityusually contains attributes from both connecting entities.
Figure 8-17Telephone-
directory diagramwith primary and
foreign keys added
modem
mdm_num PKrec_num FK
b300b1200b2400
fax
fax_num PKrec_num FKoper_fromoper_till
name
rec_num PKlnamefnamebdateannivemailchild1child2child3
address
id_num PKrec_num FK
streetcity
statezipcode
SQL: Tutorial
Resolving Your Relationships
B
faxfax_num PKrec_num FKoper_fromoper_till
To resolve a m:n relationship, analyze your business rules again. Have youaccurately diagrammed the relationship? In the telephone-directory exam-ple, we have a m:n relationship between the name and fax entities as shownin Figure 8-17 on page 8-30. To resolve the relationship between name and fax,we carefully reviewed the business rules. The business rules say: “Oneperson can have zero, one, or many fax numbers; a fax number can be for severalpeople.” Based on what we selected earlier as our primary key for the voiceentity, a m:n relationship exists.
A problem exists in the fax entity because the telephone number, which isdesignated as the primary key, can appear more than one time in the faxentity; this violates the qualification of a primary key. Remember, the primarykey must be unique.
This m:n relationship is resolved by adding an intersect entity between nameand fax entities. The new intersect entity, faxname, contains two attributes,fax_num and rec_num. The primary key for the entity is a composite of bothattributes. Individually, each attribute is a foreign key that references thetable from which it came. The relationship between the name and faxnametables is 1:n because one name can be associated with many fax numbers; inthe other direction, each faxname combination can be associated with onerec_num. The relationship between the fax and faxname tables is 1:n becauseeach number can be associated with many faxname combinations.
Figure 8-18Resolving a
many-to-many(m:n) relationship
fax
fax_num PKoper_fromoper_till
fax_num PK FKrec_num PK FK
EFORE AFTER
IntersectEntity
faxname
name
rec_num PKlnamefnamebdateannivemailchild1child2child3
rec_num PKlnamefnamebdateannivemailchild1child2child3
Building Your Data Model 8-31
8-32 Informix Guide to
Resolving Your Relationships
Resolving Other Special Relationships
You may encounter other special relationships that can hamper a smoothrunning database. These relationships are shown in the following list:
■ Complex relationships
■ Recursive relationships
■ Redundant relationships
A complex relationship is an association among three or more entities. All theentities must be present for the relationship to exist. To reduce this complex-ity, reclassify all complex relationships as an entity, related through binaryrelationships to each of the original entities.
A recursive relationship is an association between occurrences of the sameentity type. These types of relationships do not occur often. Examples ofrecursive relationships are bill-of-materials (parts are composed of subparts)and organizational structures (employee manages other employees). SeeChapter 5, “Programming with SQL,” for an extended example of a recursiverelationship. You may choose not to resolve recursive relationships.
A redundant relationship is when two or more relationships are used torepresent the same concept. Redundant relationships add complexity to thedata model and may lead a developer to incorrectly place attributes in themodel. Redundant relationships may appear as duplicated entries in yourentity-relationship diagram. For example, you may have two entities thatcontain the same attributes. To resolve a redundant relationship, review yourdata model. Do you have more than one entity that contains the sameattributes? You may need to add an entity to the model to resolve theredundancy. The INFORMIX-OnLine Dynamic Server Performance Guidediscusses additional topics related to redundancy in a data model.
SQL: Tutorial
Normalizing Your Data Model
Normalizing Your Data ModelThe telephone-directory example shown in this chapter appears to be a goodmodel. It could be implemented at this point into a database, but it mightpresent problems later on with application development and data-manipulation operations. Normalization is a formal approach to applying a setof rules used in associating attributes with entities.
Normalizing your data model can do the following things:
■ Produce greater flexibility in your design
■ Ensure that attributes are placed in the proper tables
■ Reduce data redundancy
■ Increase programmer effectiveness
■ Lower application maintenance costs
■ Maximize stability of the data structure
Normalization consists of several steps to reduce the entities to moredesirable physical properties. These steps are called normalization rules, alsoreferred to as normal forms. Several normal forms exist; this chapter discussesthe first three normal forms. Each normal form constrains the data to be moreorganized than the last form. Because of this, you must achieve first normalform before you can achieve second normal form, and you must achievesecond normal form before you can achieve third normal form.
Building Your Data Model 8-33
8-34 Informix Guide to
Normalizing Your Data Model
name
lnam
P
First Normal Form
An entity is in first normal form if it contains no repeating groups. Inrelational terms, this means that a table is in first normal form if it containsno repeating columns. Repeating columns make your data less flexible, wastedisk 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-19:
Some problems can be noted in the current table. Space is always reserved onthe disk for three child records, whether the person has children or not. Themaximum number of children that you could record is three; but some ofyour acquaintances might have four or more children. If you look for aparticular child, you would have to search all three columns in every row.
You can eliminate the repeating columns and bring the table to first normalform by separating the table into two tables as shown in Figure 8-20. Put therepeating columns into one of the tables. The association between the twotables is established with a primary and foreign key combination. Because achild cannot exist without an association in the name table, we can referencethe name table with a foreign key, rec_num.
Figure 8-19Name entity before
normalization
Figure 8-20First normal formreached for name
entity
re bdate anniv email child1 child2 child3
repeating columns
fname
rimary Key
child_namerec_num
Foreign
child
name
rec_num lname bdate anniv emailfname
SQL: Tutorial
Normalizing Your Data Model
voice
vce_num PKrec_numvce_type
In addition, the modem-name relationship is not at the first normal formbecause the columns b300, b1200, and b2400 are considered repeating col-umns. This relationship is normalized in a similar manner as the name-childrelationship, as shown in Figure 8-16 on page 8-28. A b_type attribute isadded to the entity which can contain occurrences of b300, b1200, and b2400.Figure 8-16 shows the data model normalized through first normal form.
Figure 8-21The data model of apersonal telephone
directory
name
modem
mdm_num PKrec_num FK
b_typefax
fax_num PKoper_fromoper_till
address
id_num PKrec_num FK
streetcity
statezipcode
rec_num FKchild_name
child
faxname
fax_num PK FKrec_num PK FK
rec_num PKlnamefnamebdateannivemail
Building Your Data Model 8-35
8-36 Informix Guide to
Normalizing Your Data Model
Second Normal Form
An entity is in the second normal form if it is in the first normal form and allits attributes depend on the whole (primary) key. In relational terms, thismeans that every column in a table must be functionally dependent on thewhole primary key of that table. Functional dependency indicates that a linkexists between the values in two different columns.
To say that the value of an attribute depends on a column means that, if thevalue in the column changes, the value of the attribute must also change. Theattribute is a function of the column. The following explanations make thismore specific:
■ If the table has a one-column primary key, the attribute must dependon that key.
■ If the table has a composite primary key, the attribute must dependon the values in all its columns taken as a whole, not on one or someof them.
■ If the attribute also depends on other columns, these must be col-umns of a candidate key; that is, columns that are unique in everyrow.
If you do not convert your model to the second normal form, you risk dataredundancy and difficulty in changing data. Convert first normal form tablesto second normal form tables by removing columns that are not dependenton the primary key.
Third Normal Form
An entity is in the third normal form if it is in the second normal form and allits attributes are not transitively dependent on the primary key. Transitivedependence means that descriptor key attributes depend not only on thewhole primary key but also on other descriptor key attributes that, in turn,depend on the primary key. In SQL terms, the third normal form means thatno column within a table is dependent on a descriptor column that, in turn,depends on the primary key.
To convert to the third normal form, remove attributes that depend on otherdescriptor key attributes.
SQL: Tutorial
Normalizing Your Data Model
Summary of Normalization Rules
The following normal forms are discussed in this section:
■ First normal form: A table is in the first normal form if it contains norepeating columns.
■ Second normal form: A table is in the second normal form if it is inthe first normal form and contains only columns that are dependenton the whole (primary) key.
■ Third normal form: A table is in the third normal form if it is in thesecond normal form and contains only columns that arenontransitively dependent on the primary key.
When you follow these rules, the tables of the model are in what E.F. Codd,the inventor of relational databases, calls the third normal form. When tablesare not in the third normal form, either redundant data exists in the model orproblems exist when you attempt to update the tables.
If you cannot find a place for an attribute that observes these rules, then youhave probably made one of the following errors:
■ The attribute is not well defined.
■ The attribute is derived, not direct.
■ The attribute is really an entity or a relationship.
■ Some entity or relationship is missing from the model.
Building Your Data Model 8-37
8-38 Informix Guide to
Summary
SummaryThis chapter summarized and illustrated the following steps of E-R datamodeling:
1. Identify and define your principal data objects, including the followingoptions:
❑ Entities
❑ Relationships
❑ Attributes
2. Diagram your data objects using the E-R diagram approach.
3. Translate your E-R 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 datanot once, but several times.
If you are interested in learning more about database design, you can attendthe Informix course, Relational Database Design. This thorough coursepresents how to create an E-R 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 byToby J. Teorey, Morgan Kauffman Publishers, Inc., 1990
■ Handbook of Relational Database Design by Candace C. Fleming andBarbara von Halle, Addison-Wesley Publishing Company, 1989
SQL: Tutorial
9Chapter
Implementing Your Data Model
Defining the Domains . . . . . . . . . . . . . . . . . . 9-3Data Types . . . . . . . . . . . . . . . . . . . . 9-4
Choosing a Data Type . . . . . . . . . . . . . . . 9-4Numeric Types . . . . . . . . . . . . . . . . . 9-8Chronological Types. . . . . . . . . . . . . . . . 9-13Character Types . . . . . . . . . . . . . . . . . 9-17Changing the Data Type . . . . . . . . . . . . . . 9-22
Null Values . . . . . . . . . . . . . . . . . . . . 9-22Default Values . . . . . . . . . . . . . . . . . . . 9-22Check Constraints . . . . . . . . . . . . . . . . . . 9-23
Creating the Database . . . . . . . . . . . . . . . . . . 9-24Using CREATE DATABASE . . . . . . . . . . . . . . 9-24
Using CREATE DATABASE with INFORMIX-OnLine Dynamic Server9-24
Using CREATE DATABASE with Other Informix Database Servers 9-27Using CREATE TABLE . . . . . . . . . . . . . . . . 9-28Using Command Scripts . . . . . . . . . . . . . . . 9-30
Capturing the Schema . . . . . . . . . . . . . . . 9-30Executing the File . . . . . . . . . . . . . . . . 9-31An Example . . . . . . . . . . . . . . . . . . 9-31
Populating the Tables. . . . . . . . . . . . . . . . . 9-31
Fragmenting Tables and Indexes . . . . . . . . . . . . . . 9-34
Creating a Fragmented Table . . . . . . . . . . . . . . . 9-34Fragmenting a New Table . . . . . . . . . . . . . . . 9-35Creating A Fragmented Table from Nonfragmented Tables. . . . 9-36
Creating a Table From More Than One Nonfragmented Table . 9-36Creating a Fragmented Table from a Single Nonfragmented Table 9-37
9-2 Infor
Modifying a Fragmented Table . . . . . . . . . . . . . . . 9-37Modifying Fragmentation Strategies . . . . . . . . . . . 9-38
Change a Fragmentation Strategy Using the MODIFY Clause . 9-38Adding a New Fragment . . . . . . . . . . . . . . 9-39Completely Reinitialize a Fragmentation Scheme Using the INIT
Clause . . . . . . . . . . . . . . . . . . 9-39Dropping A Fragment . . . . . . . . . . . . . . . . 9-40
Accessing Data Stored in Fragmented Tables . . . . . . . . . . 9-41Use Primary Keys Instead of Rowids . . . . . . . . . . . 9-41
Rowid in a Fragmented Table . . . . . . . . . . . . 9-41Creating a Rowid Column. . . . . . . . . . . . . . 9-42
Summary . . . . . . . . . . . . . . . . . . . . . . 9-43
mix Guide to SQL: Tutorial
Once a data model is prepared, it must be implemented as adatabase and tables. This chapter covers the decisions that you must make toimplement the model.
The first step in implementation is to complete the data model by defining adomain, or set of data values, for every column. The second step is toimplement the model using SQL statements.
The first section of this chapter covers defining domains in detail. The secondsection shows how you create the database (using the CREATE DATABASEand CREATE TABLE statements) and populate it with data.
Defining the DomainsTo complete the data model described in Chapter 8, “Building Your DataModel,” you must define a domain for each column. The domain of a columndescribes the constraints on and identifies the set of valid values attributes (orcolumns) may assume.
The purpose of a domain is to guard the semantic integrity of the data in themodel; that is, to ensure that it reflects reality in a sensible way. If a name canbe entered where a telephone number was planned or a fractional numberwhere an integer should be, the integrity of the data model is at risk.
Implementing Your Data Model 9-3
9-4 Informix Guide to S
Data Types
You define a domain by first defining the constraints that a data value mustsatisfy before it can be part of the domain. Column domains are specifiedusing the following constraints:
■ Data types
■ Default values
■ Check constraints
In addition, referential constraints can be placed on columns by identifyingthe primary and foreign keys in each table. How to identify these keys wasdiscussed in Chapter 8, “Building Your Data Model.”
Data TypesThe first constraint on any column is the one that is implicit in the data typefor the column. When you choose a data type, you constrain the column sothat it contains only values that can be represented by that type.
Each data type represents certain kinds of information and not others. Thecorrect data type for a column is the one that represents all the data valuesthat are proper for that column but as few as possible of the values that arenot proper for it.
Choosing a Data Type
Every column in a table must have a data type chosen from the types that thedatabase server supports. The choice of data type is important for thefollowing reasons:
■ It establishes the basic domain of the column; that is, the set of validdata items that the column can store.
■ It determines the kinds of operations you can perform on the data.For example, you cannot apply aggregate functions, such as SUM, tocolumns with a character data type.
■ It determines how much space each data item occupies on disk. Thisis not important for small tables, but if a table has tens or hundredsof thousands of rows, the difference between a 4-byte and an 8-bytetype can be crucial.
QL: Tutorial
Data Types
Using Data Types in Referential Constraints
Almost all data type combinations must match. For example, if a primary keyis defined as CHAR, the foreign key must also be defined as CHAR. However,when you specify a SERIAL data type on a primary key in one table, you spec-ify an INTEGER on the foreign key of the relationship. The SERIAL andINTEGER construction is the only data type combination that you can mix ina relationship.
The decision tree shown in Figure 9-1 on page 9-6 summarizes the choicesamong data types. They are explained in the following sections.
Implementing Your Data Model 9-5
9-6 Informix Guide to S
Data Types
Data items pnumeric?
no
Figure 9-1A diagram of the decisions to be made in choosing a data type
(1 of 2)
urely yes
Numbers all integral? yes
no
All numbers between-215 and 215-1?
yes
no
All numbers between-231 and 231-1?
yes
no
SMALLINT
INTEGER
DECIMAL(p,0)
Number of fractionaldigits is fixed?
yes
no
At most 8 significantdigits?
yes
no
At most 16 significantdigits?
yes
no
DECIMAL(p,s)
SMALLFLOAT
FLOAT
DECIMAL(p)
QL: Tutorial
Data Types
Data is chronol
no
Data is ASCIIcharacters?
no
BYTE
Data containsforeign charact
no
(2 of 2)
ogical? yes
Span of time or specificpoint in time?
span
point
Precise only to nearestday?
yes
no
yes
No or little variance initem lengths?
yes
noLengths under 32,511bytes?
yes
no
Length exceeds 255bytes?
yes
no
INTERVAL
DATETIMEDATE
TEXTor VARCHAR( m,r)
CHAR(n)
ers?yes
No or little variance initem lengths?
yes
no
NVARCHAR(m,r)
NCHAR(n)
VARYING(m,r)CHARACTER
Implementing Your Data Model 9-7
9-8 Informix Guide to S
Data Types
Numeric Types
Informix database servers support eight numeric data types. Some are bestsuited for counters and codes, some for engineering quantities, and some formoney.
Counters and Codes: INTEGER and SMALLINT
The INTEGER and SMALLINT data types hold small whole numbers. They aresuited for columns that contain counts, sequence numbers, numeric identitycodes, or any range of whole numbers when you know in advance themaximum and minimum values to be stored.
Both types are stored as signed binary integers. INTEGER values have 32 bitsand can represent whole numbers from −231 through 231–1; that is, from–2,147,483,647 through 2,147,483,647. (The maximum negative number,–2,147,483,248, is reserved and cannot be used.)
SMALLINT values have only 16 bits. They can represent whole numbers from–32,767 through 32,767. (The maximum negative number, -32,768, is reservedand cannot be used.)
These data types have the following advantages:
■ They take up little space (2 bytes per value for SMALLINT and 4 bytesper value for INTEGER).
■ Arithmetic expressions such as SUM and MAX as well as sort compar-isons can be done very efficiently on them.
The disadvantage to using INTEGER and SMALLINT is the limited range ofvalues they can store. The database server does not store a value that exceedsthe capacity of an integer. Of course, this is not a problem when you know themaximum and minimum values to be stored.
QL: Tutorial
Data Types
Automatic Sequences: SERIAL
The SERIAL data type is simply INTEGER with a special feature. Whenever anew row is inserted into a table, the database server automatically generatesa new value for a SERIAL column. A table can have only one SERIAL column.Because the database server generates them, the serial values in new rows arealways different even when multiple users are adding rows at the same time.This is a useful service, because it is quite difficult for an ordinary programto coin unique numeric codes under those conditions.
After inserting 231 rows in a table, the database server uses all the positiveserial numbers. Depending on your needs, you might be concerned aboutthis because to use all the positive serial numbers, a single application wouldneed to insert a row every second for 68 years, or 68 applications would needto insert a row per second for a year. . However, if it did occur, the databaseserver would continue generating new numbers. It would treat the next-serial quantity as a signed integer. Because it uses only positive values, itwould simply wrap around and start generating integer values beginningwith 1.
The sequence of generated numbers always increases. When rows aredeleted from the table, their serial numbers are not reused. This means thatrows sorted on a SERIAL column are returned in the order in which they werecreated. That cannot be said of any other data type.
You can specify the initial value in a SERIAL column in the CREATE TABLEstatement. This makes it possible to generate different subsequences ofsystem-assigned keys in different tables. The stores7 database uses this tech-nique. In stores7, the customer numbers begin at 101, and the order numbersstart at 1001. As long as this small business does not register more than 899customers, all customer numbers have three digits and order numbers havefour.
A SERIAL column is not automatically a unique column. If you want to beperfectly sure no duplicate serial numbers occur, you must apply a uniqueconstraint (see “Using CREATE TABLE” on page 9-28). However, if youdefine the table using the interactive schema editor in DB-Access orINFORMIX-SQL, it automatically applies a unique constraint to any SERIALcolumn.
Implementing Your Data Model 9-9
9-10 Informix Guide to
Data Types
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 areupdating 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 numericcodes might not be acceptable to the database users).
Altering the Next SERIAL Number
The starting value for a SERIAL column is set when the column is created (see“Using CREATE TABLE” on page 9-28). You can use the ALTER TABLE state-ment later to reset the next value, the value that is used for the next-insertedrow.
You cannot set the next value below the current maximum value in thecolumn because causes the database server to generate duplicate numbers incertain situations. However, you can set the next value to any value higherthan the current maximum, thus creating gaps in the sequence.
Approximate Numbers: FLOAT and SMALLFLOAT
In scientific, engineering, and statistical applications, numbers are oftenknown to only a few digits of accuracy, and the magnitude of a number is asimportant as its exact digits.
The floating-point data types are designed for these applications. They canrepresent any numerical quantity, fractional or whole, over a wide range ofmagnitudes from the cosmic to the microscopic. For example, they can easilyrepresent both the average distance from the Earth to the Sun (1.5 × 109
meters) or Planck’s constant (6.625 × 10-27). Their only restriction is their lim-ited precision. Floating-point numbers retain only the most significant digitsof their value. If a value has no more digits than a floating-point number canstore, the value is stored exactly. If it has more digits, it is stored inapproximate form, with its least-significant digits treated as zeros.
SQL: Tutorial
Data Types
This lack of exactitude is fine for many uses, but you should never use afloating-point data type to record money or any other quantity for which it isan error to change the least significant digits to zero.
Two sizes of floating-point data types exist. The FLOAT type is adouble-precision, binary floating-point number as implemented in the Clanguage on your computer. One usually takes up 8 bytes. The SMALLFLOAT(also known as REAL) type is a single-precision, binary floating-point numberthat usually takes up 4 bytes. The main difference between the two data typesis their precision. A FLOAT column retains about 16 digits of its values; aSMALLFLOAT column retains only about 8 digits.
Floating-point numbers have the following advantages:
■ They store very large and very small numbers, including fractionalones.
■ They represent numbers compactly in 4 or 8 bytes.
■ Arithmetic functions such as AVG, MIN, and sort comparisons, areefficient on these data types.
The main disadvantage of floating-point numbers is that digits outside theirrange of precision are treated as zeros.
Adjustable-Precision Floating Point: DECIMAL(p)
The DECIMAL(p) data type is a floating-point type similar to FLOAT andSMALLFLOAT. The important difference is that you specify how many signif-icant digits it retains. The precision you write as p may range from 1 to 32,from fewer than SMALLFLOAT up to twice the precision of FLOAT.
The magnitude of a DECIMAL(p) number ranges from 10-130 to 10124.
It is easy to be confused about decimal data types. The one under discussionis DECIMAL(p); that is, DECIMAL with only a precision specified. The size ofDECIMAL(p) numbers depends on their precision; they occupy 1+p/2 bytes(rounded up to a whole number, if necessary).
DECIMAL(p) has the following advantages over FLOAT:
■ Precision can be set to suit the application, from highly approximateto highly precise.
■ Numbers with as many as 32 digits can be represented exactly.
Implementing Your Data Model 9-11
9-12 Informix Guide to
Data Types
D
■ Storage is used in proportion to the precision of the number.
■ Every Informix database server supports the same precision andrange of magnitudes, regardless of the host operating system.
The DECIMAL(p) data type has the following disadvantages:
■ Arithmetic and sorting are somewhat slower than on FLOATnumbers.
■ Many programming languages do not support the DECIMAL(p) dataformat the way they support FLOAT and INTEGER. When a programextracts a DECIMAL(p) value from the database, it may have to con-vert the value to another format for processing. (However,INFORMIX-4GL programs can use DECIMAL(p) values directly.)
Fixed-Point Numbers: DECIMAL and MONEY
Most commercial applications need to store numbers that have fixednumbers of digits on the right and left of the decimal point. Amounts ofmoney are the most common examples. Amounts in U.S. and other curren-cies are written with two digits to the right of the decimal point. Normally,you also know the number of digits needed on the left, depending on whosetransactions are recorded—perhaps 5 digits for a personal budget, 7 for asmall business, and 12 or 13 for a national budget.
These numbers are fixed-point numbers because the decimal point is fixed ata specific place, regardless of the value of the number. The DECIMAL(p,s) datatype is designed to hold them. When you specify a column of this type, youwrite 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 thedecimal point. (The relation between precision and scale is shown inFigure 9-2.) Scale can be zero, meaning it stores only whole numbers. Whenthis is done, DECIMAL(p,s) provides a way of storing integers of up to 32digits.
Figure 9-2The relation
between precisionand scale in a fixed-
point numberECIMAL(8,3) 31964.535
scale: 3 digits
precision: 8 digits
SQL: Tutorial
Data Types
As with the DECIMAL(p) data type, DECIMAL(p,s) takes up space inproportion to its precision. One value occupies 1+p/2 bytes, rounded up toa whole number of bytes.
The MONEY type is identical to DECIMAL(p,s), but with one extra feature.Whenever the database server converts a MONEY value to characters fordisplay, it automatically includes a currency symbol.
The advantages of DECIMAL(p,s) over INTEGER and FLOAT are that muchgreater precision is available (up to 32 digits as compared with 10 forINTEGER and 16 for FLOAT), and both the precision and the amount of stor-age required can be adjusted to suit the application.
The disadvantages are that arithmetic is less efficient and that manyprogramming languages do not support numbers in this form. Therefore,when a program extracts a number, it usually must convert it to anothernumeric form for processing. (However, INFORMIX-4GL programs can useDECIMAL(p,s) and MONEY values directly.)
Whose Money? Choosing a Currency Format
Each nation has its own way of punctuating amounts of money. When anInformix database server displays a MONEY value, it refers to a currencyformat defined to the operating system, usually in a variable namedDBMONEY. A currency symbol can precede or follow the amount, and thedecimal delimiter can be set to a period, a comma, or another character. Whenin NLS mode, you can set the LC_MONETARY environment variable to specifya foreign currency symbol and format. For details, see Chapter 4 of theInformix Guide to SQL: Reference.
Chronological Types
Informix database servers support three data types for recording time. TheDATE data type stores a calendar date. DATETIME records a point in time toany degree of precision from a year to a fraction of a second. The INTERVALdata type stores a span of time; that is, a duration.
Implementing Your Data Model 9-13
9-14 Informix Guide to
Data Types
Calendar Dates: DATE
The DATE data type stores a calendar date. A DATE value is actually a signedinteger whose contents are interpreted as a count of full days since midnighton December 31, 1899. Most often it holds a positive count of days into thecurrent century.
The DATE format has ample precision to carry dates into the far future (58,000centuries). Negative DATE values are interpreted as counts of days prior tothe epoch date; that is, a DATE of -1 represents the day December 30, 1899.
Because DATE values are integers, Informix database servers permit them tobe used in arithmetic expressions. For example, you can take the average ofa DATE column, or you can add 7 or 365 to a DATE column. In addition, a richset of functions exist specifically for manipulating DATE values. (See Chapter1 of the Informix Guide to SQL: Syntax.)
The DATE data type is compact at 4 bytes per item. Arithmetic functions andcomparisons execute quickly on a DATE column.
M/D/Y? D-M-Y? Choosing a Date Format
You can punctuate and order the components of a date in many ways. Whenan Informix database server displays a DATE value, it refers to a formatdefined to the operating system, usually in a variable named DBDATE. Thenumbers for day, month, and year can be shown in any order, separated by achosen delimiter. For more information, see Chapter 4 of the Informix Guide toSQL: Reference.
Exact Points in Time: DATETIME
The DATETIME data type stores any moment in time in the era beginning1 A.D. In fact, DATETIME is really a family of 28 data types, each with a dif-ferent precision. When you define a DATETIME column, you specify its preci-sion. It may contain any sequence from the list year, month, day, hour, minute,second, and fraction. Thus, you can define a DATETIME column that stores onlya year, only a month and day, a date and time that is exact to the hour, or evento the millisecond. The size of a DATETIME value ranges from 2 to 11 bytesdepending on its precision, as shown in Figure 9-3 on page 9-15.
SQL: Tutorial
Data Types
Precisionyear to yearyear to monthyear to dayyear to houryear to minuteyear to secondyear to fractionmonth to montmonth to daymonth to hourmonth to minumonth to seconmonth to fractioday to day
* When f is odd
The advantage of DATETIME is that it can store dates more precisely than tothe 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 ofa DATETIME or INTERVAL Value” on page 9-16).
Durations: INTERVAL
The INTERVAL data type stores a duration, that is, a length of time. Thedifference between two DATETIME values is an INTERVAL, which representsthe span of time that separates them. The following examples might help toclarify the differences:
■ An employee began working on January 21, 1994 (either a DATE or aDATETIME).
■ She has worked for 254 days (an INTERVAL, the difference betweenthe 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 (anotherINTERVAL).
■ Her quitting time is 1745 hours (the sum of the DATETIME when shebegins work and the two INTERVALs).
Figure 9-3All possible
precisions of theDATETIME data type,
with their sizes inbytes
Size* Precision Size*3 day to hour 34 day to minute 45 day to second 56 day to fraction(f) 5+f/27 hour to hour 28 hour to minute 3
(f) 8+f/2 hour to second 4h 2 hour to fraction(f) 4+f/2
3 minute to minute 24 minute to second 3
te 5 minute to fraction(f) 3+f/2d 6 second to second 2n(f) 6+f/2 second to fraction(f) 2+f/2
2 fraction to fraction(f) 1+f/2
, round the size to the next full byte.
Implementing Your Data Model 9-15
9-16 Informix Guide to
Data Types
Precisionyear(p) to yearyear(p) to monthmonth(p) to monthday(p) to dayday(p) to hourday(p) to minuteday(p) to secondday(p) to fraction(hour(p) to hour
* Round a fraction
As with DATETIME, INTERVAL is a family of types with different precisions.An INTERVAL can represent a count of years and months; or it can representa count of days, hours, minutes, seconds, or fractions of seconds; 18 possibleprecisions in all. The size of an INTERVAL value ranges from 2 to 12 bytes,depending on the formulas shown in Figure 9-4.
INTERVAL values can be negative as well as positive. You can add or subtractthem, and you can scale them by multiplying or dividing by a number. Thisis 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, “Whatis one-half of April 23?”
Forcing the Format of a DATETIME or INTERVAL Value
The database server always displays the components of an INTERVAL orDATETIME value in the order year-month-day hour:minute:second.fraction. Itdoes not refer to the date format defined to the operating system, as it doeswhen formatting a DATE.
You can write a SELECT statement that displays the date part of a DATETIMEvalue in the system-defined format. The trick is to isolate the componentfields using the EXTEND function and pass them through the MDY() function,which converts them to a DATE. The following code shows a partial example:
SELECT ... MDY (EXTEND (DATE_RECEIVED, MONTH TO MONTH),EXTEND (DATE_RECEIVED, DAY TO DAY),EXTEND (DATE_RECEIVED, YEAR TO YEAR) )FROM RECEIPTS ...
Figure 9-4All possible
precisions of theINTERVAL data type,
with their sizes inbytes
Size* Precision Size*1+p/2 hour(p) to minute 2+p/22+p/2 hour(p) to second 3+p/21+p/2 hour(p) to fraction(f) 4+(p+f)/21+p/2 minute(p) to minute 1+p/22+p/2 minute(p) to second 2+p/23+p/2 minute(p) to fraction(f) 3+(p+f)/24+p/2 second(p) to second 1+p/2
f) 5+(p+f)/2 second(p) to fraction(f) 2+(p+f)/21+p/2 fraction to fraction(f) 1+f/2
al size to the next full byte.
SQL: Tutorial
Data Types
When you are designing a report using INFORMIX-4GL or INFORMIX-SQL,you have the greater flexibility of the PRINT statement. Select each compo-nent of a DATETIME or INTERVAL value as an expression using EXTEND. Giveeach expression an alias for convenience, as shown in the following partialSELECT statement:
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 thedesired punctuation, as shown in the following example:
PRINT 'Start work at ', H USING '&&', M USING '&&', 'hours.'Start work at 0800 hours.
Character Types
All Informix database servers support the CHAR(n) data type. When NLS hasbeen enabled, the Informix database servers support the NCHAR(n) datatype. INFORMIX-OnLine Dynamic Server also supports other special use char-acter data types.
Character Data: CHAR(n) and NCHAR(n)
The CHAR(n) data type contains a sequence of n ASCII characters. The lengthn ranges from 1 to 32,767. (If you are using the INFORMIX-SE database server,the maximum length is 32,511.) In NLS mode, the NCHAR(n) data type con-tains a sequence of n native characters with the same length range as CHAR.
Whenever a CHAR(n) or NCHAR(n) value is retrieved or stored, exactly nbytes are transferred. If an inserted value is short, it is extended with spacesto make up n bytes. A value longer than n is truncated. No provision existsfor variable-length data in this format.
A CHAR(n) or NCHAR(n) value can include tabs and spaces but normallycontains no other nonprinting characters. When rows are inserted usingINSERT or UPDATE, or when rows are loaded with a utility program, nomeans exists for entering nonprintable characters. However, when rows arecreated by a program using embedded SQL, the program can insert any char-acter except the null (binary zero) character. It is not a good idea to store non-printable characters in a character column because standard programs andutilities do not expect them.
Implementing Your Data Model 9-17
9-18 Informix Guide to
Data Types
The advantage of the CHAR(n) or NCHAR(n) data type is that it is availableon all database servers. The only disadvantage of CHAR(n) or NCHAR(n) isthat its length is fixed. When the length of data values varies widely from rowto row, space is wasted. NCHAR(n) is available on all database servers whenNLS has been enabled.
Variable-Length Strings: CHARACTER VARYING(m,r), VARCHAR(m,r),and NVARCHAR(m,r)Tip: The data type CHARACTER VARYING (m,r) is ANSI-compliant.VARCHAR(m,r) is an Informix data type.
Often the items in a character column have different lengths; that is, manyhave an average length and only a few have the maximum length. TheCHARACTER VARYING(m,r) or VARCHAR(m,r) data type (or NVARCHAR(m,r)when NLS has been enabled) is designed to save disk space when storingsuch data. A column defined as CHARACTER VARYING(m,r), VARCHAR(m,r),or NVARCHAR(m,r) is used just like one defined as CHAR(n). When youdefine a CHARACTER VARYING(m,r), VARCHAR(m,r), or NVARCHAR(m,r)column, you specify m as the maximum length of a data item. Only the actualcontents of each item are stored on disk, with a 1-byte length field. The limiton m is 255; that is, a CHARACTER VARYING(m,r), VARCHAR(m,r), or NVAR-CHAR(m,r) value can store as many as 255 characters. If the column isindexed, the limit on m is 254.
The second parameter, r, is an optional reserve length that sets a lower limiton 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 whenrows are updated. (See “Variable-Length Execution Time” on page 9-19.)
The advantages of the CHARACTER VARYING(m,r), VARCHAR(m,r), or NVAR-CHAR(m,r) data type over the CHAR(n) or NCHAR(m,r) type are found in thefollowing list:
■ It conserves disk space when the lengths of data items vary widelyor when only a few items are longer than average.
■ Queries on the more compact tables can be faster.
SQL: Tutorial
Data Types
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.
Variable-Length Execution Time
When the CHARACTER VARYING(m,r), VARCHAR(m,r), or NVARCHAR(m,r)data type is used, the rows of a table have varying lengths instead of fixedlengths. This has mixed effects on the speed of database operations.
Because more rows fit in a disk page, the database server can search the tableusing fewer disk operations than if the rows were of fixed length. As a result,queries can execute more quickly. Insert and delete operations can be a littlequicker for the same reason.
When you update a row, the amount of work the database server must dodepends on the length of the new row as compared with the old one. If thenew row is the same size or shorter, execution time is not significantly differ-ent than it is with fixed-length rows. But if the new row is longer than the oldone, the database server might have to perform several times as many diskoperations. Thus, updates of a table that uses CHARACTER VARYING(m,r),VARCHAR(m,r), or NVARCHAR(m,r) data can sometimes be slower thanupdates of a fixed-length field.
You can mitigate this effect by specifying r as a size that covers a highproportion of the data items. Then, most rows use the reserve length; only alittle space is wasted in padding, and updates are only slow when a normalvalue is replaced with one of the rare, longer ones.
Implementing Your Data Model 9-19
9-20 Informix Guide to
Data Types
Large Character Objects: TEXT
The TEXT data type stores a block of text. It is designed to store self-containeddocuments: business forms, program source or data files, or memos.Although you can store any data in a TEXT item, Informix tools expect that aTEXT item is printable, so this data type should be restricted to printableASCII text.
TEXT values are not stored with the rows of which they are a part. They areallocated in whole disk pages, usually areas away from rows. (See theINFORMIX-OnLine Dynamic Server Administrator’s Guide.)
The advantage of the TEXT data type over CHAR(n) and VARCHAR(m,r) isthat the size of a TEXT data item has no limit except the capacity of disk stor-age to hold it. The disadvantages of the TEXT data type are found in the fol-lowing 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 SQLstatement. (See “How Blobs Are Used”.)
■ It is not available with all Informix database servers.
You can display TEXT values in reports generated with INFORMIX-4GLprograms or the ACE report writer. You can display TEXT values on a screenand edit them using screen forms generated with INFORMIX-4GL programsor with the PERFORM screen-form processor.
How Blobs Are Used
Collectively, columns of type TEXT and BYTE are called binary large objects(blobs). The database server simply stores and retrieves them. Normally, blobvalues are fetched and stored by programs written using INFORMIX-4GL,NewEra, or a language that supports embedded SQL, such asINFORMIX-ESQL/C. In such a program you can fetch, insert, or update a blobvalue in a manner similar to the way you read or write a sequential file.
SQL: Tutorial
Data Types
In any SQL statement, interactive or programmed, a blob column cannot beused in the following ways:
■ In arithmetic or Boolean expressions
■ In a GROUP BY or ORDER BY clause
■ In a UNIQUE test
■ For indexing, either by itself or as part of a composite index
In a SELECT statement entered interactively, or in a form or report, a blob canonly perform the following functions:
■ Be selected by name, optionally with a subscript to extract part of it
■ Have its length returned by selecting LENGTH(column)
■ Be tested with the IS [NOT] NULL predicate
In an interactive INSERT statement, you can use the VALUES clause to insert ablob value, but the only value you can give that column is null. However, youcan use the SELECT form of the INSERT statement to copy a blob value fromanother table.
In an interactive UPDATE statement, you can update a blob column to null orto a subquery returning a blob column.
Binary Objects: BYTE
The BYTE data type is designed to hold any data a program can generate:graphic images, program object files, and documents saved by any word pro-cessor or spreadsheet. The database server permits any kind of data of anylength in a BYTE column.
As with TEXT, BYTE data items are stored in whole disk pages in separate diskareas from normal row data.
The advantage of THE BYTE data type, as opposed to TEXT or CHAR(n), is thatit accepts any data. Its disadvantages are the same as those of the TEXT datatype.
Implementing Your Data Model 9-21
9-22 Informix Guide to
Null Values
Changing the Data Type
You can use the ALTER TABLE statement to change the data type assigned toa column after the table is built. Although this is sometimes necessary, youshould avoid doing it for the following reasons:
■ To change a data type, the database server must copy and rebuild thetable. For large tables, that can take a lot of time and disk space.
■ Some data-type changes can cause a loss of information. For exam-ple, when you change a column from a longer to a shorter charactertype, long values are truncated; when you change to a less-precisenumeric type, low-order digits are truncated.
■ Existing programs, forms, reports, and stored queries might alsohave to be changed.
Null ValuesColumns in a table may be designated as containing null values. A null valuemeans that the value for the column may be unknown or not applicable. Forexample, in the telephone-directory example in Chapter 8, the anniv columnof the name table may contain null values; if you do not know the person’sanniversary, you do not specify it. Be careful not to confuse null value withzero or blank value.
Default ValuesA default value is the value inserted into a column when an explicit value isnot 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, constantexpressions:
■ USER
■ CURRENT
■ TODAY
■ DBSERVERNAME
SQL: Tutorial
Check Constraints
Not all columns need default values, but as you work with your data modelyou may discover instances where the use of a default value saves data-entrytime or prevents data-entry error. For example, the telephone-directorymodel 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 Statecolumn.
Check ConstraintsCheck constraints specify a condition or requirement on a data value beforedata can be assigned to a column during an INSERT or UPDATE statement. Ifa row evaluates to false for any of the check constraints defined on a tableduring an insert or update, the database server returns an error. You define aconstraint using the CREATE TABLE or ALTER TABLE statements. For exam-ple, the following requirement constrains the values of an integer domain toa certain range:
Customer_Number >= 50000 AND Customer_Number <= 99999
You can express constraints on character-based domains using the MATCHESpredicate and the regular-expression syntax it supports. For example, the fol-lowing constraint restricts a Telephone domain to the form of a U.S. local tele-phone number:
vce_num MATCHES '[2-9][2-9][0-9]-[0-9][0-9][0-9][0-9]'
For additional information about check constraints, see the CREATE TABLEand ALTER TABLE statements in the Informix Guide to SQL: Syntax.
Implementing Your Data Model 9-23
9-24 Informix Guide to
Creating the Database
Creating the DatabaseNow you are ready to create the data model as tables in a database. You dothis with the CREATE DATABASE, CREATE TABLE, and CREATE INDEX state-ments. The syntax of these statements is shown in detail in the Informix Guideto SQL: Syntax. This section discusses the use of CREATE DATABASE andCREATE TABLE in implementing a data model. The use of CREATE INDEX iscovered in Chapter 10, “Granting and Limiting Access to Your Database.”
Keep in mind that the telephone-directory data model is used for illustrativepurposes only. For the sake of the example, we translate it into SQLstatements.
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-30 for more information.
When the tables exist, you must populate them with rows of data. You can dothis manually, with a utility program, or with custom programming.
Using CREATE DATABASEA database is a container that holds all the parts that go in to a data model.These parts include not only the tables but also views, indexes, synonyms,and other objects associated with the database. You must create a databasebefore you can create anything else. Besides creating the database, theCREATE DATABASE statement establishes the kind of transaction logging tobe used. Transaction logging is discussed in Chapter 4, “Modifying Data.”
The OnLine database server differs from other database servers in the waythat it creates databases and tables: OnLine is discussed first.
Using CREATE DATABASE with INFORMIX-OnLine Dynamic Server
When the OnLine database server creates a database, it sets up records thatshow the existence of the database and its mode of logging. It manages diskspace directly, so these records are not visible to operating system com-mands.
SQL: Tutorial
Using CREATE DATABASE
Avoiding Name Conflicts
Normally, only one copy of OnLine is running on a computer, and it managesthe databases that belong to all users of that computer. It keeps only one listof database names. The name of your database must be different from that ofany other database managed by that database server. (It is possible to runmore than one copy of the database server. This is sometimes done, for exam-ple, to create a safe environment for testing apart from the operational data.In that case, you must be sure you are using the correct database server whenyou create the database, and again when you access it later.)
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 administratorwhether you should use a particular dbspace. The administrator can put adatabase in a dbspace to isolate it from other databases or to locate it on a par-ticular disk device. (The INFORMIX-OnLine Dynamic Server Administrator’sGuide discusses dbspaces and their relationship to disk devices.)
Some dbspaces are mirrored (duplicated on two disk devices for high reliabil-ity); your database can be put in a mirrored dbspace if its contents are ofexceptional importance.
Implementing Your Data Model 9-25
9-26 Informix Guide to
Using CREATE DATABASE
Choosing the Type of Logging
OnLine offers the following choices for transaction logging:
■ No logging at all. This choice is not recommended; if the database islost to a hardware failure, all data alterations since the last archiveare lost.
CREATE DATABASE db_with_no_log
When you do not choose logging, BEGIN WORK and other SQL state-ments related to transaction processing are not permitted in thedatabase. This affects the logic of programs that use the database.
■ Regular (unbuffered) logging. This is the best choice for most data-bases. In the event of a failure, only uncommitted transactions arelost.
CREATE DATABASE a_logged_db WITH LOG
■ Buffered logging. If the database is lost, a few or possibly none of themost recent alterations are lost. In return for this small risk, perfor-mance during alterations is improves slightly.
CREATE DATABASE buf_log_db WITH BUFFERED LOG
Buffered logging is best for databases that are updated frequently (sothat 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 SETLOG statement to alternate between buffered and regular logging.
■ ANSI-compliant logging. This is the same as regular logging, but theANSI rules for transaction processing are also enforced. (See the dis-cussion of ANSI-compliant databases in Chapter 1 of the InformixGuide to SQL: Reference.)
CREATE DATABASE std_rules_db WITH LOG MODE ANSI
The design of ANSI SQL prohibits the use of buffered logging.
The OnLine administrator can turn transaction logging on and off later. Forexample, it can be turned off before inserting a large number of new rows.
SQL: Tutorial
Using CREATE DATABASE
Using CREATE DATABASE with Other Informix Database Servers
Other Informix database servers create a database as a set of one or more filesmanaged by the operating system. For example, under the UNIX operatingsystem, a database is a small group of files in a directory whose name is thedatabase name. (See the manual for your database server for details on howit uses files.) This means that the rules for database names are the same as therules the operating system has for file names.
Choosing the Type of Logging
Other database servers offer the following three choices of logging:
■ No logging at all. This choice is not recommended; if the database islost to a hardware failure, all data alterations since the last archiveare lost.
CREATE DATABASE not_logged_db
When you do not choose logging, BEGIN WORK and other SQLstatements related to transaction processing are not permitted in thedatabase. This affects the logic of programs that use the database.
■ Regular logging. This is the best choice for most databases. If thedatabase is lost, only the alteration in progress at the time of failureis lost.
CREATE DATABASE a_logged_db WITH LOG IN '/logs/a_log_file'
You must specify a file to contain the transaction log. (The form of thefile name depends on the rules of your operating system.) This filegrows whenever the database is altered. Whenever the database filesare archived, you should set the log file back to an empty conditionso it reflects only transactions following the latest archive.
■ ANSI-compliant logging. This is the same as regular logging, but theANSI rules for transaction processing are also enforced. (See the dis-cussion of ANSI-compliant databases in Chapter 1 of the InformixGuide to SQL: Reference.)
CREATE DATABASE std_rules_db WITH LOG IN '/logs/a_log_file' MODE ANSI
You can add a transaction log to a nonlogged database later using the STARTDATABASE statement.
Implementing Your Data Model 9-27
9-28 Informix Guide to
Using CREATE TABLE
Using CREATE TABLEUse the CREATE TABLE statement to create each table you designed in thedata model. This statement has a complicated form, but it is basically a list ofthe columns of the table. For each column, you supply the followinginformation:
■ The name of the column
■ The data type (from the domain list you made)
■ If the column (or columns) is a primary key, the PRIMARY KEYconstraint
■ If the column (or columns) is a foreign key, the FOREIGN KEYconstraint
■ If the column is not a primary key and should not allow nulls, theNOT NULL constraint
■ If the column is not a primary key and should not allow duplicates,the UNIQUE constraint
■ If the column has a default value, the DEFAULT constraint
■ If the column has a check constraint, the CHECK constraint
In short, the CREATE TABLE statement is an image in words of the table asyou drew it in the data model diagram. Figure 9-5 on page 9-29 shows thestatements for the telephone-directory model whose diagram is shown inFigure 8-16 on page 8-28.
SQL: Tutorial
Using CREATE TABLE
CREATE TABL(reclnafnabdaannema);
CREATE TABL(chirecFOR);
CREATE TABL(id_recstrcitstazipFOR);
CREATE TABL(vcevcerecFOR);
CREATE TABL(faxopeopePRI);
:
Figure 9-5The CREATE TABLE
statements for thetelephone-directory
data model
(1 of 2)
E name
_num SERIAL PRIMARY KEY,me CHAR(20),me CHAR(20),te DATE,iv DATE,il VARCHAR(25)
E child
ld CHAR(20),_num INT,EIGN KEY (rec_num) REFERENCES NAME (rec_num)
E address
num SERIAL PRIMARY KEY,_num INT,eet VARCHAR (50,20),y VARCHAR (40,10),te CHAR(5) DEFAULT ’CA’,code CHAR(10),EIGN KEY (rec_num) REFERENCES name (rec_num)
E voice
_num CHAR(13) PRIMARY KEY,_type CHAR(10),_num INT,EIGN KEY (rec_num) REFERENCES name (rec_num)
E fax
_num CHAR(13),r_from DATETIME HOUR TO MINUTE,r_till DATETIME HOUR TO MINUTE,MARY KEY (fax_num)
Implementing Your Data Model 9-29
9-30 Informix Guide to
Using Command Scripts
CREATE TABL(faxrecPRIFORFOR);
CREATE TABL(mdmrecb_tFOR);
Using Command ScriptsYou can create the database and tables by entering the statementsinteractively. But what if you have to do it again or several more times?
You might have to do it again to make a production version after a testversion is satisfactory. You might have to implement the same data model onseveral computers . To save time and reduce the chance of errors, you can putall the commands to create a database in a file and execute themautomatically.
Capturing the Schema
You can write the statements to implement your model into a file. However,you can also have a program do it for you. See Chapter 5 of the Informix Guideto SQL: Reference. It documents the dbschema utility, a program that exam-ines the contents of a database and generates all the SQL statements requiredto re-create it. You can build the first version of your database interactively,making changes until it is exactly as you want it. Then you can use dbschemato generate the SQL statements necessary to duplicate it.
(2 of 2)
E faxname
_num CHAR(13),_num INT,MARY KEY (fax_num, rec_num),EIGN KEY (fax_num) REFERENCES fax (fax_num),EIGN KEY (rec_num) REFERENCES name (rec_num)
E modem
_num CHAR(13) PRIMARY KEY,_num INT,ype CHAR(5),EIGN KEY (rec_num) REFERENCES name (rec_num)
SQL: Tutorial
Populating the Tables
Executing the File
DB-Access or INFORMIX-SQL, the programs you use to enter SQL statementsinteractively, can be driven from a file of commands. The use of these prod-ucts is covered in the DB-Access User Manual or the INFORMIX-SQL UserGuide. You can start DB-Access or INFORMIX-SQL and have them read andexecute a file of commands prepared by you or by dbschema.
An Example
Most Informix database server products come with a demonstrationdatabase called stores7 (the one used for most of the examples in this book).The stores7 database is delivered as an operating system command scriptthat calls Informix products to build the database. You can copy thiscommand script and use it as the basis for automating your own data model.
Populating the TablesFor your initial tests, it is easiest to populate the tables interactively by typingINSERT statements in DB-Access or INFORMIX-SQL. As shown in the follow-ing example, to insert a row into the manufact table of the stores7 databasein DB-Access, enter the following command:
INSERT INTO manufact VALUES ('MKL', 'Martin', 15)
If you are preparing an application program in NewEra, INFORMIX-4GL, oranother language, you can use the program to enter rows.
Often, the initial rows of a large table can be derived from data held in tablesin another database or in operating system files. You can move the data intoyour new database in a bulk operation. If the data is in another Informixdatabase, you can retrieve it in several ways.
If you are using INFORMIX-OnLine Dynamic Server, you can simply select thedata you want from the other database on another database server as part ofan INSERT statement in your database. As shown in the following example,you could select information from the items table in the stores7 database toinsert into a new table:
INSERT INTO newtableSELECT item_num, order_num, quantity, stock_num,
manu_code, total_priceFROM stores7@otherserver:items
Implementing Your Data Model 9-31
9-32 Informix Guide to
Populating the Tables
If you are using INFORMIX-SE, you can select the data you want from onedatabase and insert it into another database as long as the databases are onthe same database server. As shown in the following example, you couldselect information from the catalog table in the stores7 database to insert intoa new table by using a temporary table:
CONNECT TO 'sharky/db1';
SELECT item_num, stock_num, manu_codeFROM itemsINTO TEMP temptable;
DISCONNECT;
CONNECT TO 'sharky/db2';
SELECT * from temptableINTO TEMP newsetable;
If you want to select data from another database server in INFORMIX-SE, youmust export the data to a file. You can use the UNLOAD statement inDB-Access, INFORMIX-SQL, NewEra, or INFORMIX-4GL; or you can write areport 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 toconvert it into a flat ASCII file; that is, a file of printable data in which eachline represents the contents of one table row.
After you have the data in a file, you can load it into a table using the dbloadutility. Read about dbload in Chapter 5 of the Informix Guide to SQL: Reference.The LOAD statement in DB-Access, INFORMIX-SQL, INFORMIX-4GL, orNewEra can also load rows from a flat ASCII file. See Chapter 1 of the InformixGuide to SQL: Syntax for information about the LOAD and UNLOADstatements.
SQL: Tutorial
Populating the Tables
Inserting hundreds or thousands of rows goes much faster if you turn offtransaction logging. No point exists in logging these insertions because, inthe event of a failure, you can easily re-create the lost work. The following listcontains the steps of a large bulk-load operation:
■ If any chance exists that other users are using the database, excludethem with the DATABASE EXCLUSIVE statement.
■ If you are using INFORMIX-OnLine Dynamic Server, ask theadministrator to turn off logging for the database.
The existing logs can be used to recover the database to its presentstate, and the bulk insertion can be run again to recover those rows ifthey are lost.
■ Perform the statements or run the utilities that load the tables withdata.
■ Archive the newly loaded database.
If you are using INFORMIX-OnLine Dynamic Server, either ask theadministrator to perform a full or incremental archive, or use theonunload utility to make a binary copy of your database only.
If you are using other database servers, use operating system com-mands to back up the files that represent the database.
■ Restore transaction logging and release the exclusive lock on thedatabase.
You can enclose the steps of populating a database in a script of operatingsystem commands. You can automate the INFORMIX-OnLine Dynamic Serveradministrator commands by invoking the command-line equivalents to ON-Monitor.
Implementing Your Data Model 9-33
9-34 Informix Guide to
Fragmenting Tables and Indexes
Fragmenting Tables and IndexesThis section on fragmentation explains how to create and manage frag-mented tables using SQL statements. It covers the following topics:
■ How to create and maintain fragmented tables and indexes
■ How to access data stored in fragmented tables
Before reading this section, you should familiarize yourself with the termsand concepts related to fragmentation and PDQ that are contained in theINFORMIX-OnLine Dynamic Server Administrator’s Guide.
Creating a Fragmented TableYou can fragment a table at the same time you create it, or you can fragmentexisting nonfragmented tables. An overview of both alternatives is given inthe following sections. For the complete syntax of the SQL statements thatyou use to create fragmented tables, see Chapter 1 of the Informix Guide toSQL: Syntax.
Before you create a fragmented table, you must decide on an appropriatedistribution scheme for your tables. See the INFORMIX-OnLine DynamicServer Administrator’s Guide for advice on choosing a distribution scheme thatmeets your needs.
SQL: Tutorial
Fragmenting a New Table
Fragmenting a New TableTo create a fragmented table, use the FRAGMENT BY clause of the CREATETABLE statement. Suppose that you wish to create a fragmented table similarto the stores7 table, orders. You decide on a round-robin distribution schemewith three fragments. Consult with the OnLine administrator to set up threedbspaces, one for each of the fragments: dbspace1, dbspace2, and dbspace3.To create the fragmented table, execute the following SQL statement:
CREATE TABLE my_orders (order_num SERIAL(1001),order_date DATE,customer_num INT,ship_instruct CHAR(40),backlog CHAR(1),po_num CHAR(10),ship_date DATE,ship_weight DECIMAL(8,2),ship_charge MONEY(6),paid_date DATE,PRIMARY KEY (order_num),FOREIGN KEY (customer_num) REFERENCES customer(customer_num))FRAGMENT BY ROUND ROBIN IN dbspace1,dbspace2,dbspace3
If you decide instead to create the table using an expression-baseddistribution scheme, you can use the FRAGMENT BY EXPRESSION clause ofCREATE TABLE. Suppose your my_orders table has 30,000 rows, and that youwish to distribute rows evenly across three fragments stored in dbspace1,dbspace2, and dbspace3. You decide to use the column order_num to definethe expression fragments.
You can define the expression as shown in the following example:
CREATE TABLE my_orders (order_num serial, ...)FRAGMENT BY EXPRESSION
order_num < 10000 IN dbspace1,order_num < 20000 IN dbspace2,order_num >= 20000 IN dbspace3
Implementing Your Data Model 9-35
9-36 Informix Guide to
Creating A Fragmented Table from Nonfragmented Tables
Creating A Fragmented Table from Nonfragmented TablesYou might need to convert nonfragmented tables into fragmented tables inthe following circumstances:
■ You have an application-implemented version of tablefragmentation.
In this case, it is likely that you will want to convert several smalltables into one large fragmented table. The following section tellsyou how to proceed when this is the case.
■ You have an existing large table that you want to fragment.
Follow the instructions in the section “Creating a Fragmented Tablefrom a Single Nonfragmented Table” on page 9-37.
Remember that before you perform the conversion, you must set up anappropriate number of dbspaces to contain the newly created fragmentedtables.
Creating a Table From More Than One Nonfragmented Table
You can combine two or more nonfragmented tables into a single fragmentedtable. The nonfragmented tables must have identical table structures andmust be stored in separate dbspaces. To combine the nonfragmented tables,use the ATTACH clause of the ALTER FRAGMENT statement.
For example, suppose that you have three nonfragmented tables, account1,account2, and account3, and that you store the tables in the dbspacesdbspace1, dbspace2, and dbspace3, respectively. All three tables have iden-tical structures, and you want to combine the three tables into one table thatis fragmented by expression on the common column acc_num.
You want rows with acc_num less than or equal to 1120 to be stored in thefragment stored in dbspace1. Rows with acc_num greater than 1120 but lessthan or equal to 2000 are to be stored in dbspace2. Finally, rows withacc_num greater than 2000 are to be stored dbspace3.
SQL: Tutorial
Modifying a Fragmented Table
To fragment the tables with this fragmentation strategy, execute the followingSQL statement:
ALTER FRAGMENT ON TABLE tab1 ATTACHtab1 AS acc_num <= 1120,tab2 AS acc_num > 1120 and acc_num <= 2000,tab3 AS acc_num > 2000
The result is a single table, tabl. The other tables, tab2 and tab3 were con-sumed and no longer exist. For more information on the ATTACH clause ofthe ALTER FRAGMENT statement, see Chapter 1 of the Informix Guide to SQL:Syntax.
Creating a Fragmented Table from a Single Nonfragmented Table
To create a fragmented table from a nonfragmented table, use the INIT clauseof the ALTER FRAGMENT statement. For example, suppose you want to con-vert the table orders to a table fragmented by round robin. The following SQLstatement performs the conversion:
ALTER FRAGMENT ON TABLE orders INIT FRAGMENT BY ROUND ROBIN
Note that any existing indexes on the nonfragmented table will becomefragmented with the same fragmentation strategy as the table.
Modifying a Fragmented TableYou can make two general types of modifications to a fragmented table. Thefirst type consists of the modifications that you can make to a nonfragmentedtable. Such modifications include adding a column, dropping a column,changing a column data type, and so on. For these modifications, use thesame SQL statements that you would normally use on a nonfragmented table.
The second type of modification consists of changes to a fragmentationstrategy. This section explains how to modify a fragmentation strategy usingSQL statements.
Implementing Your Data Model 9-37
9-38 Informix Guide to
Modifying Fragmentation Strategies
Modifying Fragmentation StrategiesThe need to alter a fragmentation strategy after you implementfragmentation sometimes occurs. Most frequently, you will need to modifyyour fragmentation strategy when fragmentation is used with intraqueryparallelization or interquery parallelization. Modifying your fragmentationstrategy in these circumstances is one of several ways you can tune the per-formance of your OnLine system.
Change a Fragmentation Strategy Using the MODIFY Clause
You can modify an existing fragmentation strategy using the ALTERFRAGMENT statement. Use the MODIFY clause of the ALTER FRAGMENTstatement to modify one or more of the expressions in a fragmentationstrategy.
For example, suppose that you initially created the fragmented table with thefollowing CREATE TABLE statement:
CREATE TABLE account (acc_num INTEGER, ............)FRAGMENT BY EXPRESSION
acc_num <= 1120 in dbspace1,acc_num > 1120 and acc_num < 2000 in dbspace2,REMAINDER IN dbspace3
Later, you want to ensure that no account numbers with a value less than orequal to zero are stored in the fragment contained in dbspace1. Executing thefollowing ALTER FRAGMENT statement will accomplish this:
ALTER FRAGMENT ON TABLE accountMODIFY dbspace1 to acc_num > 0 and acc_num <=1120
You cannot alter the number of fragments contained in your distributionscheme using the MODIFY clause. Use the INIT or ADD clause of ALTERFRAGMENT described in the next section instead.
SQL: Tutorial
Modifying Fragmentation Strategies
Adding a New Fragment
If the modifications that you want to make require adding a new fragment toyour table, use the ADD clause of the ALTER FRAGMENT statement.
For example, suppose that you want to add a fragment to a table that youcreated using the following SQL statement:
CREATE TABLE frag_table ...FRAGMENT BY ROUND ROBIN IN dbspace1,dbspace2,dbspace3
To add a fourth dbspace, dbspace4, execute the following SQL statement:
ALTER FRAGMENT ON TABLE frag_table ADD dbspace4
The ADD clause of ALTER FRAGMENT contains options for adding a dbspacebefore or after an existing dbspace, provided the fragmentation strategy isexpression-based. See the ALTER FRAGMENT statement in Chapter 1 of theInformix Guide to SQL: Syntax for more information.
Completely Reinitialize a Fragmentation Scheme Using the INITClause
Consider using the INIT clause when you want to completely reinitialize afragmentation strategy. For example, suppose that you initially created thefragmented table with the following CREATE TABLE statement:
CREATE TABLE account (acc_num INTEGER, ............)FRAGMENT BY EXPRESSION
acc_num <= 1120 in dbspace1,acc_num > 1120 and acc_num < 2000 in dbspace2,REMAINDER IN dbspace3
However, you find that after several months of operation with thisdistribution scheme, the number of rows in the fragment contained indbspace2 is twice the number of rows contained in the other two fragments.This causes the disk containing dbspace2 to become an I/O bottleneck.
To remedy this situation, you decide to modify the distribution so that thenumber of rows in each fragment is approximately even. You want to modifythe distribution scheme so that instead of three fragments, it will contain fourfragments. A new dbspace, dbspace2a, is to contain the new fragment thatwill store the first half of the rows previously contained in dbspace2. Thefragment contained in dbspace2 will contain the second half of the rows thatit previously stored.
Implementing Your Data Model 9-39
9-40 Informix Guide to
Dropping A Fragment
To implement the new distribution scheme, first create the dbspacedbspace2a. Then execute the following statement:
ALTER FRAGMENT ON TABLE account INITFRAGMENT BY EXPRESSION
acc_num <= 1120 in dbspace1,acc_num > 1120 and acc_num <= 1500 in dbspace2a,acc_num > 1500 and acc_num < 2000 in dbspace2,REMAINDER IN dbspace3
As soon as you execute this statement, OnLine discards the old fragmenta-tion strategy and the rows contained in the table are redistributed accordingto the new fragmentation strategy.
You can also use the INIT clause of ALTER FRAGMENT to perform thefollowing actions:
■ Convert a single nonfragmented table into a fragmented table
■ Convert a fragmented table into a nonfragmented table
■ Convert a table fragmented by round-robin to have an expression-based fragmentation strategy
■ Convert a table fragmented by expression to have a round robinfragmentation strategy
See the ALTER FRAGMENT statement in Chapter 1 of the Informix Guide toSQL: Syntax for more information.
Dropping A FragmentIn the process of defining a fragmentation strategy, you may find it necessaryto drop one or more fragments. Suppose you wish to drop a fragment thatwas defined by this SQL statement:
CREATE TABLE frag_table (col_a int, col_b int)FRAGMENT BY ROUND ROBIN IN dbspace1,dbspace2,dbspace3
To drop the second fragment, issue the following SQL statement:
ALTER FRAGMENT ON TABLE frag_table DROP dbspace2
When you issue this statement, all the rows in dbspace2 are moved to theremaining dbspaces, dbspace1 and dbspace3. For more information ondropping fragments, see the ALTER FRAGMENT statement in Chapter 1 of theInformix Guide to SQL: Syntax.
SQL: Tutorial
Accessing Data Stored in Fragmented Tables
Accessing Data Stored in Fragmented TablesRows stored in nonfragmented tables can be accessed by several methods.One method is to reference the rowid of the row you are seeking. The termrowid refers to an integer that defines the physical location of a row. OnLineassigns rows in a nonfragmented table a unique rowid, which allows appli-cations access to a particular row in a table.
Rows in fragmented tables, in contrast, are not assigned a rowid. If you wishto access data by rowid, you must explicitly create a rowid column as isdescribed in the section “Creating a Rowid Column” on page 9-42. If userapplications attempt to reference a rowid in a fragmented table that does notcontain a rowid that you explicitly created, OnLine displays an appropriateerror message and execution of the application is halted.
Use Primary Keys Instead of RowidsInformix recommends that you use primary keys as a method of access inyour applications rather than rowids. Because primary keys are defined inthe ANSI specification of SQL, using them to access data makes your applica-tions more portable.
Refer to the Informix Guide to SQL: Reference and the Informix Guide to SQL:Syntax for a complete description on how to define and use primary keys toaccess data.
Rowid in a Fragmented Table
From the viewpoint of an application, the functionality of a rowid column ina fragmented table is identical to the rowid of a nonfragmented table. How-ever, unlike the rowid of a nonfragmented table, OnLine uses an index tomap the rowid to a physical location. Accessing data in a fragmented table byrowid is significantly slower than accessing data in a nonfragmented table byrowid. Accessing data in a fragmented table by rowid is no faster than access-ing data using a primary key. In addition, primary key access can lead to sig-nificantly improved performance in many situations, particularly whenaccess is in parallel.
Implementing Your Data Model 9-41
When OnLine accesses a row in a fragmented table using the rowid column,it uses an index to look up the physical address of the row before it attemptsto access the row. For a nonfragmented table, OnLine uses direct physicalaccess without having to do an index lookup. Consequently, accessing a rowin a fragmented table using rowid takes slightly longer than accessing a rowusing rowid in a nonfragmented table. You should also expect a small perfor-mance impact on the processing of inserts and deletes due to the cost of main-taining the rowid index for fragmented tables.
The section that follows explains how to create a rowid in a fragmented table.
Creating a Rowid Column
If, for some reason, you find it obligatory that your applications access datain a fragmented table using a rowid column, you must create a rowid columnfor the fragmented table.
You can create the column at the same time you create the table by using theWITH ROWIDS clause of the CREATE TABLE statement. When you issue theCREATE TABLE...WITH ROWIDS statement, OnLine creates a rowid columnthat adds 4 bytes to each row in the fragmented table. In addition, OnLinecreates an internal index that it uses to access the data in the table by rowid.After the rowid column is created, OnLine inserts a row in the sysfragmentscatalog table, which indicates the existence and attributes of the rowidcolumn.
If you decide you need a rowid column after you build the fragmented table,use the ADD ROWIDS clause of the ALTER TABLE statement or the INIT clauseof the ALTER FRAGMENT statement.
You can drop the rowid column from a fragmented table with the DROPROWIDS clause of the ALTER TABLE statement. See the ALTER TABLE state-ment in Chapter 1 of the Informix Guide to SQL: Syntax for more information.
You cannot create or add a rowid column by naming it as one of the columnsin a table you create or alter. For example, when you execute the statement,CREATE TABLE test_table (rowid INTEGER, ....) you get the -227 DDLoptions on rowid are prohibited. error.
Summary
SummaryThis chapter covered the following work, which you must do to implementa data model:
■ Specify the domains, or constraints, that are used in the model, andcomplete the model diagram by assigning constraints to eachcolumn.
■ Use interactive SQL to create the database and the tables in it.
■ If you must create the database again, write the SQL statements to doso into a script of commands for the operating system.
■ Populate the tables of the model, first using interactive SQL and thenby bulk operations.
■ Possibly write the bulk-load operation into a command script so youcan repeat it easily.
■ Possibly use the fragmentation SQL statements to create, alter, andmodify fragmented tables.
You can now use and test your data model. If it contains very large tables, orif you must protect parts of it from certain users, more work remains to bedone. That is one of the subjects in the INFORMIX-OnLine Dynamic ServerPerformance Guide.
Implementing Your Data Model 9-43
10Chapter
Granting and Limiting Access toYour Database
Controlling Access to Databases . . . . . . . . . . . . . . 10-4Securing Database Files . . . . . . . . . . . . . . . . 10-4
Multiuser Systems . . . . . . . . . . . . . . . . 10-4 Single-User Systems . . . . . . . . . . . . . . . 10-5
Securing Confidential Data. . . . . . . . . . . . . . . 10-5
Granting Privileges . . . . . . . . . . . . . . . . . . . 10-6Database-Level Privileges . . . . . . . . . . . . . . . 10-6
Connect Privilege. . . . . . . . . . . . . . . . . 10-6Resource Privilege . . . . . . . . . . . . . . . . 10-7Database Administrator Privilege . . . . . . . . . . . 10-7
Ownership Rights . . . . . . . . . . . . . . . . . . 10-8Table-Level Privileges . . . . . . . . . . . . . . . . 10-8
Access Privileges . . . . . . . . . . . . . . . . . 10-9Index, Alter, and References Privileges . . . . . . . . . 10-10Column-Level Privileges . . . . . . . . . . . . . . 10-11
Procedure-Level Privileges . . . . . . . . . . . . . . . 10-13Automating Privileges . . . . . . . . . . . . . . . . 10-13
Automating with INFORMIX-4GL . . . . . . . . . . . 10-14Automating with a Command Script . . . . . . . . . . 10-15
Controlling Access to Data Using Stored Procedures . . . . . . . 10-16Restricting Reads of Data . . . . . . . . . . . . . . . 10-16Restricting Changes to Data . . . . . . . . . . . . . . 10-17Monitoring Changes to Data . . . . . . . . . . . . . . 10-18Restricting Object Creation . . . . . . . . . . . . . . . 10-20
10-2 Inf
Using Views . . . . . . . . . . . . . . . . . . . . . 10-21Creating Views . . . . . . . . . . . . . . . . . . . 10-22
Duplicate Rows from Views . . . . . . . . . . . . . 10-23Restrictions on Views . . . . . . . . . . . . . . . 10-23When the Basis Changes . . . . . . . . . . . . . . 10-24
Modifying Through a View. . . . . . . . . . . . . . . 10-25Deleting Through a View . . . . . . . . . . . . . . 10-25Updating a View . . . . . . . . . . . . . . . . . 10-25Inserting into a View. . . . . . . . . . . . . . . . 10-26Using WITH CHECK OPTION . . . . . . . . . . . . 10-27
Privileges and Views . . . . . . . . . . . . . . . . . . 10-28Privileges When Creating a View. . . . . . . . . . . . . 10-28Privileges When Using a View. . . . . . . . . . . . . . 10-29
Summary . . . . . . . . . . . . . . . . . . . . . . 10-32
ormix Guide to SQL: Tutorial
In some databases, all data is accessible to every user. In others, this isnot the case; some users are denied access to some or all of the data. You canrestrict access to data at the following levels, which are the subject of thischapter:
■ When the database is stored in operating system files, you cansometimes use the file-permission features of the operating system.
This level is not available when INFORMIX-OnLine Dynamic Serverholds the database. It manages its own disk space and the rules of theoperating system do not apply.
■ You can use the GRANT and REVOKE statements to give or denyaccess to the database or to specific tables, and you can control thekinds of uses that people can make of the database.
■ You can use the CREATE PROCEDURE statement to write and compilea stored procedure, which controls and monitors the users who canread, modify, or create database tables.
■ You can use the CREATE VIEW statement to prepare a restricted ormodified view of the data. The restriction can be vertical, excludingcertain columns, or horizontal, excluding certain rows, or both.
■ You can combine GRANT and CREATE VIEW statements to achieveprecise control over the parts of a table a user can modify and withwhat data.
In addition to these points, INFORMIX-OnLine/Secure offers a type ofautomatic security called mandatory access control (MAC). With MAC, allusers and all data are assigned a security label, and OnLine/Secure comparesthe labels before allowing access. For example, a user with the TOP SECRETlabel could view an UNCLASSIFIED row, but an UNCLASSIFIED user could notview a TOP SECRET row. This topic, and other topics related to security inOnLine/Secure are addressed in the INFORMIX-OnLine/Secure SecurityFeatures User’s Guide.
Granting and Limiting Access to Your Database 10-3
10-4 Informix Guide to
Controlling Access to Databases
Controlling Access to DatabasesThe normal database-privilege mechanisms are based on the GRANT andREVOKE statements. They are covered in “Granting Privileges” on page 10-5.However, you can sometimes use the facilities of the operating system as anadditional way to control access to a database.
Securing Database FilesDatabase servers other than INFORMIX-OnLine Dynamic Server storedatabases in operating system files. Typically, a database is represented as anumber of files: one for each table, one for the indexes on each table, and pos-sibly others. The files are collected in a directory. The directory represents thedatabase as a whole.
Multiuser Systems
You can deny access to the database by denying access to the databasedirectory. The means by which you can do this depend on your operatingsystem and your computer hardware. Multiuser operating systems havesoftware facilities such as UNIX file permissions.
Important: In UNIX, the database directory is created with group identity informix,and the database server always runs under group identity informix. Thus, you can-not use group permissions to restrict access to a particular group of users. You can,however, only remove all group permissions (file mode 700) and deny access toanyone except the owner of the directory.
You can also deny access to individual tables in this way; for example, bymaking the files that represent those tables unavailable to certain users, whileleaving the rest of the files accessible. However, the database servers are notdesigned for tricks of this kind. When an unauthorized user tries to queryone of the tables, the database server probably returns an error messageabout not being able to locate a file. This may confuse users.
SQL: Tutorial
Securing Confidential Data
Single-User Systems
Typical single-user systems have few software controls on file access; you canmake a database inaccessible to others only by writing it on a disk that youcan detach from the computer and keep locked.
None of these techniques apply when you use the OnLine database server. Itcontrols its own disk space at the device level, bypassing the file-accessmechanisms of the operating system.
Securing Confidential DataNo matter what access controls the operating system gives you, when thecontents of an entire database are highly sensitive, you might not want toleave it on a public disk fixed to the computer. You can circumvent normalsoftware controls when the data must be secure.
When the database is not being used by you or another authorized person, itdoes not have to be available on-line. You can make it inaccessible in one ofthe following ways, which have varying degrees of inconvenience:
■ Detach the physical medium from the computer, and take it away. Ifthe disk itself is not removable, the disk drive might be removable.
■ Copy the database directory to tape, and take possession of the tape.
■ Copy the database files using an encryption utility. Keep only theencrypted version.
In the latter two cases, after making the copies, you must remember to erasethe original database files using a program that overwrites an erased file withnull data.
Instead of removing the entire database directory, you can copy and thenerase the files that represent individual tables. However, do not overlook thefact that index files contain copies of the data from the indexed column orcolumns. Remove and erase the index files as well as the table files.
Granting and Limiting Access to Your Database 10-5
10-6 Informix Guide to
Granting Privileges
Granting PrivilegesThe authorization to use a database is called a privilege. For example, theauthorization to use a database is called the Connect privilege, and the autho-rization to insert a row into a table is called the Insert privilege. You controlthe use of a database by granting these privileges to other users or byrevoking them.
Two groups of privileges exist that control the actions a user can perform ondata. These are database-level privileges, which affect the entire database,and table-level privileges, which relate to individual tables. In addition tothese two groups, procedure-level privileges exist, which determine who canexecute a procedure.
Database-Level PrivilegesThe three levels of database privilege provide an overall means of controllingwho accesses a database.
Connect Privilege
The least of the privilege levels is Connect, which gives a user the basic abilityto query and modify tables. Users with the Connect privilege can perform thefollowing functions:
■ Execute the SELECT, INSERT, UPDATE, and DELETE statements, pro-vided that they have the necessary table-level privileges
■ Execute a stored procedure, provided that they have the necessarytable-level privileges
■ Create views, provided that they are permitted to query the tables onwhich the views are based
■ Create temporary tables and create indexes on the temporary tables
The Connect privilege is necessary before users can access a database.Ordinarily, in a database that does not contain highly sensitive or privatedata, you give the GRANT CONNECT TO PUBLIC privilege shortly aftercreating the database.
SQL: Tutorial
Database-Level Privileges
If you do not grant the Connect privilege to public, the only users who canaccess the database through the database server are those to whom you spe-cifically grant the Connect privilege. If limited users should have access, thisis your means of providing it to them and denying it to all others.
The Users and the Public
Privileges are granted to single users by name or to all users under the nameof PUBLIC. Any privileges granted to public serve as a default privileges.
Prior to executing a statement, the database server determines whether a userhas the necessary privileges. (The information is in the system catalog; see“Privileges in the System Catalog” on page 10-9.)
The database server looks first for privileges granted specifically to therequesting user. If it finds such a grant, it uses that information. It then checksto see if less restrictive privileges have been granted to public. If so, the data-base server uses the less-restrictive privileges. If there has been no grant tothat user, the database server looks for privileges granted to public. If it findsa relevant one, it uses that.
Thus, you can set a minimum level of privilege for all users by grantingprivileges to public. You can override that, in specific cases, by grantinghigher individual privileges to users.
Resource Privilege
The Resource privilege carries the same authorization as the Connectprivilege. In addition, users with the Resource privilege can create new, per-manent tables, indexes, and stored procedures, thus permanently allocatingdisk space.
Database Administrator Privilege
The highest level of database privilege is Database Administrator, or DBA.When you create a database, you are automatically the DBA. Holders of theDBA privilege can perform the following functions:
■ Execute the DROP DATABASE, START DATABASE, andROLLFORWARD DATABASE statements
■ Drop or alter any object regardless of who owns it
Granting and Limiting Access to Your Database 10-7
10-8 Informix Guide to
Ownership Rights
■ Create tables, views, and indexes to be owned by other users
■ Grant database privileges, including the DBA privilege, to anotheruser
■ Alter the NEXT SIZE (but no other attribute) of the system catalogtables, and insert, delete, or update rows of any system catalog tableexcept systables
Warning: Although users with the DBA privilege can modify most system catalogtables, Informix strongly recommends that you do not update, delete, or insert anyrows in them. Modifying the system catalog tables can destroy the integrity of thedatabase. Informix does support using the ALTER TABLE statement to modify the sizeof the next extent of system catalog tables.
Ownership RightsThe database, and every table, view, index, procedure, and synonym in it, hasan 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 byothers.
The owner of an object has all rights to that object and can alter or drop itwithout needing additional privileges.
Table-Level PrivilegesYou can apply seven privileges, table by table, to allow nonowners theprivileges of owners. Four of them—the Select, Insert, Delete, and Updateprivileges—control access to the contents of the table. The Index privilegecontrols index creation. The Alter privilege controls the authorization tochange the table definition. The References privilege controls theauthorization to specify referential constraints on a table.
In an ANSI-compliant database, only the table owner has any privileges. Inother databases, the database server, as part of creating a table, automaticallygrants all table privileges—except Alter and References—to public. Thismeans that a newly created table is accessible to any user with the Connectprivilege. If this is not what you want—if users exist with the Connect privi-lege who should not be able to access this table—you must revoke allprivileges on the table from public after you create the table.
SQL: Tutorial
Table-Level Privileges
Access Privileges
Four privileges govern how users can access a table. As the owner of thetable, you can grant or withhold the following privileges independently:
■ The Select privilege allows selection, including selecting intotemporary 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 Selectprivilege.
For example, your application might have a usage table. Every time a certainprogram is started, it inserts a row into the usage table to document that itwas used. Before the program terminates, it updates that row to show howlong 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 inthis usage table, you grant Insert and Update privileges on it to public.However, you might grant the Select privilege to only a few users.
Privileges in the System Catalog
Privileges are recorded in the system catalog tables. Any user with theConnect privilege can query the system catalog tables to determine whatprivileges have been granted and to whom.
Database privileges are recorded in the sysusers table, in which the primarykey is user-id and the only other column contains a single character C, R, or Dfor the privilege level. A grant to the keyword of PUBLIC is reflected as a username of public (lowercase).
Granting and Limiting Access to Your Database 10-9
10-10 Informix Guide to
Table-Level Privileges
Table-level privileges are recorded in systabauth, which uses a compositeprimary key of the table number, grantor, and grantee. In the tabauthcolumn, the privileges are encoded in a list as shown in the followingdiagram:
A hyphen means an ungranted privilege, so that a grant of all privileges isshown as su-idxar, and -u------ shows a grant of only Update. The codeletters are normally lowercase, but they are uppercase when the keywordsWITH GRANT OPTION are used in the GRANT statement.
When an asterisk (*) appears in the third position, some column-level privi-lege exists for that table and grantee. The specific privilege is recorded insyscolauth. Its primary key is a composite of the table number, the grantor,the grantee, and the column number. The only attribute is a three-letter listshowing the type of privilege: s, u, or r.
Index, Alter, and References Privileges
The Index privilege permits its holder to create and alter indexes on the table.The Index privilege, similar to the Select, Insert, Update, and Deleteprivileges, is granted automatically to public when a table is created.
You can grant the Index privilege to anyone, but to exercise the ability, theuser must also hold the Resource database privilege. So, although the Indexprivilege is granted automatically (except in ANSI-compliant databases),users who have only the Connect privilege to the database cannot exercisetheir Index privilege. This is reasonable because an index can fill a largeamount of disk space.
The Alter privilege permits its holder to use the ALTER TABLE statement onthe table, including the power to add and drop columns, reset the startingpoint for SERIAL columns, and so on. You should grant the Alter privilegeonly to users who understand the data model very well and whom you trustto exercise their power very carefully.
su-idxarunconditional Select
unconditional Update
* if column privilege granted
Insert
Delete
Index
AlterReferences
SQL: Tutorial
Table-Level Privileges
CREATE TABL(emp_keyemp_namhire_dadept_nuuser-idsalary performperform)
The References privilege allows you to impose referential constraints on atable. As with the Alter privilege, you should grant the References privilegeonly to users who understand the data model very well.
Column-Level Privileges
You can qualify the Select, Update, and References privileges with the namesof 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 toupdate only certain columns, or you can allow a user to impose referentialconstraints on certain columns.
Using INFORMIX-OnLine Dynamic Server (so that table data can be inspectedonly through a call to the database server), this feature solves the problemthat only certain users should know the salary, performance review or othersensitive attributes of an employee. To make the example specific, suppose atable of employee data is defined as shown in Figure 10-1.
Because this table contains sensitive data, you execute the followingstatement immediately after creating it:
REVOKE ALL ON hr_data FROM PUBLIC
For selected persons in the Human Resources department and for allmanagers, you execute a statement such as the one shown in the followingexample:
GRANT SELECT ON hr_data TO harold_r
Figure 10-1A table of
confidentialemployee
information
E hr_data
INTEGER,e CHAR(40),te DATE,m SMALLINT, CHAR(18),DECIMAL(8,2)ance_level CHAR(1),ance_notes TEXT
Granting and Limiting Access to Your Database 10-11
10-12 Informix Guide to
Table-Level Privileges
In this way, you permit certain users to view all columns. (The final sectionof this chapter discusses a way to limit the view of managers to only theiremployees.) For the first-line managers who carry out performance reviews,you could execute a statement such as the one shown in the followingexample:
GRANT UPDATE (performance_level, performance_notes)ON hr_data TO wallace_s, margot_t
This statement permits the managers to enter their evaluations of theiremployees. Only for the manager of the Human Resources department orwhomever is trusted to alter salary levels, would you execute a statementsuch as the one shown in the following example:
GRANT UPDATE (salary) ON hr_data to willard_b
For the clerks in the Human Resources department, you could execute astatement such as the one shown in the following example:
GRANT UPDATE (emp_key, emp_name, hire_date, dept_num)ON hr_data TO marvin_t
This statement gives certain users the ability to maintain the nonsensitivecolumns but denies them authorization to change performance ratings or sal-aries. The person in the MIS department who assigns computer user-ids is thebeneficiary of a statement such as the one shown in the following example:
GRANT UPDATE (user_id) ON hr_data TO eudora_b
On behalf of all users who are allowed to connect to the database but who arenot authorized to see salaries or performance reviews, execute statements,such as the one shown in the following example, to permit them to see thenonsensitive data:
GRANT SELECT (emp_key, emp_name, hire_date, dept_num, user-id)ON hr_data TO george_b, john_s
These users can perform queries such as the one shown in the followingexample:
SELECT COUNT(*) FROM hr_data WHERE dept_num IN (32,33,34)
However, any attempt to execute a query, such as the one shown in the fol-lowing example, produces an error message and no data:
SELECT performance_level FROM hr_dataWHERE emp_name LIKE '*Smythe'
SQL: Tutorial
Procedure-Level Privileges
Procedure-Level PrivilegesYou can apply the Execute privilege on a procedure to authorize nonownersto 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 togrant 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 havethe Execute privilege by default; you must grant specific users the Executeprivilege. The following example grants the Execute privilege to the userorion so that orion can use the stored procedure named read-address:
GRANT EXECUTE ON read_address TO orion;
Procedure-level privileges are recorded in the sysprocauth system catalogtable. The sysprocauth table uses a primary key of the procedure number,grantor, and grantee. In the procauth column, the execute privilege is indi-cated by a lowercase letter “e.” If the execute privilege was granted with theWITH GRANT option, the privilege is represented by an uppercase letter “E.”
For more information on procedure-level privileges see “Privileges on StoredProcedures” on page 12-16.
Automating PrivilegesIt might seem that this design forces you to execute a tedious number ofGRANT statements when you first set up the database. Furthermore, privi-leges require constant maintenance as people change jobs. For example, if aclerk in Human Resources is terminated, you want to revoke the Updateprivilege as soon as possible; otherwise you risk the unhappy employeeexecuting a statement such as the one shown in the following example:
UPDATE hr_dataSET (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 anticipatethis need, you can prepare some automated tools to help maintain privileges.
Granting and Limiting Access to Your Database 10-13
10-14 Informix Guide to
Automating Privileges
Your first step should be to specify privilege classes that are based on the jobsof the users, not on the structure of the tables. For example, a first-linemanager needs the following privileges:
■ The Select and limited Update privilege on the hypothetical hr_datatable
■ 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, youmust revoke all those privileges and grant a new set of privileges.
Define the privilege classes you support, and for each class specify thedatabases, tables, and columns to which you must give access. Then devisetwo automated procedures for each class, one to grant the class to a user andone to revoke it.
Automating with INFORMIX-4GL
The mechanism you use depends on your operating system and other tools.If you are a programmer, one of the tools you can use is INFORMIX-4GL. 4GLmakes it quite easy to program a simple user interaction, as shown in the fol-lowing example:
DEFINE mgr_id char(20)PROMPT 'What is the user-id of the new manager? ' FOR mgr_idCALL table_grant ('SELECT', 'hr_data', mgr_id)
Unfortunately, although INFORMIX-4GL allows you to mix GRANT andREVOKE statements freely with other program statements, it does not permityou to create parameters from them from program variables. To customize aGRANT statement with a user-id taken from user input, the program mustbuild the statement as a string, prepare it with a PREPARE statement, and exe-cute it with an EXECUTE statement. (These statements are discussed in detailin Chapter 5, “Programming with SQL,” where the following example isanalyzed in detail.)
SQL: Tutorial
Automating Privileges
FUNCTION table_gDEFINE priv_
tableuser_grant
LET grant_st
WHENEVER ERRPREPARE the_IF status =
EXECUTE tEND IFIF status <>
DISPLAY 'DISPLAY '
END IFWHENEVER ERR
END FUNCTION
Figure 10-2 shows one possible definition of the 4GL function table_grant(),which is invoked by the CALL statement in the preceding example.
Automating with a Command Script
Your operating system probably supports automatic execution of commandscripts. In most operating environments, DB-Access and INFORMIX-SQL, theinteractive SQL tools, accept commands and SQL statements to execute fromthe command line. You can combine these two features to automate privilegemaintenance.
The details depend on your operating system and the version of DB-Accessor INFORMIX-SQL that you are using. In essence, you want to create acommand 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 con-tain that user-id
■ Invokes DB-Access or INFORMIX-SQL with parameters that tell it toselect the database and execute the prepared file of GRANT orREVOKE statements
In this way, you can reduce the change of the privilege class of a user to oneor two commands.
Figure 10-2A 4GL function that
builds, prepares,and executes a
GRANT statement
rant (priv_to_grant, table_name, user_id)to_grant char(100),{may include column-list}_name CHAR(20),id CHAR(20),_stmt CHAR(200)mt =' GRANT ', priv_to_grant,
' ON ', table_name,' TO ', user_id
OR CONTINUEgrant FROM grant_stmt0 THENhe_grant
0 THENSorry, got error #', status, 'attempting:'
', grant_stmt
OR STOP
Granting and Limiting Access to Your Database 10-15
10-16 Informix Guide to
Controlling Access to Data Using Stored Procedures
Controlling Access to Data Using Stored ProceduresYou can use a stored procedure to control access to individual tables andcolumns in the database. You can accomplish various degrees of access con-trol through a procedure. (Stored procedures are fully described inChapter 12, “Creating and Using Stored Procedures.”) A powerful feature ofStored Procedure Language (SPL) is the ability to designate a stored proce-dure as a DBA-privileged procedure. Writing a DBA-privileged procedure,you can allow users who have few or no table privileges to have DBA privi-leges when they execute the procedure. In the procedure, users can carry outvery specific tasks with their temporary DBA privilege. The DBA-privilegedfeature allows you to accomplish the following tasks:
■ You can restrict how much information individual users can readfrom a table.
■ You can restrict all the changes made to the database and ensure thatentire tables are not emptied or changed accidentally.
■ You can monitor an entire class of changes made to a table, such asdeletions or insertions.
■ You can restrict all object creation (data definition) to occur within astored procedure so that you have complete control over how tables,indexes, and views are built.
Restricting Reads of DataThe procedure in Figure 10-3 on page 10-17 hides the SQL syntax from users,but it requires that users have the Select privilege on the customer table. Ifyou want to restrict what users can select, you can write your procedure towork in the following environment:
■ You are the DBA of the database.
■ The users have the Connect privilege to the database. They do nothave the Select privilege on the table.
■ Your stored procedure (or set of stored procedures) is created usingthe DBA keyword.
■ Your stored procedure (or set of stored procedures) reads from thetable for users.
SQL: Tutorial
Restricting Changes to Data
CREATE DBA RETURNING C
DEFINE p_lnDEFINE p_ph
SELECT fnamINTO p_FROM cuWHERE c
RETURN p_fn
END PROCEDU
If you want users to read only the name, address, and telephone number of acustomer, you can modify the procedure as shown in Figure 10-3.
Restricting Changes to DataUsing stored procedures, you can restrict changes made to a table. Simplychannel all changes through a stored procedure. The stored procedure makesthe changes, rather than users making the changes directly. If you want tolimit users to deleting one row at a time to ensure that they do notaccidentally remove all the rows in the table, set up the database with thefollowing privileges:
■ You are the DBA of the database.
■ All the users have the Connect privilege to the database. They mighthave the Resource privilege. They do not have the Delete (for thisexample) privilege on the table being protected.
■ Your stored procedure is created using the DBA keyword.
■ Your stored procedure performs the deletion.
Figure 10-3Stored procedure to
restrict reads oncustomer data
PROCEDURE read_customer(cnum INT)HAR(15), CHAR(15), CHAR(18);
ame,p_fname CHAR(15);one CHAR(18);
e, lname, phonefname, p_lname, p_phonestomerustomer_num = cnum;
ame, p_lname, p_phone;
RE;
Granting and Limiting Access to Your Database 10-17
10-18 Informix Guide to
Monitoring Changes to Data
CREATE DBA
DELETE FROMWHERE c
END PROCEDU
Write a stored procedure similar to the one shown in Figure 10-4, whichdeletes rows from the customer table using a WHERE clause with thecustomer_num provided by the user.
Monitoring Changes to DataUsing stored procedures, you can create a record of changes made to adatabase. You can record changes made by a particular user, or you can makea record of each time a change is made.
You can monitor all the changes made to the database by a single user. Simplychannel all changes through stored procedures that keep track of changesmade by each user. If you want to record each time the user acctclrk modifiesthe database, set up the database with the following privileges:
■ You are the DBA of the database.
■ All other users have the Connect privilege to the database. Theymight have the Resource privilege. They do not have the Delete (forthis example) privilege on the table being protected.
■ Your stored procedure is created using the DBA keyword.
■ Your stored procedure performs the deletion and records that achange has been made by a certain user.
Figure 10-4Stored procedure to
delete a row
PROCEDURE delete_customer(cnum INT)
customerustomer_num = cnum;
RE;
SQL: Tutorial
Monitoring Changes to Data
CREATE DBA PROCE
DEFINE username
DELETE FROM custWHERE custom
IF username = 'aSYSTEM 'echo
ENF IFEND PROCEDURE;
CREATE DBA PROCED
DEFINE username CLET username = USDELETE FROM tbnam
SYSTEM 'echo Deletion m||'>>/hr/records/
END PROCEDURE;
Write a stored procedure similar to the one in Figure 10-5, which updates atable using a customer number provided by the user. If the user happens tobe acctclrk, a record of the deletion is put in the file updates.
You can monitor all the deletions made through the procedure by removingthe IF statement and making the SYSTEM statement more general. If youchange the procedure in Figure 10-5 to record all deletions, it looks like theprocedure in Figure 10-6.
Figure 10-5A procedure to
delete rows andrecord changes
made by a certainuser
Figure 10-6Stored procedure to
delete rows andrecord user
DURE delete_customer(cnum INT)
CHAR(8);
omerer_num = cnum;
cctclrk' THEN Delete from customer by acctclrk >> /mis/records/updates' ;
URE delete_customer(cnum INT)
HAR(8);ER ;e WHERE customer_num = cnum;
ade from customer table, by '||usernamedeletes';
Granting and Limiting Access to Your Database 10-19
10-20 Informix Guide to
Restricting Object Creation
CREATE DBA PROCED
CREATE TABLE learCREATE INDEX learCREATE TABLE toys
descriEND PROCEDURE;
Restricting Object CreationTo put restraints on what and how objects are built, use stored procedureswithin the following setting:
■ You are the DBA of the database.
■ All the other users have the Connect privilege to the database. Theydo not have the Resource privilege.
■ Your stored procedure (or set of stored procedures) is created usingthe DBA keyword.
■ Your stored procedure (or set of stored procedures) creates tables,indexes, and views in the way you defined them. You might use sucha procedure to set up a training database environment.
Your procedure might include the creation of one or more tables andassociated indexes, as shown in Figure 10-7.
To use the all_objects procedure to control additions of columns to tables,revoke the Resource privilege on the database from all users. When users tryto create a table, index, or view using an SQL statement outside your proce-dure, they cannot do so. When users execute the procedure, they have a tem-porary DBA privilege so the CREATE TABLE statement, for example, succeeds,and you are guaranteed that every column added has a constraint placed onit. In addition, objects created by users are owned by that user. For theall_objects procedure, the two tables and the index are owned by whoeverexecuted the procedure.
Figure 10-7DBA-mode
procedure that addstables and indexes
to the database
URE all_objects()
n1 (intone SERIAL, inttwo INT NOT NULL, charcol CHAR(10) );n_ix ON learn1 (inttwo); (name CHAR(15) NOT NULL UNIQUE,ption CHAR(30), on_hand INT);
SQL: Tutorial
Using Views
Using ViewsA view is a synthetic table. You can query it as if it were a table, and in somecases, 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 definea SELECT statement that generates the contents of the view at the time theview is accessed. A user also queries a view using a SELECT statement. Thedatabase server merges the SELECT statement of the user with the onedefined for the view and then actually performs the combined statements.
The result has the appearance of a table; it is similar enough to a table that aview 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 theview, 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 10-27) toenforce constraints.
■ To provide access to derived data without having to store redundantdata in the database
You write the expressions that derive the data into the select list inthe view. Each time you query the view, the data is derived anew. Thederived data is always up to date, yet no redundancies are intro-duced 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 neitherusers nor application programmers need to repeat them.
Granting and Limiting Access to Your Database 10-21
10-22 Informix Guide to
Creating Views
Creating ViewsThe following example creates a view based on a table in the stores7database:
CREATE VIEW name_only ASSELECT customer_num, fname, lname FROM customer
The view exposes only three columns of the table. Because it contains noWHERE clause, the view does not restrict the rows that can appear.
The following example creates a view based on a table that is available whenNLS has been enabled. In it, the view, column, and table names containforeign characters.
CREATE VIEW çà_va ASSELECT numéro, nom FROM abonnés;
The following example is based on the join of two tables:
CREATE VIEW full_addr ASSELECT address1, address2, city, state.sname, zipcode
FROM customer, stateWHERE customer.state = state.code
The table of state names reduces the redundancy of the database; it allows forstoring the full state names only once, which can be very useful for lengthystate names such as Minnesota. This full_addr view lets users retrieve theaddress as if the full state name were stored in every row. The following twoqueries are equivalent:
SELECT * FROM full_addr WHERE customer_num = 105
SELECT address1, address2, city, state.sname, zipcodeFROM customer, stateWHERE customer.state = state.code
AND customer_num = 105
However, be careful when you define views that are based on joins. Suchviews are not modifiable; that is, you cannot use them with UPDATE, DELETE,or INSERT statements. (Modifying through views is covered beginning onpage 10-25.)
The following example restricts the rows that can be seen in the view:
CREATE VIEW no_cal_cust ASSELECT * FROM customer WHERE NOT state = 'CA'
SQL: Tutorial
Creating Views
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 relevantto them:
CREATE VIEW my_calls ASSELECT * FROM cust_calls WHERE user_id = USER
All the columns of the cust_calls table are available but only in those rowsthat contain the user-ids of the users who can execute the query.
Duplicate Rows from Views
It is possible for a view to produce duplicate rows, even when the underlyingtable has only unique rows. If the view SELECT statement can returnduplicate rows, the view itself can appear to contain duplicate rows.
You can prevent this problem in two ways. One way is to specify DISTINCTin the select list in the view. However, that makes it impossible to modifythrough the view. The alternative is to always select a column or group ofcolumns that is constrained to be unique. (You can be sure only unique rowsare returned if you select the columns of a primary key or of a candidate key.Primary and candidate keys are discussed in Chapter 8, “Building Your DataModel.”)
Restrictions on Views
Because a view is not really a table, it cannot be indexed, and it cannot be theobject of such statements as ALTER TABLE and RENAME TABLE. The columnsof a view cannot be renamed with RENAME COLUMN. To change anythingabout 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 onwhich a view is based cannot contain any of the following clauses:
INTO TEMP The user’s query might contain INTO TEMP; if the viewalso contains it, the data would not know where to go.
UNION The user’s query might contain UNION. No meaning hasbeen defined for nested UNION clauses.
ORDER BY The user’s query might contain ORDER BY. If the view alsocontains it, the choice of columns or sort directions couldbe in conflict.
Granting and Limiting Access to Your Database 10-23
10-24 Informix Guide to
Creating Views
When the Basis Changes
The tables and views on which a view is based can change in several ways.The view automatically reflects most of the changes.
When a table or view is dropped, any views in the same database that dependon it are automatically dropped.
The only way to alter the definition of a view is to drop and re-create it.Therefore, if you change the definition of a view on which other viewsdepend, you must also re-create the other views (because they all have beendropped).
When a table is renamed, any views in the same database that depend on itare modified to use the new name. When a column is renamed, views in thesame database that depend on that table are updated to select the proper col-umn. However, the names of columns in the views themselves are notchanged. For an example of this, recall the following view on the customertable:
CREATE VIEW name_only ASSELECT customer_num, fname, lname FROM customer
Now suppose that the customer table is changed in the following way:
RENAME COLUMN customer.lname TO surname
To select last names of customers directly, you must now select the newcolumn name. However, the name of the column as seen through the view isunchanged. The following two queries are equivalent:
SELECT fname, surname FROM customer
SELECT fname, lname FROM name_only
When you alter a table by dropping a column, views are not modified. If theyare 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 ofcolumns in a table by dropping a column and then adding a new column ofthe 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 andviews in external databases. Changes to tables and views in other databasesare not reflected in views. Such changes might not be apparent until someonequeries the view and gets an error because an external table changed.
SQL: Tutorial
Modifying Through a View
Modifying Through a ViewIt is possible to modify views as if they were tables. Some views can bemodified and others not, depending on their SELECT statements. The restric-tions are different, depending on whether you use DELETE, UPDATE, orINSERT statements.
No modification is possible on a view when its SELECT statement containsany of the following features:
■ A join of two or more tables
Many anomalies arise if the database server tries to distribute modi-fied data correctly across the joined tables.
■ An aggregate function or the GROUP BY clause
The rows of the view represent many combined rows of data; thedatabase server cannot distribute modified data into them.
■ The DISTINCT keyword or its synonym UNIQUE
The rows of the view represent a selection from among possiblymany duplicate rows; the database server cannot tell which of theoriginal rows should receive the modification.
When a view avoids all these things, each row of the view corresponds toexactly one row of one table. Such a view is modifiable. (Of course, particularusers can modify a view only if they have suitable privileges. Privileges onviews are discussed beginning on page 10-28.)
Deleting Through a View
A modifiable view can be used with a DELETE statement as if it were a table.The database server deletes the proper row of the underlying table.
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 VIEWstatement. You cannot update derived columns (sometimes called virtualcolumns).
Granting and Limiting Access to Your Database 10-25
10-26 Informix Guide to
Modifying Through a View
CREATE VIEWcallSELECT user
FROM cusWHERE us
UPDATE call_resWHERE resol
When a column is derived from a simple arithmetic combination of a columnwith a constant value (for example, order_date+30), the database servercan, 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, muchmore complicated expressions are possible, most of which cannot easily beinverted. Therefore, the database server does not support updating anyderived column.
Figure 10-8 shows a modifiable view that contains a derived column and anUPDATE statement that can be accepted against it.
The duration column of the view cannot be updated because it represents anexpression (the database server cannot, even in principle, decide how to dis-tribute an update value between the two columns named in the expression).But as long as no derived columns are named in the SET clause, the updatecan be performed as if the view were a table.
A view can return duplicate rows even though the rows of the underlyingtable are unique. You cannot distinguish one duplicate row from another. Ifyou update one of a set of duplicate rows (for example, by using a cursor toupdate WHERE CURRENT), you cannot be sure which row in the underlyingtable receives the update.
Inserting into a View
You can insert rows into a view provided that the view is modifiable andcontains no derived columns. The reason for the second restriction is that aninserted row must provide values for all columns, and the database servercannot tell how to distribute an inserted value through an expression. Anattempt to insert into the call_response view, shown in Figure 10-8, wouldfail.
Figure 10-8A modifiable view
and an UPDATEstatement
_response(user_id,received,resolved,duration)AS_id,call_dtime,res_dtime,res_dtime-call_dtimet_callser_id = USER
ponse SET resolved = TODAYved IS NULL
SQL: Tutorial
Modifying Through a View
When a modifiable view contains no derived columns, you can insert into itas if it were a table. However, the database server uses null as the value forany column that is not exposed by the view. If such a column does not allownulls, an error occurs and the insert fails.
Using WITH CHECK OPTION
It is possible to insert into a view a row that does not satisfy the conditions ofthe view; that is, a row that is not visible through the view. It is also possibleto update a row of a view so that it no longer satisfies the conditions of theview.
If this is improper, you can add the clause WITH CHECK OPTION when youcreate the view. This clause asks the database server to test every inserted orupdated row to ensure that it meets the conditions set by the WHERE clauseof the view. The database server rejects the operation with an error if theconditions are not met.
In Figure 10-8 on page 10-26, the view named call_response is defined asshown in the following example:
CREATEVIEWcall_response(user_id,received,resolved,duration)ASSELECT user_id,call_dtime,res_dtime,res_dtime-call_dtime
FROM cust_callsWHERE user_id = USER
It is possible to update the user_id column of the view, as shown in thefollowing example:
UPDATE call_response SET user_id = 'lenora'WHERE received BETWEEN TODAY AND TODAY - 7
The view requires rows in which user_id equals USER. If this update isperformed by a user named tony, the updated rows vanish from the view.However, you can create the view as shown in the following example:
CREATEVIEW call_response(user_id,received,resolved,duration) ASSELECT user_id,call_dtime,res_dtime,res_dtime-call_dtime
FROM cust_callsWHERE user_id = USER
WITH CHECK OPTION
The preceding update by tony is rejected as an error.
Granting and Limiting Access to Your Database 10-27
10-28 Informix Guide to
Privileges and Views
You can use the WITH CHECK OPTION feature to enforce any kind of dataconstraint 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 dataare expressed as conditions of the WHERE clause. Then you can require allmodifications to the table to be made through the view.
CREATE VIEW order_insert ASSELECT * FROM orders O
WHERE order_date = TODAY -- no back-dated entriesAND EXISTS -- ensure valid foreign key
(SELECT * FROM customer CWHERE O.customer_num = C.customer_num)
AND ship_weight < 1000 -- reasonableness checksAND ship_charge < 1000
WITH CHECK OPTION
Because of EXISTS and other tests, which are expected to be successful whenretrieving existing rows, this is a most inefficient view for displaying datafrom orders. However, if insertions to orders are made only through thisview (and you are not already using integrity constraints to constrain data),it is impossible to insert a back-dated order, an invalid customer number, oran excessive shipping weight and shipping charge.
Privileges and ViewsWhen you create a view, the database server tests your privileges on theunderlying tables and views. When you use a view, only your privileges withregard to the view are tested.
Privileges When Creating a ViewTherefore, , the database server tests to make sure that you have all the priv-ileges needed to execute the SELECT statement in the view definition. If youdo not, the view is not created.
This test ensures that users cannot gain unauthorized access to a table bycreating a view on the table and querying the view.
After you create the view, the database server grants you, the creator andowner of the view, at least the Select privilege on it. No automatic grant ismade to public, as is the case with a newly created table.
SQL: Tutorial
Privileges When Using a View
CREATE TABL(emp_keyemp_namhire_dadept_nuuser-idsalary performperform)
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, thedatabase server copies your Insert, Delete, and Update privileges from theunderlying table or view, and grants them on the new view. If you have onlythe Insert privilege on the underlying table, you receive only the Insertprivilege on the view.
This test ensures that users cannot use a view to gain access to any privilegesthat they did not already have.
Because you cannot alter or index a view, the Alter and Index privileges arenever granted on a view.
Privileges When Using a ViewWhen you attempt to use a view, the database server tests only the privilegesyou are granted on the view. It does not test your right to access the underly-ing tables.
If you created the view, your privileges are the ones noted in the precedingparagraph. If you are not the creator, you have the privileges that weregranted to you by the creator or someone who had the WITH GRANT OPTIONprivilege.
Therefore you can create a table and revoke public access to it; then you cangrant limited access privileges to the table through views. This can be dem-onstrated through the previous examples using the hr_data table. Its defini-tion is shown in Figure 10-9.
Figure 10-9A table of
confidentialemployee
information
E hr_data
INTEGER,e CHAR(40),te DATE,m SMALLINT, CHAR(18),DECIMAL(8,2),ance_level CHAR(1),ance_notes TEXT
Granting and Limiting Access to Your Database 10-29
10-30 Informix Guide to
Privileges When Using a View
In Figure 10-9 on page 10-29, the example centered on granting privilegesdirectly on this table. The following examples take a different approach.Assume that when the table was created, the following statement was exe-cuted:
REVOKE ALL ON hr_data FROM PUBLIC
(This is not necessary in an ANSI-compliant database.) Now you create aseries of views for different classes of users. For those who should haveread-only access to the nonsensitive columns, you create the following view:
CREATE VIEW hr_public ASSELECT emp_key, emp_name, hire_date, dept_num, user_id
FROM hr_data
Users who are given the Select privilege for this view can see nonsensitivedata and update nothing. For Human Resources personnel who must enternew rows, you create a different view, as shown in the following example:
CREATE VIEW hr_enter ASSELECT emp_key, emp_name, hire_date, dept_num
FROM hr_data
You grant these users both Select and Insert privileges on this view. Becauseyou, the creator of both the table and the view, have the Insert privilege onthe table and the view, you can grant the Insert privilege on the view to otherswho have no privileges on the table.
On behalf of the person in the MIS department who enters or updates newuser-ids, you create still another view, as shown in the following example:
CREATE VIEW hr_MIS ASSELECT emp_key, emp_name, user_id
FROM hr_data
This view differs from the previous view in that it does not expose thedepartment number and date of hire.
SQL: Tutorial
Privileges When Using a View
Finally, the managers need access to all columns and need the ability toupdate the performance-review data for their own employees only. Theserequirements can be met by creating a table, hr_data, that contains adepartment number and a computer user-id for each employee. Let it be arule that the managers are members of the departments that they manage.Then the following view restricts managers to rows that reflect only theiremployees:
CREATE VIEW hr_mgr_data ASSELECT * FROM hr_data
WHERE dept_num =(SELECT dept_num FROM hr_data
WHERE user_id = USER)AND NOT user_id = USER
The final condition is required so that the managers do not have updateaccess to their own row of the table. It is, therefore, safe to grant the Updateprivilege to managers for this view, but only on selected columns, as shownin this statement:
GRANT SELECT, UPDATE (performance_level, performance_notes)ON hr_mgr_data TO peter_m
Granting and Limiting Access to Your Database 10-31
10-32 Informix Guide to
Summary
SummaryIn a database that contains public material or is used only by you and trustedassociates, security is not an important consideration and few of the ideas inthis chapter are needed. But as more people are allowed to use and modifythe data, and as the data becomes increasingly confidential, you must spendmore time and be ever more ingenious at controlling the way people canapproach the data.
The techniques discussed here can be divided into the following groups:
■ Keeping data confidential
When the database resides in operating system files you can use fea-tures of the operating system to deny access to the database. In anycase, you control the granting of the Connect privilege to keep peo-ple out of the database.
When different classes of users have different degrees of authoriza-tion, you must give 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 confiden-tial tables or columns. In addition, you can deny all access to tablesand allow it only through views that do not expose confidential rowsor columns.
■ Controlling changes to data and database structure
You safeguard the integrity of the data model by restricting grants ofthe Resource, Alter, References, and DBA privileges. You ensure thatonly authorized persons modify the data by controlling the grants ofthe Delete and Update privileges, and by granting the Update privi-lege on as few columns as possible. You ensure that consistent,reasonable data is entered by granting the Insert privilege only onviews that express logical constraints on the data. Alternatively, youcan control the insertion and modification of data, or the modifica-tion of the database itself, by limiting access to constrictive storedprocedures.
SQL: Tutorial
11Chapter
Understanding InformixNetworking
What Is a Network? . . . . . . . . . . . . . . . . . . 11-4
Database Management System Configurations . . . . . . . . . 11-4A Single-User Configuration . . . . . . . . . . . . . . 11-5
Advantages and Disadvantages of a Single-User System . . . 11-6A Local Multiuser Configuration. . . . . . . . . . . . . 11-7
Advantages and Disadvantages of Local Multiuser Systems . . 11-8A Remote Configuration . . . . . . . . . . . . . . . 11-9
Advantages and Disadvantages of Remote Network Connections 11-10Single-Computer Configuration Using Network Communication . 11-10
Advantages and Disadvantages of Local Loopback . . . . . 11-11Distributed Databases . . . . . . . . . . . . . . . . 11-12
Advantages and Disadvantages of Distributed Databases . . . 11-12Distributed Databases Using Multiple Vendor Servers . . . . . 11-13
Connecting to Data on a UNIX Network . . . . . . . . . . . 11-14Example of Client / Server Connections . . . . . . . . . . 11-15Environment Variables . . . . . . . . . . . . . . . . 11-16Connection Information . . . . . . . . . . . . . . . . 11-17SQL Connection Statements . . . . . . . . . . . . . . 11-17
Accessing Tables. . . . . . . . . . . . . . . . . . . . 11-18Using Synonyms with Table Names. . . . . . . . . . . . 11-19Synonym Chains . . . . . . . . . . . . . . . . . . 11-20
11-2 Inf
Protecting Your Data in a Networked Environment. . . . . . . . 11-21Data Protection with INFORMIX-SE . . . . . . . . . . . 11-21Data Protection with INFORMIX-OnLine Dynamic Server . . . . 11-21
Data Replication . . . . . . . . . . . . . . . . . 11-21Archives . . . . . . . . . . . . . . . . . . . . 11-22
Data Integrity for Distributed Data . . . . . . . . . . . . 11-22Two-Phase Commit . . . . . . . . . . . . . . . . 11-22
Summary . . . . . . . . . . . . . . . . . . . . . . 11-23
ormix Guide to SQL: Tutorial
This chapter gives an overview of the use of databases on a computernetwork. It introduces some commonly used terminology and illustrates var-ious network configurations. The chapter also presents an overview of howthe components of either a local or network connection fit together so that aclient application can find data on a database server.
This chapter discusses the following networking configurations that you canuse with Informix databases and point out some of their effects onperformance and usability:
■ All on one computer
■ A simple network connection
■ Multiple connections on a network
■ Data managed by non-Informix database servers(INFORMIX-TP/XA)
It is not enough to simply build a computer network; you have to re-examinehow your applications and database servers share data. This chapter alsocovers the following topics concerned with managing data shared over anetwork:
■ Distributed data
■ Connecting to data
■ Protecting your data
■ Synonym chains
■ Network transparency
The final sections of the chapter discuss protecting your data in a networkedenvironment.
Understanding Informix Networking 11-3
11-4 Informix Guide to
What Is a Network?
What Is a Network?A computer network is a group of computers, workstations, and other devicesconnected together over a communications system to share resources anddata. A network site is simply the location of one of the computers on the net-work. Sometimes the network sites are widely separated, but they might alsobe in the same room or building. Two network sites can even coexist on thesame computer.
To make a practical computer network work, you must master a multitude oftechnical details regarding hardware and software. There are far too manydetails, and they change too rapidly to cover them in this book. This chaptergives a conceptual discussion of some of the issues that you might encounterwhen you use a computer network. For more information, refer to themanual that accompanies the Informix client/server product that you useand to the manuals provided by the vendor of your operating system.
Database Management System ConfigurationsA relational database management system (RDBMS) includes all the componentsnecessary to create and maintain a relational database. An Informix RDBMShas several pieces: the user interface, the database server, and the data itself.It is easiest to think of these pieces as all being located in the same computer,but many other arrangements are possible. In some arrangements, the appli-cation and the database server are on different computers, and the data isdistributed across several others.
The client applications of an RDBMS do not need to be modified to run on anetwork. The communications tools that are part of all Informix productshandle the tasks of locating and attaching to the database servers. To theapplication, a database on a networked computer appears no different thana database on the computer where the application resides.
SQL: Tutorial
A Single-User Configuration
user
A Single-User ConfigurationFigure 11-1 shows a diagram of a simple database management system on asingle computer. The organization in Figure 11-1 is one you would typicallyfind on a personal computer running DOS. It is unusual to have a single-usersituation on a UNIX system, but you certainly can. One example of a single-user UNIX system would be a desktop workstation in a developmentenvironment.
Figure 11-1A database
managementsystem on a
personal computer
personal computer
INFORMIX-SE
application
databases
Connection
Understanding Informix Networking 11-5
11-6 Informix Guide to
A Single-User Configuration
The components of the system in Figure 11-1 on page 11-5 are described inthe following list:
■ An application program
Any program that issues a query can be the application. It could, forexample, be a program written in INFORMIX-4GL, a C language pro-gram with embedded SQL, or compiled screen forms and reports.
■ A connection
On a simple system such as this one, the communication componentis frequently so well integrated with the system that it is omittedfrom diagrams and not discussed. However, it does exist.
■ A database server
The database server receives queries from the application, searchesthe database, and returns information to the application. The data-base server manages or administers the databases that it controls.
The database server in Figure 11-1 is a local server because it resideson the same host computer as the client application.
■ A database
Databases are usually stored on a magnetic disk. If this system werea UNIX system with INFORMIX-OnLine Dynamic Server, the databasemight be located on some other medium, such as a WORM (write-once read-many-times) drive controlled byINFORMIX-OnLine/Optical.
Advantages and Disadvantages of a Single-User System
A configuration involving only one computer is the easiest configuration toset up and maintain, and it gives the fastest access to data. However, the datais not available to users on other computers and the size of the databases orthe amount of processing needed may outgrow the capacity of the computer.
SQL: Tutorial
A Local Multiuser Configuration
user
user
A Local Multiuser ConfigurationFigure 11-2 shows another database management system configuration, amultiuser system with a local database server such as one you might find ona computer with a UNIX operating system.
The components of the systems in Figure 11-2 are similar to the componentsin Figure 11-1 on page 11-5, as described in the following list:
■ Application programs
Two or more applications use the same database server to accessinformation in the databases. You might have two users at individualterminals, as shown, or you might have multiple windows on asingle workstation.
Figure 11-2A database
managementsystem on a UNIX
computer
databaseserver
databasesConnection
application
application
Unix Computer
Understanding Informix Networking 11-7
11-8 Informix Guide to
A Local Multiuser Configuration
■ A connection
On a local UNIX system, the following types of connection arepossible:
❑ Network connection
❑ Interprocess communication (IPC)
IPC is a UNIX feature that transfers information very quicklybetween the application and the database server. It is availableonly when the application and the database server reside on thesame computer. INFORMIX-SE databases use a type of IPCconnection called unnamed pipes and INFORMIX-OnLine DynamicServer databases use an IPC connection technique called sharedmemory.
■ A database server, either INFORMIX-OnLine Dynamic Server orINFORMIX-SE
■ Databases
Advantages and Disadvantages of Local Multiuser Systems
A configuration that allows multiple users gives better access to the data thandoes a single-user system. With a local database, it is still easy to set up andmaintain. However, as with the single-user system, the data is not availableto users on other computers and the size of the databases or the amount ofprocessing needed may outgrow the capacity of the computer.
IPC shared memory provides very fast communication between the clientapplication and the database server. However, IPC shared memorycommunication is vulnerable to programming errors if the client applicationdoes explicit memory addressing or overindexes data arrays. Such errors donot affect the application if you use IPC unnamed pipes or networkcommunication. (See “Single-Computer Configuration Using NetworkCommunication” on page 11-10.)
SQL: Tutorial
A Remote Configuration
user
user
A Remote ConfigurationFigure 11-3 shows a remote or network configuration, where the applicationresides on one computer and the database server and its associated databasesreside on another computer on the network. In contrast, the database serversin Figure 11-1 on page 11-5 and Figure 11-2 on page 11-7 are local databaseservers.
In Figure 11-3 the applications might be INFORMIX-ESQL/COBOL orINFORMIX-ESQL/C applications. The database server might beINFORMIX-OnLine Dynamic Server (UNIX) or INFORMIX-SE for Windows NT.
Different computers are referred to as sites or host computers. The databaseserver in Figure 11-3 is a remote database server because it is on a differenthost computer, from the application that uses its services. A database servercan be local with respect to one application and remote with respect toanother application, as illustrated in Figure 11-6 on page 11-15.
Figure 11-3A simple network connection
databaseserver
databases
host 1
networkconnection
application
application
host 2
networkconnection
Understanding Informix Networking 11-9
11-10 Informix Guide to
Single-Computer Configuration Using Network Communication
Advantages and Disadvantages of Remote Network Connections
The configuration shown in Figure 11-3 on page 11-9 is an example of distrib-uted processing. In distributed processing, multiple computers contribute to asingle computing task. In this example, host1 handles the computingrequirements of the application, such as screen display, generation of reports,and printing; host2 handles the computing required to manipulate informa-tion in the databases. Using a network also gives the client application theopportunity to access data from several computers.
Response from a database server using network communication is not as fastas response from a database server using IPC because of the extra computingrequired to prepare the data for network communication and because of thetransmit time. A network is somewhat more difficult to configure andmaintain than a local system that uses IPC communication.
Single-Computer Configuration Using NetworkCommunicationFigure 11-4 on page 11-11 shows a configuration that behaves as if there weremultiple sites residing on one computer. In this configuration, which isknown as local loopback, all the components are on the same computer, but theconnections are made as if they were connected through a network.
Because the connections use network software, the database server appearsto the application as a remote site. The dashed line indicates the divisionbetween the two sites. The database administrator configures the system toprovide local or local loopback connections (or both).
SQL: Tutorial
Single-Computer Configuration Using Network Communication
netcon
user
The software for the client application and the software for the databaseserver can be stored in the same directory, or the software can be stored intwo separate directories.
Advantages and Disadvantages of Local Loopback
Local loopback allows you to test network operations without requiring anactual remote computer , but it is not as fast as a IPC. However, unlike IPCshared-memory communication, local loopback is not vulnerable to corrup-tion due to memory-addressing errors or overindexed data arrays. (See“Advantages and Disadvantages of Local Multiuser Systems” on page 11-8.)
Figure 11-4An example of local
loopback
databases
databaseserver
computer
worknection
application
client site server site
Understanding Informix Networking 11-11
11-12 Informix Guide to
Distributed Databases
Distributed DatabasesAlthough a network lets you separate the application from the data, theapplication still is limited to the contents of a single database. With mostdatabase servers, you can query or modify tables only in the currentdatabase.
A distributed database has information on multiple databases that areorganized to appear as a a single database to the user. The data can be main-tained by a variety of database servers and located on computers supportedby different operating systems and communication networks.
The OnLine database server allows you to query data in multiple databasesanywhere on the network. When the INFORMIX-TP/XA feature is added toINFORMIX-OnLine Dynamic Server, you can create global transactions thatspan multiple computer systems and even multiple XA-compliant databasesystems from different vendors. INFORMIX-SE does not provide distributeddatabase processing capabilities.
The INFORMIX-Gateway with DRDA allows you to perform distributedqueries that include non-Informix databases that conform to the distributedrelational database architecture (DRDA) protocols defined by IBM.
Advantages and Disadvantages of Distributed Databases
You may find distributed databases useful because operations that usedatabases are often naturally distributed into separate pieces, either organi-zationally, geographically, or both. A distributed database system includesthe following advantages:
■ Local data can be kept locally where it is most easily maintained andmost frequently used.
■ Data from remote sites is available to all users.
■ Duplicate copies can be maintained for safety of the data.
A distributed database system has the following disadvantages:
■ Management of the distributed system is more involved thanmanagement of a single-host system.
■ Network access is slower than local access.
SQL: Tutorial
Distributed Databases Using Multiple Vendor Servers
user
user
Distributed Databases Using Multiple Vendor ServersINFORMIX-TP/XA allows you to use database management systems frommultiple vendors to store and access your data. INFORMIX-TP/XA is a libraryof functions that allows the INFORMIX-OnLine Dynamic Server databaseserver to act as a resource manager in a distributed transaction-processing(DTP) environment that follows an interface standard, which was defined bythe X/Open Company.
The terminology used by the XA standard is different from the terminologyused by Informix products and documentation. A transaction manager acts asan intermediary and relays requests from a user interface to a resource man-ager. Transaction managers are third-party products such as TUXEDO. In thiscontext, a resource manager corresponds to a database server. Figure 11-5illustrates a configuration that uses transaction processing.
Figure 11-5A configuration using a transaction manager
INFORMIXOnLine/XA
interface
server portionof each
application
client portionof each
application
interface
transactionmanager
Vendor aDBMS/XA
Vendor bDBMS/XA
resourcemanagers
databases
Understanding Informix Networking 11-13
11-14 Informix Guide to
Connecting to Data on a UNIX Network
Connecting to Data on a UNIX NetworkWhen the application and data are moved to separate computers, twoquestions immediately arise: What connections can you implement? How doyou instruct your applications to find the data that is now somewhere else?
In fact, connecting a client application to a database server that is on anetworked computer is no different from connecting to a local databaseserver. To connect a client application with a database, you must consider thefollowing parts of your configuration:
■ Environment variables
■ Connection information
■ Connection statements
This section summarizes how connections are made for Version 6.0 and laterclients and servers. Detailed instructions for setting up local and networkconnections, as well as for those between Version 6.0 servers and earlier cli-ents are given in the INFORMIX-OnLine Dynamic Server Administrator’sGuide, the INFORMIX-SE Administrator’s Guide and the INFORMIX-Gatewaywith DRDA User Manual.
SQL: Tutorial
Example of Client / Server Connections
Host 1
A
OnLine 7.1
7.1 Client X
1
Example of Client / Server ConnectionsFigure 11-6 shows local and networked connections of Version 6.0 and laterproducts. Although all these connections are possible, you cannot do them allat once. Client X can make connection 1, 2, or 3, and Client Y can makeconnection 4 or 5.
You can connect clients directly to OnLine database servers using eithershared memory (IPC) or a network communications. Notice also that OnLinedatabase servers (OnLine A and OnLine B) can communicate with each other.
Local clients can connect directly to an INFORMIX-SE database server usingunnamed pipes (IPC). Clients using network communications connect toINFORMIX-SE by connecting first to a daemon, sqlexecd. A daemon is a back-ground process that listens for requests from other programs. The sqlexecddaemon is started by the system administrator. When a client requests a con-nection to an INFORMIX-SE database server, sqlexecd notices the request andcreates a temporary (light gray arrows) connection between the client and SE.This temporary connection (shown as (3) - (1) in Figure 11-6) enables theclient and INFORMIX-SE database server to establish a direct connection (3).Then sqlexecd removes itself from the loop, leaving the client attached to theSE database server.
Figure 11-6Local and network
connection ofVersion 6.0 and later
products
Host 2
7.1 Client Y
B
OnLine 7.1
SE 7.1
sqlexecd
Daemon2
3
4
5
Understanding Informix Networking 11-15
11-16 Informix Guide to
Environment Variables
Environment VariablesThe Informix administrator must make sure that each user sets the correctenvironment variables. The following list shows the most importantenvironment variables used by OnLine and INFORMIX-SE:
■ PATH
■ INFORMIXDIR
■ INFORMIXSERVER
■ TERM
■ DBPATH
■ ONCONFIG
The INFORMIXDIR environment variable must be set to the full pathname ofthe directory where the Informix files reside. The PATH environment variablemust include the full pathname of the directory where the executables forINFORMIX-SE and/or INFORMIX-OnLine Dynamic Server reside. These twoenvironment variables are required. After the Informix administrator hasspecified them, you usually do not change them.
The INFORMIXSERVER environment variable is the name of the defaultdatabase server. It is also a required variable. You may choose to changeINFORMIXSERVER when you change applications.
The TERM (or TERMCAP and/or INFORMIXTERM) environment variableenables the clients to recognize and communicate with your terminal. Thesevariables are system- and terminal-dependent. To set them, you may needthe assistance of your system administrator.
The DBPATH environment variable is optional. If the application does notfully specify the location of an SE database server, the directories listed inDBPATH are searched by the database server to find the specified database.The DBPATH environment variable is also used to specify directory names forreports, forms, and command files used by both INFORMIX-OnLine DynamicServer and INFORMIX-SE.
The ONCONFIG environment variable is required when OnLine is initialized:It is not used by SE.
These environment variables are described in detail in Chapter 4 of theInformix Guide to SQL: Reference.
SQL: Tutorial
Connection Information
Connection InformationThe location of the database server and the type of connection (protocol) forthe database server are specified in the $INFORMIXDIR/etc/sqlhosts file.Each database server that might be accessed by an application must have anentry in sqlhosts file on every computer on the network.
In addition to the sqlhosts files, TCP/IP connections require entries in theUNIX systems files, /etc/hosts and /etc/services. IPX/SPX connections alsorequire auxiliary files, However, unlike TCP/IP, the names of the auxiliaryfiles depend on the hardware vendor.
Informix database servers follow UNIX security requirements for makingconnections. Thus, the UNIX system administrator may need to make modi-fications to the /etc/passwd, /etc/hosts, rhosts and other related files. Thesefiles are described in the INFORMIX-OnLine Dynamic Server Administrator’sGuide, the INFORMIX-SE Administrator’s Guide, the INFORMIX-Gateway withDRDA User Manual, and in operating system manuals.
SQL Connection StatementsBefore it can do anything else, the client application must open a database byexecuting a CONNECT statement or a DATABASE statement. The CONNECTstatement is preferred because it conforms with both ANSI andX/Open standards, which attempt to specify uniform syntax for networkedand nonnetworked environments.
The following command is an example of the CONNECT statement:
CONNECT TO databasename@servername
If the servername is omitted from the statement, the application connects tothe default database server specified by the INFORMIXSERVER environmentvariable.
If the databasename is omitted, the application connects to the database serverservername but does not open a database. Before you can use a database, youmust issue a DATABASE, CREATE DATABASE, or START DATABASE statement.
Understanding Informix Networking 11-17
11-18 Informix Guide to
Accessing Tables
Notice that the CONNECT statement does not give any information about thelocation of the database server. The location information for the databaseserver is in the sqlhosts file. (Refer to “Connection Information” onpage 11-17.)
The complete syntax for the CONNECT and DATABASE statements is coveredin Chapter 1 of the Informix Guide to SQL: Syntax.
Accessing TablesThe database that is opened by a CONNECT, DATABASE or CREATEDATABASE statement is the current database. If you are usingINFORMIX-OnLine Dynamic Server, you can query tables that are not in thecurrent 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 thefollowing SELECT statement:
SELECT name, number FROM salesdb:contacts
The database is salesdb. The table in salesdb is named contacts. You can usethe 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 toshorten them, as shown in the following example:
SELECT C.custname, S.phoneFROM salesdb:contacts C, stores:customer SWHERE C.custname = S.company
To specify a table in a database that is managed by a different OnLine data-base server, you must qualify the database name with a database server name.For example, the following SELECT statement refers to table customer fromdatabase masterdb, which resides on the database server central:
SELECT O.order_num, C.fname, C.lnameFROM masterdb@central:customer C, sales@boston:orders OWHERE C.customer_num = O.Customer_numINTO TEMP mycopy
In the example, two tables are being joined. The joined rows are stored in atemporary table mycopy in the current database. The tables are located intwo database servers, central and boston.
SQL: Tutorial
Using Synonyms with Table Names
Informix allows you to overqualify (to give more information than is required)table names. Because both table names are fully qualified, you cannot tellwhether the current database is masterdb or sales.
Using Synonyms with Table NamesA synonym is a name that you can use in place of another name. The main useof the CREATE SYNONYM statement is to make it more convenient to refer totables that are not in the current database.
The preceding example has been revised, as shown in the following example,to use synonyms for the table names:
CREATE SYNONYM mcust FOR masterdb@central:customer;
CREATE SYNONYM bords FOR sales@boston:orders;
SELECT bords.order_num, mcust.fname, mcust.lnameFROM mcust, bordsWHERE mcust.customer_num = bords.Customer_numINTO TEMP mycopy;
The CREATE SYNONYM statement stores the synonym name in the systemcatalog table syssyntable in the current database. The synonym is availableto any query made within that database.
A short synonym makes it easier to write queries, but synonyms can playanother role. They allow you to move a table to a different database, or evento a different computer, while leaving your queries the same.
Suppose you have several queries that refer to the tables customer andorders. The queries are embedded in programs, forms, and reports. Thetables are part of database stores7, which is kept on database server avignon.
Now the decision is made that the same programs, forms, and reports are tobe made available to users of a different computer on the network (databaseserver nantes). Those users have a database that contains a table namedorders containing the orders at their location, but they need access to thetable customer at avignon.
Understanding Informix Networking 11-19
11-20 Informix Guide to
Synonym Chains
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 thecustomer table is qualified with a database server name? A better solution isto create a synonym in the users’ database, as shown in the followingexample:
DATABASE stores7@nantes;CREATE SYNONYM customer FOR stores7@avignon:customer;
When the stored queries are executed in your database, the name customerrefers to the actual table. When they are executed in the other database, thename is translated through the synonym into a reference to the external table.
Synonym ChainsTo continue the preceding example, suppose that a new computer is addedto your network. Its name is db_crunch. The customer table and other tablesare moved to it to reduce the load on avignon. You can reproduce the tableon the new database server easily enough, but how can you redirect allaccesses to it? One way is to install a synonym to replace the old table, asshown in the following example:
DATABASE stores7@avignon EXCLUSIVE;RENAME TABLE customer TO old_cust;CREATE SYNONYM customer FOR stores7@db_crunch:customer;CLOSE DATABASE;
When you execute a query within stores7@avignon, a reference to tablecustomer finds the synonym and is redirected to the version on the new com-puter. This is also true of queries executed from database server nantes. Thesynonym in the database stores7@nantes still redirects references tocustomer to database stores7@avignon; however, the new synonym theresends the query to database stores7@db_crunch.
Chains of synonyms can be useful when, as in this example, you want to redi-rect all access to a table in one operation. However, you should update allusers’ databases as soon as possible so their synonyms point directly to thetable. You incur extra overhead in handling the extra synonyms and, if anycomputer in the chain is down, the table cannot be found.
SQL: Tutorial
Protecting Your Data in a Networked Environment
It is possible to run an application against a local database and later to run theidentical application against a database on another computer. The programruns equally well in either case (although it may run more slowly on the net-work database). As long as the data model is the same, a program cannot tellthe difference between a local database server and a remote one.
Protecting Your Data in a Networked EnvironmentThis section gives an overview of data-protection features used on a network.Chapter 4, “Modifying Data,” has a general discussion of data protection.
Data Protection with INFORMIX-SEINFORMIX-SE databases use the normal UNIX file structures, so SE databasescan be archived with the usual operating system backup procedures. On anetwork, you can write the archives to a device in another location.
Data Protection with INFORMIX-OnLine Dynamic ServerOnLine includes several tools that make multiple copies of data. Each one hasits own unique task in the area of data protection. The following discussionsgive a general description of these tools and highlight the distinctionsbetween them.
Data Replication
In a general sense, data replication means that a given piece of data has severaldistinct representations on several distinct servers. OnLine does data replica-tion by using two networked computers. Each computer has an OnLinedatabase server and databases that have identical characteristics. One data-base server is the primary and the other is the secondary. Data is alwayswritten to the primary server and then transferred to the secondary server.
Applications can read data from either database server. Thus the secondarysite can provide a dual purpose: It provides data protection and improvedperformance for users at the secondary site who need to read—but notwrite—data.
Understanding Informix Networking 11-21
11-22 Informix Guide to
Data Integrity for Distributed Data
If the primary database server (call it serverA) fails for any reason, the sec-ondary server (call it serverB) can become an independent database server.Users who would normally use serverA can be switched to serverB. Serviceto all the users can continue with a minimum of disruption while serverA isbeing repaired.
Data replication provides good data protection and continuity of service, butit is expensive: Memory must be provided for two complete copies of thedata, 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 beprepared locally or on a networked computer. Archives should be stored in alocation that is physically removed from the database server, so it may beconvenient to build the archives on a networked computer located at adifferent physical site. For descriptions of archiving tools for OnLine, see theINFORMIX-OnLine Dynamic Server Archive and Backup Guide.
Data Integrity for Distributed DataOnLine allows you to update data in several databases on different databaseservers. For example, a purchase order (a single transaction) might requireupdating information in databases on different database servers. To maintainthe integrity of the data, it is essential that either all the different databasesare updated or none of the databases are updated.
Two-Phase Commit
Two-phase commit is a protocol that coordinates work performed at multipledatabase servers on behalf of a single transaction. Unlike the data-replicationand archiving tools discussed earlier in this section, two-phase commit doesnot make two copies of the data. It protects the validity of one transaction thatinvolves several databases. Because two-phase commit involves only onetransaction, it is not usually considered as data protection.
SQL: Tutorial
Summary
A transaction that involves multiple database servers is called a globaltransaction. Two-phase commit is a natural extension of transaction handling,which is discussed in “Interrupted Modifications” on page 4-25. TheINFORMIX-OnLine Dynamic Server Administrator’s Guide discussestwo-phase commit in detail.
The two-phase commit begins when a client application has completed all itswork and requests a commit of the global transaction.
Phase 1
The current database server asks each participating database server if it cancommit its local transactions. Each database server responds Yes or No.
Phase 2
If all the database servers respond affirmatively, the current database servertells each one to commit its transactions and then the global transaction iscomplete. If any database server responds negatively or does not respond, alldatabase servers are instructed to abort the local transactions.
SummaryA network allows a client application to run on one computer, while thedatabase server operates in another computer to which the data is physicallyattached. 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 bemastered.
Understanding Informix Networking 11-23
III
Using Advanced SQLSect
ion
12Chapter
Creating and Using StoredProcedures
Introduction to Stored Procedures and SPL . . . . . . . . . . 12-3What You Can Do with Stored Procedures . . . . . . . . . 12-4Relationship Between SQL and a Stored Procedure . . . . . . 12-4
Creating and Using Stored Procedures . . . . . . . . . . . . 12-5Creating a Procedure Using DB-Access . . . . . . . . . . 12-6Creating a Procedure in a Program . . . . . . . . . . . . 12-6Commenting and Documenting a Procedure . . . . . . . . 12-7Diagnosing Compile-Time Errors . . . . . . . . . . . . 12-7
Finding Syntax Errors in a Procedure Using DB-Access . . . 12-8Finding Syntax Errors in a Procedure Using an SQL API . . . 12-8
Looking at Compile-Time Warnings . . . . . . . . . . . 12-9Generating the Text or Documentation. . . . . . . . . . . 12-10
Looking at the Procedure Text . . . . . . . . . . . . 12-10Looking at the Procedure Documentation . . . . . . . . 12-11
Executing a Procedure . . . . . . . . . . . . . . . . 12-11Executing a Stored Procedure Dynamically . . . . . . . . . 12-13Debugging a Procedure . . . . . . . . . . . . . . . . 12-13
Re-creating a Procedure . . . . . . . . . . . . . . 12-15
Privileges on Stored Procedures . . . . . . . . . . . . . . 12-16Privileges Necessary at Creation . . . . . . . . . . . . . 12-17Privileges Necessary at Execution . . . . . . . . . . . . 12-17
Owner-Privileged Procedures . . . . . . . . . . . . 12-17DBA-Privileged Procedures . . . . . . . . . . . . . 12-18Privileges and Nested Procedures . . . . . . . . . . . 12-18
Revoking Privileges . . . . . . . . . . . . . . . . . 12-19
12-2 Inf
Variables and Expressions . . . . . . . . . . . . . . . . 12-19Variables . . . . . . . . . . . . . . . . . . . . . 12-19
Format of Variables . . . . . . . . . . . . . . . . 12-19Global and Local Variables . . . . . . . . . . . . . 12-20Defining Variables . . . . . . . . . . . . . . . . 12-20Data Types for Variables . . . . . . . . . . . . . . 12-21Using Subscripts with Variables . . . . . . . . . . . . 12-21Scope of Variables . . . . . . . . . . . . . . . . 12-22Variable/Keyword Ambiguity . . . . . . . . . . . . 12-22
SPL Expressions . . . . . . . . . . . . . . . . . . 12-24Assigning Values to Variables . . . . . . . . . . . . 12-24
Program Flow Control . . . . . . . . . . . . . . . . . . 12-25Branching . . . . . . . . . . . . . . . . . . . . . 12-25Looping . . . . . . . . . . . . . . . . . . . . . 12-26Function Handling . . . . . . . . . . . . . . . . . 12-27
Calling Procedures Within a Procedure . . . . . . . . . 12-27Running an Operating System Command from Within a Procedure
12-27Recursively Calling a Procedure. . . . . . . . . . . . 12-27
Passing Information into and out of a Procedure. . . . . . . . . 12-28Returning Results . . . . . . . . . . . . . . . . . . 12-28
Specifying Return Data Types . . . . . . . . . . . . 12-28Returning the Value . . . . . . . . . . . . . . . . 12-29Returning More Than One Set of Values from a Procedure . . 12-29
Exception Handling . . . . . . . . . . . . . . . . . . 12-31Trapping an Error and Recovering . . . . . . . . . . . . 12-31Scope of Control of an ON EXCEPTION Statement . . . . . . 12-32User-Generated Exceptions. . . . . . . . . . . . . . . 12-34
Simulating SQL Errors . . . . . . . . . . . . . . . 12-34Using RAISE EXCEPTION to Exit Nested Code . . . . . . 12-35
Summary . . . . . . . . . . . . . . . . . . . . . . 12-36
ormix Guide to SQL: Tutorial
You can write procedures using SQL and some additional statementsbelonging to the Stored Procedure Language (SPL), and store this procedurein the database. These stored procedures are effective tools for controllingSQL activity. This chapter provides instruction on how to write stored proce-dures. To help you learn how to write them, examples of working storedprocedures are provided.
The syntax for each SPL statement is described in Chapter 1 of the InformixGuide to SQL: Syntax. Accompanying the syntax for each statement are usagenotes and examples pertinent to that statement.
Introduction to Stored Procedures and SPLTo SQL, a stored procedure is a user-defined function. Anyone who has theResource privilege on a database can create a stored procedure. Once thestored procedure is created, it is stored in an executable format in the data-base as an object of the database. You can use stored procedures to performany function you can perform in SQL as well as to expand what you canaccomplish with SQL alone.
You write a stored procedure using SQL and SPL statements. SPL statementscan be used only inside the CREATE PROCEDURE and CREATE PROCEDUREFROM statements. The CREATE PROCEDURE statement is available withDB-Access, and the CREATE PROCEDURE and CREATE PROCEDURE FROMstatements are available with SQL APIs such as INFORMIX-ESQL/C andINFORMIX-ESQL/COBOL. The CREATE PROCEDURE FROM statement is alsoavailable with INFORMIX-4GL and NewEra.
Creating and Using Stored Procedures 12-3
12-4 Informix Guide to
What You Can Do with Stored Procedures
What You Can Do with Stored ProceduresYou can accomplish a wide range of objectives with stored procedures,including improving database performance, simplifying writingapplications, and limiting or monitoring access to data.
Because a stored procedure is stored in an executable format, you can use itto execute frequently repeated tasks to improve performance. Executing astored procedure rather than straight SQL code allows you to bypass repeatedparsing, validity checking, and query optimization.
Because a stored procedure is an object in the database, it is available to everyapplication running on the database. Several applications can use the samestored procedure, so development time for applications is reduced.
You can write a stored procedure to be run with the DBA privilege by a userwho does not have the DBA privilege. This allows you to limit and controlaccess to data in the database. Alternatively, a stored procedure can monitorthe users who access certain tables or data. (See “Controlling Access to DataUsing Stored Procedures” on page 10-16 for a discussion of this topic.)
Relationship Between SQL and a Stored ProcedureYou can call a procedure within data-manipulation SQL statements and issueSQL statements within a procedure. See Chapter 1 of the Informix Guide toSQL: Syntax for a complete list of data manipulation SQL statements.
You use a stored procedure within a data-manipulation SQL statement tosupply values to that statement. For example, you can use a procedure toperform the following actions:
■ Supply values to be inserted into a table
■ Supply a value that makes up part of a condition clause in a SELECT,DELETE, or UPDATE statement
SQL: Tutorial
Creating and Using Stored Procedures
These are two possible uses of a procedure within a data manipulationstatement, but others exist. In fact, any expression within a datamanipulation SQL statement can consist of a procedure call.
You can also issue SQL statements within a stored procedure to hide thoseSQL statements from a database user. Rather than having all users learn howto use SQL, one experienced SQL user can write a stored procedure toencapsulate an SQL activity and let others know that the procedure is storedin the database so they can execute it.
Creating and Using Stored ProceduresTo write a stored procedure, put the SQL statements that you want run as partof the procedure inside the statement block in a CREATE PROCEDURE state-ment. You can use SPL statements to control the flow of the operation withinthe procedure. SPL statements include IF, FOR, and others and are describedin the Informix Guide to SQL: Syntax. The CREATE PROCEDURE and CREATEPROCEDURE FROM statements are also described in Chapter 1 of the InformixGuide to SQL: Syntax.
Creating and Using Stored Procedures 12-5
12-6 Informix Guide to
Creating a Procedure Using DB-Access
CREATE PROCEDURRETURNING C
items
DEFINE p_lnDEFINE p_adDEFINE p_stDEFINE p_zi
SELECT fnamINTO p_fFROM cusWHERE ln
RETURN p_fnEND PROCEDURE
DOCUMENT 'This
'its only a'the custom
WITH LISTING IN; -- end of the
Creating a Procedure Using DB-AccessTo create a stored procedure using DB-Access, issue the CREATE PROCEDUREstatement, including all the statements that are part of the procedure in thestatement block. For example, to create a procedure that reads a customeraddress, use a statement such as the one in Figure 12-1.
Creating a Procedure in a ProgramTo create a stored procedure using NewEra, INFORMIX-4GL, or an SQL API,put the text of the CREATE PROCEDURE statement in a file. Use the CREATEPROCEDURE FROM statement and refer to that file to compile the procedure.For example, to create a procedure to read a customer name, you can use astatement such as the one in Figure 12-1 and store it in a file. If the file isnamed read_add_source, the following statement compiles theread_address procedure:
CREATE PROCEDURE FROM 'read_add_source';
Figure 12-1Procedure thatreads from thecustomer table
E read_address (lastname CHAR(15)) -- one argumentHAR(15), CHAR(15), CHAR(20), CHAR(15),CHAR(2), CHAR(5); -- 6
ame,p_fname, p_city CHAR(15); --define each procedure variabled CHAR(20);ate CHAR(2);p CHAR(5);
e, address1, city, state, zipcodename, p_add, p_city, p_state, p_ziptomerame = lastname;
ame, lastname, p_add, p_city, p_state, p_zip; --6 items
procedure takes the last name of a customer as', --brief--description
rgument. It returns the full name and address of',er.' '/acctng/test/listfile' -- compile-time warnings go here procedure read_address
SQL: Tutorial
Commenting and Documenting a Procedure
/* This pro * the file */#include <sEXEC SQL inEXEC SQL inEXEC SQL in/* Program
main(){EXEC SQL daEXEC SQL cr}
Figure 12-2 shows how the previous SQL statement looks in an ESQL/Cprogram.
Commenting and Documenting a ProcedureObserve that the read_address procedure in Figure 12-2 includes commentsand a DOCUMENT clause. The comments are incorporated into the text of theprocedure. Any characters following a double hyphen (--) are considered tobe a comment. The double hyphen can be used anywhere within a line.
The text in the DOCUMENT clause should give a summary of the procedure.You can extract this text by querying the sysprocbody system catalog table.See “Looking at the Procedure Documentation” on page 12-11 for moreinformation about reading the DOCUMENT clause.
Diagnosing Compile-Time ErrorsWhen you issue a CREATE PROCEDURE or CREATE PROCEDURE FROMstatement, the statement fails if a syntax error occurs in the body of theprocedure. The database server stops processing the text of the procedureand returns the location of the error.
Figure 12-2SQL statement that
compiles and storesthe read_address
procedure in anESQL/C program
gram creates whatever procedure is in * 'read_add_source'.
tdio.h>clude sqlca;clude sqlda;clude datetime;to create a procedure from the pwd */
tabase play;eate procedure from 'read_add_source';
Creating and Using Stored Procedures 12-7
12-8 Informix Guide to
Diagnosing Compile-Time Errors
Finding Syntax Errors in a Procedure Using DB-Access
If a procedure created using DB-Access has a syntax error, when you choosethe Modify option of the SQL menu, the cursor sits on the line containing theoffending syntax.
Finding Syntax Errors in a Procedure Using an SQL API
If a procedure created using an SQL API has a syntax error, the CREATEPROCEDURE statement fails and sets SQLCA and SQLSTATE values. The data-base server sets the SQLCODE field of the SQLCA to a negative number andsets the fifth element of the SQLERRD array to the character offset into the file.The particular fields of the SQLCA for each product are shown in thefollowing table:
In case of syntax error, the database server sets SQLSTATE to 42000.
ESQL/C ESQL/FORTRAN ESQL/COBOL
sqlca.sqlcodeSQLCODE
sqlcod SQLCODE OF SQLCA
sqlca.sqlerrd[4] sqlca.sqlerr(5) SQLERRD[5] OF SQLCA
SQL: Tutorial
Looking at Compile-Time Warnings
#include <stdio.EXEC SQL includeEXEC SQL includeEXEC SQL include/* Program to cr
main(){long char_num;
EXEC SQL databasEXEC SQL create if (sqlca.sqlcod{
printf(" char_num printf("
%ld\n}...
Figure 12-3 shows how to trap for a syntax error when you are creating aprocedure. It also shows how to display a message and character positionwhere the error occurred.
In Figure 12-3, if the CREATE PROCEDURE FROM statement fails, the programdisplays a message in addition to the character position at which the syntaxerror occurred.
Looking at Compile-Time WarningsIf the database server detects a potential problem but the procedure issyntactically correct, the database server generates a warning and places it ina listing file. You can examine this file to check for potential problems beforeexecuting the procedure.
Figure 12-3Checking for failure
when creating aprocedure using
ESQL/C
h> sqlca; sqlda; datetime;eate a procedure from procfile in pwd */
e play;procedure from 'procfile';e != 0 )
\nsqlca.sqlcode = %ld\n", sqlca.sqlcode); = sqlca.sqlerrd[4];\nError in creating read_address. Check character position", char_num);
Creating and Using Stored Procedures 12-9
12-10 Informix Guide to
Generating the Text or Documentation
To obtain the listing of compile-time warnings for your procedure, use theWITH LISTING IN clause in your CREATE PROCEDURE statement, as shown inthe following example:
CREATE PROCEDURE read_address (lastname CHAR(15)) -- one argumentRETURNING CHAR(15), CHAR(15), CHAR(20), CHAR(15), CHAR(2), CHAR(5); -- 6 items...WITH LISTING IN '/acctng/test/listfile' -- compile-time warnings go here
; -- end of the procedure read_address
If you are working on a network, the listing file is created on the computerwhere 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 rela-tive pathname for the listing file, the file is created in your home directory onthe computer where the database resides. (If you do not have a home direc-tory, the file is created in the root directory.)
After you create the procedure, you can view the file specified in the WITHLISTING IN clause to see the warnings it contains.
Generating the Text or DocumentationOnce you create the procedure, it is stored in the sysprocbody system catalogtable. The sysprocbody system catalog table contains the executable proce-dure as well as the text of the original CREATE PROCEDURE statement and thedocumentation text.
Looking at the Procedure Text
To generate the text of the procedure, select the data column from thesysprocbody system catalog table. The following SELECT statement reads theread_address procedure text:
SELECT data FROM informix.sysprocbodyWHERE datakey = 'T' -- find text linesANDprocid = (SELECT procid FROM informix.sysprocedures
WHERE informix.sysprocedures.procname = 'read_address')
SQL: Tutorial
Executing a Procedure
Looking at the Procedure Documentation
If you want to view only the documenting text of the procedure, use thefollowing SELECT statement to read the documentation string. The documen-tation lines found in the following example are those in the DOCUMENTclause of the CREATE PROCEDURE statement.
SELECT data FROM informix.sysprocbodyWHERE datakey = 'D' -- find documentation linesANDprocid = (SELECT procid FROM informix.sysprocedures
WHERE informix.sysprocedures.procname = 'read_address')
Executing a ProcedureYou can execute a procedure in several ways. You can use the SQL statementEXECUTE PROCEDURE or either the LET or CALL SPL statement. In addition,you can dynamically execute procedures, as described in “Executing a StoredProcedure Dynamically” on page 12-13.
The read_address procedure returns the full name and address of a customer.To run read_address on a customer called “Putnum” using EXECUTEPROCEDURE, enter the following statement:
EXECUTE PROCEDURE read_address ('Putnum');
Creating and Using Stored Procedures 12-11
12-12 Informix Guide to
Executing a Procedure
#include <stdio.EXEC SQL includeEXEC SQL includeEXEC SQL include/* Program to ex
main(){EXEC SQL BEGIN D
char lname[1char city[16
EXEC SQL END DECEXEC SQL connectEXEC SQL EXECUTE
INTO :lname,if (sqlca.sqlcod
printf("\nF}
CREATE PROC
DEFINE DEFINE DEFINE DEFINE ...CALL re
p_a...-- use
END PROCEDU
The read_address procedure returns values; therefore, if you are executing aprocedure from an SQL API, INFORMIX-4GL, NewEra, or from another proce-dure, you must use an INTO clause with host variables to receive the data. Forexample, executing the read_address procedure in an ESQL/C program isaccomplished with the code segment shown in Figure 12-4.
If you are executing a procedure within another procedure, you can use theSPL statements CALL or LET to run the procedure. To use the CALL statementwith the read_address procedure, you can use the code shown in Figure 12-5.
Figure 12-4Executing a
procedure usingESQL/C
Figure 12-5Calling a procedure
inside anotherprocedure with the
CALL statement
h> sqlca; sqlda; datetime;ecute a procedure in the database named 'play' */
ECLARE SECTION;6], fname[16], address[21];], state[3], zip[6];LARE SECTION; to 'play'; PROCEDURE read_address ('Putnum') :fname, :address, :city, :state, :zip;e != 0 )ailure on execute");
EDURE address_list ()
p_lname, p_fname, p_city CHAR(15);p_add CHAR(20);p_state CHAR(2);p_zip CHAR(5);
ad_address ('Putnum') RETURNING p_fname, p_lname,dd, p_city, p_state, p_zip;
the returned data some wayRE;
SQL: Tutorial
Executing a Stored Procedure Dynamically
CREATE PROCEDUR
DEFINE p_lnDEFINE p_adDEFINE p_stDEFINE p_zi...LET p_fname
('Putnum');...-- use the
END PROCEDURE;
Figure 12-6 provides an example of using the LET statement to assign valuesto procedural variables through a procedure call.
Executing a Stored Procedure DynamicallyYou can prepare an EXECUTE PROCEDURE statement in conjunction with theALLOCATE DESCRIPTOR and GET DESCRIPTOR statements in an ESQL/Cprogram. Parameters to the stored procedure can be passed in the samemanner as the SELECT statement and may be passed at run time or compiletime. For a detailed example of executing a stored procedure dynamically, seeChapter 10 of the INFORMIX-ESQL/C Programmer’s Manual. For informationabout dynamic SQL and using a prepared SELECT statement, see Chapter 5,“Programming with SQL.”
Debugging a ProcedureOnce you successfully create and run a procedure, you can encounter logicalerrors. If logical errors are in the procedure, use the TRACE statement to helpfind them. You can trace the values of the following procedural entities:
■ Variables
■ Procedure arguments
■ Return values
■ SQL error codes
■ ISAM error codes
Figure 12-6Assigning valuesfrom a procedure
call with a LETstatement
E address_list ()
ame, p_fname, p_city CHAR(15);d CHAR(20);ate CHAR(2);p CHAR(5);
, p_lname,p_add, p_city, p_state, p_zip = read_address
returned data some way
Creating and Using Stored Procedures 12-13
12-14 Informix Guide to
Debugging a Procedure
CREATE PROCEDURERETURNING CH
DEFINE p_lnaDEFINE p_addDEFINE p_staDEFINE p_zipDEFINE lcoun
LET lcount =
TRACE ON; --TRACE 'ForeaFOREACHSELECT fname
INTO p_f FROM cus WHERE ln
RETURN p_fnaLET lcount =END FOREACH;
TRACE 'Loop FOR i IN (1
BEGIN RETURN END
END FOR;
END PROCEDURE;
To generate a listing of traced values, first use the SQL statement SET DEBUGFILE to name the file that is to contain the traced output. When you createyour procedure, include the TRACE statement in one of its forms.
The following ways specify the form of TRACE output:
Figure 12-7 shows how you can use the TRACE statement with a version ofthe read_address procedure. Several SPL statements shown in this examplehave not been discussed, but the entire example demonstrates how theTRACE statement can help you monitor execution of the procedure.
TRACE ON traces all statements except SQL statements. Thecontents of variables are printed before being used.Procedure calls and returned values are also traced.
TRACEPROCEDURE
traces only the procedure calls and returned values.
TRACE expression prints a literal or an expression. If necessary, the valueof the expression is calculated before being sent to thefile.
Figure 12-7Using the TRACE
statement tomonitor execution
of a procedure
read_many (lastname CHAR(15))AR(15), CHAR(15), CHAR(20), CHAR(15),CHAR(2), CHAR(5);
me,p_fname, p_city CHAR(15); CHAR(20);te CHAR(2); CHAR(5);t, i INT;
1;
Every expression will be traced from here onch starts';-- A trace statement with a literal
, lname, address1, city, state, zipcodename, p_lname, p_add, p_city, p_state, p_ziptomerame = lastnameme, p_lname, p_add, p_city, p_state, p_zip WITH RESUME; lcount + 1; -- count of returned addresses
starts'; -- Another literalTO 5)
i , i+1, i*i, i/i, i-1,i with resume;
SQL: Tutorial
Debugging a Procedure
Each time you execute the traced procedure, entries are added to the file youspecified using the SET DEBUG FILE statement. To see the debug entries, viewthe output file using any text editor.
The following list contains some of the output generated by the procedure inFigure 12-7 on page 12-14. Next to each traced statement is an explanation ofits contents.
Re-creating a Procedure
If a procedure exists in a database, you must drop it explicitly using the DROPPROCEDURE statement before you can create another procedure with thesame name. If you debug your procedure and attempt to use the CREATEPROCEDURE statement with the same procedure name again, the attemptfails unless you first drop the existing procedure from the database.
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.
Creating and Using Stored Procedures 12-15
12-16 Informix Guide to
Privileges on Stored Procedures
Privileges on Stored ProceduresA stored procedure resides in the database in which it was created. As withother database objects, you need appropriate privileges to create a stored pro-cedure. In addition, you need appropriate privileges to execute a storedprocedure.
Two types of stored procedures exist in a database: DBA-privileged andowner-privileged. When you create the procedure, you specify which type itis. You need different privileges to create and execute these two types of pro-cedures. The differences are described in the sections that follow and aresummarized in Figure 12-8.
Figure 12-8Differences between DBA-privileged and owner-privileged procedures
DBA-privilegedprocedure
Owner-privileged procedure
Can be created by: Any user with theDBA privilege
Any user with at least theResource privilege
Users having theExecute privilege bydefault:
Any user with theDBA privilege
Not ANSI-compliant:
Public (any user with Connectdatabase privilege)
ANSI-compliant:
The procedure owner and anyuser with the DBA privilege
Privileges the proce-dure owner or DBAmust grant anotheruser to enable that userto run a procedure:
Execute privilege Execute privilege and privilegeson underlying objects.
If owner has privileges on under-lying objects with the GRANTWITH option, only the Executeprivilege is required
SQL: Tutorial
Privileges Necessary at Creation
Privileges Necessary at CreationOnly users who have the DBA privilege can create a DBA-privilegedprocedure. To create an owner-privileged procedure, you need to have atleast the Resource privilege. See Chapter 10, “Granting and Limiting Accessto Your Database.”.
Privileges Necessary at ExecutionTo run a procedure, you always need the Execute privilege for that procedureor DBA database privileges. Depending on whether the procedure is a DBA-mode procedure and if the database is ANSI-compliant, certain privileges aregranted to users implicitly by the database server.
If the procedure is owner-privileged, the database server grants the Executeprivilege to PUBLIC. If the database is ANSI-compliant, the database servergrants only the Execute privilege to the owner and users with DBA status.
If the procedure is DBA-privileged, the database server grants the Executeprivilege to all users having the DBA privilege.
Owner-Privileged Procedures
When you execute an owner-privileged procedure, the database serverchecks the existence of any referenced objects. In addition, the databaseserver verifies that you have the necessary privileges on the referencedobjects.
If you execute a procedure that only references objects that you own, noprivilege conflicts occurs. If you do not own the referenced objects and youexecute a procedure that contains SELECT statements, for example, you needthe Select privilege on the appropriate tables to run the procedure withoutgenerating errors.
If the owner has the necessary privileges with the WITH GRANT option, thoseprivileges are automatically conferred to you when the owner issues aGRANT EXECUTE statement.
Creating and Using Stored Procedures 12-17
12-18 Informix Guide to
Privileges Necessary at Execution
Unqualified objects created in the course of the procedure are owned by theowner of the procedure, not the user running the procedure. For example, thefollowing example shows lines in an owner-privileged stored procedure thatcreate two tables. If this procedure is owned by tony and a user marty runsthe 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 ownerlibby, so libby owns the table tiny.
CREATE PROCEDURE tryit()...CREATE TABLE gargantuan (col1 INT, col2 INT, col3 INT);CREATE TABLE libby.tiny (col1 INT, col2 INT, col3 INT);
END PROCEDURE;
DBA-Privileged Procedures
When you execute a DBA-privileged procedure, you assume the privileges ofa DBA for the duration of the procedure. A DBA-privileged procedure acts asif the user running the procedure is first granted DBA privilege, then executeseach statement of the procedure manually, and finally has DBA privilegerevoked.
Objects created in the course of running a DBA procedure are owned by theuser running the procedure, unless the data-definition statement in theprocedure explicitly names the owner to be someone else.
Privileges and Nested Procedures
DBA-privileged status is not inherited by a called procedure. For example, ifa DBA-privileged procedure executes an owner-privileged procedure, theowner-privileged procedure does not run as a DBA procedure. If an owner-privileged procedure calls a DBA-privileged procedure, the statementswithin the DBA-privileged procedure execute as they would within anyDBA-privileged procedure.
SQL: Tutorial
Revoking Privileges
Revoking PrivilegesThe owner of a procedure can revoke the Execute privilege from a user. If auser loses the Execute privilege on a procedure, the Execute privilege is alsorevoked from all users who were granted the Execute privilege by that user.
Variables and ExpressionsThis section discusses how to define and use variables in SPL. The differencesbetween SPL and SQL expressions also are covered here.
VariablesYou can use a variable in a stored procedure in several ways. You can use avariable in a database query or other SQL statement wherever a constant isexpected. You can use a variable with SPL statements to assign and calculatevalues, keep track of the number of rows returned from a query, and executea loop as well as handle other tasks.
The value of a variable is held in memory; the variable is not a databaseobject. Hence, rolling back a transaction does not restore values of proceduralvariables.
Format of Variables
A variable follows the rules of an SQL identifier. (See Chapter 1 of the InformixGuide to SQL: Syntax.) Once you define a variable, you can use it anywhere inthe procedure as appropriate.
If you are using an SQL API, you do not have to set off the variable with aspecial symbol (unlike host variables in an SQL API).
Creating and Using Stored Procedures 12-19
12-20 Informix Guide to
Variables
Global and Local Variables
You can define a variable to be either local or global. A variable is local bydefault. The following definitions describe the differences between the twotypes:
Local A local variable is available only within the procedure in whichit is defined. Local variables do not allow a default value to beassigned at compile time.
Global A global variable is available to other procedures run by thesame user session in the same database. The values of globalvariables are stored in memory. The global environment is thememory used by all the procedures run within a given sessionon a given database server, such as all procedures run by anSQL API or in a DB-Access session. The values of the variablesare lost when the session ends.
Global variables require a default value to be assigned at com-pile time.
The first definition of a global variable puts the variable into theglobal environment. Subsequent definitions of the same vari-able, in different procedures, simply bind the variable to theglobal environment.
Defining Variables
You define variables using the DEFINE statement. If you list a variable in theargument list of a procedure, the variable is defined implicitly, and you donot need to define it formally with the DEFINE statement. You must assign avalue, which may be null, to a variable before you can use it.
SQL: Tutorial
Variables
Data Types for Variables
You can define a variable as any of the data types available for columns in atable except SERIAL. The following example shows several cases of definedprocedural variables:
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 actuallycontain the data; instead, it serves as a pointer to the data. However, use thisprocedural variable as you would use any other procedural variable. Whenyou define a TEXT or BYTE variable, you must use the wordREFERENCES, which emphasizes that these variables do not contain the data;they simply reference the data. The following example shows the definitionof a TEXT and a BYTE variable:
DEFINE ttt REFERENCES TEXT;DEFINE bbb REFERENCES BYTE;
Using Subscripts with Variables
You can use subscripts with variables having CHAR, VARCHAR, NCHAR,NVARCHAR, BYTE or TEXT data types, just as you can with SQL columnnames. The subscripts indicate the starting and ending character positions ofthe variable. Subscripts must always be constants. You cannot use variablesas subscripts. The following example illustrates the usage:
DEFINE name CHAR(15);LET name[4,7] = 'Ream';SELECT fname[1,3] INTO name[1,3] FROM customer
WHERE lname = 'Ream';
The portion of the variable contents that is delimited by the two subscripts isreferred to as a substring.
Creating and Using Stored Procedures 12-21
12-22 Informix Guide to
Variables
CREATE PROCDEFINE LET x =LET z =BEGIN
DEFLETLETLET
ENDLET y =LET x =
END PROCEDU
Scope of Variables
A variable is valid within the statement block in which it is defined. It is validwithin statement blocks nested within that statement block as well, unless itis masked by a redefinition of a variable with the same name.
In the beginning of the procedure in Figure 12-9, the integer variables x, y,and z are defined and initialized. The BEGIN and END statements mark anested statement block in which the integer variables x and q are defined aswell as the CHAR variable z. Within the nested block, the redefined variablex masks the original variable x. After the END statement, which marks theend 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 followingrules for identifiers help you avoid ambiguities for variables, procedurenames, and system function names:
■ Defined variables take the highest precedence.
■ Procedures defined as such in a DEFINE statement take precedenceover SQL functions.
■ SQL functions take precedence over procedures that exist but are notidentified as procedures in a DEFINE statement.
In some cases, you must change the name of the variable. For example, youcannot define a variable with the name count or max, because these are thenames 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.
Figure 12-9Masking of variables
with nestedstatement blocks
EDURE scope()x,y,z INT; 5; LET y = 10; x + y; --z is 15
INE x, q INT; DEFINE z CHAR(5); x = 100; q = x + y; -- q = 110 z = 'silly'; -- z receives a character value
x; -- y is now 5 z; -- z is now 15, not 'silly'RE;
SQL: Tutorial
Variables
Variables and Column Names
If you use the same identifier for a procedural variable as you use for acolumn name, the database server assumes that each instance of the identifieris a variable. Qualify the column name with the table name to use the identi-fier as a column name. In the following example, the procedure variablelname is the same as the column name. In the following SELECT statement,customer.lname is a column name and lname is a variable name:
CREATE PROCEDURE table_test()
DEFINE lname CHAR(15);LET lname = 'Miller';
.
.
.SELECT customer.lname FROM customer INTO lname
WHERE customer_num = 502;...
Variables and SQL Functions
If you use the same identifier for a procedural variable as for an SQL function,the database server assumes that an instance of the identifier is a variable anddisallows the use of the SQL function. You cannot use the SQL function withinthe block of code in which the variable is defined. The following exampleshows a block within a procedure in which the variable called user is defined.This definition disallows the use of the USER function in the BEGIN...ENDblock.
CREATE PROCEDURE user_test()DEFINE name CHAR(10);DEFINE name2 CHAR(10);LET name = user; -- the SQL function
BEGINDEFINE user CHAR(15); -- disables user functionLET user = 'Miller';LET name = user; -- assigns 'Miller' to variable name
END...LET name2 = user; -- SQL function again
Creating and Using Stored Procedures 12-23
12-24 Informix Guide to
SPL Expressions
Procedure Names and SQL Functions
For information about ambiguities between procedure names and SQLfunction names, see the Informix Guide to SQL: Syntax.
SPL ExpressionsYou can use any SQL expression in a stored procedure except for an aggregateexpression. The complete syntax and notes for SQL expressions are describedin Chapter 1 of the Informix Guide to SQL: Syntax.
The following examples contain SQL expressions:
var1var1 + var2 + 5read_address('Miller')read_address(lastname = 'Miller')get_duedate(acct_num) + 10 UNITS DAYfname[1,5] || ''|| lname'(415)' || get_phonenum(cust_name)
Assigning Values to Variables
You can assign a value to a procedure variable in the following ways:
■ Using a LET statement
■ Using a SELECT...INTO statement
■ Using a CALL statement with a procedure that has a RETURNINGclause
■ Using an EXECUTE PROCEDURE...INTO statement
Use the LET statement to assign a value to one or more variables. Thefollowing example illustrates several forms of the LET statement:
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);
SQL: Tutorial
Program Flow Control
Use the SELECT statement to assign a value directly from the database to avariable. The statement in the following example accomplishes the same taskas the third LET statement in the previous example:
SELECT fname, lname into a, b FROM customerWHERE customer_num = 101
Use the CALL or EXECUTE PROCEDURE statements to assign values returnedby a procedure to one or more procedural variables. Both statements in thefollowing example return the full address from the procedure read_addressinto the specified procedural variables:
EXECUTE PROCEDURE read_address('Smith')INTO p_fname, p_lname, p_add, p_city, p_state, p_zip;
CALL read_address('Smith')RETURNING p_fname, p_lname, p_add, p_city, p_state, p_zip;
Program Flow ControlSPL contains several statements that enable you to control the flow of yourstored procedure and to make decisions based on data obtained at run time.These program-flow-control statements are described briefly in this section.Their syntax and complete descriptions are provided in Chapter 2 of theInformix Guide to SQL: Syntax.
BranchingUse an IF statement to form a logic branch in a stored procedure. An IFstatement first evaluates a condition and, if the condition is true, thestatement 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 12-10 on page 12-26 shows an example of an IF statement.
Creating and Using Stored Procedures 12-25
12-26 Informix Guide to
Looping
CREATE PROCRETURNIDEFINE
IF str1res
ELIF stres
ELSEres
END IFRETURN
END PROCEDU
LoopingThree methods of looping exist in SPL, accomplished with one of thefollowing statements:
FOR initiates a controlled loop. Termination is guaranteed.
FOREACH allows you to select and manipulate more than one rowfrom the database. It declares and opens a cursorimplicitly.
WHILE initiates a loop. Termination is not guaranteed.
Four ways exist to leave a loop, which can accomplished with one of thefollowing statements:
CONTINUE skips the remaining statements in the present, identifiedloop and starts the next iteration of that loop.
EXIT exits The present, identified loop. Execution resumes atthe first statement after the loop.
RETURN exits the procedure. If a return value is specified, thatvalue is returned upon exit.
RAISE EXCEPTION exits the loop if the exception is not trapped (caught) inthe body of the loop.
See Chapter 2 of the Informix Guide to SQL: Syntax for more informationconcerning the syntax and use of these statements.
Figure 12-10Using an IF
statement
EDURE str_compare (str1 CHAR(20), str2 CHAR(20))NG INT;result INT;
> str2 THENult = 1;r2 > str1 THENult = -1;
ult = 0;
result;RE; -- str_compare
SQL: Tutorial
Function Handling
CREATE PROCRETURNI
DEFINE CALL re
IF fnamELSE REEND IF
END PROCEDU
CREATE DBA PROCE
DEFINE username
DELETE FROM custWHERE custom
IF username = 'aSYSTEM 'echo
END IFEND PROCEDURE; -
Function HandlingYou can call procedures as well as run operating system commands fromwithin a procedure.
Calling Procedures Within a Procedure
Use a CALL statement or the SQL statement EXECUTE PROCEDURE to executea procedure from a procedure. Figure 12-11 shows a call to the read_nameprocedure using a CALL statement.
Running an Operating System Command from Within a Procedure
Use the SYSTEM statement to execute a system call from a procedure.Figure 12-12 shows a call to the echo command.
Recursively Calling a Procedure
You can call a procedure from itself. No restrictions apply on calling aprocedure recursively.
Figure 12-11Calling a procedure
with a CALLstatement
Figure 12-12Making a system
call from aprocedure with a
SYSTEM statement
EDURE call_test()NG CHAR(15), CHAR(15);
fname, lname CHAR(15);ad_name('Putnum') RETURNING fname, lname;
e = 'Eileen' THEN RETURN 'Jessica', lname;TURN fname, lname;
RE;
DURE delete_customer(cnum INT)
CHAR(8);
omerer_num = cnum;
cctclrk' THEN ''Delete from customer by acctclrk'' >> /mis/records/updates' ;
- delete_customer
Creating and Using Stored Procedures 12-27
12-28 Informix Guide to
Passing Information into and out of a Procedure
Passing Information into and out of a ProcedureWhen you create a procedure, you determine whether it expects informationto be passed to it by specifying an argument list. For each piece of informa-tion that the procedure expects, you specify one argument and the data typeof that argument.
For example, if a procedure needs to have a single piece of integerinformation passed to it, you can provide a procedure heading as shown inthe following example:
CREATE PROCEDURE safe_delete(cnum INT)
Returning ResultsA procedure that returns one or more values must contain two lines of codeto accomplish the transfer of information: one line to state the data types thatare going to be returned, and one line to return the values explicitly.
Specifying Return Data Types
Immediately after you specify the name and input parameters of yourprocedure, you must include a RETURNING clause with the data type of eachvalue you expect to be returned. The following example shows the header ofa procedure (name, parameters, and RETURNING clause) that expects oneinteger as input and returns one integer and one 10-byte character value:
CREATE PROCEDURE get_call(cnum INT)RETURNING INT, CHAR(10);
SQL: Tutorial
Returning Results
Returning the Value
Once you use the RETURNING clause to indicate the type of values that are tobe returned, you can use the RETURN statement at any point in your proce-dure to return the same number and data types as listed in the RETURNINGclause. The following example shows how you can return information fromthe get_call procedure:
CREATE PROCEDURE get_call(cnum INT)RETURNING INT, CHAR(10);DEFINE ncalls INT;DEFINE o_name CHAR(10);...RETURN ncalls, o_name;...
END PROCEDURE;
If you neglect to include a RETURN statement, you do not get an errormessage at compile time.
Returning More Than One Set of Values from a Procedure
If your procedure performs a select that can return more than one row fromthe database or if you return values from inside a loop, you must use theWITH RESUME keywords in the RETURN statement. Using a RETURN...WITHRESUME statement causes the value or values to be returned to the callingprogram or procedure. After the calling program receives the values, execu-tion returns to the statement immediately following the RETURN...WITHRESUME statement.
Creating and Using Stored Procedures 12-29
12-30 Informix Guide to
Returning Results
CREATE PROCEDURERETURNING CHCHAR(5);
DEFINE p_lnaDEFINE p_addDEFINE p_staDEFINE p_zipDEFINE lcounDEFINE i INT
LET lcount =TRACE ON;CREATE VIEW TRACE 'ForeaFOREACHSELECT fname
INTO p_f FROM cus WHERE ln
RETURN p_fnaWITH RESU
LET lcount =END FOREACH;
FOR i IN (1 BEGIN
RETURN END
END FOR;END PROCEDURE;
Figure 12-13 is an example of a cursory procedure. It returns values from aFOREACH loop and a FOR loop. This procedure is called a cursory procedurebecause it contains a FOREACH loop.
When you execute this procedure, it returns the name and address for eachperson with the specified last name. It also returns a sequence of letters. Thecalling procedure or program must be expecting multiple returned values,and it must use a cursor or a FOREACH statement to handle the multiplereturned values.
Figure 12-13Procedure that
returns values froma FOREACH loop
and a FOR loop
read_many (lastname CHAR(15))AR(15), CHAR(15), CHAR(20), CHAR(15),CHAR(2),
me,p_fname, p_city CHAR(15); CHAR(20);te CHAR(2); CHAR(5);t INT ; ;
0;
myview AS SELECT * FROM customer;ch starts';
, lname, address1, city, state, zipcodename, p_lname, p_add, p_city, p_state, p_ziptomerame = lastnameme, p_lname, p_add, p_city, p_state, p_zipME; lcount +1;
TO 5)
'a', 'b', 'c', 'd', 'e' WITH RESUME;
SQL: Tutorial
Exception Handling
BEGINDEFINE c INON EXCEPTIO
(-206, --217 -) SET e
IF err_num CREINS--
ELSEALTLET--
END IFEND EXCEPTI
INSERT INTO
LET c = (SEEND
Exception HandlingYou can trap any exception (or error) returned by the database server to yourprocedure, or raised by your procedure, with the ON EXCEPTION statement.The RAISE EXCEPTION statement lets you generate an exception within yourprocedure.
Trapping an Error and RecoveringThe ON EXCEPTION statement provides a mechanism to trap any error.
To trap an error, enclose a group of statements in a statement block andprecede the statement block with an ON EXCEPTION statement. If an erroroccurs in the block that follows the ON EXCEPTION statement, you can takerecovery action.
Figure 12-14 shows an example of an ON EXCEPTION statement within aBEGIN...END block.
Figure 12-14An ON EXCEPTIONstatement within aBEGIN...END block
T;N IN
- table does not exist- column does not existrr_num
= -206 THENATE TABLE t (c INT);ERT INTO t VALUES (10);continue after the insert statement
ER TABLE t ADD(d INT); c = (SELECT d FROM t);continue after the select statement.
ON WITH RESUME
t VALUES (10); -- will fail if t does not exist
LECT d FROM t); -- will fail if d does not exist
Creating and Using Stored Procedures 12-31
12-32 Informix Guide to
Scope of Control of an ON EXCEPTION Statement
When an error occurs, the SPL interpreter searches for the innermost ONEXCEPTION declaration that traps the error. Note that the first action aftertrapping the error is to reset the error. When execution of the error actioncode is complete, and if the ON EXCEPTION declaration that was raisedincluded the WITH RESUME keywords, execution resumes automaticallywith the statement following the statement that generated the error. If the ONEXCEPTION declaration did not include the WITH RESUME keywords,execution exits the current block completely.
Scope of Control of an ON EXCEPTION StatementAn ON EXCEPTION statement is valid for the statement block that follows theON EXCEPTION statement, all the statement blocks nested within that follow-ing statement block, and all the statement blocks that follow the ONEXCEPTION statement. It is not valid in the statement block that contains theON EXCEPTION statement.
The pseudocode in Figure 12-15 on page 12-33 shows where the exception isvalid within the procedure. That is, if error 201 occurs in any of the indicatedblocks, the action labeled a201 occurs.
SQL: Tutorial
Scope of Control of an ON EXCEPTION Statement
CREATE PROCDEFINE ...BEGIN...
ON -- ENDBEG
ENDBEG
ENDWHI
END
ENDBEGIN
-- --
ENDEND PROCEDU
Figure 12-15Pseudocode
showing the ONEXCEPTION
statement is validwithin a procedure
EDURE scope()i INT;
-- begin statement block A
EXCEPTION IN (201)do action a201 EXCEPTIONIN -- statement block aa-- do action, a201 valid here
IN -- statement block bb-- do action, a201 valid here
LE i < 10-- do something, a201 is valid here
WHILE
-- begin statement block Bdo somethinga201 is NOT valid here
RE;
Creating and Using Stored Procedures 12-33
12-34 Informix Guide to
User-Generated Exceptions
User-Generated ExceptionsYou can generate your own error using the RAISE EXCEPTION statement, asshown in the following pseudocode example. In this example, the ONEXCEPTION statement uses two variables, esql and eisam, to hold the errornumbers returned by the database server. If an error occurs and the SQL errornumber is -206, the action defined in the IF clause is taken. If any other SQLerror is caught, it is passed out of this BEGIN...END block to the block thatcontains this block.
BEGINON EXCEPTION SET esql, eisam -- trap all errors
IF esql = -206 THEN -- table not found-- recover somehow
ELSERAISE exception esql, eisam ; -- pass the error up
END IFEND EXCEPTION
-- do somethingEND
Simulating SQL Errors
You can generate errors to simulate SQL errors, as shown in the followingexample. Here, if the user is pault, then the stored procedure acts as if thatuser has no update privileges, even if he really does have that privilege.
BEGINIF user = 'pault' THEN
RAISE EXCEPTION -273; -- deny Paul update privilegeEND IF
END
SQL: Tutorial
User-Generated Exceptions
BEGINON EXCEEND EXC
BEGINFOR
ENDRET
END
--do so TRACE 'RETURN
END
Using RAISE EXCEPTION to Exit Nested Code
You can use the RAISE EXCEPTION statement to break out of a deeply nestedblock, as shown in Figure 12-16. If the innermost condition is true (if aa isnegative), then the exception is raised and execution jumps to the code fol-lowing the END of the block. In this case, execution jumps to the TRACEstatement.
Remember that a BEGIN...END block is a single statement. When an erroroccurs somewhere inside a block and the trap is outside the block, when exe-cution resumes, the rest of the block is skipped and execution resumes at thenext statement.
Unless you set a trap for this error somewhere in the block, the errorcondition is passed back to the block that contains the call and back to anyblocks that contain the block. If no ON EXCEPTION statement exists that is setto handle the error, execution of the procedure stops, creating an error for theprogram or procedure that is executing the procedure.
Figure 12-16Breaking out of
nested loop with aRAISE EXCEPTION
statement
PTION IN (1)EPTION WITH RESUME -- do nothing significant (cont
i IN (1 TO 1000)FOREACH select ..INTO aa FROM t
IF aa < 0 THENRAISE EXCEPTION 1 ; -- emergency exit
END IFEND FOREACH
FORURN 1;
mething; -- emergency exit to -- this statement.Negative value returned';-10;
Creating and Using Stored Procedures 12-35
12-36 Informix Guide to
Summary
SummaryStored procedures provide many opportunities for streamlining yourdatabase process, including enhanced database performance, simplifiedapplications, and limited or monitored access to data. See the Informix Guideto SQL: Syntax for syntax diagrams of SPL statements.
SQL: Tutorial
13Chapter
Creating and Using Triggers
When to Use Triggers . . . . . . . . . . . . . . . . . . 13-3
How to Create a Trigger . . . . . . . . . . . . . . . . . 13-4Assigning a Trigger Name . . . . . . . . . . . . . . . 13-5Specifying the Trigger Event . . . . . . . . . . . . . . 13-5Defining the Triggered Actions . . . . . . . . . . . . . 13-6A Complete CREATE TRIGGER Statement . . . . . . . . . 13-7
Using Triggered Actions . . . . . . . . . . . . . . . . . 13-7Using BEFORE and AFTER Triggered Actions . . . . . . . . 13-7Using FOR EACH ROW Triggered Actions . . . . . . . . . 13-9
Using the REFERENCING Clause . . . . . . . . . . . 13-9Using the WHEN Condition . . . . . . . . . . . . . 13-10
Using Stored Procedures as Triggered Actions . . . . . . . . 13-11Passing Data to a Stored Procedure . . . . . . . . . . 13-11Using the Stored Procedure Language . . . . . . . . . 13-12Updating Nontriggering Columns with Data from a Stored Procedure
13-12
Tracing Triggered Actions . . . . . . . . . . . . . . . . 13-13
Generating Error Messages . . . . . . . . . . . . . . . . 13-15Applying a Fixed Error Message . . . . . . . . . . . . . 13-15Generating a Variable Error Message . . . . . . . . . . . 13-17
Summary . . . . . . . . . . . . . . . . . . . . . . 13-18
13-2 Inf
ormix Guide to SQL: TutorialAn SQL trigger is a mechanism that resides in the database. It isavailable to any user who has permission to use it. It specifies that when aparticular action—an insert, a delete, or an update—occurs on a particulartable, the database server should automatically perform one or more addi-tional actions. The additional actions can be INSERT, DELETE, UPDATE, orEXECUTE PROCEDURE statements.
This chapter describes the purpose of each component of the CREATETRIGGER statement, illustrates some uses for triggers, and describes theadvantages of using a stored procedure as a triggered action.
When to Use TriggersBecause a trigger resides in the database and anyone who has the requiredprivilege can use it, a trigger enables you to write a set of SQL statements thatmultiple applications can use. It enables you to prevent redundant codewhen multiple programs need to perform the same database operation.
You can use triggers to perform the following actions as well as others thatare not found in this list:
■ Create an audit trail of activity in the database. For example, you cantrack updates to the orders table by updating corroboratinginforation to an audit table.
■ Implement a business rule. For example, you can determine when anorder exceeds a customer’s credit limit and display a message to thateffect.
Creating and Using Triggers 13-3
13-4 Informix Guide to
How to Create a Trigger
item_num qua2 33 14 45 1
UPDA
trig
■ Derive additional data that is not available within a table or withinthe database. For example, when an update occurs to the quantitycolumn of the items table, you can calculate the correspondingadjustment to the total_price column.
■ Enforce referential integrity. When you delete a customer, forexample, you can use a trigger to delete corresponding rows (that is,rows having the same customer number) in the orders table.
How to Create a TriggerYou use the CREATE TRIGGER statement to create a trigger. The CREATETRIGGER statement is a data definition statement that associates SQL state-ments with a precipitating action on a table. When the precipitating actionoccurs, the associated SQL statements, which are stored in the database, aretriggered. Figure 13-1 illustrates the relationship of the precipitating action,or trigger event, to the triggered action.
The CREATE TRIGGER statement consists of clauses that perform thefollowing actions:
■ Assign a trigger name.
■ Specify the trigger event— that is, the table and the type of actionthat initiate the trigger.
■ Define the SQL actions that are triggered.
Figure 13-1A trigger consists ofa trigger event and a
triggered action
ntity total_price15.00
236.00100.00280.00
TE
ger event
EXECUTE PROCEDUREupd_items
SQL: Tutorial
Assigning a Trigger Name
An optional clause, called the REFERENCING clause is discussed in “UsingFOR EACH ROW Triggered Actions” on page 13-9.
You can create a trigger using the DB-Access utility, NewEra, INFORMIX-4GL,or one of the SQL APIs, INFORMIX-ESQL/C or INFORMIX-ESQL/COBOL. Thissection describes the CREATE TRIGGER statement as you would enter it usingthe interactive Query-language option in DB-Access. In an SQL API, yousimply precede the statement with the symbol or keywords that identify it asan embedded statement. In NewEra and INFORMIX-4GL, you must end thetrigger definition with the END TRIGGER keywords.
Assigning a Trigger NameThe trigger name identifies the trigger. It follows the words CREATE TRIGGERin the statement. It can be up to 18 characters inclusive, in length, beginningwith a letter and consisting of letters, the digits 0-9, and the underscore. In thefollowing example, the portion of the CREATE TRIGGER statement that isshown assigns the name upqty to the trigger:
CREATE TRIGGER upqty -- assign trigger name
Specifying the Trigger EventThe trigger event is the type of statement that activates the trigger. When astatement of this type is performed on the table, the database server executesthe SQL statements that make up the triggered action. The trigger event canbe an INSERT, DELETE, or UPDATE statement. When you define an UPDATEtrigger event, you can name one or more columns in the table to activate thetrigger. If you do not name any columns, then an update of any column in thetable activates the trigger. You can create only one INSERT and one DELETEtrigger per table, but you can create multiple UPDATE triggers as long as thetriggering columns are mutually exclusive.
In the following excerpt of a CREATE TRIGGER statement, the trigger event isdefined as an update of the quantity column in the items table:
CREATE TRIGGER upqtyUPDATE OF quantity ON items-- an UPDATE trigger event
Creating and Using Triggers 13-5
13-6 Informix Guide to
Defining the Triggered Actions
Notice that this portion of the statement identifies the table on which youcreate the trigger. If the trigger event is an insert or delete, only the type ofstatement and the table name are required, as shown in the followingexample:
CREATE TRIGGER ins_qtyINSERT ON items -- an INSERT trigger event
Defining the Triggered ActionsThe triggered actions are the SQL statements that are performed when thetrigger event occurs. The triggered actions can consist of INSERT, DELETE,UPDATE, and EXECUTE PROCEDURE statements. In addition to specifyingwhat actions are to be performed, however, you must also specify when theyare to be performed in relation to the triggering statement. You have thefollowing choices:
■ Before the triggering statement executes
■ After the triggering statement executes
■ For each row that is affected by the triggering statement
A single trigger can define actions for each of these times.
You define a triggered action by specifying when it occurs and thenproviding the SQL statement or statements to execute. You specify when theaction is to occur with the keywords BEFORE, AFTER, or FOR EACH ROW. Thetriggered actions follow, enclosed in parentheses. The following triggeredaction definition specifies that the stored procedure upd_items_p1 is to beexecuted before the triggering statement:
BEFORE(EXECUTE PROCEDURE upd_items_p1)-- a BEFORE action
SQL: Tutorial
A Complete CREATE TRIGGER Statement
A Complete CREATE TRIGGER StatementIf you combine the trigger name clause, the trigger event clause, and thetriggered action clause, you have a complete CREATE TRIGGER statement.The following CREATE TRIGGER statement is the result of combining thecomponents of the statement from the preceding examples. This triggerexecutes the stored procedure upd_items_p1 whenever the quantity columnof the items table is updated.
CREATE TRIGGER upqtyUPDATE OF quantity ON itemsBEFORE(EXECUTE PROCEDURE upd_items_p1)
Note that if a database object in the trigger definition, such as the storedprocedure upd_items_p1 in this example, does not exist when the databaseserver processes the CREATE TRIGGER statement, it returns an error.
Using Triggered ActionsTo use triggers effectively, you need to understand the relationship betweenthe triggering statement and the resulting triggered actions. You define thisrelationship when you specify the time that the triggered action occurs —thatis, BEFORE, AFTER, or FOR EACH ROW.
Using BEFORE and AFTER Triggered ActionsTriggered actions that occur before or after the trigger event execute onlyonce. A BEFORE triggered action executes before the triggering statement —that is, before the occurrence of the trigger event. An AFTER triggered actionexecutes after the action of the triggering statement is complete. BEFORE andAFTER triggered actions execute even if the triggering statement does notprocess any rows.
Creating and Using Triggers 13-7
13-8 Informix Guide to
Using BEFORE and AFTER Triggered Actions
Among other uses, you can use BEFORE and AFTER triggered actions todetermine the effect of the triggering statement. For example, before updat-ing the quantity column in the items table, you could call the stored proce-dure upd_items_p1, shown in the following example, to calculate the totalquantity on order for all items in the table. Notice that the procedure storesthe total in a global variable called old_qty.
CREATE PROCEDURE upd_items_p1()DEFINE GLOBAL old_qty INT DEFAULT 0;LET old_qty = (SELECT SUM(quantity) FROM items);
END PROCEDURE;
After the triggering update completes, you can calculate the total again to seehow much it has changed. The following stored procedure, upd_items_p2,calculates the total of quantity again and stores the result in the local variablenew_qty. Then it compares new_qty to the global variable old_qty to see ifthe 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.
CREATE PROCEDURE upd_items_p2()DEFINE GLOBAL old_qty INT DEFAULT 0;DEFINE new_qty INT;LET new_qty = (SELECT SUM(quantity) FROM items);IF new_qty > old_qty * 1.50 THEN
RAISE EXCEPTION -746, 0, 'Not allowed - rule violation';END IF
END PROCEDURE;
The following trigger calls upd_items_p1 and upd_items_p2 to prevent anextraordinary update on the quantity column of the items table:
CREATE TRIGGER up_itemsUPDATE OF quantity ON itemsBEFORE(EXECUTE PROCEDURE upd_items_p1())AFTER(EXECUTE PROCEDURE upd_items_p2());
If an update raises the total quantity on order for all items by more than 50percent, the RAISE EXCEPTION statement in upd_items_p2 terminates thetrigger with an error. When a trigger fails in INFORMIX-OnLine DynamicServer and the database has logging, the database server rolls back thechanges made by both the triggering statement and the triggered actions. SeeCREATE TRIGGER in Chapter 1 of the Informix Guide to SQL: Syntax for moreinformation on what happens when a trigger fails.
SQL: Tutorial
Using FOR EACH ROW Triggered Actions
Using FOR EACH ROW Triggered ActionsA FOR EACH ROW triggered action executes once for each row that thetriggering statement effects. For example, if the triggering statement is hasthe following syntax:
UPDATE items SET quantity = quantity * 2 WHERE manu_code = 'KAR'
A FOR EACH ROW triggered action executes once for each row in the itemstable in which the manu_code column has a value of ‘KAR’.
If the triggering statement does not process any rows, A FOR EACH ROWtriggered action does not execute.
Using the REFERENCING Clause
When you create a FOR EACH ROW triggered action, you must usuallyindicate in the triggered action statements whether you are referring to thevalue of a column before or after the effect of the triggering statement. Forexample, imagine that you want to track updates to the quantity column ofthe items table. To do this, you create the following table to record theactivity:
CREATE TABLE log_record(item_num SMALLINT,ord_num INTEGER,username CHARACTER(8),update_time DATETIME YEAR TO MINUTE,old_qty SMALLINT,new_qty SMALLINT);
To supply values for the old_qty and new_qty columns in this table, youmust 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. TheREFERENCING clause enables you to do this.
The REFERENCING clause lets you create two prefixes that you can combinewith a column name, one to reference the old value of the column and one toreference its new value. These prefixes are called correlation names. You cancreate one or both correlation names, depending on your requirements. Youindicate which one you are creating with the keywords OLD and NEW. Thefollowing REFERENCING clause creates the correlation names pre_upd andpost_upd to refer to the old and new values in a row:
REFERENCING OLD AS pre_upd NEW AS post_upd
Creating and Using Triggers 13-9
13-10 Informix Guide to
Using FOR EACH ROW Triggered Actions
The following triggered action creates a row in log_record when quantity isupdated in a row of the items table. The INSERT statement refers to the oldvalues of the item_num and order_num columns and to both the old andnew values of the quantity column.
FOR EACH ROW(INSERT INTO log_recordVALUES (pre_upd.item_num, pre_upd.order_num, USER, CURRENT,
pre_upd.quantity, post_upd.quantity));
The correlation names defined in the REFERENCING clause apply to all rowsaffected by the triggering statement.
Important: If you refer to a column name in the triggering table without using a cor-relation name, the database server makes no special effort to search for the column inthe definition of the triggering table. You must always use a correlation name with acolumn name in SQL statements within a FOR EACH ROW triggered action, unlessthe statement is valid independent of the triggered action. See CREATE TRIGGER inChapter 1 of the Informix Guide to SQL: Syntax.
Using the WHEN Condition
As an option, you can precede a triggered action with a WHEN clause to makethe action dependent on the outcome of a test. The WHEN clause consists ofthe keyword WHEN followed by the condition statement, given in parenthe-ses. In the CREATE TRIGGER statement, the WHEN clause follows the key-words BEFORE, AFTER, or FOR EACH ROW and precedes the triggered actionlist.
When a WHEN condition is present, if it evaluates to true, the triggeredactions execute in the order in which they appear. If the WHEN conditionevaluates to false or unknown, the actions in the triggered action list do notexecute. If the trigger specifies FOR EACH ROW, the condition is evaluated foreach row also.
In the following trigger example, the triggered action executes only if thecondition in the WHEN clause is true — that is, if the post-update unit priceis greater than two times the pre-update unit price:
CREATE TRIGGER up_priceUPDATE OF unit_price ON stockREFERENCING OLD AS pre NEW AS postFOR EACH ROW WHEN(post.unit_price > pre_unit_price * 2)
(INSERT INTO warn_tab VALUES(pre.stock_num, pre.order_num,pre.unit_price, post.unit_price, CURRENT))
SQL: Tutorial
Using Stored Procedures as Triggered Actions
See CREATE TRIGGER in Chapter 1 of the Informix Guide to SQL: Syntax formore information on the WHEN condition.
Using Stored Procedures as Triggered ActionsProbably the most powerful feature of triggers is the ability to call a storedprocedure as a triggered action. The EXECUTE PROCEDURE statement, whichcalls a stored procedure, enables you to pass data from the triggering table tothe stored procedure and also to update the triggering table with datareturned by the stored procedure. SPL also lets you define variables, assigndata to them, make comparisons, and use procedural statements toaccomplish complex tasks within a triggered action.
Passing Data to a Stored Procedure
You can pass data to a stored procedure in the argument list of the EXECUTEPROCEDURE statement. The EXECUTE PROCEDURE statement in the follow-ing trigger example passes values from the quantity and total_price columnsof the items table to the stored procedure calc_totpr:
CREATE TRIGGER upd_totprUPDATE OF quantity ON itemsREFERENCING OLD AS pre_upd NEW AS post_updFOR EACH ROW(EXECUTE PROCEDURE calc_totpr(pre_upd.quantity,
post_upd.quantity, pre_upd.total_price) INTO total_price)
Passing data to a stored procedure allows you to use it in the operations thatthe procedure performs.
Creating and Using Triggers 13-11
13-12 Informix Guide to
Using Stored Procedures as Triggered Actions
Using the Stored Procedure Language
The EXECUTE PROCEDURE statement in the preceding trigger calls the storedprocedure that is shown in the following example. The procedure uses theSPL to calculate the change that needs to be made to the total_price columnwhen quantity is updated in the items table. The procedure receives both theold and new values of quantity and the old value of total_price. It divides theold total price by the old quantity to derive the unit price. It then multipliesthe unit price by the new quantity to obtain the new total price.
CREATE PROCEDURE calc_totpr(old_qty SMALLINT, new_qty SMALLINT,total MONEY(8)) RETURNING MONEY(8);DEFINE u_price LIKE items.total_price;DEFINE n_total LIKE items.total_price;LET u_price = total / old_qty;LET n_total = new_qty * u_price;RETURN n_total;
END PROCEDURE;
In this example, SPL enables the trigger to derive data that is not directlyavailable from the triggering table.
Updating Nontriggering Columns with Data from a Stored Procedure
Within a triggered action, the INTO clause of the EXECUTE PROCEDUREstatement lets you update nontriggering columns in the triggering table. TheEXECUTE PROCEDURE statement in the following example calls thecalc_totpr stored procedure that contains an INTO clause, which referencesthe column total_price:
FOR EACH ROW(EXECUTE PROCEDURE calc_totpr(pre_upd.quantity,post_upd.quantity, pre_upd.total_price) INTO total_price);
The value that is updated into total_price is returned by the RETURNstatement at the conclusion of the stored procedure. The total_price columnis updated for each row that the triggering statement affects.
SQL: Tutorial
Tracing Triggered Actions
Tracing Triggered ActionsIf a triggered action does not behave as you expect, place it in a storedprocedure and use the SPL TRACE statement to monitor its operation. Beforestarting the trace, you must direct the output to a file with the SET DEBUGFILE TO statement. The following example shows TRACE statements thathave been added to the stored procedure items_pct. The SET DEBUG FILE TOstatement directs the trace output to the file /usr/mydir/trig.trace. The TRACEON statement begins tracing the statements and variables within the proce-dure.
CREATE PROCEDURE items_pct(mac CHAR(3))DEFINE tp MONEY;DEFINE mc_tot MONEY;DEFINE pct DECIMAL;SET DEBUG FILE TO '/usr/mydir/trig.trace';TRACE 'begin trace';TRACE ON;LET tp = (SELECT SUM(total_price) FROM items);LET mc_tot = (SELECT SUM(total_price) FROM items
WHERE manu_code = mac);LET pct = mc_tot / tp;IF pct > .10 THEN
RAISE EXCEPTION -745;END IFTRACE OFF;END PROCEDURE;
CREATE TRIGGER items_insINSERT ON itemsREFERENCING NEW AS post_insFOR EACH ROW(EXECUTE PROCEDURE items_pct (post_ins.manu_code));
Creating and Using Triggers 13-13
13-14 Informix Guide to
Tracing Triggered Actions
trace expretrace onexpression: (select ( from itevaluates tlet tp = $expression: (select ( from it where (evaluates tlet mc_totexpression:evaluates tlet pct = expression:evaluates texpression:evaluates traise excepexception :SQL error =exception :
Figure 13-2 shows sample trace output from the items_pct procedure as itappears in the file /usr/mydir/trig.trace. The output reveals the values ofprocedure variables, procedure arguments, return values, and error codes.
See Chapter 12, “Creating and Using Stored Procedures” for moreinformation on using the TRACE statement to diagnose logic errors in storedprocedures.
ssion :begin trace
sum total_price)ems)o $18280.77 ;18280.77
sum total_price)ems= manu_code, mac))o $3008.00 ; = $3008.00(/ mc_tot, tp)o 0.160.16(> pct, 0.1)o 1(- 745)o -745tion :-745, 0, '' looking for handler -745 ISAM error = 0 error string = = '' no appropriate handler
Figure 13-2Trace output from
the items.pctstored procedure
SQL: Tutorial
Generating Error Messages
Generating Error MessagesWhen a trigger fails because of an SQL statement, the database server returnsthe SQL error number that applies to the specific cause of the failure.
When the triggered action is a stored procedure, you can generate errormessages for other error conditions by using one of two reserved error num-bers. The first one is error number -745, which has a generalized and fixederror message. The second one is error number -746, which allows you tosupply the message text, up to a maximum of 71 characters.
Applying a Fixed Error MessageYou can apply error number -745 to any trigger failure that is not an SQL error.The following fixed message is for this error:
-745 Trigger execution has failed.
You can apply this message with the RAISE EXCEPTION statement in SPL. Thefollowing example generates error -745 if new_qty is greater thanold_qty multiplied by 1.50:
CREATE PROCEDURE upd_items_p2()DEFINE GLOBAL old_qty INT DEFAULT 0;DEFINE new_qty INT;LET new_qty = (SELECT SUM(quantity) FROM items);IF new_qty > old_qty * 1.50 THEN
RAISE EXCEPTION -745;END IF
END PROCEDURE
Creating and Using Triggers 13-15
13-16 Informix Guide to
Applying a Fixed Error Message
Press CTRL-SQL: New RuModify the cu
-------------
INSERT INTO i
745: Trigg
If you are using DB-Access, the text of the message for error -745 displays onthe bottom of the screen, as seen in Figure 13-3.
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 toyour program. To display the text of the message, follow the procedure thatyour Informix application development tool provides for retrieving the textof an SQL error message.
Figure 13-3Error message -745 with fixed message
W for Helpn Modify Use-editor Output Choose Save Info Drop Exitrrent SQL statements using the SQL editor.
--------- stores7@myserver --------- Press CTRL-W for Help ----
tems VALUES( 2, 1001, 2, 'HRO', 1, 126.00);
er execution has failed.
SQL: Tutorial
Generating a Variable Error Message
Press CTRL-SQL: New RModify the cu
-------------
INSERT INTO i
746: Too m
Generating a Variable Error MessageError number -746 allows you to provide the text of the error message. Aswith the preceding example, the following one also generates an error ifnew_qty is greater than old_qty multiplied by 1.50. However, in this case theerror number is -746 and the message text Too many items for Mfr. issupplied as the third argument in the RAISE EXCEPTION statement. See theRAISE EXCEPTION statement in Chapter 12, “Creating and Using Stored Pro-cedures,” for more information on the syntax and use of this statement.
CREATE PROCEDURE upd_items_p2()DEFINE GLOBAL old_qty INT DEFAULT 0;DEFINE new_qty INT;LET new_qty = (SELECT SUM(quantity) FROM items);IF new_qty > old_qty * 1.50 THEN
RAISE EXCEPTION -746, 0, 'Too many items for Mfr.';END IF
END PROCEDURE;
If you use DB-Access to submit the triggering statement, and if new_qty isgreater than old_qty, the result of this stored procedure is as shown inFigure 13-4.
Figure 13-4Error number -746 with user-specified message text
W for Helpun Modify Use-editor Output Choose Save Info Drop Exitrrent SQL statements using the SQL editor.
--------- store7@myserver --------- Press CTRL-W for Help -----
tems VALUES( 2, 1001, 2, 'HRO', 1, 126.00);
any items for Mfr.
Creating and Using Triggers 13-17
If you invoke the trigger through an SQL statement in an SQL API, thedatabase server sets sqlcode to -746 and returns the message text in thesqlerrm field of the SQL Communications Area (SQLCA). See the manual foryour SQL API for in-depth information about using the SQLCA.
SummaryIn 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 usethem to determine the impact of the triggering statement
■ How to create a FOR EACH ROW triggered action and how to use theREFERENCING clause to refer to the values of columns both beforeand 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 triggeredaction
Index
Index
AAccess control. See Privilege.Access modes
discussed 7-16Accessing data in a fragmented
table 9-41Accessing tables 12-18Active set
definition of 2-29of a cursor 5-25
ADD ROWID clause, of ALTERTABLE 9-42
Aggregate functionand GROUP BY clause 3-5description of 2-53in ESQL 5-15in SPL expressions 14-24in subquery 3-35null value signalled 5-14restrictions in modifiable
view 11-25Alias
for table name 2-80to assign column names in
temporary table 3-12with self-join 3-11
ALL keywordbeginning a subquery 3-32
ALTER FRAGMENT statementexample 9-38INIT clause 9-42MODIFY clause 9-38
ALTER INDEX statementlocks table 7-8
Alter privilege 11-10
ALTER TABLE statementADD ROWIDS clause 9-42changing column data type 9-22DROP ROWIDS clause 9-42privilege for 11-10
American National StandardsInstitute. See ANSI.
AND logical operator 2-37ANSI 1-17ANSI-compliant database
buffered logging restrictedin 9-26
description of 1-18FOR UPDATE not required in 6-
16signalled in SQLAWARN 5-13table privileges 11-8
ANY keywordbeginning a subquery 3-34
Applicationcommon features 1-21description of 1-19design of order-entry 4-25handling errors 5-18report generator 1-20screen forms 1-20
Archiveswith INFORMIX-SE 12-21
Archivingdescription of 1-11, 4-28INFORMIX-OnLine Dynamic
Server methods 4-29transaction log 4-29
Arithmetic operator, inexpression 2-47
Ascending order in SELECT 2-15
Asteriskwild card character in
SELECT 2-12Attribute
identifying 8-17important qualities of 8-17nondecomposable 8-17
Automatic type conversion. SeeData type conversion.
AVG functionas aggregate function 2-53
BBachman, C.R. 8-19Backup. See Archive.BEGIN WORK statement
specifies start of atransaction 4-27
BETWEEN keyword, used to testfor equality in WHEREclause 2-29
BETWEEN operator 2-33Boolean expression
and logical operator 2-37Buffered logging 9-26Building your data
model 8-3 to 8-38BYTE data type
description of 9-21restrictions
with GROUP BY 3-6with LIKE or MATCHES 2-38with relational expression 2-30
BYTE value, displaying 2-11
CCALL statement
assigning values with 14-24executing a procedure 14-11
Candidate keydefined 8-27
Cardinality 8-11Cardinality in relationship 8-15Cartesian product
basis of any join 2-71description of 2-69
Cascading deletesdefined 4-23locking associated with 4-23logging 4-23restriction 4-24
Chaining synonyms 12-20Changing the number of
fragments 9-39CHAR data type
description of 9-17in relational expressions 2-30subscripting 2-45substrings of 2-27truncation signalled 5-14
CHARACTER VARYING data typedescription of 9-18
Check constraintdefinition of 4-21
CLOSE DATABASE statementeffect on database locks 7-7
COBOL 5-7Codd, E. F. 1-12, 8-37Collation order and NLS 2-25Column
defined 2-5defining 8-24description of 1-13in relational model 1-13, 8-24label on 3-46
Column number 2-24Column-level privilege 11-11Columns of a fragmented table,
modifying 9-37Command script, creating
database 9-30Commit, two-phase 12-22COMMIT WORK statement
closes cursors 7-22releases locks 7-10, 7-22sets SQLCODE 6- 5
Committed Read isolation level(Informix) 7-13
Comparison conditiondescription of 2-29
Complexrelationship 8-32
Composite key 8-27Compound query 3-42Computer network 12-4
Concurrencyaccess modes 7-16ANSI Read Committed
isolation 7-13ANSI Read Uncommitted
isolation 7-12ANSI Repeatable Read
isolation 7-15ANSI Serializable isolation 7-15database lock 7-7deadlock 7-18description of 4-30, 7-3effect on performance 7-3Informix Cursor Stability
isolation 7-13Informix Dirty Read
isolation 7-12Informix Read Committed
isolation 7-13Informix Repeatable Read
isolation 7-15isolation level 7-11kinds of locks 7-6lock duration 7-9lock scope 7-7SERIAL values 9-9table lock 7-8
Configuring a databaseserver 12-17
Connect privilege 11-6CONNECT statement
opening a database 12-17Connecting to data 12-14Connectivity in relationship 8-10,
8-13, 8-20Constraint
cardinality 8-11defining domains 9-4
CONTINUE statementexiting a loop 14-26
Conventionsexample code Intro-7typographical Intro-5
Coordinated deletes 6- 6Correlated subquery
definition of 3-31restriction with cascading
deletes 4-24
2 INFORMIX
COUNT functionand GROUP BY 3-6as aggregate function 2-53count rows to delete 4-5use in a subquery 4-6with DISTINCT 2-54
CREATE DATABASE statementin command script 9-30sets shared lock 7-7SQLAWARN after 5-13using with
INFORMIX-SE 9-27OnLine 9-24
CREATE INDEX statementlocks table 7-8
CREATE PROCEDURE FROMstatement
in embedded languages 14-6CREATE PROCEDURE statement
inside a CREATE PROCEDUREFROM 14-6
using 14-6CREATE TABLE statement
description of 9-28in command script 9-30sets initial SERIAL value 9-9WITH ROWIDS clause 9-42
CREATE VIEW statementrestrictions on 11-23using 11-22WITH CHECK OPTION
keywords 11-27CURRENT function
comparing column values 2-56Cursor
active set of 5-25closing 7-22declaring 5-21for insert 6- 9for update 6- 15, 7-10hold 7-22opening 5-22, 5-25retrieving values with
FETCH 5-23scroll 5-24sequential 5-24, 5-26with
prepared statements 5-34WITH HOLD 7-22
Cursor Stability isolation level(Informix) 7-13
Cyclic query 4-24
DDaemon 12-15Data
connecting to 12-14how to access in fragmented
tables 9-41integrity 12-22
Data definition statements 5-36Data integrity 4-25 to 4-28, 12-22Data model
attribute 8-17building 8-3 to 8-38defining relationships 8-9description of 1-4, 8-3entity-relationship 8-5many-to-many relationship 8-13one-to-many relationship 8-13one-to-one relationship 8-13See also Relational model.telephone-directory example 8-7
Data protectionwith OnLine 12-21
Data replication 12-21Data type
automatic conversions 5-16BYTE 9-21CHAR 9-17character data 9-17CHARACTER VARYING 9-18choosing 9-22chronological 9-13conversion 4-9DATE 9-14DATETIME 9-14DECIMAL 9-11, 9-12fixed-point 9-12floating-point 9-10in SPL variables 14-21INTEGER 9-8INTERVAL 9-15MONEY 9-12NCHAR 9-17numeric 9-8
NVARCHAR 9-18REAL 9-10SERIAL 9-9SMALLFLOAT 9-10TEXT 9-20VARCHAR 9-18
DatabaseANSI-compliant 1-18application 1-19archiving 1-11concurrent use 1-9defined 1-3, 1-12management of 1-10mission-critical 1-11naming unique to engine 9-25NLS 1-18populating new tables 9-31relational, defined 1-12server 1-9, 1-19server, definition of 1-19stores7 Intro-9table names 12-18
Database Administrator(DBA) 11-7
Database lock 7-7Database management system 12-4Database server
configuration 12-17definition of 1-19local 12-6remote 12-9
DATABASE statementexclusive mode 7-7locking 7-7SQLAWARN after 5-13
Database-level privilegedescription of 4-16See also Privilege.
DATE data typedescription of 9-14functions in 2-56in ORDER BY sequence 2-15
DATE functionas time function 2-56use in expression 2-60
DATETIME data typedescription of 9-14displaying format 2-60, 9-16
Index 3
functions on 2-56in
ORDER BY sequence 2-15relational expressions 2-30
precision and size 9-15DAY function
as time function 2-57use
as time function 2-56DB-Access
creating database with 5-36, 9-31UNLOAD statement 9-32
DBANSIWARN environmentvariable 5-11
DBA-privileged procedure 14-16DBDATE environment
variable 4-9, 9-14dbload utility
loading data into a table 9-32DBMONEY environment
variable 9-13DBMS. SeeDatabase management
system.DBPATH environment
variable 12-16dbschema utility
use of 9-30DBSERVERNAME function
usein SELECT 2-62, 2-65, 3-20
dbspaceselecting with CREATE
DATABASE 9-25skipping if unavailable 5-11
Deadlock detection 7-18DECIMAL data type
fixed-point 9-12floating-point 9-11signalled in SQLAWARN 5-13
DECLARE statementdescription of 5-21FOR INSERT clause 6- 9FOR UPDATE 6- 15SCROLL keyword 5-24WITH HOLD clause 7-23
Default valuedescription of 4-20
DEFINE statementin stored procedures 14-20
Delete privilege 11-9, 11-29DELETE statement
all rows of table 4-4and end of data 6- 14applied to view 11-25coordinated deletes 6- 6count of rows 6- 4description of 4-4embedded 5-7, 6- 3 to 6- 8number of rows 5-13preparing 5-32privilege for 11-6, 11-9transactions with 6- 5using subquery 4-6WHERE clause restricted 4-7with cursor 6- 7
Demonstration databasecopying Intro-10installation script Intro-9overview Intro-9
Derived dataproduced by view 11-21
Descending order in SELECT 2-15DESCRIBE statement
describing statement type 5-35Device
optical 12-6storage 12-6
Dirty Read isolation level(Informix) 7-12
Display labelin ORDER BY clause 2-52with SELECT 2-50
DISTINCT keywordrelation to GROUP BY 3-4restrictions in modifiable
view 11-25use
in SELECT 2-20with COUNT function 2-54
Distributed deadlock 7-19Distributed processing 12-10Distribution scheme
changing the number offragments 9-39
DOCUMENT keyword, use instored procedures 14-7
Documentation notes Intro-8Dominant table 3-21
DOS operating system 12-5DROP INDEX statement
locks table 7-8DROP ROWIDS clause, of ALTER
TABLE 9-42Dropping a fragment 9-40Duplicate values
finding 3-15Dynamic SQL
cursor use with 5-34description of 5-5, 5-30freeing prepared statements 5-36
EEmbedded SQL
defined 5-4languages available 5-4
End of datasignal in SQLCODE 5-12, 5-18signal only for SELECT 6- 14when opening cursor 5-22
Entityattributes associated with 8-17business rules 8-5criteria for choosing 8-8defined 8-5important qualities of 8-6in telephone-directory
example 8-9integrity 4-19naming 8-5represented by a table 8-26
Entity occurrence, defined 8-19Entity-relationship diagram
connectivity 8-20discussed 8-19meaning of symbols 8-20reading 8-21
Environment variableDBPATH 12-16INFORMIXDIR 12-16INFORMIXSERVER 12-16PATH 12-16TERMCAP 12-16
Equals (=) relational operator 2-31,2-71
Equi-join 2-71
4 INFORMIX
Error checkingexception handling 14-31in stored procedures 14-31simulating errors 14-34
Error messagesfor trigger failure 15-15generating in a trigger 15-15retrieving trigger text in a
program 15-16, 15-18Errors
after DELETE 6- 4at compile time 14-7codes for 5-13dealing with 5-18detected on opening cursor 5-22during updates 4-25in stored procedure syntax 14-8inserting with a cursor 6- 11ISAM error code 5-13
ESCAPE keyworduse
with WHERE keyword 2-45ESQL
cursor use 5-21 to 5-29DELETE statement in 6- 3delimiting host variables 5-7dynamic embedding 5-5, 5-30error handling 5-18fetching rows from cursor 5-23host variable 5-6, 5-8indicator variable 5-17INSERT in 6- 9overview 5-3 to 5-40, 6- 3 to 6- 18preprocessor 5-4scroll cursor 5-24selecting single rows 5-14SQL Communications Area 5-9SQLCODE 5-12SQLERRD fields 5-13static embedding 5-5UPDATE in 6- 15
Exclusive lock 7-6EXECUTE IMMEDIATE statement
description of 5-36EXECUTE PROCEDURE statement
assigning values with 14-24using 14-11
EXECUTE statementdescription of 5-33
Existence dependency 8-10EXISTS keyword
in a WHERE clause 3-32use in condition subquery 11-28
EXIT statementexiting a loop 14-26
Expressiondate-oriented 2-56description of 2-47display label for 2-50
EXTEND functionwith DATE, DATETIME and
INTERVAL 2-56, 2-60
FFETCH statement
ABSOLUTE keyword 5-25description of 5-23sequential 5-24with
sequential cursor 5-26File
compared to database 1-4permissions in UNIX 11-4
First normal form 8-34Fixed point 9-12FLOAT data type
description of 9-10Floating point 9-10FLUSH statement
count of rows inserted 6- 11writing rows to buffer 6- 10
FOR statementlooping in a stored
procedure 14-26FOR UPDATE keywords
conflicts with ORDER BY 6- 8not needed in ANSI-compliant
database 6- 16specific columns 6- 16
FOREACH statementlooping in a stored
procedure 14-26Foreign key 4-21Fragment
altering 9-38dropping 9-40
Fragmentation strategymodifying 9-38
Fragmented tableaccessing data 9-41created from multiple non-
fragmented table 9-36creating 9-36creating from one non-
fragmented table 9-37how to create 9-34modifying 9-37use of rowid 9-41using primary keys 3-15, 9-41
FREE statementfreeing prepared statements 5-36
FROM keywordalias names 2-80
Functionaggregate 2-53date-oriented 2-56in SELECT statements 2-53within a stored procedure 14-27
Functional dependency 8-36
GGlobal transaction 12-23GRANT statement
automated 11-13database-level privileges 11-6in 4GL 11-14in embedded SQL 5-37 to 5-39table-level privileges 11-8
GROUP BY keywordscolumn number with 3-7description of 3-4restrictions in modifiable
view 11-25
HHAVING keyword
description of 3-8Header, of a procedure 14-28Hold cursor
definition of 7-22Host machine 12-9
Index 5
Host variabledelimiter for 5-7description of 5-6dynamic allocation of 5-35fetching data into 5-23in DELETE statement 6- 4in INSERT 6- 9in UPDATE 6- 15in WHERE clause 5-15INTO keyword sets 5-15null indicator 5-17restrictions in prepared
statement 5-31truncation signalled 5-14with EXECUTE 5-33
IIF statement
branching 14-25IN keyword
used to test for equality inWHERE clause 2-29
IN relational operator 3-32Index
locks table 7-8Index privilege 11-10Indicator variable
definition of 5-17INFORMIX-4GL 12-6
detecting null value 5-17example of dynamic SQL 11-14indicator variable not used 5-17program variable 5-6STATUS variable 5-12terminates on errors 5-39, 6- 14using SQLCODE with 5-12WHENEVER ERROR
statement 5-39INFORMIXDIR environment
variable 12-16INFORMIX-OnLine Dynamic
Serverallows views on external
tables 11-24archiving 4-29characteristics of 1-11
signalled in SQLAWARN 5-13when tables are locked 7-8
INFORMIX-OnLine/Optical 12-6INFORMIX-SE
characteristics of 1-10creating database 9-27
INFORMIXSERVER environmentvariable 12-16
INFORMIX-SQLcreating database with 5-36, 9-31UNLOAD statement 9-31
Insert cursordefinition of 6- 9use of 6- 12
Insert privilege 11-9, 11-29INSERT statement
and end of data 6- 14constant data with 6- 12count of rows inserted 6- 11duplicate values in 4-8embedded 6- 9 to 6- 14inserting
multiple rows 4-10rows 4-7single rows 4-7
null values in 4-8number of rows 5-13privilege for 11-6, 11-9SELECT statement in 4-10VALUES clause 4-7with
a view 11-26Inserting rows of constant data 6-
12INTEGER data type
description of 9-8Integrity. See Data integrity.Interrupted modifications 4-25INTERVAL data type
description of 9-15display format 9-16in relational expressions 2-30precision and size 9-16
INTO keywordchoice of location 5-24in FETCH statement 5-24mismatch signalled in
SQLAWARN 5-14restrictions in INSERT 4-11
restrictions in preparedstatement 5-31
retrieving multiple rows 5-21retrieving single rows 5-15
INTO TEMP keywordsdescription of 2-83restrictions in view 11-23
ISAM error code 5-13Isolation level
ANSI Read Committed 7-13ANSI Read Uncommitted 7-12ANSI Repeatable Read 7-15ANSI Serializable 7-15description of 7-11Informix Committed Read 7-13Informix Cursor Stability 7-13Informix Dirty Read 7-12Informix Repeatable Read 7-15setting 7-11
JJoin
associative 2-76creating 2-71definition of 2-9dominant table 3-21equi-join 2-71multiple-table join 2-78natural 2-75nested outer 3-27nested simple 3-24outer 3-21restrictions in modifiable
view 11-25self-join 3-11subservient table 3-21
Join column. See Foreign key.
KKey lock 7-9Key, composite 8-27Key, primary 8-26
6 INFORMIX
LLabel 2-50, 3-46LENGTH function
on TEXT 2-63on VARCHAR 2-63use in expression 2-62
LET statementassigning values 14-24executing a procedure 14-11
LIKE keyword, used to test forequality in WHERE clause 2-29
LIKE relational operator 2-38Local loopback 12-10Local server 12-6LOCK TABLE statement
locking a table explicitly 7-8Locking
and concurrency 4-30and integrity 7-3deadlock 7-18description of 7-6granularity 7-7lock duration 7-9lock mode 7-17
not-wait 7-17wait 7-17
locks released at end oftransaction 7-22
scope 7-7scope of lock 7-7setting lock mode 7-17types of locks
database lock 7-7exclusive lock 7-6key lock 7-9page lock 7-9promotable lock 7-6, 7-10row lock 7-9shared lock 7-6table lock 7-8
withDELETE 6- 4update cursor 7-10
Loggingbuffered 9-26choosing for OnLine database
server 9-26choosing for SE database
server 9-27unbuffered 9-26
Logical logdefinition of 4-28
Logical operatorAND 2-37NOT 2-37OR 2-37
Loopcreating and exiting in SPL 14-26exiting using RAISE
exception 14-35Loopback, local 12-10
MMachine notes Intro-8Mandatory, entity in
relationship 8-10Many-to-many relationship 8-10,
8-13, 8-30MATCHES keyword
usewith NLS 2-43
used to test for equality inWHERE clause 2-29
MATCHES relational operatorin WHERE clause 2-38
MAX functionas aggregate function 2-53
MDY functionas time function 2-56
Memoryshared 12-8
Message fileserror messages Intro-8
MIN functionas aggregate function 2-53
MODE ANSI keywordsANSI-compliant database 1-18ANSI-compliant logging 9-26specifying transactions 4-27
Model. See Data model.
MODIFY clause of ALTERFRAGMENT 9-38
Modifying a fragmentationstrategy 9-38
Modifying fragmented tables 9-37MONEY data type 9-13
description of 9-12display format 9-13in INSERT 4-9
MONTH functionas time function 2-56
Multiple-table join 2-78
NNaming conventions
tables 12-18Natural join 2-75NCHAR data type
description of 9-17Nested ordering, in SELECT 2-16Network
computer 12-4connection information 12-17site 12-4
New featuresfor Version 7.1 Intro-12
NLSactivating 2-25and collation order 2-25and MATCHES keyword 2-43and ORDER BY keywords 2-25,
2-43specifying a language
environment 2-25NLS database
description of 1-18Nondecomposable attributes 8-17Normal form 8-33Normalization
benefits 8-33first normal form 8-34of data model 8-33rules 8-33rules, summary 8-37second normal form 8-36third normal form 8-36
NOT logical operator 2-37
Index 7
NOT NULL keywordsuse
in CREATE TABLE 9-28NOT relational operator 2-33NULL relational operator 2-37Null value
defined 9-22detecting in ESQL 5-17in INSERT statement 4-8restrictions in primary key 8-26testing for 2-37with logical operator 2-37
Number of fragments,changing 9-39
NVARCHAR data typedescription of 9-18
OON EXCEPTION statement
scope of control 14-32trapping errors 14-31user-generated errors 14-34
One-to-many relationship 8-10,8-13
One-to-one relationship 8-10, 8-13On-line
files Intro-8onload utility 4-30onunload utility 4-30OPEN statement
activating a cursor 5-22opening select or update
cursors 5-22Opening a cursor 5-22, 5-25Operating system
DOS 12-5UNIX 12-5
Optical device 12-6Optional, entity in
relationship 8-10OR logical operator 2-37OR relational operator 2-34ORDER BY keywords
and NLS 2-25ascending order 2-15DESC keyword 2-15, 2-25display label with 2-52
multiple columns 2-15relation to GROUP BY 3-6restrictions in INSERT 4-11restrictions in view 11-23restrictions with FOR
UPDATE 6- 8select columns by number 2-24sorting rows 2-14
Output from TRACEcommand 15-14
Owner-privileged procedure 14-16Ownership 11-8
PPage lock 7-9Parameter
to a stored procedure 14-28Parts explosion 5-28PATH environment variable 12-16Performance
buffered log 9-26depends on concurrency 7-3increasing with stored
procedures 14-4Pipes, unnamed 12-8Populating tables 9-31PREPARE statement
description of 5-31error return in SQLERRD 5-13missing WHERE signalled 5-11multiple SQL statements 5-32preparing GRANT 11-14
Primary keydefinition of 8-26restrictions with 8-26
Primary key constraintcomposite 8-27definition of 4-21
Primary key, use in fragmentedtable 3-15, 9-41
Primary site 12-21Privilege
Alter 11-10and views 11-28 to 11-31automating grants of 11-13column-level 11-11Connect 11-6
DBA 11-7default for stored
procedures 14-17Delete 11-9, 11-29displaying 4-18encoded in system catalog 11-9Execute 11-13, 14-17granting 11-6 to 11-15Index 11-10Insert 11-9, 11-29needed
to create a view 11-28to modify data 4-16
on a view 11-29on stored procedures 14-16overview 1-9Resource 11-7Select 11-9, 11-11, 11-28Update 11-9, 11-11, 11-29with DBA-privileged
procedures 14-16with owner-privileged
procedures 14-16Processing, distributed 12-10Projection, described 2-7Project, description of 1-14Promotable lock 7-6, 7-10PUBLIC keyword
privilege granted to all users 11-7PUT statement
constant data with 6- 12count of rows inserted 6- 11sends returned data to buffer 6-
10
QQuery
cyclic 4-24self-referencing 4-24stated in terms of data model 1-7
RRAISE EXCEPTION statement
exiting a loop 14-26Read Committed isolation level
(ANSI) 7-13
8 INFORMIX
Read Uncommitted isolation level(ANSI) 7-12
Recursion, in a storedprocedure 14-27
Recursive relationship 8-12, 8-32Redundant relationship 8-32REFERENCING clause
using referencing 15-9Referential constraint
definition of 4-21Referential integrity 4-21
defining primary and foreignkeys 8-28
Relational database, defined 1-12Relational model
attribute 8-17description of 1-12, 8-3 to 8-38entity 8-5join 2-9many-to-many relationship 8-13normalizing data 8-33one-to-many relationship 8-13one-to-one relationship 8-13projection 2-7resolving relationships 8-30rules for defining tables, rows,
and columns 8-24selection 2-6
Relational operation 2-5Relational operator
BETWEEN 2-33equals 2-31EXISTS 3-32IN 3-32in a WHERE clause 2-29 to ??LIKE 2-38NOT 2-33NULL 2-37OR 2-34
Relationshipattribute 8-17cardinality 8-11, 8-15complex 8-32connectivity 8-10, 8-13defining in data model 8-9entity 8-6existence dependency 8-10mandatory 8-10many-to-many 8-10, 8-13
many-to-many, resolving 8-30one-to-many 8-10, 8-13one-to-one 8-10, 8-13optional 8-10recursive 8-32redundant 8-32using matrix to discover 8-11
Release notes Intro-8Remote database server 12-9Repeatable Read isolation level
(Informix and ANSI)description of 7-15
Replication of data 12-21Report generator 1-20Resource manager 12-13Resource privilege 11-7Restricting access, using file
system 11-4RETURN statement
exiting a loop 14-26REVOKE statement
granting privileges 11-6 to 11-15in embedded SQL 5-37 to 5-39with a view 11-30
ROLLBACK WORK statementcancels a transaction 4-27closes cursors 7-22releases locks 7-10, 7-22sets SQLCODE 6- 5
ROLLFORWARD DATABASEstatement
applies log to restoreddatabase 4-29
Rowdefined 2-5defining 8-24deleting 4-4description of 1-13in relational model 1-13, 8-24inserting 4-7
Row lock 7-9Rowid
creating in a fragmentedtable 9-42
description of 9-41dropping in a fragmented
table 9-42in fragmented tables 9-41
locating internal rownumbers 3-17
use in a join 3-15
SSchema. See Data Model.Scroll cursor
active set 5-26definition of 5-24
SCROLL keyworduse in DECLARE 5-24
Second normal form 8-36Secondary site 12-21Security
constraining insertedvalues 11-21, 11-27
database-level privileges 11-5making database
inaccessible 11-5restricting access to
columns 11-21, 11-22restricting access to rows 11-21,
11-22restricting access to view 11-28table-level privileges 11-11using host file system 11-4using operating system
facilities 11-4with stored procedures 11-3
Selectdescription of 1-14
Select cursoropening 5-22use of 5-22
Select listdisplay label 2-50expressions in 2-47functions in 2-53 to 2-66labels in 3-46selecting all columns 2-12selecting specific columns 2-18specifying a substring in 2-27
Select privilegecolumn level 11-11definition of 11-9with a view 11-28
Index 9
SELECT statementactive set 2-29aggregate functions in 2-53alias names 2-80assigning values with 14-24compound query 3-42cursor for 5-21date-oriented functions in 2-56description of
advanced 3-4 to 3-54description of simple 2-3 to 2-83display label 2-50DISTINCT keyword 2-20embedded 5-15 to 5-17for joined tables 2-69 to 2-83for single tables 2-12 to 2-66functions 2-53 to 2-66GROUP BY clause 3-4HAVING clause 3-8in modifiable view 11-25INTO TEMP clause 2-83join 2-71 to 2-79multiple-table 2-69natural join 2-75ORDER BY clause 2-14outer join 3-21 to 3-30privilege for 11-6, 11-9rowid 3-15, 3-20SELECT clause 2-12 to 2-28selecting a substring 2-27selecting expressions 2-47selection list 2-12self-join 3-11single-table 2-12singleton 2-29subquery 3-31 to 3-41UNION operator 3-42using
for join 2-9for projection 2-7for selection 2-6
Selection, described 2-6Self-join
assigning column names withINTO TEMP 3-12
description of 3-11Self-referencing query 3-11, 4-24Semantic integrity 4-20, 9-3
Sequential cursordefinition of 5-24
SERIAL data typedescription of 9-9generated number in
SQLERRD 5-13inserting a starting value 4-9
Serializable isolation level (ANSI)description of 7-15
Server. See Database server.SET clause 4-15Set difference 3-52Set intersection 3-50SET ISOLATION statement
controlling the effect of locks 4-31discussed 7-11similarities to SET
TRANSACTIONstatement 7-11
SET keyworduse in UPDATE 4-13
SET LOCK MODE statementcontrolling the effect of locks 4-31description of 7-17
SET LOG statementbuffered vs. unbuffered 9-26
SET TRANSACTION statementsimilarities to SET ISOLATION
statement 7-11Shared memory
network connection 12-8Singleton SELECT statement 2-29Site
network 12-4primary 12-21secondary 12-21
SITENAME functionuse
in SELECT 2-62, 2-65, 3-20SMALLFLOAT data type
description of 9-10SMALLINT data type
description of 9-8SOME keyword
beginning a subquery 3-32Sorting
nested 2-15with NLS activated 2-25with ORDER BY 2-15
SPLflow control statements 14-25program variable 5-6relation to SQL 14-3
SQLANSI standard 1-17cursor 5-21description of 1-16error handling 5-18history 1-17Informix SQL and ANSI SQL 1-17interactive use 1-20standardization 1-17
SQL Communications Area(SQLCA)
altered by end of transaction 6- 5description of 5-9inserting rows 6- 11
SQLAWARN arraydescription of 5-13syntax of naming 5-12with PREPARE 5-32
SQLCODE fieldafter opening cursor 5-22description of 5-12end of data on SELECT only 6- 14end of data signalled 5-18set by DELETE 6- 4set by DESCRIBE 5-35set by PUT, FLUSH 6- 11
SQLERRD arraycount of deleted rows 6- 4count of inserted rows 6- 11count of rows 6- 14description of 5-13syntax of naming 5-12
sqlexecd 12-15sqlhosts. See
$INFORMIXDIR/etc/sqlhosts.SQLSTATE
in databases that are not ANSI-compliant 5-18
use with a cursor 5-22START DATABASE statement
adding a transaction log 9-27Static SQL 5-5STATUS variable (4GL) 5-12Storage device 12-6
10 INFORMIX
Stored procedurealtering 14-15as triggered action 15-11branching 14-25comments in 14-7creating from an embedded
language 14-6creating from DB-Access 14-6DBA-privileged, use with
triggers 14-16debugging 14-13default privileges 14-17DEFINE statement 14-20definition of 14-4displaying contents 14-10displaying documentation 14-11executing 14-11general programming 1-21granting privileges on 11-13,
14-17, 14-18header 14-28in SELECT statements 2-67introduction to 14-3looping 14-26name confusion with SQL
functions 14-24owner-privileged 14-16privileges necessary at
execution 14-17program flow control 14-25recursion 14-27REFERENCES clause 14-21returning values 14-28revoking privileges on 14-19security purposes 11-3tracing triggered actions 15-13use 14-4variable 14-19
stores7 databasecopying Intro-10creating Intro-10overview Intro-9
Structured Query Language. SeeSQL.
Subquerycorrelated 3-31, 4-24in DELETE statement 4-6in SELECT 3-31 to 3-41
in UPDATE-SET 4-14in UPDATE-WHERE 4-13
Subscriptingin a WHERE clause 2-45SPL variables 14-21
Subservient table 3-21Substring 2-27, 14-21SUM function
as aggregate function 2-53Synonym
chains 12-20Synonyms for table names 12-19syssyntable system catalog
table 12-19System catalog
privileges in 4-18, 11-9querying 4-18syscolauth 11-9sysprocbody 14-10systabauth 4-18, 11-9sysusers 11-9
TTable
candidate keys, defined 8-27composite key, defined 8-27creating 9-28description of 1-12in relational model 1-12, 8-24lock 7-8names 12-18names, synonyms 12-19ownership 11-8primary key in 8-26primary key, defined 8-26represents an entity 8-26
Table-level privilegecolumn-specific privileges 11-11definition and use 11-8
Temporary tableand active set of cursor 5-26assigning column names 3-12example 4-12
TERMCAP environmentvariable 12-16
TEXT data typedescription of 9-20restrictions
with GROUP BY 3-6with LIKE or MATCHES 2-38with relational expression 2-30
with LENGTH function 2-63TEXT value, displaying 2-11Third normal form 8-36TODAY function
usein constant expression 2-62, 4-9
TP/XA. See Transaction manager.TRACE command
output from 15-14TRACE statement
debugging a storedprocedure 14-13
Transactioncursors closed at end 7-22description of 4-25example with DELETE 6- 5global 12-23locks held to end of 7-10locks released at end 7-10, 7-22transaction log 4-26, 4-29transaction log required 9-26use signalled in
SQLAWARN 5-13Transaction logging
buffered 9-26contents of log 4-28establishing with CREATE
DATABASE 9-24OnLine methods of 9-26turning off for faster loading 9-33turning off not possible 9-27
Transaction manager 12-13Transitive dependency 8-36Trigger
creating 15-4definition of 15-3when to use 15-3
Trigger eventdefinition of 15-5example of 15-5
Trigger nameassigning 15-5
Index 11
Triggered actionBEFORE and AFTER 15-7FOR EACH ROW 15-9generating an error
message 15-15in relation to triggering
statement 15-6statements 15-3tracing 15-13using 15-7using stored procedures 15-11WHEN condition 15-10
Truncation, signalled inSQLAWARN 5-14
Two-phase commit 12-22Typographical conventions Intro-5
UUnbuffered logging 9-26UNION operator
description of 3-42display labels with 3-46restrictions in view 11-23
UNIQUE keywordconstraint in CREATE
TABLE 9-28restrictions in modifiable
view 11-25use
in SELECT 2-20UNIX operating system 12-5, 12-7UNLOAD statement
exporting data to a file 9-31Unnamed pipes 12-8Update cursor
definition of 6- 15Update privilege
column level 11-11definition of 11-9with a view 11-29
UPDATE statementand end of data 6- 14applied to view 11-25description of 4-12embedded 6- 15 to 6- 17missing WHERE signalled 5-11multiple assignment 4-15
number of rows 5-13preparing 5-32privilege for 11-6, 11-9restrictions on subqueries 4-15
USER functionuse
in expression 2-62, 2-63, 3-19USING keyword
usein EXECUTE 5-33
Utility programdbload 9-32dbschema 9-30onload 4-30onunload 4-30
VVALUES clause
use in INSERT 4-7VARCHAR data type
description of 9-18value, displaying 2-11with LENGTH function 2-63
Variableglobal, in SPL 14-20in SPL 14-19local, in SPL 14-20with same name as a
keyword 14-22View
creating a view 11-22deleting rows in 11-25description of 11-21dropped when basis is
dropped 11-24effect of changing basis 11-24inserting rows in 11-26modifying 11-25 to 11-28null inserted in unexposed
columns 11-27privilege when accessing 11-29privileges 11-28 to 11-31produces duplicate rows 11-23updating duplicate rows 11-26using CHECK OPTION 11-27virtual column 11-25
WWarning
if dbspace is skipped 5-11Warnings, with stored procedures
at compile time 14-9WEEKDAY function
as time function 2-56, 2-59WHERE clause, subscripting 2-45WHERE CURRENT OF keywords
usein DELETE 6- 7in UPDATE 6- 15
WHERE keywordBoolean expression in 2-37comparison condition 2-29 to ??date-oriented functions in 2-59enforcing data constraints 11-28host variables in 5-15in DELETE 4-4 to 4-7null data tests 2-37range of values 2-33relational operators 2-29selecting rows 2-28subqueries in 3-32testing a subscript 2-45use
with NOT keyword 2-33with OR keyword 2-34
wildcard comparisons 2-38WHILE statement
looping in a storedprocedure 14-26
Wildcard characterasterisk 2-12
Wildcard comparisonin WHERE clause 2-38 to 2-45
WITH CHECK OPTION keywordsof CREATE VIEW
statement 11-27WITH HOLD keywords
declaring a hold cursor 7-23WITH LISTING IN keywords
warnings in a storedprocedure 14-10
WITH ROWIDS clause, of CREATETABLE 9-42
12 INFORMIX
WORM drive 12-6Write-once read-many-times
device. See WORM drive.
YYEAR function
as time function 2-56
Symbols$INFORMIXDIR/etc/sqlhosts 12-
17/etc/hosts 12-17/etc/services 12-17=, equals, relational operator 2-31,
2-71?, question mark
as placeholder in PREPARE 5-31
Index 13
14 INFORMIX