DataDef-Interbase
DataDef-Interbase
InterBase XE
December, 2010
Copyright © 1994-2010 Embarcadero Technologies, Inc.
All brands and product names are trademarks or registered trademarks of their respective owners.
This software/documentation contains proprietary information of Embarcadero Technologies, Inc.;
it is provided under a license agreement containing restrictions on use and disclosure and is also
protected by copyright law. Reverse engineering of the software is prohibited.
Restricted Rights Legend Use, duplication, or disclosure by the Government is subject to restrictions
as set forth in subparagraph (c)(1)(ii) of DFARS 252.227-7013, Rights in Technical Data and Computer
Software (October 1988).
If this software/documentation is delivered to a U.S. Government Agency not within the Department
of Defense, then it is delivered with Restricted Rights, as defined in FAR 552.227-14, Rights in
Data-General, including Alternate III (June 1987).
Information in this document is subject to change without notice. Revisions may be issued to advise
of such changes and additions. Embarcadero Technologies, Inc. does not warrant that this
documentation is error-free.
Contents
Tables . . . . . . . . . . . . . . . . . . . . . . . . . 9 Creating a database . . . . . . . . . . . . . . . . . . 3-2
Figures . . . . . . . . . . . . . . . . . . . . . . . . . 11 File naming conventions . . . . . . . . . . . . . 3-2
Using a data definition file . . . . . . . . . . . . 3-2
Chapter 1 Using CREATE DATABASE . . . . . . . . . . . . . 3-2
Creating a single-file database. . . . . . . . . 3-3
Using the Data Definition Guide Creating a multifile database . . . . . . . . . 3-4
What is data definition? . . . . . . . . . . . . . . . 1-1
Using LENGTH to specify a secondary file . . 3-4
Who should use this guide . . . . . . . . . . . . . . 1-2
Specifying the starting page number of a
Topics covered in this guide . . . . . . . . . . . . . 1-3
secondary file . . . . . . . . . . . . . . . . 3-4
Using isql . . . . . . . . . . . . . . . . . . . . . . 1-4
Specifying user name and password. . . . . . 3-5
Using a data definition file. . . . . . . . . . . . . . 1-4
Specifying database page size . . . . . . . . . 3-5
Specifying the default character set . . . . . . 3-6
Chapter 2 When there is no default character set . . . . . 3-6
Designing Databases Read-only databases. . . . . . . . . . . . . . . . 3-6
Overview of design issues . . . . . . . . . . . . . . 2-1 Altering a database . . . . . . . . . . . . . . . . . . 3-7
Database versus data model . . . . . . . . . . . 2-2 Dropping a database . . . . . . . . . . . . . . . . . 3-8
Design goals . . . . . . . . . . . . . . . . . . . 2-2 Creating a database shadow . . . . . . . . . . . . . 3-8
Design framework . . . . . . . . . . . . . . . . . . 2-3 Advantages of shadowing . . . . . . . . . . . . . 3-8
Analyzing requirements . . . . . . . . . . . . . . . 2-3 Limitations of shadowing . . . . . . . . . . . . . 3-9
Collecting and analyzing data . . . . . . . . . . . . 2-4 Before creating a shadow . . . . . . . . . . . . . 3-9
Identifying entities and attributes . . . . . . . . . . 2-4 Using CREATE SHADOW . . . . . . . . . . . . . . 3-10
Designing tables . . . . . . . . . . . . . . . . . . . 2-6 Creating a single-file shadow . . . . . . . . 3-10
Determining unique attributes . . . . . . . . . . . . 2-7 Shadow location . . . . . . . . . . . . . . . 3-10
Developing a set of rules . . . . . . . . . . . . . . 2-7 Creating a multifile shadow . . . . . . . . . 3-11
Specifying a data type . . . . . . . . . . . . . . 2-8 Auto mode and manual mode . . . . . . . . 3-11
Choosing international character sets . . . . . . 2-8 Conditional shadows. . . . . . . . . . . . . 3-12
Specifying domains . . . . . . . . . . . . . . . 2-9 Dropping a shadow . . . . . . . . . . . . . . . . . 3-13
Setting default values and NULL status . . . . . 2-9 Expanding the size of a shadow . . . . . . . . . . 3-13
Defining integrity constraints . . . . . . . . . . 2-10 Using isql to extract data definitions . . . . . . . . 3-14
Defining CHECK constraints . . . . . . . . . . . 2-10 Extracting an InterBase 4.0 database . . . . . . 3-14
Establishing relationships between objects . . . . . 2-10 Extracting a 3.x database . . . . . . . . . . . . 3-14
Enforcing referential integrity . . . . . . . . . . 2-11
Normalizing the database . . . . . . . . . . . . 2-12 Chapter 4
Eliminating repeating groups . . . . . . . . . 2-12 Specifying Data types
Removing partially-dependent columns . . . 2-14
About InterBase data types . . . . . . . . . . . . . . 4-1
Removing transitively-dependent columns. . 2-14
Where to specify data types. . . . . . . . . . . . . . 4-3
When to break the rules. . . . . . . . . . . . 2-15
Defining numeric data types . . . . . . . . . . . . . 4-4
Choosing indexes. . . . . . . . . . . . . . . . . 2-16
Integer data types . . . . . . . . . . . . . . . . . 4-4
Increasing cache size . . . . . . . . . . . . . . . 2-16
Fixed-decimal data types . . . . . . . . . . . . . 4-5
Creating a multifile, distributed database . . . . 2-17
NUMERIC data type . . . . . . . . . . . . . . 4-5
Planning security. . . . . . . . . . . . . . . . . . . 2-17
DECIMAL data type . . . . . . . . . . . . . . 4-5
Naming Objects . . . . . . . . . . . . . . . . . . . 2-17
How fixed-decimal data types are stored . . . 4-6
Specifying NUMERIC and DECIMAL with scale
Chapter 3 and precision . . . . . . . . . . . . . . . . . 4-7
Creating Databases Numeric input and exponents . . . . . . . . . 4-7
What you should know . . . . . . . . . . . . . . . 3-1
3
Specifying data types using embedded Specifying domain collation order . . . . . . . . 5-5
applications . . . . . . . . . . . . . . . . . 4-8 Altering domains . . . . . . . . . . . . . . . . . . . 5-5
Considering migration for NUMERIC and Dropping a domain . . . . . . . . . . . . . . . . . . 5-6
DECIMAL data types . . . . . . . . . . . . 4-8
Migrating databases with NUMERIC and Chapter 6
DECIMAL data types . . . . . . . . . . . . 4-8 Working with Tables
Using exact numeric data types in arithmetic 4-9
Before creating a table . . . . . . . . . . . . . . . . 6-1
Floating-point data types . . . . . . . . . . . . . 4-10
Creating tables . . . . . . . . . . . . . . . . . . . . 6-2
Date and time data types . . . . . . . . . . . . . . . 4-11
Defining columns . . . . . . . . . . . . . . . . . 6-2
Converting to the DATE, TIME, and TIMESTAMP data
Required attributes. . . . . . . . . . . . . . . 6-2
types . . . . . . . . . . . . . . . . . . . . . . 4-11
Optional attributes . . . . . . . . . . . . . . . 6-3
How InterBase stores date values . . . . . . . . 4-12
Specifying the data type . . . . . . . . . . . . 6-3
Character data types . . . . . . . . . . . . . . . . . 4-12
Casting data types . . . . . . . . . . . . . . . 6-4
Specifying a character set . . . . . . . . . . . . 4-13
Defining a character set . . . . . . . . . . . . 6-4
Characters vs. bytes. . . . . . . . . . . . . . 4-13
The COLLATE clause . . . . . . . . . . . . . 6-4
Using CHARACTER SET NONE . . . . . . . . 4-13
Defining domain-based columns . . . . . . . 6-5
About collation order . . . . . . . . . . . . . 4-14
Defining expression-based columns . . . . . . 6-5
Fixed-length character data . . . . . . . . . . . 4-14
Specifying column default values . . . . . . . 6-6
CHAR(n) or CHARACTER(n) . . . . . . . . . 4-14
Specifying NOT NULL . . . . . . . . . . . . . 6-7
NCHAR(n) or NATIONAL CHAR(n) . . . . . . 4-15
Defining integrity constraints . . . . . . . . . . . 6-7
Variable-length character data . . . . . . . . . . 4-15
PRIMARY KEY and UNIQUE constraints . . . 6-7
VARCHAR(n) . . . . . . . . . . . . . . . . . 4-15
Using the FOREIGN KEY to enforce referential
NCHAR VARYING(n) . . . . . . . . . . . . . 4-16
integrity . . . . . . . . . . . . . . . . . . . 6-8
The BOOLEAN data type. . . . . . . . . . . . . . . 4-16
Referencing tables owned by others . . . . . 6-10
Defining BLOB data types . . . . . . . . . . . . . . 4-17
Circular references. . . . . . . . . . . . . . 6-10
BLOB columns . . . . . . . . . . . . . . . . . . 4-17
How to declare constraints. . . . . . . . . . 6-11
BLOB segment length . . . . . . . . . . . . . . 4-18
Defining a CHECK constraint . . . . . . . . . . 6-12
Defining segment length . . . . . . . . . . . 4-18
Using the EXTERNAL FILE option . . . . . . . 6-13
Segment syntax . . . . . . . . . . . . . . . . 4-18
Restrictions . . . . . . . . . . . . . . . . . 6-14
BLOB subtypes . . . . . . . . . . . . . . . . . 4-19
Importing external files . . . . . . . . . . . 6-15
BLOB filters . . . . . . . . . . . . . . . . . . . 4-20
Exporting InterBase tables to an external file 6-16
Using BLOBs with VARCHAR data. . . . . . . 4-20
Altering tables . . . . . . . . . . . . . . . . . . . 6-17
About text BLOB syntax . . . . . . . . . . . 4-20
Before using ALTER TABLE . . . . . . . . . . . . . 6-17
Defining arrays . . . . . . . . . . . . . . . . . . . 4-22
Saving existing data . . . . . . . . . . . . . 6-18
Multi-dimensional arrays. . . . . . . . . . . . . 4-23
Dropping columns . . . . . . . . . . . . . . 6-19
Specifying subscript ranges for array dimensions . .
Using ALTER TABLE . . . . . . . . . . . . . . . . . 6-19
4-23
Adding a new column to a table . . . . . . . 6-19
Converting data types . . . . . . . . . . . . . . . . 4-24
Adding new table constraints . . . . . . . . 6-20
Implicit type conversions . . . . . . . . . . . . 4-24
Dropping an existing column from a table . 6-21
Explicit type conversions . . . . . . . . . . . . 4-25
Dropping existing constraints from a column 6-21
Modifying columns in a table . . . . . . . . 6-22
Chapter 5 Summary of ALTER TABLE arguments . . . 6-23
Working with Domains Dropping tables . . . . . . . . . . . . . . . . . . . 6-24
Creating domains . . . . . . . . . . . . . . . . . . 5-1 Dropping a table. . . . . . . . . . . . . . . . . 6-24
Specifying the domain data type . . . . . . . . . 5-2 DROP TABLE syntax. . . . . . . . . . . . . . . 6-24
Specifying domain defaults . . . . . . . . . . . 5-3 SQL global temporary tables . . . . . . . . . . . . 6-25
Specifying NOT NULL. . . . . . . . . . . . . . . . . 5-3 Creating a SQL global temporary table . . . . . 6-25
Specifying domain CHECK constraints . . . . . 5-4 Altering a SQL global temporary table . . . . . 6-25
Using the VALUE keyword . . . . . . . . . . . . 5-4 Requirements and constraints . . . . . . . . . . 6-26
4
Chapter 7 Using assignment statements . . . . . . . . 9-11
Using SELECT statements . . . . . . . . . . 9-11
Working with Indexes Using FOR SELECT … DO statements . . . . 9-12
Index basics . . . . . . . . . . . . . . . . . . . . . 7-1 Using WHILE … DO statements . . . . . . . 9-12
When to index . . . . . . . . . . . . . . . . . . . . 7-2 Using IF … THEN … ELSE statements . . . . 9-13
Creating indexes . . . . . . . . . . . . . . . . . . . 7-2 Using event alerters . . . . . . . . . . . . . 9-13
Using CREATE INDEX. . . . . . . . . . . . . . . . . 7-2
Adding comments . . . . . . . . . . . . . . 9-14
Preventing duplicate entries . . . . . . . . . 7-3 Creating nested and recursive procedures . . 9-14
Specifying index sort order . . . . . . . . . . 7-3 Using SUSPEND, EXIT, and END with procedures
When to use a multi-column index. . . . . . . . 7-4 9-15
Examples using multi-column indexes. . . . . . 7-4 Altering and dropping stored procedures . . . . . . 9-17
Improving index performance . . . . . . . . . . . . 7-5 Altering stored procedures . . . . . . . . . . . 9-17
ALTER INDEX: deactivating an index . . . . . . 7-5 ALTER PROCEDURE syntax . . . . . . . . . . . 9-18
SET STATISTICS: recomputing index selectivity . 7-6 Dropping procedures . . . . . . . . . . . . . . 9-18
Dropping a user-defined index . . . . . . . . . . 7-7 Drop procedure syntax . . . . . . . . . . . . . 9-18
Altering and dropping procedures in use . . . . 9-19
Chapter 8 Using stored procedures . . . . . . . . . . . . . . 9-20
Working with Views Using executable procedures in isql. . . . . . . 9-20
Introduction . . . . . . . . . . . . . . . . . . . . . 8-1 Using select procedures in isql . . . . . . . . . 9-20
Advantages of views . . . . . . . . . . . . . . . . . 8-2 Using WHERE and ORDER BY clauses . . . 9-23
Creating views . . . . . . . . . . . . . . . . . . . . 8-3 Selecting aggregates from procedures . . . . 9-23
Specifying view column names . . . . . . . . . 8-3 Viewing arrays with stored procedures . . . . . 9-24
Using the SELECT statement . . . . . . . . . . . 8-3 Exceptions . . . . . . . . . . . . . . . . . . . . . 9-26
Using expressions to define columns . . . . . . 8-4 Creating exceptions . . . . . . . . . . . . . . . 9-26
Types of views: read-only and update-able . . . 8-5 Altering exceptions . . . . . . . . . . . . . . . 9-26
View privileges . . . . . . . . . . . . . . . . 8-5 Dropping exceptions . . . . . . . . . . . . . . 9-26
Examples of views . . . . . . . . . . . . . . 8-5 Raising an exception in a stored procedure . . . 9-27
Inserting data through a view . . . . . . . . . . 8-6 Handling errors . . . . . . . . . . . . . . . . . . . 9-27
Using WITH CHECK OPTION . . . . . . . . . 8-6 Handling exceptions. . . . . . . . . . . . . . . 9-28
Examples . . . . . . . . . . . . . . . . . . . 8-6 Handling SQL errors . . . . . . . . . . . . . . 9-28
Dropping views . . . . . . . . . . . . . . . . . . . 8-7 Handling InterBase errors . . . . . . . . . . . . 9-29
Examples of error behavior and handling . . . . 9-29
Chapter 9
Working with Stored Procedures Chapter 10
Overview of stored procedures . . . . . . . . . . . 9-1 Working with Triggers
Working with procedures . . . . . . . . . . . . . . 9-2 About triggers. . . . . . . . . . . . . . . . . . . . 10-1
Using a data definition file . . . . . . . . . . . . 9-2 Working with triggers . . . . . . . . . . . . . . 10-2
Calling stored procedures . . . . . . . . . . . . 9-3 Using a data definition file . . . . . . . . . . . 10-2
Privileges for stored procedures . . . . . . . . . 9-3 Creating triggers . . . . . . . . . . . . . . . . . . 10-2
Creating procedures . . . . . . . . . . . . . . . . . 9-4 CREATE TRIGGER syntax. . . . . . . . . . . 10-3
CREATE PROCEDURE syntax . . . . . . . . . . 9-4 InterBase procedure and trigger language . . . 10-4
Procedure and trigger language . . . . . . . . . 9-5 Syntax errors in triggers . . . . . . . . . . . 10-6
Syntax errors in stored procedures . . . . . . 9-7 The trigger header . . . . . . . . . . . . . . . . 10-7
The procedure header . . . . . . . . . . . . . . 9-8 The trigger body. . . . . . . . . . . . . . . . . 10-7
Declaring input parameters . . . . . . . . . . 9-8 NEW and OLD context variables. . . . . . . 10-8
Declaring output parameters . . . . . . . . . 9-8 Using generators . . . . . . . . . . . . . . . 10-9
The procedure body . . . . . . . . . . . . . . . 9-9 Altering triggers . . . . . . . . . . . . . . . . . 10-10
BEGIN … END statements . . . . . . . . . . 9-9 Altering a trigger header . . . . . . . . . . . 10-10
Using variables . . . . . . . . . . . . . . . . 9-9 Altering a trigger body . . . . . . . . . . . . .10-11
5
Dropping triggers . . . . . . . . . . . . . . . . . 10-11 Revocation restrictions . . . . . . . . . . . . 12-14
Using triggers . . . . . . . . . . . . . . . . . . . 10-12 Revoking multiple privileges . . . . . . . . . 12-14
Triggers and transactions. . . . . . . . . . . . 10-12 Revoking all privileges . . . . . . . . . . . . 12-15
Triggers and security . . . . . . . . . . . . . . 10-13 Revoking privileges for a list of users . . . . 12-15
Triggers as event alerters . . . . . . . . . . . . 10-13 Revoking privileges for a role. . . . . . . . . 12-15
Updating views with triggers. . . . . . . . . . 10-14 Revoking a role from users . . . . . . . . . . 12-15
Exceptions . . . . . . . . . . . . . . . . . . . . . 10-15 Revoking EXECUTE privileges . . . . . . . . 12-16
Raising an exception in a trigger . . . . . . . . 10-15 Revoking privileges from objects . . . . . . . 12-16
Error handling in triggers . . . . . . . . . . . 10-16 Revoking privileges for all users . . . . . . . 12-16
Revoking grant authority . . . . . . . . . . . 12-16
Chapter 11 Using views to restrict data access . . . . . . . . 12-17
Working with Generators
About generators. . . . . . . . . . . . . . . . . . . 11-1
Chapter 13
Creating generators . . . . . . . . . . . . . . . . . 11-1 Encrypting Your Data
Setting or resetting generator values. . . . . . . . . 11-2 About InterBase encryption. . . . . . . . . . . . . 13-1
Using generators . . . . . . . . . . . . . . . . . . . 11-2 About industry encryption standards . . . . . . 13-2
Dropping generators . . . . . . . . . . . . . . . . . 11-3 Who can create encryption?. . . . . . . . . . . 13-3
Creating the SYSDSO user . . . . . . . . . 13-3
Chapter 12 An overview of encryption tasks . . . . . . . . 13-4
Planning Security Requirements and support. . . . . . . . . . . . 13-4
Using isql to enable and implement encryption . . 13-5
Overview of SQL access privileges . . . . . . . . . 12-1
Setting the System Encryption Password (SEP) 13-5
Default security and access . . . . . . . . . . . 12-2
Altering the database to create the SEP . . . 13-5
Privileges available. . . . . . . . . . . . . . . . 12-2
Removing the System Encryption Password
SQL ROLES . . . . . . . . . . . . . . . . . . . 12-3
(SEP) . . . . . . . . . . . . . . . . . . . . 13-6
Granting privileges . . . . . . . . . . . . . . . . . 12-4
Creating encryption keys . . . . . . . . . . . . 13-6
Granting privileges to a whole table . . . . . . . 12-4
Setting a user-defined password for an encryption
Granting access to columns in a table . . . . . . 12-5
key . . . . . . . . . . . . . . . . . . . . . 13-8
Granting privileges to a stored procedure or trigger .
Dropping an encryption key . . . . . . . . . 13-8
12-5
Granting encryption permission to the database
Multiple privileges and multiple grantees . . . . . . 12-6
owner . . . . . . . . . . . . . . . . . . . . . 13-9
Granting multiple privileges . . . . . . . . . . . 12-6
Encrypting data . . . . . . . . . . . . . . . . . 13-9
Granting all privileges . . . . . . . . . . . . . . 12-6
About the encryption commands . . . . . . 13-9
Granting privileges to multiple users . . . . . . 12-7
Setting a decrypt default value for a column 13-10
Granting privileges to a list of users . . . . . 12-7
Encrypting blob columns . . . . . . . . . 13-10
Granting privileges to a UNIX group. . . . . 12-7
Decrypting data . . . . . . . . . . . . . . . . .13-11
Granting privileges to all users . . . . . . . . 12-7
Granting decrypt permission . . . . . . . . . .13-11
Granting privileges to a list of procedures . . . . 12-8
Permissions for roles and views . . . . . . 13-12
Using roles to grant privileges . . . . . . . . . . . . 12-8
Revoking encrypt and decrypt permissions . . 13-12
Granting privileges to a role . . . . . . . . . . . 12-8
Using IBConsole to set up and perform encryption 13-13
Granting a role to users. . . . . . . . . . . . . . 12-9
Enabling EUA and performing encryption when
Granting users the right to grant privileges . . . . . 12-9
creating a new database . . . . . . . . . . . 13-13
Grant authority restrictions. . . . . . . . . . . . 12-9
Enabling EUA and performing encryption on an
Grant authority implications . . . . . . . . . . 12-10
existing database. . . . . . . . . . . . . . . 13-14
Granting privileges to execute stored procedures . 12-11
Performing database-level encryption using
Granting access to views. . . . . . . . . . . . . . 12-11
IBConsole . . . . . . . . . . . . . . . . . . 13-15
Update-able views . . . . . . . . . . . . . . . 12-12
Decrypting the database . . . . . . . . . . 13-17
Read-only views . . . . . . . . . . . . . . . . 12-13
Performing column-level encryption using
Revoking user access . . . . . . . . . . . . . . . 12-13
IBConsole . . . . . . . . . . . . . . . . . . 13-17
6
Encrypting backup files . . . . . . . . . . . . . . 13-18 UNICODE_BE and UNICODE_LE Character Sets .
Avoiding embedded spaces in GBAK encrypt/ 14-7
decrypt and sep statements . . . . . . . . . . 13-18 Additional character sets and collations. . . . . 14-8
Encrypting a database backup file . . . . . . . 13-19 Specifying defaults . . . . . . . . . . . . . . . . . 14-8
Decrypting a database backup file during a restore . Specifying a default character set for a database 14-8
13-19 Specifying a character set for a column in a table . .
Additional guidelines for encrypting and decrypting 14-9
database backup files . . . . . . . . . . . . . 13-19 Specifying a character set for a client connection14-9
Specifying collation orders . . . . . . . . . . . . 14-10
Chapter 14 Specifying collation order for a column . . . 14-10
Character Sets and Specifying collation order in a comparison operation
14-10
Collation Orders Specifying collation order in an ORDER BY clause . .
About character sets and collation orders . . . . . . 14-1 14-10
Character set storage requirements . . . . . . . . . 14-2 Specifying collation order in a GROUP BY clause . .
InterBase character sets . . . . . . . . . . . . . . . 14-2 14-11
Character sets for DOS . . . . . . . . . . . . . . . 14-6
Index . . . . . . . . . . . . . . . . . . . . . . . . . I-1
Character sets for Microsoft Windows . . . . . . 14-7
7
8
Tables
1.1 Chapter list for the Data Definition Guide . . 1-3 4.6 Minimum character lengths for numeric
2.1 List of entities and attributes . . . . . . . . . 2-5 conversions . . . . . . . . . . . . . . . . . 4-25
2.2 EMPLOYEE table . . . . . . . . . . . . . . . 2-7 6.1 The EMPLOYEE table . . . . . . . . . . . . . 6-7
2.3 PROJECT table . . . . . . . . . . . . . . . . 2-11 6.2 The PROJECT table . . . . . . . . . . . . . . 6-8
2.4 EMPLOYEE table . . . . . . . . . . . . . . . 2-11 6.3 The EMPLOYEE table . . . . . . . . . . . . . 6-8
2.5 DEPARTMENT table . . . . . . . . . . . . . 2-13 6.4 Referential integrity check options . . . . . . 6-9
2.6 DEPARTMENT table . . . . . . . . . . . . . 2-13 6.5 Valid data type conversions using ALTER
2.7 DEPT_LOCATIONS table . . . . . . . . . . . 2-13 COLUMN and ALTER DOMAIN . . . . . . . . . 6-23
2.8 PROJECT table . . . . . . . . . . . . . . . . 2-14 9.1 Arguments of the CREATE PROCEDURE
2.9 PROJECT table . . . . . . . . . . . . . . . . 2-14 statement . . . . . . . . . . . . . . . . . . . . 9-5
2.10 PROJECT table . . . . . . . . . . . . . . . . 2-15 9.2 Procedure and trigger language extensions . . 9-6
2.11 EMPLOYEE table . . . . . . . . . . . . . . . 2-15 9.3 SUSPEND, EXIT, and END . . . . . . . . . . . . 9-16
3.1 Auto vs. manual shadows. . . . . . . . . . . 3-12 10.1 Arguments of the CREATE TRIGGER statement . .
4.1 Data types supported by InterBase . . . . . . 4-2 10-3
4.2 NUMERIC and DECIMAL data type storage: 10.2 Procedure and trigger language extensions . 10-5
dialects 1 and 3 . . . . . . . . . . . . . . . . 4-6 12.1 SQL access privileges . . . . . . . . . . . . 12-2
4.3 NUMERIC and DECIMAL data type storage based 13.1 Encryption implementation tasks . . . . . . 13-4
on precision and scale . . . . . . . . . . . . 4-6 13.2 Encryption Key Options . . . . . . . . . . . 13-7
4.4 Blob subtypes . . . . . . . . . . . . . . . . . 4-19 14.1 Character sets and collation orders . . . . . 14-3
4.5 Text BLOB Example Result . . . . . . . . . 4-22 14.2 Character sets corresponding to DOS code pages .
14-6
9
10
Figures
2.1 Identifying relationships between objects . . . 2-4 13.2 Encryption wizard, initial page . . . . . . . 13-15
4.1 Blob relationships . . . . . . . . . . . . . . . 4-18 13.3 Step 1: Enter the SYSDSO password. . . . 13-16
6.1 Circular references. . . . . . . . . . . . . . . 6-10 13.4 Step 2: Create the SEP . . . . . . . . . . . 13-16
13.1 Enabling EUA and encryption. . . . . . . . 13-14 13.5 Step 3: Create an encryption key . . . . . . 13-17
11
12
Chapter
Definition Guide
The InterBase Data Definition Guide provides information on the following topics:
• Designing and creating databases
• Working with InterBase structures and objects, including data types, domains, tables,
indexes, and views
• Working with tools and utilities such as stored procedures, triggers, Blob filters, and
generators
• Planning and implementing database security
• Character sets and collation orders
DDL statements that create metadata begin with the keyword CREATE, statements that
modify metadata begin with the keyword ALTER, and statements that delete metadata begin
with the keyword DROP. Some of the basic data definition tasks include:
• Creating a database (CREATE DATABASE).
• Creating tables (CREATE TABLE).
• Altering tables (ALTER TABLE).
• Dropping tables (DROP TABLE).
InterBase stores database metadata and other information about it in system tables, which
are automatically created when you create a database. All system table names begin with
“RDB$”. Examples of system tables include RDB$RELATIONS, which has information about
each table in the database, and RDB$FIELDS, which has information on the domains in the
database.
Writing to these system tables without sufficient knowledge can corrupt a database.
Therefore, public users can only select from them. The database owner and SYSDBA user
have full read and write privileges and can assign these privileges to others if they wish.
For more information about the system tables, see the Language Reference Guide.
Important If you have permission, you can directly modify columns of a system table, but unless you
understand all of the interrelationships between the system tables, modifying them directly
can adversely affect other system tables and corrupt your database.
Chapter 6, “Working with • Creating and altering database tables, CREATE/ALTER/DROP TABLE
Tables” columns, and domains
• Setting up referential integrity
Chapter 10, “Working with Using triggers, what you can do with CREATE/ALTER/DROP
Triggers” triggers TRIGGER
CREATE/ALTER/DROP
EXCEPTION
Chapter 11, “Working with Creating, setting, and resetting generators CREATE GENERATOR
Generators” SET GENERATOR
Chapter 12, “Planning Securing data and system catalogs with GRANT, REVOKE
Security” SQL: tables, views, triggers, and
procedures
Chapter 13, “Encrypting Your Encrypt database and/or specific columns CREATE ENCRYPTION,
Data” in a database; create specific users and ENCRYPT, DECRYPT
password types; grant and revoke encrypt
and decrypt permissions.
Chapter 14, “Character Sets Specifying character sets and collation CHARACTER SET COLLATE
and Collation Orders” orders
Using isql
You can use isql to interactively create, update, and drop metadata, or you can input a file
to isql that contains data definition statements, which is then executed by isql without
prompting the user. It is usually preferable to use a data definition file because it is easier to
modify the file than to retype a series of individual SQL statements, and the file provides a
record of the changes made to the database.
The isql interface can be convenient for simple changes to existing data, or for querying
the database and displaying the results. You can also use the interactive interface as a
learning tool. By creating one or more sample databases, you can quickly become more
familiar with InterBase.
Designing Databases
Chapter 2
This chapter provides a general overview of how to design an InterBase database—it is not
intended to be a comprehensive description of the principles of database design. This
chapter includes:
• An overview of basic design issues and goals
• A framework for designing the database
• InterBase-specific suggestions for designing your database
• Suggestions for planning database security
Design goals
Although relational databases are very flexible, the only way to guarantee data integrity
and satisfactory database performance is a solid database design—there is no built-in
protection against poor design decisions. A good database design:
• Satisfies the users’ content requirements for the database. Before you can design the
database, you must do extensive research on the requirements of the users and how the
database will be used.
• Ensures the consistency and integrity of the data. When you design a table, you
define certain attributes and constraints that restrict what a user or an application can
enter into the table and its columns. By validating the data before it is stored in the table,
the database enforces the rules of the data model and preserves data integrity.
• Provides a natural, easy-to-understand structuring of information. Good design
makes queries easier to understand, so users are less likely to introduce inconsistencies
into the data, or to be forced to enter redundant data. This facilitates database updates
and maintenance.
• Satisfies the users’ performance requirements. Good database design ensures better
performance. If tables are allowed to be too large, or if there are too many (or too few)
indexes, long waits can result. If the database is very large with a high volume of
transactions, performance problems resulting from poor design are magnified.
Design framework
The following steps provide a framework for designing a database:
1 Determine the information requirements for the database by interviewing prospective
users.
2 Analyze the real-world objects that you want to model in your database. Organize the
objects into entities and attributes and make a list.
3 Map the entities and attributes to InterBase tables and columns.
4 Determine an attribute that will uniquely identify each object.
5 Develop a set of rules that govern how each table is accessed, populated, and modified.
6 Establish relationships between the objects (tables and columns).
7 Plan database security.
The following sections describe each of these steps in more detail.
Analyzing requirements
The first step in the design process is to research the environment that you are trying to
model. This involves interviewing prospective users in order to understand and document
their requirements. Ask the following types of questions:
• Will your applications continue to function properly during the implementation phase?
Will the system accommodate existing applications, or will you need to restructure
applications to fit the new system?
• Whose applications use which data? Will your applications share common data?
• How do the applications use the data stored in the database? Who will be entering the
data, and in what form? How often will the data objects be changed?
• What access do current applications require? Do your applications use only one
database, or do they need to use several databases which might be different in structure?
What access do they anticipate for future applications, and how easy is it be to
implement new access paths?
• Which information is the most time-critical, requiring fast retrieval or updates?
• Identify certain relationships between the objects For example, how do the
EMPLOYEE, JOB, and DEPARTMENT entities relate to each other? The employee has one
job title and belongs to one department, while a single department has many employees
and jobs. Simple graphical flow charts help to identify the relationships.
Departme
Job Job
Entities Attributes
Last Name
First Name
Department Number
Job Code
Phone Extension
Salary
DEPARTMENT Department Number
Department Name
Budget
Location
Phone Number
PROJECT Project ID
Project Name
Project Description
Team Leader
Product
CUSTOMER Customer Number
Customer Name
Contact Name
Phone Number
Address
Entities Attributes
SALES PO Number
Customer Number
Sales Rep
Order Date
Ship Date
Order Status
By listing the entities and associated attributes this way, you can begin to eliminate
redundant entries. Do the entities in your list work as tables? Should some columns be
moved from one group to another? Does the same attribute appear in several entities? Each
attribute should appear only once, and you need to determine which entity is the primary
owner of the attribute. For example, DEPARTMENT HEAD NAME should be eliminated
because employee names (FIRST NAME and LAST NAME) already exist in the EMPLOYEE
entity. DEPARTMENT HEAD EMPLOYEE NUM can then be used to access all of the
employee-specific information by referencing EMPLOYEE NUMBER in the EMPLOYEE
entity. For more information about accessing information by reference, see “Establishing
relationships between objects” on page 2-10.
The next section describes how to map your lists to actual database objects—entities to
tables and attributes to columns.
Designing tables
In a relational database, the database object that represents a single entity is a table, which
is a two-dimensional matrix of rows and columns. Each column in a table represents an
attribute. Each row in the table represents a specific instance of the entity. After you
identify the entities and attributes, create the data model, which serves as a logical design
framework for creating your InterBase database. The data model maps entities and
attributes to InterBase tables and columns, and is a detailed description of the database—
the tables, the columns, the properties of the columns, and the relationships between tables
and columns.
The example below shows how the EMPLOYEE entity from the entities/attributes list has
been converted to a table.
Each row in the EMPLOYEE table represents a single employee. EMP_NO, LAST_NAME,
FIRST_NAME, DEPT_NO, JOB_CODE, PHONE_EXT, and SALARY are the columns that
represent employee attributes. When the table is populated with data, rows are added to the
table, and a value is stored at the intersection of each row and column, called a field. In the
EMPLOYEE table, “Smith” is a data value that resides in a single field of an employee
record.
Specifying domains
When several tables in the database contain columns with the same definitions and data
types, you can create domain definitions and store them in the database. Users who create
tables can then reference the domain definition to define column attributes locally.
For more information about creating and referencing domains, see Chapter 5, “Working
with Domains.”
Assign a NULL default to insert a NULL into the column if the user does not enter a value.
Assign NOT NULL to force the user to enter a value, or to define a default value for the
column. NOT NULL must be defined for PRIMARY KEY and UNIQUE key columns.
For more information on using PRIMARY KEY and FOREIGN KEY constraints, see Chapter
6, “Working with Tables.”
deleted, set to the column default, or set to null when the primary key is deleted. If you
choose NO ACTION as the ON DELETE action, you must manually delete the foreign key
before deleting the referenced primary key.
• InterBase also prevents users from adding a value in a column defined as a foreign key
that does not reference an existing primary key value. For example, to change a value in
the TEAM_LEADER column of the PROJECT table, that value must first be updated in the
EMP_NO column of the EMPLOYEE table.
For more information on using PRIMARY KEY and FOREIGN KEY constraints, see Chapter
6, “Working with Tables.”
Refer to the DEPARTMENT table. For any occurrence of a given primary key, if a column
can have more than one value, then this set of values is a repeating group. Therefore, the
first row, where DEPT_NO = “100”, contains a repeating group in the DEPT_LOCATIONS
column.
Table 2.5 DEPARTMENT table
DEPT_N HEAD_DEP
O DEPARTMENT T BUDGET DEPT_LOCATIONS
In the next example, even if you change the attribute to represent only one location, for
every occurrence of the primary key “100”, all of the columns contain repeating
information except for DEPT_LOCATION, so this is still a repeating group.
Table 2.6 DEPARTMENT table
DEPT_NO DEPARTMENT HEAD_DEPT BUDGET DEPT_LOCATION
To normalize this table, we could eliminate the DEPT_LOCATION attribute from the
DEPARTMENT table, and create another table called DEPT_LOCATIONS. We could then
create a primary key that is a combination of DEPT_NO and DEPT_LOCATION. Now a
distinct row exists for each location of the department, and we have eliminated the
repeating groups.
100 Monterey
100 Salinas
The problem with this table is that PROJ_NAME, PROJ_DESC, and PRODUCT are attributes
of PROJ_ID, but not EMP_NO, and are therefore only partially dependent on the EMP_NO/
PROJ_ID primary key. This is also true for LAST_NAME because it is an attribute of
EMP_NO, but does not relate to PROJ_ID. To normalize this table, we would remove the
EMP_NO and LAST_NAME columns from the PROJECT table, and create another table called
EMPLOYEE_PROJECT that has EMP_NO and PROJ_ID as a composite primary key. Now a
unique row exists for every project that an employee is assigned to.
Choosing indexes
Once you have your design, you need to consider what indexes are necessary. The basic
trade-off with indexes is that more distinct indexes make retrieval by specific criteria
faster, but updating and storage slower. One optimization is to avoid creating several
indexes on the same column. For example, if you sometimes retrieve employees based on
name, department, badge number, or department name, you should define one index for
each of these columns. If a query includes more than one column value to retrieve,
InterBase will use more than one index to qualify records. In contrast, defining indexes for
every permutation of those three columns will actually slow both retrieval and update
operations.
When you are testing your design to find the optimum combination of indexes, remember
that the size of the tables affects the retrieval performance significantly. If you expect to
have tables with 10,000 to 100,000 records each, do not run tests with only 10 to 100
records.
Another factor that affects index and data retrieval times is page size. By increasing the
page size, you can store more records on each page, thus reducing the number of pages
used by indexes. If any of your indexes are more than 4 levels deep, you should consider
increasing the page size. If indexes on volatile data (data that is regularly deleted and
restored, or data that has index key values that change frequently) are less than three levels
deep, you should consider reducing your page size. In general, you should use a page size
larger than your largest record, although InterBase’s data compression will generally shrink
records that contain lots of string data, or lots of numeric values that are 0 or NULL. If
your records have those characteristics, you can probably store records on pages which are
20% smaller than the full record size. On the other hand, if your records are not
compressible, you should add 5% to the actual record size when comparing it to the page
size.
For more information on creating indexes, see Chapter 7, “Working with Indexes.”
recommended because it affects all databases on the server and can easily result in overuse
of memory or in small caches, that are un-usable. It’s is better to tune your cache on a per-
database basis using gfix -buffers.
For more information about cache size, see the Embedded SQL Guide. For more
information about using gfix -buffers, see the Operations Guide.
Planning security
Planning security for a database is important. When implementing the database design, you
should answer the following questions:
• Who will have authority to use InterBase?
• Who will have authority to open a particular database?
• Who will have authority to create and access a particular database object within a given
database?
For more information about database security, see Chapter 12, “Planning Security.”
Naming Objects
Valid names for InterBase objects must use the 7-bit ASCII character set (character set ID
2) and must have the following characteristics:
• no spaces
• not case sensitive
• not InterBase keywords
• a maximum of 68 bytes long: 67 bytes plus a null terminator
Using delimited identifiers You create metadata names that are case sensitive, can
contain spaces, and can be InterBase keywords by placing them double quotes. Such names
in double quotes are called delimited identifiers.
Tip When you use an object name without double quotes, InterBase maps all the characters to
uppercase. For example, if you create a table with a double-quote delimited name in all
uppercase, you can use the name subsequently without double quotes. For example:
CREATE TABLE “UPPERCASE_NAME”...
Creating Databases
Chapter 3
• How large you expect the database to grow. The number of records also affects the page
size because the number of pages affects the depth of the index tree. Larger page size
means fewer total pages. InterBase operates more efficiently with a shallow index tree.
• The number of users that will be accessing the database.
Creating a database
Create a database in isql with an interactive command or with the CREATE DATABASE
statement in an isql script file. For a description of creating a database interactively with
IBConsole, see the Operations Guide.
Although you can create, alter, and drop a database interactively, it is preferable to use a
data definition file because it provides a record of the structure of the database. It is easier
to modify a source file than it is to start over by retyping interactive SQL statements.
Important In DSQL, CREATE DATABASE can be executed only with EXECUTE IMMEDIATE. The
database handle and transaction name, if present, must be initialized to zero prior to use.
The syntax for CREATE DATABASE is:
CREATE {DATABASE | SCHEMA} 'filespec'
[USER 'username' [PASSWORD 'password']]
[PAGE_SIZE [=] int]
[LENGTH [=] int [PAGE[S]]]
[DEFAULT CHARACTER SET charset]
[<secondary_file>]
[WITH ADMIN OPTION];
<secondary_file> = FILE 'filespec' [<fileinfo>] [<secondary_file>]
<fileinfo> = LENGTH [=] int [PAGE[S]] | STARTING [AT [PAGE]] int
[<fileinfo>]
Important Use single quotes to delimit strings such as file names, user names, and passwords.
The following example produces exactly the same results as the previous one, but uses a
mixture of LENGTH and STARTING AT:
CREATE DATABASE 'employee.ib'
FILE 'employee2.ib' STARTING AT 10001 LENGTH 10000 PAGES
FILE 'employee3.ib' LENGTH 10000 PAGES
FILE 'employee4.ib';
Read-only databases
By default, databases are in read-write mode at creation time. Such databases must be on a
writable file system even if they are used only for SELECT, because InterBase writes
information about transaction states to a data structure in the database file.
You have the option of changing a database to read-only mode. Such databases can reside
on read-only file systems, such as CD-ROMs. To change the mode of a database to read-
only, you can either use gfix (or the equivalent choice in IBConsole), or you can back up
the database and restore it in read-only mode. See the Operations Guide for details on
how to change the mode of a database using gfix, gbak, or IBConsole.
Altering a database
Use ALTER DATABASE to add one or more secondary files to an existing database.
Secondary files are useful for controlling the growth and location of a database. They
permit database files to be spread across storage devices, but must remain on the same
node as the primary database file. For more information on secondary files, see “Creating
a multifile database” on page 3-4.
A database can be altered by its creator, the SYSDBA user, and any users with operating
system root privileges.
ALTER DATABASE requires exclusive access to the database. For more information about
exclusive database access, see “Shutting down and restarting databases” in the “Database
Configuration and Maintenance” chapter of the Operations Guide.
The syntax for ALTER DATABASE is:
ALTER {DATABASE | SCHEMA}
{ADD add_clause | DROP drop_clause | SET set_clause};
add_clause = FILE 'filespec' [fileinfo] [add_clause] | ADMIN OPTION
<fileinfo> = {LENGTH [=] int [PAGE[S]] | STARTING [AT [PAGE]] int }[<fileinfo>]
drop_clause = ADMIN OPTION
set_clause = {FLUSH INTERVAL <number> | NO FLUSH INTERVAL | GROUP
COMMINT | NO GROUP COMMIT | LINGER INTERVAL <number> | NO LINGER
INTERVAL | RECLAIM INTERVAL <number> | NO RECLAIM INTERVAL}
You must specify a range of pages for each file either by providing the number of pages in
each file, or by providing the starting page number for the file.
Note It is never necessary to specify a length for the last—or only—file, because InterBase
always dynamically sizes the last file and will increase the file size as necessary until all
the available space is used.
The first example adds two secondary files to the currently connected database by
specifying the starting page numbers:
ALTER DATABASE
ADD FILE 'employee2.ib' STARTING AT PAGE 10001
ADD FILE 'employee3.ib' STARTING AT PAGE 20001
The next example does nearly the same thing as the previous example, but it specifies the
secondary file length rather than the starting page number. The difference is that in the
previous example, the original file will grow until it reaches 10000 pages. In the second
example, InterBase starts the secondary file at the next available page and begins using it
immediately.
ALTER DATABASE
ADD FILE 'employee2.ib' LENGTH 10000
ADD FILE 'employee3.ib'
Dropping a database
DROP DATABASE is the command that deletes the database currently connected to,
including any associated shadow and log files. Dropping a database deletes any data it
contains. A database can be dropped by its creator, the SYSDBA user, and any users with
operating system root privileges.
The following statement deletes the current database:
DROP DATABASE;
Advantages of shadowing
Shadowing offers several advantages:
• Recovery is quick: Activating a shadow makes it available immediately.
Limitations of shadowing
Shadowing has the following limitations:
• Shadowing is useful only for recovery from hardware failures or accidental deletion of
the database. User errors or software failures that corrupt the database are duplicated in
the shadow.
• Recovery to a specific point in time is not possible. When a shadow is activated, it takes
over as a duplicate of the database. Shadowing is an “all or nothing” recovery method.
• Shadowing can occur only to a local disk. InterBase does not support shadowing to an
NFS file system, mapped drive, tape, or other media.
Shadow location
On non-NFS systems, which includes all Microsoft Windows machines, the shadow must
reside on the same host as the database. You cannot specify a different host name or a
mapped drive as the location of the shadow.
On UNIX systems, it is possible to place the shadow on any NFS-mounted directory, but
you run the risk of losing the shadow if you experience problems with NFS, so this is not a
recommended procedure.
shadowing. If a shadow becomes unavailable, and it was created in MANUAL mode, further
access to the database is denied until the database administrator intervenes. The benefits of
AUTO mode and MANUAL mode are compared in the following table:
Table 3.1 Auto vs. manual shadows
Auto mode
The AUTO keyword directs the CREATE SHADOW statement to create a shadow in AUTO
mode:
CREATE SHADOW 1 AUTO 'employee.shd';
Auto mode is the default, so omitting the AUTO keyword achieves the same result.
In AUTO mode, database operation continues even if the shadow becomes inoperable. If the
original shadow was created as a conditional shadow, a new shadow is automatically
created. If the shadow was not conditional, you must create a new shadow manually. For
more information about conditional shadows, see “Conditional shadows” on
page 3-12.
Manual mode
The MANUAL keyword directs the CREATE SHADOW statement to create a shadow in
manual mode:
CREATE SHADOW 1 MANUAL 'employee.shd';
Manual mode is useful when continuous shadowing is more important than continuous
operation of the database. When a manual-mode shadow becomes unavailable, further
connections to the database are prevented. To allow database connections again, the
database administrator must remove the old shadow file, delete references to it, and create
a new shadow.
Conditional shadows
A shadow can be defined so that if it replaces a database, a new shadow will be
automatically created, allowing shadowing to continue uninterrupted. A shadow defined
with this behavior is called a conditional shadow.
To create a conditional shadow, specify the CONDITIONAL keyword with the CREATE
SHADOW statement. For example:
Creating a conditional file directs InterBase to automatically create a new shadow. This
happens in either of two cases:
• The database or one of its shadow files becomes unavailable.
• The shadow takes over for the database due to hardware failure.
Dropping a shadow
To stop shadowing, use the shadow number as an argument to the DROP SHADOW
statement. DROP SHADOW deletes shadow references from a database’s metadata, as well
as the physical files on disk.
A shadow can be dropped by its creator, the SYSDBA user, or any user with operating
system root privileges.
DROP SHADOW syntax
DROP SHADOW set_num;
The following example drops all of the files associated with the shadow set
number 1:
DROP SHADOW 1;
If you need to look up the shadow number, use the isql command SHOW DATABASE.
SHOW DATABASE;
Database: employee.ib
Shadow 1: 'employee.shd' auto
PAGE_SIZE 1024
Number of DB pages allocated = 392
Sweep interval = 20000
The page length allocated for secondary shadow files need not correspond to the page
length of the database’s secondary files. As the database grows and its first shadow file
becomes full, updates to the database automatically overflow into the next shadow file.
DECIMAL (precision, scale) Variable • precision = 1 to 18; specifies • Number with a decimal point
(16, 32, or at least precision digits of scale digits from the right
64 bits) precision to store • Example: DECIMAL(10, 3)
• scale = 0 to 18; specifies holds numbers accurately in
number of decimal places must the following format:
be less than or equal to ppppppp.sss
precision
DOUBLE PRECISION 64 bitsa 2.225 x 10–308 to 1.797 x 10308 IEEE double precision: 15 digits
FLOAT 32 bits 1.175 x 10–38 to 3.402 x 1038 IEEE single precision: 7 digits
NUMERIC (precision, scale) Variable (16, • precision = 1 to 18; specifies • Number with a decimal point
32, or exactly precision digits of scale digits from the right
64 bits) precision to store • Example: NUMERIC(10,3)
• scale = 0 to 18; specifies holds numbers accurately in
number of decimal places and the following format:
must be less than or equal to ppppppp.sss
precision
a. Actual size of DOUBLE is platform-dependent. Most platforms support the 64-bit size.
• Conversions. When performing arithmetic operations that involve mixed data types,
InterBase automatically converts between INTEGER, FLOAT, and CHAR data types. For
operations that involve comparisons of numeric data with other data types, InterBase
first converts the data to a numeric type, then performs the arithmetic operation or
comparison.
• Sorts. By default, a query retrieves rows in the exact order that it finds them in the table,
which is likely to be unordered. You can sort rows using the ORDER BY clause of a
SELECT statement in descending or ascending order.
declares that a column of this type must be capable of holding at least five but possibly
more digits and exactly two digits to the right of the decimal point: ppp.ss.
Table 4.2 NUMERIC and DECIMAL data type storage: dialects 1 and 3
5 to 9 INTEGER INTEGER
NUMERIC and DECIMAL data types with precision greater than 10 always produce an error
when you create a dialect 2 database. This forces you to examine each instance during a
migration. For more about migrating exact numerics, see “Migrating databases with
NUMERIC and DECIMAL data types” on page 4-8. For a broader discussion of
migration issues, see the migration appendix in the InterBase Operations Guide.
The following table summarizes how InterBase stores NUMERIC and
DECIMAL data types based on precision and scale:
Table 4.3 NUMERIC and DECIMAL data type storage based on precision and scale
NUMERIC INTEGER
NUMERIC(4) SMALLINT
NUMERIC(9) INTEGER
NUMERIC(4,2) SMALLINT
NUMERIC(9,3) INTEGER
Table 4.3 NUMERIC and DECIMAL data type storage based on precision and scale
DECIMAL(4) INTEGER
DECIMAL(9) INTEGER
DECIMAL(9,3) INTEGER
• In many cases, the answer is “yes.” If you want to continue to store your data as
DOUBLE PRECISION, change the audiotape of the column to DOUBLE PRECISION
either before or after migrating your database to dialect 3. This doesn’t change any
functionality in dialect 3, but it brings the declaration into line with the storage mode.
In a dialect 3 database, newly-created columns of this type are stored as INT64, but
migrated columns are still stored as DOUBLE PRECISION. Changing the declaration
avoids confusion.
• DOUBLE PRECISION might not be appropriate or desirable for financial applications
and others that are sensitive to rounding errors. In this case, you need to take steps to
migrate your column so that it is stored as INT64 in dialect 3. As you make this
decision, remember that INT64 does not store the same range as DOUBLE PRECISION.
Check whether you will lose information in this conversion and whether this is
acceptable.
1 Back up your original database. Read the “migration” appendix in the Operations
Guide to determine what preparations you need to make before migrating the database.
Typically, this includes detecting metadata that uses double quotes around strings. After
making necessary preparations as indicated in the migration chapter, back up the
database using its current gbak version and restore it using the latest InterBase.
2 Use gfix -set_db_SQL_dialect 3 to change the database to dialect 3
3 Use the ALTER COLUMN clause of the ALTER DATABASE statement to change the name
of each affected column to something different from its original name. If column
position is going to be an issue with any of your clients, use ALTER COLUMN to change
the positions as well.
4 Create a new column for each one that you are migrating. Use the original column
names and if necessary, positions. Declare each one as a DECIMAL or NUMERIC with
precision greater than 9.
5 Use UPDATE to copy the data from each old column to its corresponding new column:
UPDATE tablename
SET new_col_name = old_col_name;
6 Check that your data has been successfully copied to the new columns and drop the old
columns.
The following CREATE TABLE statement provides an example of how the different numeric
types can be used: an INTEGER for the total number of orders, a fixed DECIMAL for the
dollar value of total sales, and a FLOAT for a discount rate applied to the sale.
CREATE TABLE SALES
(. . .
QTY_ORDERED INTEGER
DEFAULT 1
CHECK (QTY_ORDERED >= 1),
TOTAL_VALUE DECIMAL (9,2)
CHECK (TOTAL_VALUE >= 0),
DISCOUNT FLOAT
DEFAULT 0
CHECK (DISCOUNT >= 0 AND DISCOUNT <= 1));
The following examples specify a CHAR data type using the UNICODE_FSS character set,
which has a maximum size of three bytes for a single character:
CHAR (10922) CHARACTER SET UNICODE_FSS; /* succeeds */
CHAR (10923) CHARACTER SET UNICODE_FSS; /* fails */
data into another column that has been defined with a different character set. No
transliteration will be performed between the source and destination character sets, so in
most cases, errors will occur during the attempted assignment.
For example:
CREATE TABLE MYDATA (PART_NUMBER CHARACTER(30) CHARACTER SET NONE);
SET NAMES LATIN1;
INSERT INTO MYDATA (PART_NUMBER) VALUES('à');
SET NAMES DOS437;
SELECT * FROM MYDATA;
The data (“à”) is returned just as it was entered, without the à being transliterated from the
input character (LATIN1) to the output character (DOS437). If the column had been set to
anything other than NONE, the transliteration would have occurred.
CHAR(n) or CHARACTER(n)
The CHAR(n) or CHARACTER(n) data type contains character strings. The number of
characters n is fixed. For the maximum number of characters allowed for the character set
that you have specified, see Chapter 14, “Character Sets and Collation Orders.”
When the string to be stored or read contains less than n characters, InterBase fills in the
blanks to make up the difference. If a string is larger than n, then the value is truncated. If
you do not supply n, it will default to 1, so CHAR is the same as CHAR(1). The next
statement illustrates this:
CREATE TABLE SALES
(. . .
PAID CHAR
DEFAULT 'n'
CHECK (PAID IN ('y', 'n'), …);
Trailing blanks InterBase compresses trailing blanks when it stores fixed-length strings,
so data with trailing blanks uses the same amount of space as an equivalent variable-length
string. When the data is read, InterBase reinserts the blanks. This saves disk space when
the length of the data items varies widely.
Note InterBase provides SQL syntax that allows you to use BLOBs and VARCHAR data
interchangeably. For more information, see “Using BLOBs with VARCHAR data.”
VARCHAR(n)
VARCHAR(n)—also called CHAR VARYING(n), or CHARACTER VARYING(n)—allows you to
store the exact number of characters that is contained in your data, up to a maximum of n.
You must supply n; there is no default to 1.
If the length of the data within a column varies widely, and you do not want to pad your
character strings with blanks, use the VARCHAR(n) or CHARACTER VARYING(n) data type.
InterBase converts from variable-length character data to fixed-length character data by
adding spaces to the value in the varying column until the column reaches its maximum
length n. When the data is read, InterBase removes the blanks.
The main advantages of using the VARCHAR(n) data type are that it saves disk space, and
since more rows fit on a disk page, the database server can search the table with fewer disk
I/O operations. The disadvantage is that table updates can be slower than using a fixed-
length column in some cases.
The next statement illustrates the VARCHAR(n) data type:
CREATE TABLE SALES
(…
ORDER_STATUS VARCHAR(7)
DEFAULT 'new'
NOT NULL
CHECK (ORDER_STATUS IN ('new', 'open',
'shipped', 'waiting')), …);
NCHAR VARYING(n)
NCHAR VARYING(n)—also called NATIONAL CHARACTER VARYING (n) or NATIONAL
CHAR VARYING(n)—is exactly the same as VARCHAR(n), except that the ISO8859_1
character set is used. Using NCHAR VARYING(n) is a shortcut for using the CHARACTER
SET clause of CREATE TABLE, CREATE DOMAIN, or ALTER TABLE to specify the
ISO8859_1 character set.
In ISQL and IBConsole, the output for a BOOLEAN, regardless of values given, is always
TRUE, FALSE or UNKNOWN. However, using API function calls, UNKNOWN is treated as
NULL, TRUE returns 1, and FALSE returns 0.
Note InterBase looks for Booleans of the form “literal <relop> literal” that evaluate to FALSE and
returns a false Boolean inversion node to short-circuit data retrieval.
Examples The following code illustrates the use of the BOOLEAN data type:
CREATE TABLE AWARDS_1 (isEligible BOOLEAN, name VARCHAR(20));
INSERT INTO AWARDS_1 VALUES (TRUE, 'Jim Smith');
INSERT INTO AWARDS_1 VALUES (FALSE, 'John Buttler');
SELECT * FROM AWARDS_1;
ISELIGIBLE NAME
========== ====================
TRUE Jim Smith
FALSE John Buttler
SELECT * FROM AWARDS_1 WHERE isEligible = TRUE;
ISELIGIBLE NAME
========== ====================
TRUE Jim Smith
SELECT * FROM AWARDS_1 WHERE isEligible;
ISELIGIBLE NAME
========== ====================
TRUE Jim Smith
SELECT * FROM AWARDS_1 WHERE NOT isEligible;
ISELIGIBLE NAME
========== ====================
FALSE John Buttler
Example 2:
SELECT * FROM AWARDS_1 WHERE isEligible = TRUE;
BLOB columns
You define BLOB columns in database tables just as you do non-BLOB columns. For
example, the following statement creates a table with a BLOB column:
CREATE TABLE PROJECT
(PROJ_ID PROJNO NOT NULL,
PROJ_NAME VARCHAR(20) NOT NULL UNIQUE,
PROJ_DESC BLOB,
TEAM_LEADER EMPNO,
PRODUCT PRODTYPE,
. . .);
Rather than storing BLOB data directly, a BLOB column stores a BLOB ID. A BLOB ID is a
unique numeric value that references BLOB data. The BLOB data is stored elsewhere in the
database, in a series of BLOB segments, which are units of BLOB data that are read and
written in chunks. InterBase writes data to a BLOB one segment at a time. Similarly, it reads
a BLOB one segment at a time.
The following diagram shows the relationship between a BLOB column containing a BLOB
ID and the BLOB data referenced by the BLOB ID:
BLOB
column
Table row … BLOB ID …
Segment syntax
The following statement creates two BLOB columns, BLOB1, with a default segment size
of 80, and BLOB2, with a specified segment length of 512:
CREATE TABLE TABLE2
(BLOB1 BLOB,
BLOB2 BLOB SEGMENT SIZE 512);
BLOB subtypes
When you define a BLOB column, you have the option of specifying a subtype. A BLOB
subtype is a positive or negative integer that describes the nature of the BLOB data
contained in the column. InterBase provides two predefined subtypes, 0, signifying that a
BLOB contains binary data, the default, and 1, signifying that a BLOB contains ASCII text.
User-defined subtypes must always be represented as negative integers. Positive integers
are reserved for use by InterBase.
Table 4.4 Blob subtypes
Blob
subtype Description
1 Text
Note TEXT is a keyword and can be used in a BLOB column declaration instead of the subtype
number.
For example, the following statement defines three BLOB columns: BLOB1 with subtype 0
(the default), BLOB2 with InterBase subtype 1 (TEXT), and BLOB3 with user-defined
subtype –1:
CREATE TABLE TABLE2
(BLOB1 BLOB,
BLOB2 BLOB SUB_TYPE 1,
BLOB3 BLOB SUB_TYPE –1);
The application is responsible for ensuring that data stored in a BLOB column agrees with
its subtype. For example, if subtype –10 denotes a certain data type in a particular
application, then the application must ensure that only data of that data type is written to a
BLOB column of subtype –10. InterBase does not check the type or format of BLOB data.
To specify both a default segment length and a subtype when creating a BLOB column, use
the SEGMENT SIZE option after the SUB_TYPE option, as in the following example:
CREATE TABLE TABLE2
(BLOB1 BLOB SUB_TYPE 1 SEGMENT SIZE 100 CHARACTER SET DOS437);
BLOB filters
BLOB subtypes are used in conjunction with BLOB filters. A BLOB filter is a routine that
translates BLOB data from one subtype to another. InterBase includes a set of special
internal BLOB filters that convert from subtype 0 to subtype 1 (TEXT), and from InterBase
system subtypes to subtype 1 (TEXT). In addition to using the internal text filters,
programmers can write their own external filters to provide special data translation. For
example, an external filter might automatically translate from one bit-mapped image
format to another.
Note Associated with every filter is an integer pair that specifies the input subtype and the output
subtype. When declaring a cursor to read or write BLOB data, specify FROM and TO
subtypes that correspond to a particular BLOB filter. InterBase invokes the filter based on
the FROM and TO subtype specified by the read or write cursor declaration.
The display of BLOB subtypes in isql can be specified with SET BLOBDISPLAY in
command-line isql or with the Session | Advanced Settings command in Windows ISQL.
For more information about Windows ISQL and command-line isql, see the Operations
Guide. For more information about creating external BLOB filters, see the Embedded
SQL Guide.
To make text blobs interchangeable with VARCHAR data, you can use the following SQL
syntax:
INSERT INTO <table-name> values (<text values>, ….);
UPDATE <table_name> set <blob column name> = <text value>;
And:
In addition, store procedures which accept a BLOB can now accept a text value as a
parameter and implicitly be converted to a text blob. For example:
CREATE PROCEDURE MYTEST (AINT INTEGER, INBLOB BLOB)
AS
Declare variable var_blob blob;
begin
insert
var_blob
You can use the SELECT CAST, UPDATE, and INSERT INTO statements with the
InterBase Client APIs. In such cases, InterBase returns the values as C structures.
Specifically, the returned XSQLVARS would be of the type SQLVARYING, with the
length of the text followed by the text data.
The following example demonstrates the use of the new SQL syntax for text BLOBs.
Example
/* Same syntax to create a table... */
/* Note all sub-types are supported; SUB_TYPE 1 forces conversion
*/
/* to the column’s character data type. */
CREATE TABLE BLOB_TEST (B_ID INT, BLOB_CL BLOB SUB_TYPE 1);
COMMIT;
/* New functionality for the INSERT statement... */
INSERT INTO BLOB_TEST VALUES (1, ‘Fellowship of the Ring’);
INSERT INTO BLOB_TEST VALUES (2, ‘The Two Towers’);
INSERT INTO BLOB_TEST VALUES (3, ‘Return of the Jedi’);
/* New syntax for UPDATE... */
UPDATE BLOB_TEST SET BLOB_CL=’Return of the King’ WHERE B_ID=3;
COMMIT;
/* New syntax for SELECT. The BLOB will be returned as a TEXT
string. */
SELECT B_ID, CAST (BLOB_CL AS VARCHAR(25)) FROM BLOB_TEST;
B_ID BLOB_CL
Defining arrays
InterBase allows you to create arrays of data types. Using an array enables multiple data
items to be stored in a single column. InterBase can perform operations on an entire array,
effectively treating it as a single element, or it can operate on an array slice, a subset of
array elements. An array slice can consist of a single element, or a set of many contiguous
elements.
Using an array is appropriate when:
• The data items naturally form a set of the same data type.
• The entire set of data items in a single database column must be represented and
controlled as a unit, as opposed to storing each item in a separate column.
• Each item must also be identified and accessed individually.
The data items in an array are called array elements. An array can contain elements of any
InterBase data type except BLOB, and cannot be an array of arrays. All of the elements of a
particular array are of the same data type.
Arrays are defined with the CREATE DOMAIN or CREATE TABLE statements. Defining an
array column is just like defining any other column, except that the array dimensions must
also be specified. For example, the following statement defines both a regular character
column, and a single-dimension, character array column containing four elements:
EXEC SQL
CREATE TABLE TABLE1
(NAME CHAR(10),
CHAR_ARR CHAR(10)[4]);
Array dimensions are always enclosed in square brackets following a column’s data type
specification.
For a complete discussion of CREATE TABLE and array syntax, see the Language
Reference. To learn more about the flexible data access provided by arrays, see the
Embedded SQL Guide.
Multi-dimensional arrays
InterBase supports multi-dimensional arrays, arrays with 1 to 16 dimensions. For example,
the following statement defines three INTEGER array columns with two, three, and four
dimensions respectively:
EXEC SQL
CREATE TABLE TABLE1
(INT_ARR2 INTEGER[4,5],
INT_ARR3 INTEGER[4,5,6],
INT_ARR4 INTEGER[4,5,6,7]);
In this example, INT_ARR2 allocates storage for 4 rows, 5 elements in width, for a total of
20 integer elements, INT_ARR3 allocates 120 elements, and INT_ARR4 allocates 840
elements.
Important InterBase stores multi-dimensional arrays in row-major order. Some host languages, such
as FORTRAN, expect arrays to be in column-major order. In these cases, care must be taken
to translate element ordering correctly between InterBase and the host language.
When creating multi-dimensional arrays with explicit array boundaries, separate each
dimension’s set of subscripts from the next with commas. For example, the following
statement creates a table with a two-dimensional array column where each dimension has
four elements with boundaries of 0 and 3:
EXEC SQL
CREATE TABLE TABLE1
(INT_ARR INTEGER[0:3, 0:3]);
Decimal 20
Double 22
Float 13
Integer 11
Numeric 22
Smallint 6
Creating domains
When you create a table, you can use a global column definition, called a domain, to define
a column locally. Before defining a column that references a domain, you must first create
the domain definition in the database with CREATE DOMAIN. CREATE DOMAIN acts as a
template for defining columns in subsequent CREATE TABLE and ALTER TABLE statements.
For more information on creating and modifying tables, see Chapter 6, “Working with
Tables.”
Domains are useful when many tables in a database contain identical column definitions.
Columns based on a domain definition inherit all characteristics of the domain; some of
these attributes can be overridden by local column definitions.
Note You cannot apply referential integrity constraints to a domain.
When you create a domain in the database, you must specify a unique name for the domain
and specify the data type. Optionally, you provide default values and NULL status, CHECK
constraints, and a collation order.
The syntax for CREATE DOMAIN is:
CREATE DOMAIN domain [AS] <datatype>
[DEFAULT {literal | NULL | USER}]
[NOT NULL] [CHECK (<dom_search_condition>)]
[COLLATE collation];
• A BLOB data type to represent unstructured binary data, such as graphics and digitized
voice.
• Arrays of data types (except for BLOB data).
See Table 4.1 on page 4-2 for a complete list and description of data types that InterBase
supports.
For more information about data types, see Chapter 4, “Specifying Data types.”
The following statement creates a domain that defines an array of CHARACTER data type:
CREATE DOMAIN DEPTARRAY AS CHAR(67) [4:5];
The next statement creates a BLOB domain with a text subtype that has an assigned
character set:
The following statement creates a domain that must have a positive value greater than
1,000, with a default value of 9,999.
CREATE DOMAIN CUSTNO
AS INTEGER
DEFAULT 9999
CHECK (VALUE > 1000);
The next statement limits the values entered in the domain to four specific values:
CREATE DOMAIN PRODTYPE
AS VARCHAR(12)
CHECK (VALUE IN ('software', 'hardware', 'other', 'N/A'));
When a problem cannot be solved using comparisons, you can instruct the system to search
for a specific pattern in a character column. For example, the next search condition allows
only cities in California to be entered into columns that are based on the CALIFORNIA
domain:
CREATE DOMAIN CALIFORNIA
AS VARCHAR(25)
CHECK (VALUE LIKE '%, CA');
Altering domains
ALTER DOMAIN changes any aspect of an existing domain except its NOT NULL setting.
Changes that you make to a domain definition affect all column definitions based on the
domain that have not been overridden at the table level.
Note To change the NOT NULL setting of a domain, drop the domain and recreate it with the
desired combination of features.
A domain can be altered by its creator, the SYSDBA user, and any users with operating
system root privileges.
ALTER DOMAIN allows you to:
Dropping a domain
DROP DOMAIN removes an existing domain definition from a database.
If a domain is currently used in any column definition in the database, the DROP operation
fails. To prevent failure, delete the columns based on the domain with ALTER TABLE before
executing DROP DOMAIN.
A domain can be dropped by its creator, the SYSDBA, and any users with operating
system root privileges.
Creating tables
You can create tables in the database with the CREATE TABLE statement. The syntax for
CREATE TABLE is:
Defining columns
When you create a table in the database, your main task is to define the various attributes
and constraints for each of the columns in the table. The syntax for defining a column is:
<col_def> = col {datatype | COMPUTED [BY] (<expr>) | domain}
[DEFAULT {literal | NULL | USER}]
[NOT NULL] [<col_constraint>]
[COLLATE collation]
The next sections list the required and optional attributes that you can define for a column.
Required attributes
You are required to specify:
• A column name, which must be unique among the columns in the table.
• One of the following:
• A SQL data type (datatype).
• An expression (expr) for a computed column.
• A domain definition (domain) for a domain-based column.
Optional attributes
You have the option to specify:
• A default value for the column.
• Integrity constraints. Constraints can be applied to a set of columns (a table-level
constraint), or to a single column (a column-level constraint). Integrity constraints
include:
• The PRIMARY KEY column constraint, if the column is a PRIMARY KEY, and the
PRIMARY KEY constraint is not defined at the table level. Creating a PRIMARY KEY
requires exclusive database access.
• The UNIQUE constraint, if the column is not a PRIMARY KEY, but should still disallow
duplicate and NULL values.
• The FOREIGN KEY constraint, if the column references a PRIMARY KEY in another
table. Creating a FOREIGN KEY requires exclusive database access. The foreign key
constraint includes the ON UPDATE and ON DELETE mechanisms for specifying what
happens to the foreign key when the primary key is updated (cascading referential
integrity).
• A NOT NULL attribute does not allow NULL values. This attribute is required if the
column is a PRIMARY KEY or UNIQUE key.
• A CHECK constraint for the column. A CHECK constraint enforces a condition that must
be true before an insert or an update to a column or group of columns is allowed.
• A CHARACTER SET can be specified for a single column when you define the data type.
If you do not specify a character set, the column assumes the database character set as a
default.
In the following statement, BOOKNO keeps the default collating order for the database’s
default character set. The second (TITLE) and third (EUROPUB) columns specify different
character sets and collating orders.
CREATE TABLE BOOKADVANCE (BOOKNO CHAR(6),
TITLE CHAR(50) CHARACTER SET DOS437 COLLATE PDOX_INTL,
EUROPUB CHAR(50) CHARACTER SET ISO8859_1 COLLATE FR_FR);
For a list of the available characters sets and collation orders that InterBase recognizes, see
Chapter 14, “Character Sets and Collation Orders.”
The next example creates a table with a calculated column (NEW_SALARY) using the
previously created EMPNO and SALARY domains.
CREATE TABLE SALARY_HISTORY (EMP_NO EMPNO NOT NULL,
CHANGE_DATE DATE DEFAULT 'NOW' NOT NULL,
UPDATER_ID VARCHAR(20) NOT NULL,
OLD_SALARY SALARY NOT NULL,
PERCENT_CHANGE DOUBLE PRECISION
DEFAULT 0
NOT NULL
CHECK (PERCENT_CHANGE BETWEEN –50 AND 50),
NEW_SALARY COMPUTED BY
(OLD_SALARY + OLD_SALARY * PERCENT_CHANGE / 100),
PRIMARY KEY (EMP_NO, CHANGE_DATE, UPDATER_ID),
FOREIGN KEY (EMP_NO) REFERENCES EMPLOYEE (EMP_NO)
ON UPDATE CASCADE
ON DELETE CASCADE);
Note Constraints on computed columns are not enforced, but InterBase does not return an error
if you do define such a constraint.
In the EMPLOYEE table, EMP_NO is the primary key that uniquely identifies each employee.
EMP_NO is the primary key because no two values in the column are alike. If the EMP_NO
column did not exist, then no other column is a candidate for primary key due to the high
probability for duplication of values. LAST_NAME, FIRST_NAME, and JOB_TITLE fail
because more than one employee can have the same first name, last name, and job title. In
a large database, a combination of LAST_NAME and FIRST_NAME could still result in
duplicate values. A primary key that combines LAST_NAME and PHONE_EXT might work,
but there could be two people with identical last names at the same extension. In this table,
the EMP_NO column is actually the only acceptable candidate for the primary key because
it guarantees a unique number for each employee in the table.
A table can have only one primary key. If you define a PRIMARY KEY constraint at the table
level, you cannot do it again at the column level. The reverse is also true; if you define a
PRIMARY KEY constraint at the column level, you cannot define a primary key at the table
level. You must define the NOT NULL attribute for a PRIMARY KEY column in order to
preserve the uniqueness of the data values in that column.
Like primary keys, a unique key ensures that no two rows have the same value for a
specified column or ordered set of columns. You must define the NOT NULL attribute for a
UNIQUE column. A unique key is different from a primary key in that the UNIQUE
constraint specifies alternate keys that you can use to uniquely identify a row. You can have
more than one unique key defined for a table, but the same set of columns cannot make up
more than one PRIMARY KEY or UNIQUE constraint for a table. Like a primary key, a
unique key can be referenced by a foreign key in another table.
The primary reason for defining foreign keys is to ensure that data integrity is maintained
when more than one table uses the same data: rows in the referencing table must always
have corresponding rows in the referenced table.
InterBase enforces referential integrity in the following ways:
• The unique or primary key columns must already be defined before you can create the
foreign key that references them.
• Referential integrity checks are available in the form of the ON UPDATE and ON DELETE
options to the REFERENCES statement. When you create a foreign key by defining a
column or table REFERENCES constraint, you can specify what should happen to the
foreign key when the referenced primary key changes. The options are:
Table 6.4 Referential integrity check options
Action
specified Effect on foreign key
RESTRICT [Default]
NO ACTION The foreign key does not change (can cause the primary key update or
delete to fail due to referential integrity checks)
CASCADE The corresponding foreign key is updated or deleted as appropriate to the
new value of the primary key
SET DEFAULT Every column of the corresponding foreign key is set to its default value;
fails if the default value of the foreign key is not found in the primary key
SET NULL Every column of the corresponding foreign key is set to NULL
• If you do not use the ON UPDATE and ON DELETE options when defining foreign keys,
you must make sure that when information changes in one place, it changes in all
referencing columns as well. Typically, you write triggers to do this. For example, to
change a value in the EMP_NO column of the EMPLOYEE table (the primary key), that
value must also be updated in the TEAM_LEADER column of the PROJECT table (the
foreign key).
• If you delete a row from a table that is a primary key, you must first delete all foreign
keys that reference that row. If you use the ON DELETE CASCADE option when defining
the foreign keys, InterBase does this for you.
When you specify SET DEFAULT as the action, the default value used is the one in effect
when the referential integrity constraint was defined. When the default for a foreign key
column is changed after the referential integrity constraint is set up, the change does not
have an effect on the default value used in the referential integrity constraint.
• You cannot add a value to a column defined as a foreign key unless that value exists in
the referenced primary key. For example, to enter a value in the TEAM_LEADER column
of the PROJECT table, that value must first exist in the EMP_NO column of the
EMPLOYEE table.
The following example specifies that when a value is deleted from a primary key, the
corresponding values in the foreign key are set to NULL. When the primary key is updated,
the changes are cascaded so that the corresponding foreign key values match the new
primary key values.
Circular references
When two tables reference each other’s foreign keys and primary keys, a circular reference
exists between the two tables. In the following illustration, the foreign key in the
EMPLOYEE table, DEPT_NO, references the primary key, DEPT_NO, in the DEPARTMENT
table. Therefore, the primary key, DEPT_NO must be defined in the DEPARTMENT table
before it can be referenced by a foreign key in the EMPLOYEE table. In the same manner,
EMP_NO, which is the EMPLOYEE table’s primary key, must be created before the
DEPARTMENT table can define EMP_NO as its foreign key.
The problem with circular referencing occurs when you try to insert a new row into either
table. Inserting a new row into the EMPLOYEE table causes a new value to be inserted into
the DEPT_NO (foreign key) column, but you cannot insert a value into the foreign key
column unless that value already exists in the DEPT_NO (primary key) column of the
DEPARTMENT table. It is also true that you cannot add a new row to the DEPARTMENT table
unless the values placed in the EMP_NO (foreign key) column already exist in the EMP_NO
(primary key) column of the EMPLOYEE table. Therefore, you are in a deadlock situation
because you cannot add a new row to either table!
InterBase gets around the problem of circular referencing by allowing you to insert a NULL
value into a foreign key column before the corresponding primary key value exists. The
following example illustrates the sequence for inserting a new row into each table:
• Insert a new row into the EMPLOYEE table by placing “1” in the EMP_NO primary key
column, and a NULL in the DEPT_NO foreign key column.
• Insert a new row into the DEPARTMENT table, placing “2” in the DEPT_NO primary key
column, and “1” in the foreign key column.
• Use ALTER TABLE to modify the EMPLOYEE table. Change the DEPT_NO column from
NULL to “2.”
Tip To ensure that the constraint names are visible in RDB$RELATION_CONSTRAINTS, commit
your transaction before trying to view the constraint in the RDB$RELATION_CONSTRAINTS
system table.
The syntax for a column-level constraint is:
<col_constraint> = [CONSTRAINT constraint] <constraint_def>
[<col_constraint> ...]
<constraint_def> =
UNIQUE | PRIMARY KEY
| CHECK (<search_condition>)
| REFERENCES other_table [(other_col [, other_col …])]
[ON DELETE {NO ACTION|CASCADE|SET DEFAULT|SET NULL}]
[ON UPDATE {NO ACTION|CASCADE|SET DEFAULT|SET NULL}]
The syntax for a table-level constraint is:
<tconstraint> = [CONSTRAINT constraint] <tconstraint_def>
[<tconstraint> ...]
<tconstraint_def> = {PRIMARY KEY | UNIQUE} (col [, col …])
| FOREIGN KEY (col [, col …])
REFERENCES other_table [(other_col [, other_col …])]
[ON DELETE {RESTRICT|NO ACTION|CASCADE|SET DEFAULT|SET
NULL}]
[ON UPDATE {RESTRICT|NO ACTION|CASCADE|SET DEFAULT|SET
NULL}]
| CHECK (<search_condition>)
Tip Although naming a constraint is optional, assigning a descriptive name with the
CONSTRAINT clause can make the constraint easier to find for changing or dropping, and
easier to find when its name appears in a constraint violation error message.
The following statement illustrates how to create a simple, column-level PRIMARY KEY
constraint:
CREATE TABLE COUNTRY
(COUNTRY COUNTRYNAME NOT NULL PRIMARY KEY,
CURRENCY VARCHAR(10) NOT NULL);
The next example illustrates how to create a UNIQUE constraint at both the
column level and the table level:
CREATE TABLE STOCK
(MODEL SMALLINT NOT NULL UNIQUE,
MODELNAME CHAR(10) NOT NULL,
ITEMID INTEGER NOT NULL,
CONSTRAINT MOD_UNIQUE UNIQUE (MODELNAME, ITEMID));
| NOT <search_condition>
| <search_condition> OR <search_condition>
| <search_condition> AND <search_condition>
When creating CHECK constraints, the following restrictions apply:
• A CHECK constraint cannot reference a domain.
• A column can have only one CHECK constraint.
• On a domain-based column, you cannot override a CHECK constraint imposed by the
domain with a local CHECK constraint. A column based on a domain can add additional
CHECK constraints to the local column definition.
In the next example, a CHECK constraint is placed on the SALARY domain. VALUE is a
placeholder for the name of a column that will eventually be based on the domain.
CREATE DOMAIN BUDGET
AS NUMERIC(12,2)
DEFAULT 0
CHECK (VALUE > 0);
The next statement illustrates PRIMARY KEY, FOREIGN KEY, CHECK, and the referential
integrity constraints ON UPDATE and ON DELETE. The PRIMARY KEY constraint is based on
three columns, so it is a table-level constraint. The FOREIGN KEY column (JOB_COUNTRY)
references the PRIMARY KEY column (COUNTRY) in the table, COUNTRY. When the
primary key changes, the ON UPDATE and ON DELETE clauses guarantee that the foreign
key column will reflect the changes. This example also illustrates using domains
(JOBCODE, JOBGRADE, COUNTRYNAME, SALARY) and a CHECK constraint to define
columns:
CREATE TABLE JOB
(JOB_CODE JOBCODE NOT NULL,
JOB_GRADE JOBGRADE NOT NULL,
JOB_COUNTRY COUNTRYNAME NOT NULL,
JOB_TITLE VARCHAR(25) NOT NULL,
MIN_SALARY SALARY NOT NULL,
MAX_SALARY SALARY NOT NULL,
JOB_REQUIREMENT BLOB(400,1),
LANGUAGE_REQ VARCHAR(15) [5],
PRIMARY KEY (JOB_CODE, JOB_GRADE, JOB_COUNTRY),
FOREIGN KEY (JOB_COUNTRY) REFERENCES COUNTRY (COUNTRY)
ON UPDATE CASCADE
ON DELETE CASCADE,
CHECK (MIN_SALARY < MAX_SALARY));
filespec that accompanies the EXTERNAL keyword is the fully qualified file specification
for the external data file. You can modify the external file outside of InterBase, since
InterBase accesses it only when needed.
Note The 2GB external file size limit has been removed from InterBase XE onward.
Use the EXTERNAL FILE option to:
• Import data from a flat external file in a known fixed-length format into a new or
existing InterBase table. This allows you to populate an InterBase table with data from
an external source. Many applications allow you to create an external file with fixed-
length records.
• SELECT from the external file as if it were a standard InterBase table.
• Export data from an existing InterBase table to an external file. You can format the data
from the InterBase table into a fixed-length file that another application can use.
Important For security reasons, it is extremely important that you not place files with
sensitive content in the same directory with external tables.
Restrictions
The following restrictions apply to using the EXTERNAL FILE option:
• The default location for external files is <InterBase_home>/ext. InterBase can always
find external files that you place here. If you want to place them elsewhere, you must
specify the location in the ibconfig configuration file using the
EXTERNAL_FILE_DIRECTORY entry.
Migration note: If you are migrating from InterBase 6.x or older to InterBase 7.x or
newer, and your database includes external table files, you must either move these files
to <InterBase_home>/ext or note their locations in ibconfig using the
EXTERNAL_FILE_DIRECTORY entry
• You must create the external file before you try to access the external table inside of the
database.
• Each record in the external file must be of fixed length. You cannot put BLOB or array
data into an external file.
• When you create the table that will be used to import the external data, you must define
a column to contain the end-of-line (EOL) or new-line character. The size of this
column must be exactly large enough to contain a particular system’s EOL symbol
(usually one or two bytes). For most versions of UNIX, it is 1 byte. For Microsoft
Windows, it is 2 bytes.
• While it is possible to read in numeric data directly from an external table, it is much
easier to read it in as character data, and convert using the CAST() function.
• Data to be treated as VARCHAR in InterBase must be stored in an external file in the
following format:
<2-byte unsigned short><string of character bytes>
where the two-byte unsigned short indicates the number of bytes in the actual string, and
the string immediately follows. Because it is not readily portable, using VARCHAR data
in an external file is not recommended.
• You can perform only INSERT and SELECT operations on an external table. You cannot
perform UPDATEs or DELETEs on it; if you try to do so, InterBase returns an error
message.
• Inserting into and selecting from an external table are not under standard transaction
control because the external file is outside of the database. Therefore, changes are
immediate and permanent—you cannot roll back your changes. If you want your table
to be under transaction control, create another internal InterBase table, and insert the
data from the external table into the internal one.
• If you use DROP DATABASE to delete the database, you must also remove the external
file—it will not be automatically deleted as a result of DROP DATABASE.
The number of characters in the EOL is platform-specific. You need to know how many
characters are contained in your platform’s EOL (typically one or two) in order to
correctly format the columns of the tables and the corresponding records in the external
file. In the following example, the record length is 36 characters. “b” represents a blank
space, and “n” represents the EOL:
123456789012345678901234567890123
456
fname.....lname.............hdate..n
------------------------------------
RobertbbbbBrickmanbbbbbbbbbb6/12/
92n
When exporting data to or from an external file, the file must already exist before you
begin the operation. Also, you must specify a directory path whenever you reference the
external file.
4 At this point, when you do a SELECT statement from table EXT_TBL, you will see the
records from the external file:
SELECT FNAME, LNAME, HDATE FROM EXT_TBL;
FNAME LNAME HDATE
======== ================= ===========
Robert Brickman 12-JUN-1992
Sam Jones 13-DEC-1993
5 Insert the data into the destination table.
INSERT INTO PEOPLE SELECT FNAME, LNAME, CAST(HDATE AS DATE),
NEWLINE FROM EXT_TBL;
Now if you SELECT from PEOPLE, the data from your external table will be there.
SELECT FIRST_NAME, LAST_NAME, HIRE_DATE FROM PEOPLE;
FIRST_NAME LAST_NAME HIRE_DATE
========== =================== ===========
Robert Brickman 12-JUN-1992
Sam Jones 13-DEC-1993
InterBase allows you to store the date as an integer by converting from a CHAR(8) to
DATE using the CAST() function.
This section explains how to export InterBase data to an external file. Using the example
developed in the previous section, follow these steps:
1 Open the external file in a text editor and remove everything from the file. If you then
do a SELECT on EXT_TBL, it should be empty.
2 Use an INSERT statement to copy the InterBase records from PEOPLE into the external
file, file.txt. Be sure to specify the file directory.
INSERT INTO EXT_TBL SELECT FIRST_NAME, LAST_NAME, HIRE_DATE,
NEW_LINE FROM PEOPLE WHERE FIRST_NAME LIKE 'Rob%';
3 Now if you do a SELECT from the external table, EXT_TBL, only the records you inserted
should be there. In this example, only a single record should be displayed:
SELECT FNAME, LNAME, HDATE FROM EXT_TBL;
FNAME LNAME HDATE
======== ================= ===========
Robert Brickman 12-JUN-1992
Important Make sure that all records that you intend to export from the internal table to the external
file have the correct EOL character(s) in the newline column.
Altering tables
Use ALTER TABLE to modify the structure of an existing table. ALTER TABLE allows you to:
• Add a new column to a table.
• Drop a column from a table.
• Drop integrity constraints from a table or column.
• Modify the column name, data type, and position.
You can perform any number of the above operations with a single ALTER TABLE
statement. A table can be altered by its creator, the SYSDBA user, and any users with
operating system root privileges.
Note Any one table (and its triggers) can be altered at most 255 times before you must back up
and restore the database.
Dropping columns
Before attempting to drop or modify a column, you should be aware of the different ways
that ALTER TABLE can fail:
• The person attempting to alter data does not have the required privileges.
• Current data in a table violates a PRIMARY KEY or UNIQUE constraint definition added
to the table; there is duplicate data in columns that you are trying to define as PRIMARY
KEY or UNIQUE.
Important When you alter or drop a column, all data stored in it is lost.
• Add new column definitions. To create a column using an existing name, you must drop
existing column definitions before adding new ones.
• Add new table constraints. To create a constraint using an existing name, you must drop
existing constraints with that name before adding a new one.
• Drop existing column definitions without adding new ones.
• Drop existing table constraints without adding new ones.
• Modify column names, data types, and position
For a detailed specification of ALTER TABLE syntax, see the Language Reference.
Table 6.5 Valid data type conversions using ALTER COLUMN and ALTER DOMAIN
Blo Boole Cha Dat De Dbl Fl Int Nu Tstm Tim Smli Var
Convert: b an r e c. e o . m. p e nt .
Blob
Boolean X X X
Char X X X
Date X X X
Decimal X X X X
Double X X X X
Float X X X X
Integer X X X X X X
Numeric X X X
Timestamp X X X
Time X X X
Smallint X X X X X X X X
Varchar X X X
Dropping tables
Use DROP TABLE to delete an entire table from the database.
Note If you want to drop columns from a table, use ALTER TABLE.
Dropping a table
Use DROP TABLE to remove a table’s data, metadata, and indexes from a database. It also
drops any triggers that are based on the table. A table can be dropped by its creator, the
SYSDBA user, or any user with operating system root privileges.
You cannot drop a table that is referenced in a computed column, a view, integrity
constraint, or stored procedure. You cannot drop a table that is being used by an active
transaction until the table is no longer in use.
DROP TABLE fails and returns an error if:
• The person who attempts to drop the table is not the owner of the table.
• The table is in use when the drop is attempted. The drop is postponed until the table is
no longer in use.
• The table has a UNIQUE or PRIMARY KEY defined for it, and the PRIMARY KEY is
referenced by a FOREIGN KEY in another table. First drop the FOREIGN KEY constraints
in the other table, then drop the table.
• The table is used in a view, trigger, stored procedure, or computed column. Remove the
other elements before dropping the table.
• The table is referenced in another table’s CHECK constraint.
Note DROP TABLE does not delete external tables; it removes the table definition from the
database. You must explicitly delete the external file.
Index basics
An index is a mechanism that is used to speed the retrieval of records in response to certain
search conditions, and to enforce uniqueness constraints on columns. Just as you search an
index in a book for a list of page numbers to quickly find the pages that you want to read, a
database index serves as a logical pointer to the physical location (address) of a row in a
table. An index stores each value of the indexed column or columns along with pointers to
all of the disk blocks that contain rows with that column value.
When executing a query, the InterBase engine first checks to see if any indexes exist for the
named tables. It then determines whether it is more efficient to scan the entire table, or to
use an existing index to process the query. If the engine decides to use an index, it searches
the index to find the key values requested, and follows the pointers to locate the rows in the
table containing the values.
Data retrieval is fast because the values in the index are ordered, and the index is relatively
small. This allows the system to quickly locate the key value. Once the key value is found,
the system follows the pointer to the physical location of the associated data. Using an
index typically requires fewer page fetches than a sequential read of every row in the table.
An index can be defined on a single column or on multiple columns of a table. The engine
will use an index to look up a subset of columns, as long as that subset of columns forms a
prefix of a multi-column index definition.
When to index
An index on a column can mean the difference between an immediate response to a query
and a long wait, as the length of time it takes to search the whole table is directly
proportional to the number of rows in the table. So why not index every column? The main
drawbacks are that indexes consume additional disk space, and inserting, deleting, and
updating data takes longer on indexed columns than on non-indexed columns. The reason
is that the index must be updated each time the data in the indexed column changes, and
each time a row is added to or deleted from the table.
Nevertheless, the overhead of indexes is usually outweighed by the boost in performance
for data retrieval queries. You should create an index on a column when:
• Search conditions frequently reference the column.
• Join conditions frequently reference the column.
• ORDER BY statements frequently use the column to sort data.
You do not need to create an index for:
• Columns that are seldom referenced in search conditions.
• Frequently updated non-key columns.
• Columns that have a small number of possible values.
Creating indexes
Indexes are either created by the user with the CREATE INDEX statement, or they are
created automatically by the system as part of the CREATE TABLE statement. InterBase
allows users to create as many as 64 indexes on a given table. To create indexes you must
have authority to connect to the database.
Note To see all indexes defined for the current database, use the isql command SHOW INDEX. To
see all indexes defined for a specific table, use the command, SHOW INDEX tablename. To
view information about a specific index, use SHOW INDEX indexname.
InterBase automatically generates system-level indexes on a column or set of columns
when tables are defined using PRIMARY KEY, FOREIGN KEY, and UNIQUE constraints.
Indexes on PRIMARY KEY and FOREIGN KEY constraints preserve referential integrity.
Use CREATE INDEX to improve speed of data access. For faster response to queries that
require sorted values, use the index order that matches the query’s ORDER BY clause. Use
an index for columns that appear in a WHERE clause to speed searching.
To improve index performance, use SET STATISTICS to recompute index selectivity, or
rebuild the index by making it inactive, then active with sequential calls to ALTER INDEX.
For more information about improving performance, see “SET STATISTICS:
recomputing index selectivity” on page 7-6.
The syntax for CREATE INDEX is:
CREATE [UNIQUE] [ASC[ENDING] | DESC[ENDING]]
INDEX index ON table (col [, col ...]);
If you intend to use both ascending and descending sort orders on a particular column,
define both an ascending and a descending index for the same column. The following
example illustrates this:
CREATE ASCENDING INDEX ASCEND_X ON SALARY_HISTORY
(CHANGE_DATE);
CREATE DESCENDING INDEX DESC_X ON SALARY_HISTORY
(CHANGE_DATE);
ORDER BY LAST_NAME;
Conversely, the following query will not be optimized against the index because the
ORDER BY clause uses FIRST_NAME, which is not the first indexed column in the NAMEX
column list.
SELECT LASTNAME, SALARY FROM EMP
WHERE SALARY > 40000
ORDER BY FIRST_NAME;
The same rules that apply to the ORDER BY clause also apply to queries containing a
WHERE clause. The next example creates a multi-column index for the PROJECT table:
Note You can also rebuild an index by backing up and restoring the database with the gbak utility.
gbak stores only the definition of the index, not the data structure, so when you restore the
database, gbak rebuilds the indexes.
Tip Before inserting a large number of rows, deactivate a table’s indexes during the insert, then
reactivate the index to rebuild it. Otherwise, InterBase incrementally updates the index
each time a single row is inserted.
The syntax for ALTER INDEX is:
ALTER INDEX name {ACTIVE | INACTIVE};
The following statements deactivate and reactivate an index to rebuild it:
ALTER INDEX BUDGETX INACTIVE;
ALTER INDEX BUDGETX ACTIVE;
Note The following restrictions apply to altering an index:
• In order to alter an index, you must be the creator of the index, a SYSDBA user, or a
user with operating system root privileges.
• You cannot alter an index if it is in use in an active database. An index is in use if it is
currently being used by a compiled request to process a query. All requests using an
index must be released to make it available.
• You cannot alter an index that has been defined with a UNIQUE, PRIMARY KEY, or
FOREIGN KEY constraint. If you want to modify the constraints, you must use ALTER
TABLE. For more information about ALTER TABLE, see the Language Reference.
• You cannot use ALTER INDEX to add or drop index columns or keys. Use DROP INDEX
to delete the index and then redefine it with CREATE INDEX.
Index selectivity is a calculation that is made by the InterBase optimizer when a table is
accessed, and is based on the number of distinct rows in a table. It is cached in memory,
where the optimizer can access it to calculate the optimal retrieval plan for a given query.
The syntax for SET STATISTICS is:
SET STATISTICS INDEX name;
The following statement recomputes the selectivity for an index:
SET STATISTICS INDEX MINSALX;
Note The following restrictions apply to the SET STATISTICS statement:
• In order to use SET STATISTICS, you must be the creator of the index, a SYSDBA user,
or a user with operating system root privileges.
• SET STATISTICS does not rebuild an index. To rebuild an index, use ALTER INDEX.
Introduction
Database users typically need to access a particular subset of the data that is stored in the
database. Further, the data requirements within an individual user or group are often quite
consistent. Views provide a way to create a customized version of the underlying tables
that display only the clusters of data that a given user or group of users is interested in.
Once a view is defined, you can display and operate on it as if it were an ordinary table. A
view can be derived from one or more tables, or from another view. Views look just like
ordinary database tables, but they are not physically stored in the database. The database
stores only the view definition, and uses this definition to filter the data when a query
referencing the view occurs.
Important It is important to understand that creating a view does not generate a copy of the data stored
in another table; when you change the data through a view, you are changing the data in the
actual underlying tables. Conversely, when the data in the base tables is changed directly,
the views that were derived from the base tables are automatically updated to reflect the
changes. Think of a view as a movable “window” or frame through which you can see the
actual data. The data definition is the “frame.” For restrictions on operations using views,
see “Types of views: read-only and update-able” on page 8-5.
Advantages of views
The main advantages of views are:
• Simplified access to the data. Views enable you to encapsulate a subset of data from one
or more tables to use as a foundation for future queries without requiring you to repeat
the same set of SQL statements to retrieve the same subset of data.
• Customized access to the data. Views provide a way to tailor the database to suit a
variety of users with dissimilar skills and interests. You can focus on the information
that specifically concerns you without having to process extraneous data.
• Data independence. Views protect users from the effects of changes to the underlying
database structure. For example, if the database administrator decides to split one table
into two, a view can be created that is a join of the two new tables, thus shielding the
users from the change.
• Data security. Views provide security by restricting access to sensitive or irrelevant
portions of the database. For example, you might be able to look up job information, but
not be able to see associated salary information.
Creating views
The CREATE VIEW statement creates a virtual table based on one or more underlying tables
in the database. You can perform select, project, join, and union operations on views just as
if they were tables.
The user who creates a view is its owner and has all privileges for it, including the ability to
GRANT privileges to other users, triggers, and stored procedures. A user can be granted
privileges to a view without having access to its base tables.
The syntax for CREATE VIEW is:
CREATE VIEW name [(view_col [, view_col …])]
AS <select> [WITH CHECK OPTION];
Note You cannot define a view that is based on the result set of a stored procedure.
• Lists the columns to be included from the base table. When SELECT * is used rather than
a column list, the view contains all columns from the base table, and displays them in
the order in which they appear in the base table. The following example creates a view,
MY_VIEW, that contains all of the columns in the EMPLOYEE table:
View privileges
The creator of the view must have the following privileges:
• To create a read-only view, the creator needs SELECT privileges for any underlying
tables.
• To create an update-able view, the creator needs ALL privileges to the underlying tables.
For more information on SQL privileges, see Chapter 12, “Planning Security.”
Examples of views
The following statement creates an update-able view:
CREATE VIEW EMP_MNGRS (FIRST, LAST, SALARY) AS
SELECT FIRST_NAME, LAST_NAME, SALARY
FROM EMPLOYEE
WHERE JOB_CODE = 'Mngr';
The next statement uses a nested query to create a view, so the view is read-only:
CREATE VIEW ALL_MNGRS AS
SELECT FIRST_NAME, LAST_NAME, JOB_COUNTRY FROM EMPLOYEE
WHERE JOB_COUNTRY IN
(SELECT JOB_COUNTRY FROM JOB
WHERE JOB_TITLE = 'manager');
The next statement creates a view that joins two tables, and so it is also read-only:
Examples
Suppose you want to create a view that allows access to information about all departments
with budgets between $10,000 and $500,000. The view, SUB_DEPT, is defined as follows:
CREATE VIEW SUB_DEPT (DEPT_NAME, DEPT_NO, SUB_DEPT_NO,
LOW_BUDGET) AS
SELECT DEPARTMENT, DEPT_NO, HEAD_DEPT, BUDGET
FROM DEPARTMENT WHERE BUDGET BETWEEN 10000 AND 500000
WITH CHECK OPTION;
The SUB_DEPT view references a single table, DEPARTMENT. If you are the creator of the
view or have INSERT privileges, you can insert new data into the DEPARTMENT, DEPT_NO,
HEAD_DEPT, and BUDGET columns of the base table, DEPARTMENT. WITH CHECK OPTION
assures that all values entered through the view fall within the range prescribed for each
column in the WHERE clause of the SUB_DEPT view.
The following statement inserts a new row for the Publications Department through the
SUB_DEPT view:
Dropping views
The DROP VIEW statement enables a view’s creator to remove a view definition from the
database. It does not affect the base tables associated with the view. You can drop a view
only if:
• You created the view.
• The view is not used in another view, a stored procedure, or CHECK constraint
definition. You must delete the associated database objects before dropping the view.
The syntax for DROP VIEW is:
DROP VIEW name;
The following statement removes a view definition:
DROP VIEW SUB_DEPT;
Note You cannot alter a view directly. To change a view, drop it and use the CREATE VIEW
statement to create a view with the same name and the features you want.
Working with
Chapter 9
Stored Procedures
This chapter describes the following:
• How to create, alter, and drop procedures
• The InterBase procedure and trigger language
• How to use stored procedures
• How to create, alter, drop, and raise exceptions
• How to handle errors
• Streamlined maintenance
When a procedure is updated, the changes are automatically reflected in all applications
that use it without the need to recompile and re-link them; applications are compiled and
optimized only once for each client
• Improved performance
Stored procedures are executed by the server, not the client, which reduces network
traffic, and improves performance—especially for remote client access.
See also For more information on working with EXECUTE STATEMENTS, see Chapter 3:
Procedures and Triggers: EXECUTE STATEMENT.
Creating procedures
You can define a stored procedure with the CREATE PROCEDURE statement in isql. You
cannot create stored procedures in embedded SQL. A stored procedure is composed of a
header and a body.
The header contains:
• The name of the stored procedure, which must be unique among procedure, view, and
table names in the database.
• An optional list of input parameters and their data types that a procedure receives from
the calling program.
• If the procedure returns values to the calling program, RETURNS followed by a list of
output parameters and their data types.
The procedure body contains:
• An optional list of local variables and their data types.
• A block of statements in InterBase procedure and trigger language, bracketed by BEGIN
and END. A block can itself include other blocks, so that there can be many levels of
nesting.
Argument Description
name Name of the procedure; must be unique among procedure, table, and
view names in the database
param datatype Input parameters that the calling program uses to pass values to the
procedure
• param: Name of the input parameter, unique for variables in the
procedure
• datatype: An InterBase datatype
RETURNS Output parameters that the procedure uses to return values to the calling
param datatype program
• param: Name of the output parameter, unique for variables within the
procedure
• datatype: An InterBase datatype
• The procedure returns the values of output parameters when it reaches
a SUSPEND statement in the procedure body.
AS Keyword that separates the procedure header and the procedure body
• Input and output parameters, and the SUSPEND and EXIT statements, which return
values and are unique to stored procedures.
The stored procedure and trigger language does not include many of the statement types
available in DSQL or gpre. The following statement types are not supported in triggers or
stored procedures:
• Data definition language statements: CREATE, ALTER, DROP, DECLARE EXTERNAL
FUNCTION, and DECLARE FILTER
Statement Description
EXECUTE PROCEDURE proc_name Executes stored procedure, proc_name, with the input
[var [, var …]] arguments listed following the procedure name, returning
[RETURNING_VALUES var values in the output arguments listed following
[, var …]] RETURNING_VALUES
Enables nested procedures and recursion
Input and output parameters must be variables defined within
the procedure.
Statement Description
The line numbers are counted from the beginning of the CREATE PROCEDURE statement,
not from the beginning of the data definition file. Characters are counted from the left, and
the unknown token indicated is either the source of the error, or immediately to the right of
the source of the error. When in doubt, examine the entire line to determine the source of
the syntax error.
...
[RETURNS (var datatype [, var datatype …])]
AS
...
Each output parameter declaration has two parts: a name and a data type. The name of the
parameter must be unique within the procedure, and the data type can be any standard SQL
data type except arrays.
Using variables
There are three types of variables that can be used in the body of a procedure:
• Input parameters, used to pass values from an application to a stored procedure.
• Output parameters, used to pass values from a stored procedure back to the calling
application.
• Local variables, used to hold values used only within a procedure.
Any of these types of variables can be used in the body of a stored procedure where an
expression can appear. They can be assigned a literal value, or assigned a value derived
from queries or expression evaluations.
Note In SQL statements, precede variables with a colon (:) to signify that they are variables rather
than column names. In procedure and trigger language extension statements, you need not
precede variables with a colon.
Local variables
Local variables are declared and used within a stored procedure. They have no effect
outside the procedure.
Local variables must be declared at the beginning of a procedure body before they can be
used. Declare a local variable as follows:
DECLARE VARIABLE var datatype;
where var is the name of the local variable, unique within the procedure, and datatype is
the datatype, which can be any SQL datatype except BLOB or an array. Each local variable
requires a separate DECLARE VARIABLE statement, followed by a semicolon (;).
The following header declares the local variable, ANY_SALES:
CREATE PROCEDURE DELETE_EMPLOYEE (EMP_NUM INTEGER)
AS
DECLARE VARIABLE ANY_SALES INTEGER;
BEGIN
...
Input parameters
Input parameters are used to pass values from an application to a procedure. They are
declared in a comma-delimited list in parentheses following the procedure name. Once
declared, they can be used in the procedure body anywhere an expression can appear.
Input parameters are passed by value from the calling program to a stored procedure. This
means that if the procedure changes the value of an input parameter, the change has effect
only within the procedure. When control returns to the calling program, the input
parameter still has its original value.
The following procedure header declares two input parameters, EMP_NO and
PROJ_ID:
Output parameters
Output parameters are used to return values from a procedure to the calling application.
Declare them in a comma-delimited list in parentheses following the RETURNS keyword in
the procedure header. Once declared, they can be used in the procedure body anywhere an
expression can appear. For example, the following procedure header declares five output
parameters, HEAD_DEPT, DEPARTMENT, MNGR_NAME, TITLE, and EMP_CNT:
• It is a loop statement that retrieves the row specified in the select_expr and performs the
statement or block following DO for each row retrieved.
• The INTO clause in the select_expr is required and must come last. This syntax allows
FOR … SELECT to use the SQL UNION clause, if needed.
For example, the following statement from a procedure selects department numbers into
the local variable, RDNO, which is then used as an input parameter to the DEPT_BUDGET
procedure:
FOR SELECT DEPT_NO
FROM DEPARTMENT
WHERE HEAD_DEPT = :DNO
INTO :RDNO
DO
BEGIN
EXECUTE PROCEDURE DEPT_BUDGET :RDNO RETURNS :SUMB;
TOT = TOT + SUMB;
END
…;
...
IF (FIRST IS NOT NULL)
THEN LINE2 = FIRST || ' ' || LAST;
ELSE LINE2 = LAST;
...
POST_EVENT <event_name>;
The parameter, event_name, can be either a quoted literal or string variable.
Note Variable names do not need to be—and must not be—preceded by a colon in stored
procedures except in SELECT, INSERT, UPDATE, and DELETE clauses where they would be
interpreted as column names without the colon.
When the procedure is executed, this statement notifies the event manager, which alerts
applications waiting for the named event. For example, the following statement posts an
event named “new_order”:
POST_EVENT 'new_order';
Alternatively, a variable can be used for the event name:
POST_EVENT event_name;
So, the statement can post different events, depending on the value of the string variable,
event_name.
For more information on events and event alerters, see the Embedded SQL Guide.
Adding comments
Stored procedure code should be commented to aid debugging and application
development. Comments are especially important in stored procedures since they are
global to the database and can be used by many different application developers.
Comments in stored procedure definitions are exactly like comments in standard C code,
and use the following syntax:
/* comment_text */
comment_text can be any number of lines of text. A comment can appear on the same line
as code. For example:
x = 42; /* Initialize value of x. */
In a select procedure, the SUSPEND statement returns current values of output parameters to
the calling program and continues execution. If an output parameter has not been assigned
a value, its value is unpredictable, which can lead to errors. A procedure should ensure that
all output parameters are assigned values before a SUSPEND.
In both select and executable procedures, EXIT jumps program control to the final END
statement in the procedure.
What happens when a procedure reaches the final END statement depends on the type of
procedure:
• In a select procedure, the final END statement returns control to the application and sets
SQLCODE to 100, which indicates there are no more rows to retrieve.
• In an executable procedure, the final END statement returns control and values of output
parameters, if any, to the calling application.
The behavior of these statements is summarized in the following table:
Table 9.3 SUSPEND, EXIT, and END
Procedure type SUSPEND EXIT END
Select procedure • Suspends execution of Jumps to final END • Returns control to application
procedure until next FETCH • Sets SQLCODE to 100
• Returns values
Executable procedure • Jumps to final END Jumps to final END • Returns values
• Not recommended • Returns control to application
EXECUTE PROCEDURE P;
then it returns 1, since the SUSPEND statement terminates the procedure and returns the
current value of R to the calling application. This is not recommended, but is included here
for comparison.
Note If a select procedure has executable statements following the last SUSPEND in the procedure,
all of those statements are executed, even though no more rows are returned to the calling
program. The procedure terminates with the final END statement.
Error behavior
When a procedure encounters an error—either a SQLCODE error, GDSCODE error, or user-
defined exception—all statements since the last SUSPEND are undone.
Since select procedures can have multiple SUSPENDs, possibly inside a loop statement,
only the actions since the last SUSPEND are undone. Since executable procedures should
not use SUSPEND, when an error occurs the entire executable procedure is undone (if EXIT
is used, as recommended).
2 Edit the file, changing CREATE to ALTER, and changing the procedure definition as
desired. Retain whatever is still useful.
Dropping procedures
The DROP PROCEDURE statement deletes an existing stored procedure from the database.
DROP PROCEDURE can be used interactively with isql or in a data definition file.
• They can take input parameters that can affect the output.
• They can contain logic not available in normal queries or views.
• They can return rows from multiple tables using UNION.
The syntax of SELECT from a procedure is:
SELECT <col_list> from name ([param [, param …]])
WHERE <search_condition>
ORDER BY <order_list>;
The procedure name must be specified, and in isql each param is a constant passed to the
corresponding input parameter. All input parameters required by the procedure must be
supplied. The col_list is a comma-delimited list of output parameters returned by the
procedure, or * to select all rows.
The WHERE clause specifies a search_condition that selects a subset of rows to return. The
ORDER BY clause specifies how to order the rows returned. For more information on
SELECT, see the Language Reference.
Note The following code defines the procedure, GET_EMP_PROJ, which returns EMP_PROJ, the
project numbers assigned to an employee, when it is passed the employee number, EMP_NO,
as the input parameter.
CREATE PROCEDURE GET_EMP_PROJ (EMP_NO SMALLINT)
RETURNS (EMP_PROJ SMALLINT) AS
BEGIN
FOR SELECT PROJ_ID
FROM EMPLOYEE_PROJECT
WHERE EMP_NO = :EMP_NO
INTO :EMP_PROJ
DO
SUSPEND;
END ;
The following statement selects from GET_EMP_PROJ in isql:
SELECT * FROM GET_EMP_PROJ(24);
The output is:
PROJ_ID
=======
DGPII
GUIDE
The following select procedure, ORG_CHART, displays an organizational chart:
CREATE PROCEDURE ORG_CHART
RETURNS (HEAD_DEPT CHAR(25), DEPARTMENT CHAR(25),
MNGR_NAME CHAR(20), TITLE CHAR(5), EMP_CNT INTEGER)
AS
DECLARE VARIABLE MNGR_NO INTEGER;
DECLARE VARIABLE DNO CHAR(3);
BEGIN
FOR SELECT H.DEPARTMENT, D.DEPARTMENT, D.MNGR_NO,
D.DEPT_NO
FROM DEPARTMENT D
LEFT OUTER JOIN DEPARTMENT H ON D.HEAD_DEPT = H.DEPT_NO
ORDER BY D.DEPT_NO
INTO :HEAD_DEPT, :DEPARTMENT, :MNGR_NO, :DNO
DO
BEGIN
IF (:MNGR_NO IS NULL) THEN
BEGIN
MNGR_NAME = '--TBH--';
TITLE = '';
END
ELSE
SELECT FULL_NAME, JOB_CODE
FROM EMPLOYEE
WHERE EMP_NO = :MNGR_NO
INTO :MNGR_NAME, :TITLE;
SELECT COUNT(EMP_NO)
FROM EMPLOYEE
WHERE DEPT_NO = :DNO
INTO :EMP_CNT;
SUSPEND;
END
END ;
ORG_CHART is invoked from isql as follows:
ORG_CHART must be used as a select procedure to display the full organization. If called
with EXECUTE PROCEDURE, then the first time it encounters the SUSPEND statement, the
procedure terminates, returning the information for Corporate Headquarters only.
SELECT can specify columns to retrieve from a procedure. For example, if ORG_CHART is
invoked as follows:
SELECT DEPARTMENT FROM ORG_CHART;
then only the second column, DEPARTMENT, is displayed.
The WHERE clause limits the results returned by the procedure to rows matching the search
condition. For example, the following statement returns only those rows where the
HEAD_DEPT is Sales and Marketing:
EMP_C
HEAD_DEPT MNGR_NAME NT
=============== DEPARTMENT ============ TITLE ======
= =============== = ===== =
Sales and Marketing Pacific Rim Headquarters Baldwin, Janet Sales 2
The ORDER BY clause can be used to order the results returned by the procedure. For
example, the following statement orders the results by EMP_CNT, the number of
employees in each department, in ascending order (the default):
SELECT * FROM ORG_CHART ORDER BY EMP_CNT;
Similarly, to use ORG_CHART to display the maximum and average number of employees
in each department, use the following statement:
SELECT MAX(EMP_CNT), AVG(EMP_CNT) FROM ORG_CHART;
The results are:
MAX AVG
======= =======
5 2
If a procedure encounters an error or exception, the aggregate functions do not return the
correct values, since the procedure terminates before all rows are processed.
To view the contents of the LANGUAGE_REQ column, use a stored procedure, such as the
following:
CREATE PROCEDURE VIEW_LANGS
RETURNS (code VARCHAR(5), grade SMALLINT, cty VARCHAR(15),
lang VARCHAR(15))
AS
DECLARE VARIABLE i INTEGER;
BEGIN
FOR SELECT JOB_CODE, JOB_GRADE, JOB_COUNTRY
FROM JOB
WHERE LANGUAGE_REQ IS NOT NULL
INTO :code, :grade, :cty
DO
BEGIN
i = 1;
WHILE (i <= 5) DO
BEGIN
SELECT LANGUAGE_REQ[:i] FROM JOB
WHERE ((JOB_CODE = :code) AND (JOB_GRADE = :grade)
AND (JOB_COUNTRY = :cty)) INTO :lang;
i = i + 1;
SUSPEND;
END
END
END ;
This procedure, VIEW_LANGS, uses a FOR … SELECT loop to retrieve each row from JOB
for which LANGUAGE_REQ is not NULL. Then a WHILE loop retrieves each element of the
LANGUAGE_REQ array and returns the value to the calling application (in this case, isql).
Exceptions
An exception is a named error message that can be raised from a stored procedure.
Exceptions are created with CREATE EXCEPTION, modified with ALTER EXCEPTION, and
dropped with DROP EXCEPTION. A stored procedure raises an exception with EXCEPTION
name.
When raised, an exception returns an error message to the calling program and terminates
execution of the procedure that raised it, unless the exception is handled by a WHEN
statement.
Important Like procedures, exceptions are created and stored in a database, where they can be used
by any procedure that needs them. Exceptions must be created and committed before they
can be raised.
For more information on raising and handling exceptions, see “Raising an exception in
a stored procedure” on page 9-27.
Creating exceptions
To create an exception, use the following CREATE EXCEPTION syntax:
CREATE EXCEPTION name '<message>';
For example, the following statement creates an exception named
REASSIGN_SALES:
Altering exceptions
To change the message returned by an exception, use the following syntax:
ALTER EXCEPTION name '<message>';
Only the creator of an exception can alter it. For example, the following statement changes
the text of the exception created in the previous section:
ALTER EXCEPTION REASSIGN_SALES 'Can’t delete employee--Reassign
Sales';
You can alter an exception even though a database object depends on it. If the exception is
raised by a trigger, you cannot drop the exception unless you first drop the trigger or stored
procedure. Use ALTER EXCEPTION instead.
Dropping exceptions
To delete an exception, use the following syntax:
DROP EXCEPTION name;
Handling errors
Procedures can handle three kinds of errors with a WHEN … DO statement:
• Exceptions raised by EXCEPTION statements in the current procedure, in a nested
procedure, or in a trigger fired as a result of actions by such a procedure.
• SQL errors reported in SQLCODE.
• InterBase errors reported in GDSCODE.
The WHEN ANY statement handles any of the three types of errors.
For more information about InterBase error codes and SQLCODE values, see the Language
Reference.
The syntax of the WHEN … DO statement is:
WHEN {<error> [, <error> …] | ANY}
DO <compound_statement>
<error> =
{EXCEPTION exception_name | SQLCODE number | GDSCODE errcode}
Important If used, WHEN must be the last statement in a BEGIN … END block. It should come after
SUSPEND, if present.
Handling exceptions
Instead of terminating when an exception occurs, a procedure can respond to and perhaps
correct the error condition by handling the exception. When an exception is raised, it does
the following:
• Seeks a WHEN statement that handles the exception. If one is not found, it terminates
execution of the BEGIN … END block containing the exception and undoes any actions
performed in the block.
• Backs out one level to the surrounding BEGIN … END block and seeks a WHEN statement
that handles the exception, and continues backing out levels until one is found. If no
WHEN statement is found, the procedure is terminated and all its actions are undone.
• Performs the ensuing statement or block of statements specified by the WHEN statement
that handles the exception.
• Returns program control to the block in the procedure following the WHEN statement.
Note An exception that is handled does not return an error message.
The following procedure includes a WHEN statement to handle SQLCODE -803 (attempt to
insert a duplicate value in a UNIQUE key column). If the first column in TABLE1 is a
UNIQUE key, and the value of parameter A is the same as one already in the table, then
SQLCODE -803 is generated, and the WHEN statement sets an error message returned by the
procedure.
CREATE PROCEDURE NUMBERPROC (A INTEGER, B INTEGER)
RETURNS (E CHAR(60)) AS
BEGIN
BEGIN
INSERT INTO TABLE1 VALUES (:A, :B);
WHEN SQLCODE -803 DO
E = 'Error Attempting to Insert in TABLE1 - Duplicate Value.';
END;
END;!
For more information about SQLCODE, see the Language Reference.
For example, here is a simple executable procedure that attempts to insert the same values
twice into the PROJECT table.
CREATE PROCEDURE NEW_PROJECT
(id CHAR(5), name VARCHAR(20), product VARCHAR(12))
RETURNS (result VARCHAR(80))
AS
BEGIN
INSERT INTO PROJECT (PROJ_ID, PROJ_NAME, PRODUCT)
VALUES (:id, :name, :product);
result = 'Values inserted OK.';
INSERT INTO PROJECT (PROJ_ID, PROJ_NAME, PRODUCT)
VALUES (:id, :name, :product);
result = 'Values Inserted Again.';
EXIT;
WHEN SQLCODE -803 DO
BEGIN
result = 'Could Not Insert Into Table - Duplicate Value';
EXIT;
END
END ;
This procedure can be invoked with a statement such as:
EXECUTE PROCEDURE NEW_PROJECT 'XXX', 'Project X', 'N/A';
The second INSERT generates an error (SQLCODE -803, “invalid insert—no two rows can
have duplicate values.”). The procedure returns the string, “Could Not Insert Into Table -
Duplicate Value,” as specified in the WHEN clause, and the entire procedure is undone.
The next example is written as a select procedure, and invoked with the SELECT statement
that follows it:
...
INSERT INTO PROJECT (PROJ_ID, PROJ_NAME, PRODUCT)
VALUES (:id, :name, :product);
result = 'Values inserted OK.';
SUSPEND;
INSERT INTO PROJECT (PROJ_ID, PROJ_NAME, PRODUCT)
VALUES (:id, :name, :product);
result = 'Values Inserted Again.';
SUSPEND;
WHEN SQLCODE -803 DO
BEGIN
result = 'Could Not Insert Into Table - Duplicate Value';
EXIT;
END
SELECT * FROM SIMPLE('XXX', 'Project X', 'N/A');
The first INSERT is performed, and SUSPEND returns the result string, “Values Inserted
OK.” The second INSERT generates the error because there have been no statements
performed since the last SUSPEND, and no statements are undone. The WHEN statement
returns the string, “Could Not Insert Into Table - Duplicate Value”, in addition to the
previous result string.
The select procedure successfully performs the insert, while the executable procedure does
not.
The next example is a more complex stored procedure that demonstrates SQLCODE error
handling and exception handling. It is based on the previous example of a select procedure,
and does the following:
• Accepts a project ID, name, and product type, and ensures that the ID is in all capitals,
and the product type is acceptable.
• Inserts the new project data into the PROJECT table, and returns a string confirming the
operation, or an error message saying the project is a duplicate.
• Uses a FOR … SELECT loop with a correlated subquery to get the first three employees
not assigned to any project and assign them to the new project using the ADD_EMP_PROJ
procedure.
• If the CEO’s employee number is selected, raises the exception, CEO, which is handled
with a WHEN statement that assigns the CEO’s administrative assistant (employee
number 28) instead to the new project.
Note that the exception, CEO, is handled within the FOR … SELECT loop, so that only the
block containing the exception is undone, and the loop and procedure continue after the
exception is raised.
CREATE EXCEPTION CEO 'Can’t Assign CEO to Project.';
CREATE PROCEDURE NEW_PROJECT
(id CHAR(5), name VARCHAR(20), product VARCHAR(12))
RETURNS (result VARCHAR(30), num smallint)
AS
DECLARE VARIABLE emp_wo_proj smallint;
DECLARE VARIABLE i smallint;
BEGIN
id = UPPER(id); /* Project id must be in uppercase. */
INSERT INTO PROJECT (PROJ_ID, PROJ_NAME, PRODUCT)
VALUES (:id, :name, :product);
result = 'New Project Inserted OK.';
SUSPEND;
/* Add Employees to the new project */
i = 0;
result = 'Project Got Employee Number:';
FOR SELECT EMP_NO FROM EMPLOYEE
WHERE EMP_NO NOT IN (SELECT EMP_NO FROM EMPLOYEE_PROJECT)
INTO :emp_wo_proj
DO
BEGIN
IF (i < 3) THEN
BEGIN
IF (emp_wo_proj = 5) THEN
EXCEPTION CEO;
EXECUTE PROCEDURE ADD_EMP_PROJ :emp_wo_proj, :id;
num = emp_wo_proj;
SUSPEND;
END
ELSE
EXIT;
i = i + 1;
WHEN EXCEPTION CEO DO
BEGIN
EXECUTE PROCEDURE ADD_EMP_PROJ 28, :id;
num = 28;
SUSPEND;
END
END
/* Error Handling */
WHEN SQLCODE -625 DO
BEGIN
IF ((:product <> 'software') OR (:product <> 'hardware') OR
(:product <> 'other') OR (:product <> 'N/A')) THEN
result = 'Enter product: software, hardware, other, or N/A';
END
WHEN SQLCODE -803 DO
result = 'Could not insert into table - Duplicate Value';
END ;
This procedure can be called with a statement such as:
SELECT * FROM NEW_PROJECT('XYZ', 'Alpha project', 'software');
With results such as the following:
RESULT NUM
=========================== ======
New Project Inserted OK. <null>
Project Got Employee Number: 28
Project Got Employee Number: 29
Project Got Employee Number: 36
About triggers
A trigger is a self-contained routine associated with a table or view that automatically
performs an action when a row in the table or view is inserted, updated, or deleted.
A trigger is never called directly. Instead, when an application or user attempts to INSERT,
UPDATE, or DELETE a row in a table, any triggers associated with that table and operation
are automatically executed, or fired.
Triggers can make use of exceptions, named messages called for error handling. When an
exception is raised by a trigger, it returns an error message, terminates the trigger, and
undoes any changes made by the trigger, unless the exception is handled with a WHEN
statement in the trigger.
The advantages of using triggers are:
• Automatic enforcement of data restrictions, to make sure users enter only valid
values into columns.
• Reduced application maintenance, since changes to a trigger are automatically
reflected in all applications that use the associated table without the need to recompile
and re-link.
Creating triggers
A trigger is defined with the CREATE TRIGGER statement, which is composed of a header
and a body. The trigger header contains:
• A trigger name, unique within the database.
• A table name, identifying the table with which to associate the trigger.
• Statements that determine when the trigger fires.
The trigger body contains:
• An optional list of local variables and their data types.
• A block of statements in InterBase procedure and trigger language, bracketed by BEGIN
and END. These statements are performed when the trigger fires. A block can itself
include other blocks, so that there may be many levels of nesting.
Argument Description
table Name of the table or view that causes the trigger to fire when
the specified operation occurs on the table or view.
DELETE|INSERT | UPDATE Specifies the table operation that causes the trigger to fire.
Argument Description
POSITION number Specifies firing order for triggers before the same action or
after the same action. number must be an integer between 0
and 32,767, inclusive. Lower-number triggers fire first.
Default: 0 = first trigger to fire.
Triggers for a table need not be consecutive. Triggers on the
same action with the same position number will fire in
alphabetic order by name.
DECLARE VARIABLE var Declares local variables used only in the trigger. Each
datatype declaration must be preceded by DECLARE VARIABLE and
followed by a semicolon (;).
var: Local variable name, unique in the trigger.
datatype: The datatype of the local variable.
Statement Description
EXECUTE PROCEDURE proc_name Executes stored procedure, proc_name, with the listed
[var [, var …]] input arguments, returning values in the listed output
[RETURNING_VALUES arguments. Input and output arguments must be local
var [, var …]] variables.
Statement Description
For example, the following trigger fires after the EMPLOYEE table is updated, and
compares an employee’s old and new salary. If there is a change in salary, the trigger
inserts an entry in the SALARY_HISTORY table.
CREATE TRIGGER SAVE_SALARY_CHANGE FOR EMPLOYEE
AFTER UPDATE AS
BEGIN
IF (old.salary <> new.salary) THEN
INSERT INTO SALARY_HISTORY (EMP_NO, CHANGE_DATE,
UPDATER_ID, OLD_SALARY, PERCENT_CHANGE)
VALUES (old.emp_no, 'now', USER, old.salary,
(new.salary - old.salary) * 100 / old.salary);
END ;
Note Context variables are never preceded by a colon, even in SQL statements.
Using generators
In a read-write database, a generator is a database object that automatically increments
each time the special function, GEN_ID(), is called.
Important Generators cannot be used in read-only databases.
GEN_ID() can be used in a statement anywhere that a variable can be used. Generators are
typically used to ensure that a number inserted into a column is unique, or in sequential
order. Generators can be used in procedures and applications as well as in triggers, but they
are particularly useful in triggers for inserting unique column values.
Use the CREATE GENERATOR statement the create a generator and SET GENERATOR to
initialize it. If not otherwise initialized, a generator starts with a value of one. For more
information about creating and initializing a generator, see CREATE GENERATOR and SET
GENERATOR in the Language Reference.
A generator must be created with CREATE GENERATOR before it can be called by GEN_ID().
The syntax for using GEN_ID() in a SQL statement is:
GEN_ID(genname, step)
genname must be the name of an existing generator, and step is the amount by which the
current value of the generator is incremented. step can be an integer or an expression that
evaluates to an integer.
The following trigger uses GEN_ID() to increment a new customer number before values
are inserted into the CUSTOMER table:
CREATE TRIGGER SET_CUST_NO FOR CUSTOMER
BEFORE INSERT AS
BEGIN
NEW.CUST_NO = GEN_ID(CUST_NO_GEN, 1);
END ;
Note This trigger must be defined to fire before the insert, since it assigns values to
NEW.CUST_NO.
Altering triggers
To update a trigger definition, use ALTER TRIGGER. A trigger can be altered only by its
creator.
ALTER TRIGGER can change:
• Only trigger header information, including the trigger activation status, when it
performs its actions, the event that fires the trigger, and the order in which the trigger
fires compared to other triggers.
• Only trigger body information, the trigger statements that follow the AS clause.
• Both trigger header and trigger body information. In this case, the new trigger definition
replaces the old trigger definition.
To alter a trigger defined automatically by a CHECK constraint on a table, use ALTER TABLE
to change the table definition. For more information on the ALTER TABLE statement, see
Chapter 6, “Working with Tables.”
Note Direct metadata operations, such as altering triggers, increase the metadata version. At most
255 such operations can be performed before you must back up and restore the database.
The ALTER TRIGGER syntax is as follows:
ALTER TRIGGER name
[ACTIVE | INACTIVE]
[{BEFORE | AFTER} {DELETE | INSERT | UPDATE}]
[POSITION number]
AS <trigger_body>;
The syntax of ALTER TRIGGER is the same as CREATE TRIGGER, except:
• The CREATE keyword is replaced by ALTER.
• FOR table is omitted. ALTER TRIGGER cannot be used to change the table with which the
trigger is associated.
• The statement need only include parameters that are to be altered in the existing trigger,
with certain exceptions listed in the following sections.
Note This example assumes that you have a table named NEW_CUSTOMERS with a column
cust_no.
ALTER TRIGGER SET_CUST_NO
BEFORE INSERT AS
BEGIN
new.cust_no = GEN_ID(CUST_NO_GEN, 1);
INSERT INTO NEW_CUSTOMERS(new.cust_no, TODAY)
END ;
Dropping triggers
During database design and application development, a trigger may no longer be useful. To
permanently remove a trigger, use DROP TRIGGER.
The following restrictions apply to dropping triggers:
• Only the creator of a trigger can drop it.
• Triggers currently in use cannot be dropped.
To temporarily remove a trigger, use ALTER TRIGGER and specify INACTIVE in the header.
The DROP TRIGGER syntax is as follows:
DROP TRIGGER name;
The trigger name must be the name of an existing trigger. The following example drops the
trigger, SET_CUST_NO:
DROP TRIGGER SET_CUST_NO;
You cannot drop a trigger if it is in use by a CHECK constraint (a system-defined trigger).
Use ALTER TABLE to remove or modify the CHECK clause that defines the trigger.
Note Direct metadata operations, such as dropping triggers, increase the metadata version. At
most 255 such operations can be performed before you must back up and restore the
database.
Using triggers
Triggers are a powerful feature with a variety of uses. Among the ways that triggers can be
used are:
• To make correlated updates. For example, to keep a log file of changes to a database or
table.
• To enforce data restrictions, so that only valid data is entered in tables.
• Automatic transformation of data. For example, to automatically convert text input to
uppercase.
• To notify applications of changes in the database using event alerters.
• To perform cascading referential integrity updates.
Triggers are stored as part of a database, like stored procedures and exceptions. Once
defined to be ACTIVE, they remain active until deactivated with ALTER TRIGGER or
removed from the database with DROP TRIGGER.
A trigger is never explicitly called. Rather, an active trigger automatically fires when the
specified action occurs on the specified table.
Important If a trigger performs an action that causes it to fire again—or fires another trigger that
performs an action that causes it to fire—an infinite loop results. For this reason, it is
important to ensure that a trigger’s actions never cause the trigger to fire, even indirectly.
For example, an endless loop will occur if a trigger fires on INSERT to a table and then
performs an INSERT into the same table.
EXEC SQL
EVENT INIT ORDER_WAIT EMPDB ('NEW_ORDER');
EXEC SQL
EVENT WAIT ORDER_WAIT;
For more information on event alerters, see the Embedded SQL Guide.
Exceptions
An exception is a named error message that can be raised from a trigger or a stored
procedure. Exceptions are created with CREATE EXCEPTION, modified with ALTER
EXCEPTION, and removed from the database with DROP EXCEPTION. For more information
about these statements, see Chapter 9, “Working with Stored Procedures.”
When raised in a trigger, an exception returns an error message to the calling program and
terminates the trigger, unless the exception is handled by a WHEN statement in the trigger.
For more information on error handling with WHEN, see Chapter 9, “Working with
Stored Procedures.”
For example, a trigger that fires when the EMPLOYEE table is updated might compare the
employee’s old salary and new salary, and raise an exception if the salary increase exceeds
50%. The exception could return an message such as:
New salary exceeds old by more than 50%. Cannot update record.
Important Like procedures and triggers, exceptions are created and stored in a database, where they
can be used by any procedure or trigger in the database. Exceptions must be created and
committed before they can be used in triggers.
where name is the name of an exception that already exists in the database. Raising an
exception:
• Terminates the trigger, undoing any changes caused (directly or indirectly) by the
trigger.
• Returns the exception message to the application which performed the action that fired
the trigger. If an isql command fired the trigger, the error message is displayed on the
screen.
Note If an exception is handled with a WHEN statement, it will behave differently. For more
information on exception handling, see Chapter 9, “Working with Stored Procedures.”
For example, suppose an exception is created as follows:
CREATE EXCEPTION RAISE_TOO_HIGH 'New salary exceeds old by
more than 50%. Cannot update record.';
The trigger, SAVE_SALARY_CHANGE, might raise the exception as follows:
CREATE TRIGGER SAVE_SALARY_CHANGE FOR EMPLOYEE
AFTER UPDATE AS
DECLARE VARIABLE PCNT_RAISE;
BEGIN
PCNT_RAISE = (NEW.SALARY - OLD.SALARY) * 100 / OLD.SALARY;
IF (OLD.SALARY <> NEW.SALARY)
THEN
IF (PCNT_RAISE > 50)
THEN EXCEPTION RAISE_TOO_HIGH;
ELSE
BEGIN
INSERT INTO SALARY_HISTORY (EMP_NO, CHANGE_DATE,
UPDATER_ID, OLD_SALARY, PERCENT_CHANGE)
VALUES (OLD.EMP_NO, 'NOW', USER, OLD.SALARY,
PCNT_RAISE);
END
END ;
About generators
A generator is a mechanism that creates a unique, sequential number that is automatically
inserted into a column in a read-write database when SQL data manipulation operations
such as INSERT or UPDATE occur. Generators are typically used to produce unique values
that can be inserted into a column that is used as a PRIMARY KEY. For example, a
programmer writing an application to log and track invoices may want to ensure that each
invoice number entered into the database is unique. The programmer can use a generator to
create the invoice numbers automatically, rather than writing specific application code to
accomplish this task.
Any number of generators can be defined for a database, as long as each generator has a
unique name. A generator is global to the database where it is declared. Any transaction
that activates the generator can use or update the current sequence number. InterBase will
not assign duplicate generator values across transactions.
Creating generators
To create a unique number generator in the database, use the CREATE GENERATOR
statement. CREATE GENERATOR declares a generator to the database and sets its starting
value to zero (the default). If you want to set the starting value for the generator to a
number other than zero, use SET GENERATOR to specify the new value.
Using generators
Once a generator has been created using the CREATE GENERATOR statement, it exists
within the database but no numbers have actually been generated. To invoke the number
generator, you must call the InterBase GEN_ID() function. GEN_ID() takes two arguments:
the name of the generator to call, which must already be defined for the database, and a
step value, indicating the amount by which the current value should be incremented (or
decremented, if the value is negative). GEN_ID() can be called from within a trigger, a
stored procedure, or an application whenever an INSERT, UPDATE, or DELETE operation
occurs. Applications can also use GEN_ID() with SELECT statements to obtain a generator
value for inclusion as part of an INSERT statement.
The syntax for GEN_ID() is:
GEN_ID(genname, step);
To generate a number, follow these steps:
1 Create the generator.
2 Within a trigger, stored procedure, or application, reference the generator with a call to
GEN_ID().
3 The generator returns a value when a trigger fires, or when a stored procedure or
application executes. It is up to the trigger, stored procedure, or application to use the
value. For example, a trigger can insert the value into a column.
To stop inserting a generated number in a database column, delete or modify the trigger,
stored procedure, or application so that it no longer invokes GEN_ID().
Important Generators return a 64-bit value. You should define the column that holds the generated
value as an ISC_INT64 variable with a DECIMAL or NUMERIC data type.
Example The following statement uses GEN_ID() to call the generator G to increment a purchase
order number in the SALES table by one:
INSERT INTO SALES (PO_NUMBER) VALUES (GEN_ID(G,1));
For more information on using generators in triggers, see Chapter 10, “Working with
Triggers.” For more information on using generators in stored procedures, see Chapter 9,
“Working with Stored Procedures.”
Dropping generators
To drop a generator from a database, use the following syntax:
DROP GENERATOR generator_name
The DROP GENERATOR command checks for any existing dependencies on the
generator (as in triggers or UDFs) and fails if such dependencies exist. The statement fails
if generator_name is not the name of a generator defined on the database. An application
that tries to call a deleted generator returns runtime errors.
Note In previous versions of InterBase that lacked the DROP GENERATOR command, users
issued a SQL statement to delete the generator from the appropriate system table. This
approach is strongly discouraged now that the DROP GENERATOR command is available,
since modifying system tables always carries with it the possibility of rendering the entire
database unusable as a result of even a slight error or miscalculation.
Planning Security
Chapter 12
• Grant SELECT, INSERT, UPDATE, and DELETE privileges for a view to users, triggers,
stored procedures, or views (optionally WITH GRANT OPTION)
• Grant SELECT, INSERT, UPDATE, DELETE, DECRYPT, and REFERENCES privileges for a table
to a role
• Grant SELECT, INSERT, UPDATE, DECRYPT, and DELETE privileges for a view to a role
• Grant ENCRYPT ON ENCRYPTION permission to a user
• Grant a role to users (optionally WITH ADMIN OPTION)
• Grant EXECUTE permission on a stored procedure to users, triggers, stored procedures, or
views (optionally WITH GRANT OPTION)
Privileges available
The following table lists the SQL access privileges that can be granted and revoked:
Table 12.1 SQL access privileges
Privilege Access
ALL Select, insert, update, delete data, and reference a primary key from a foreign key
SELECT Read data
INSERT Write new data
UPDATE Modify existing data
DELETE Delete data
ENCRYPT ON Enables the database owner or individual table owner to use a specific
ENCRYPTION encryption key to encrypt a database or column. Only the SYSDSO
(Data Security Owner) can grant encrypt permission. For information
about the InterBase encryption feature, which enables encryption at the
database and column levels, and about the privileges needed to grant and
revoke encrypt and decrypt permissions, see Chapter 13, “Encrypting
Your Data.”
Privilege Access
DECRYPT After encrypting a column, the database owner or the individual table
owner can grant decrypt permission to users who need to access the
values in an encrypted column. For information about the InterBase
encryption feature, which enables encryption at the database and column
levels, and about the privileges needed to grant and revoke encrypt and
decrypt permissions, see Chapter 13, “Encrypting Your Data.”
REFERENCES Reference a primary key with a foreign key
EXECUTE Execute or call a stored procedure
The ALL keyword provides a mechanism for assigning SELECT, DELETE, INSERT, UPDATE,
and REFERENCES privileges using a single keyword. ALL does not grant a role or the
EXECUTE privilege. SELECT, DELETE, INSERT, UPDATE, and REFERENCES privileges can also be
granted or revoked singly or in combination.
Note Statements that grant or revoke either the EXECUTE privilege or a role cannot grant or revoke
other privileges.
SQL ROLES
InterBase implements features for assigning SQL privileges to groups of users, fully
supporting SQL group-level security with the GRANT, REVOKE, and DROP ROLE
statements. It partially supports GRANT ROLE and REVOKE ROLE.
Note These features replace the Security Classes feature in versions prior to InterBase 5. In the
past, group privileges could be granted only through the InterBase-proprietary GDML
language. In Version 5, new SQL features were added to assist in migrating InterBase users
from GDML to SQL.
Using roles
Implementing roles is a four-step process.
1 Create a role using the CREATE ROLE statement.
2 Assign privileges to the role using GRANT privilege TO rolename.
3 Grant the role to users using GRANT rolename TO user.
4 Users specify the role when attaching to a database.
These steps are described in detail in this chapter. In addition, the CONNECT, CREATE ROLE,
GRANT, and REVOKE statements are described in the Language Reference.
Granting privileges
You can grant access privileges on an entire table or view or to only certain columns of the
table or view. This section discusses the basic operation of granting privileges.
• Granting multiple privileges at one time, or granting privileges to groups of users is
discussed in “Multiple privileges and multiple grantees” on page 12-6.
• “Using roles to grant privileges” on page 12-8 discusses both how to grant
privileges to roles and how to grant roles to users.
• You can grant access privileges to views, but there are limitations. See “Granting
access to views” on page 12-11.
• The power to grant GRANT authority is discussed in “Granting users the right to
grant privileges” on page 12-9.
• Granting EXECUTE privileges on stored procedures is discussed in “Granting privileges
to execute stored procedures” on page 12-11.
<object> = {
PROCEDURE procname
| TRIGGER trigname
| VIEW viewname
| PUBLIC
}[, <object> …]
<userlist> = {
[USER] username
| rolename
| UNIX_user
}[, <userlist> …]
<role_granted> = rolename[, rolename …]
<role_grantee_list> = [USER] username[, [USER] username …]
Notice that this syntax includes the provisions for restricting UPDATE or REFERENCES to
certain columns, discussed on the next section, “Granting access to columns in a
table”
The following statement grants SELECT privilege for the DEPARTMENTS table to a user, EMIL:
GRANT SELECT ON DEPARTMENTS TO EMIL;
The next example grants REFERENCES privileges on DEPARTMENTS to EMIL, permitting EMIL
to create a foreign key that references the primary key of the DEPARTMENTS table, even
though he doesn’t own that table:
GRANT REFERENCES ON DEPARTMENTS(DEPT_NO) TO EMIL;
Tip Views offer a way to further restrict access to tables, by restricting either the columns or the
rows that are visible to the user. See Chapter 8, “Working with Views” for more
information.
Important When a trigger, stored procedure or view needs to access a table or view, it is sufficient for
either the accessing object or the user who is executing it to have the necessary
permissions.
The following statement grants the INSERT privilege for the ACCOUNTS table to the
procedure, MONEY_TRANSFER:
GRANT INSERT ON ACCOUNTS TO PROCEDURE MONEY_TRANSFER;
Tip As a security measure, privileges to tables can be granted to a procedure instead of to
individual users. If a user has EXECUTE privilege on a procedure that accesses a table, then
the user does not need privileges to the table.
Procedures can be assigned ALL privileges. When a procedure is assigned privileges, the
PROCEDURE keyword must precede its name. For example, the following statement grants
all privileges for the ACCOUNTS table to the procedure, MONEY_TRANSFER:
GRANT ALL ON ACCOUNTS TO PROCEDURE MONEY_TRANSFER;
The following statement assigns SELECT access to user EMIL and allows EMIL to grant
SELECT access to other users:
GRANT SELECT ON DEPARTMENTS TO EMIL WITH GRANT OPTION;
Note You cannot assign the WITH GRANT OPTION to a stored procedure.
WITH GRANT OPTION clauses are cumulative, even if issued by different users. For example,
EMIL can be given grant authority for SELECT by one user, and grant authority for INSERT by
another user. For more information about cumulative privileges, see “Grant authority
implications” on page 12-10.
• Users can grant privileges to any table or view that they own.
• Users can grant any privileges on another user’s table or view when they have been
assigned those privileges WITH GRANT OPTION.
• Users can grant privileges that they have acquired by being granted a role WITH ADMIN
OPTION.
For example, in an earlier GRANT statement, EMIL was granted SELECT access to the
DEPARTMENTS table WITH GRANT OPTION. EMIL can grant SELECT privilege to other users.
Suppose EMIL is now given INSERT access as well, but without the WITH GRANT OPTION:
GRANT INSERT ON DEPARTMENTS TO EMIL;
EMIL can SELECT from and INSERT to the DEPARTMENTS table. He can grant SELECT
privileges to other users, but cannot assign INSERT privileges.
To change a user’s existing privileges to include grant authority, issue a second GRANT
statement that includes the WITH GRANT OPTION clause. For example, to allow EMIL to grant
INSERT privileges on DEPARTMENTS to others, reissue the GRANT statement and include the
WITH GRANT OPTION clause:
When full control of access privileges on a table is desired, grant authority should not be
assigned indiscriminately. In cases where privileges must be universally revoked for a user
who might have received rights from several users, there are two options:
• Each user who assigned rights must issue an appropriate REVOKE statement.
• The table’s owner must issue a REVOKE statement for all users of the table, then issue
GRANT statements to reestablish access privileges for the users who should not lose their
rights.
For more information about the REVOKE statement, see “Revoking user access” on
page 12-13.
Any view that is based on a join or an aggregate is considered to be a read-only view, since
it is not directly update-able. Views that are based on a single table which have no
aggregates or reflexive joins are often update-able. See “Types of views: read-only and
update-able” on page 8-5 for more information about this topic.
Important It is meaningful to grant INSERT, UPDATE, and DELETE privileges for a view only if the view
is update-able. Although you can grant the privileges to a read-only view without receiving
an error message, any actual write operation fails because the view is read-only. SELECT
privileges can be granted on a view just as they are on a table, since reading data from a
view does not change anything.
You cannot assign REFERENCES privileges to views.
Tip If you are creating a view for which you plan to grant INSERT and UPDATE privileges, use
the WITH CHECK OPTION constraint so that users can update only base table rows that are
accessible through the view.
Update-able views
You can assign SELECT, UPDATE, INSERT, and DELETE privileges to update-able views, just
as you can to tables. UPDATES, INSERTS, and DELETES to a view are made to the view’s base
tables. You cannot assign REFERENCES privileges to a view.
The syntax for granting privileges to a view is:
GRANT <privileges> ON viewname
TO {<object> | <userlist> | GROUP UNIX_group};
<privileges> = ALL [PRIVILEGES] | <privilege_list>
<privilege_list> = {
SELECT
| DELETE
| INSERT
| UPDATE [(col [, col …])]
}
[, <privilege_list> …]
<object> = {
PROCEDURE procname
| TRIGGER trigname
| VIEW viewname
| PUBLIC
}
[, <object> …]
<userlist> = {
[USER] username
| rolename
| UNIX_user
}
[, <userlist> …]
[WITH GRANT OPTION]
When a view is based on a single table, data changes are made directly to the view’s
underlying base table.
For UPDATE, changes to the view affect only the base table columns selected through the
view. Values in other columns are invisible to the view and its users and are never changed.
Views created using the WITH CHECK OPTION integrity constraint can be updated only if the
UPDATE statement fulfills the constraint’s requirements.
For DELETE, removing a row from the view, and therefore from the base table removes all
columns of the row, even those not visible to the view. If SQL integrity constraints or
triggers exist for any column in the underlying table and the deletion of the row violates
any of those constraints or trigger conditions, the DELETE statement fails.
For INSERT, adding a row to the view necessarily adds a row with all columns to the base
table, including those not visible to the view. Inserting a row into a view succeeds only
when:
• Data being inserted into the columns visible to the view meet all existing integrity
constraints and trigger conditions for those columns.
• All other columns of the base table are allowed to contain NULL values.
For more information about working with views, see Chapter 8, “Working with Views.”
Read-only views
When a view definition contains a join of any kind or an aggregate, it is no longer a legally
update-able view, and InterBase cannot directly update the underlying tables.
Note You can use triggers to simulate updating a read-only view. Be aware, however, that any
triggers you write are subject to all the integrity constraints on the base tables. To see an
example of how to use triggers to “update” a read-only view, see “Updating views with
triggers” on page 10-14.
For more information about integrity constraints and triggers, see Chapter 10, “Working
with Triggers.”
<object> = {
PROCEDURE procname
| TRIGGER trigname
| VIEW viewname
| PUBLIC
} [, <object> …]
<userlist> = [USER] username [, [USER] username …]
The following statement removes the SELECT privilege for the user, SUSAN, on the
DEPARTMENTS table:
Revocation restrictions
The following restrictions and rules of scope apply to the REVOKE statement:
• Privileges can be revoked only by the user who granted them.
• Other privileges assigned by other users are not affected.
• Revoking a privilege for a user, A, to whom grant authority was given, automatically
revokes that privilege for all users to whom it was subsequently assigned by user A.
• Privileges granted to PUBLIC can only be revoked for PUBLIC.
Important If you drop a role using the DROP ROLE statement, all privileges that were conferred by that
role are revoked.
RENEE no longer has any of the access privileges that she acquired as a result of
membership in the DOITALL role. However, if any others users have granted the same
privileges to her, she still has them.
Important PUBLIC does not revoke privileges for stored procedures. PUBLIC cannot be used to strip
privileges from users who were granted them as individual users.
Note Be careful when creating a view from base tables that contain sensitive information.
Depending on the data included in a view, it may be possible for users to recreate or infer
the missing data.
You cannot specify which pages in a database to encrypt. Instead, you issue the encrypt
database command from the database to which you are connected, and InterBase
encrypts all the user-related pages in that database.
• Column-level encryption:
Column-level encryption is both more flexible and more specific. To encrypt a column,
you specify the table that contains the column, followed by the name of the column. You
can encrypt all of the columns in a table, or only individual columns you specify. For
example, you can encrypt a payroll column in an Employee table so that both payroll
and HR employees can access it. Then you might encrypt SSN information in the same
table so that only payroll employees can access it. Users who need to access data in
encrypted columns can be given decrypt privileges for that column.
Generally speaking, encrypting all of a database’s user pages takes much greater overhead
than selectively encrypting individual columns. In addition, database performance can be
adversely affected when a large number of concurrent queries access the same encrypted
columns.
You must keep the SYSDSO user for as long as you use the encryption keys created by that
same SYSDSO.
If the SET PASSWORD clause is not specified, the default SYSDSO password will be the
password of the person who creates the account. This makes it easier for the account
creator to temporarily acquire SYSDSO privileges to create and test encryptions during
development without having to login to do so. When the SYSDSO password is
subsequently changed, the account creator loses this privilege. Presumably, this handoff
would occur at deployment time, when transferring these duties to a security authority.
• Due to government regulation of strong encryption, you must obtain a license from
InterBase to use AES with InterBase.You do not need a special license to use DES
with InterBase.
• This feature requires ODS 13 and is not available on older ODS databases. Therefore,
a backup and restore to ODS 13 is required for pre-existing databases to use InterBase
encryption. For information about performing backups and restores, see the InterBase
Operations Guide.
Note InterBase uses OpenSSL or a derivation of that version to support InterBase encryption.
InterBase embeds OpenSSL libraries in InterBase server/client to help implement
encryption-related features. OpenSSL contains libraries for the most widely known
encryption and message digest algorithms in use today. InterBase uses these libraries as the
basis for supporting database and column-level encryption functionality.
The string can be up to 255 characters long and can include spaces. The system encryption
password is encrypted with a key derived from machine specific information and stored in
the database. This effectively node locks the database to the machine but allows the
database to be attached without a user having to pass the system encryption password in
plaintext. Thus, subsequent connections on the same machine need not provide the SEP.
However, if the database file is copied and installed on a different machine, the node-lock
feature disallows direct loading of the database without the user providing the SEP. After
moving a database with a node-locked SEP to another machine, you must login as
SYSDSO with the current SEP set via the SEP environment variable or DPB. The
SYSDSO can then perform ALTER DATABASE SET SYSTEM ENCRYPTION PASSWORD to create
a new SEP.
Just “setting” the SEP to connect to the database does not redefine or re-node-lock the SEP.
Users can continue to provide the SEP externally though you may want to alter the sep
command to re-node-lock it to the new machine.
where CREATE ENCRYPTION is the command, and “payroll_key” is the name of the key
created. Thus, the basic syntax for creating an encryption key is:
CREATE ENCRYPTION key-name for AES | for DES
To create an encryption key using all of the available isql statement options, use the
following syntax:
create encryption key-name [as default] [for {AES | DES}] [with length
number-of-bits [bits]]
[password {'user-password' | system encryption password}]
[init_vector {NULL | random}] [pad {NULL | random}]
[description ‘some user description’]
For example:
CREATE ENCRYPTION revenue_key FOR AES WITH LENGTH 192 BITS INIT_VECTOR
RANDOM
Option Description
Default This key is used as the database default when no explicit key is
named for database or column encryption.
Length Specifies key length. If using DES, 56 bits is the default. If using
AES, you can specify 128, 192, or 256 bits. For AES, 128 is the
default.
Option Description
Note A random initialization vector or random padding prevents an encrypted column from being
used in an index, and raises an error if a create index DDL statement tries to do so. The
NULL defaults for both of these options favor index-enabled access optimization over a
more stringent level of protection afforded by the random counterparts.
Assuming the same user also has decrypt and access permissions on the column, he or she
can now access all columns encrypted by that key.
gives the SYSDBA permission to use the payroll-key to encrypt a database or a column.
Important Only the user who encrypts a column or database can grant decrypt privileges to those who
need to view the encrypted data. Only the database owner can grant decrypt privileges.
Encrypting data
As indicated at the beginning of this chapter, InterBase can be used to encrypt data at the
database-level, and to encrypt specific columns in a database. Generally speaking,
encrypting at the column-level offers the greatest data protection. When you encrypt at the
database- or column-level, it is also recommended that you encrypt the database’s backup
files. For instructions on how to do so, see “Encrypting backup files” on page 13-18.
uses the fin_key to encrypt all the database pages in the current database (i.e. in the
database to which you are connected).
To encrypt a column in an existing table, use the following syntax:
alter table table-name (alter column column-name encrypt [[with] key-
name]
A decrypt default can be changed or dropped from a column. Note that a decrypt default is
not automatically dropped when a column is decrypted.
alter table table-name alter [column] column-name [no] decrypt default
value
The workaround described here also pertains to special cases in which one of the blobs is
not encrypted. If an encrypted blob ID is assigned to a blob column with no encryption, the
assignment is allowed but a warning error is returned.
Decrypting data
Only the database owner can perform database-level decryption. Decrypting a database
causes all pages to be decrypted and rewritten in plaintext.
To decrypt a database, use the following syntax:
alter database decrypt
Decrypting columns
A column can be re-encrypted with another key or decrypted. The table needs exclusive
access before this operation can proceed. All rows in the table are re-encrypted and the
former column data, including blobs, are zeroed from the database so that it is no longer
visible. If more than a single column in a table is altered for a change in encryption, you
should disable auto-commit of DDL statements. This allows the multiple columns to be re-
encrypted in a single pass over the table, which can save time on very large tables.
To decrypt a column, use the following syntax:
alter table table-name alter [column] column-name decrypt
Note If the database owner or the individual table owner has explicitly granted execute and select
privileges to users on stored procedures and views, respectively, a chain of ownership
implicitly grants decrypt privilege on any referenced encrypted columns in those schema
elements owned by that schema owner.
After issuing these commands, all the members in the HR_role can use their role affiliation
to decrypt columns A and B.
Similarly, you can give users access to a view that has decrypt access to encrypted
columns. First you create the view:
CREATE VIEW Payroll_View as SELECT
Column_C, Column_D, Column_E, Column_I FROM Payroll
Payroll_View now contains data from columns C, D, E, and I. Next, you can grant decrypt
access to encrypted columns on Payroll to view Payroll_View:
GRANT DECRYPT (Column_C, Column_D, Column_E, Column I) ON Payroll TO VIEW
Payroll_View
or to all the users assigned to a role (after creating the role), as shown below:
GRANT SELECT ON Payroll_View TO Payroll_Role
To revoke decrypt permission, the database or table owner uses the following syntax:
revoke decrypt[(column-name, …)] on table-name from {user-name | role-
name | public}
6 Type in an Alias, and click OK to create the database. This both enables EUA and
performs database-level encryption. Notice that the Encrypt Database appears action
at the bottom of the right pane of IBConsole.
For more information about Embedded User Authentication, see the InterBase
Operations Guide.
4 Click OK to enable EUA. This action also enables encryption: notice that the Encrypt
Database action appears at the bottom of the right pane of IBConsole.
For more information about Embedded User Authentication, see the InterBase
Operations Guide.
5 On Encryption Wizard, Step 2, shown in Figure 13.4, create and confirm a System
Encryption Password. Then click Next.
6 On Encryption Wizard, Step 3, shown in Figure 13.5, type a name for the Encryption
Key in the Encryption Name field. Change the fields in the Options section as desired.
For a description of each option, see Table 13.2 earlier in this chapter.
7 Click OK to complete the database-level encryption process. You’ll now see a dialog
confirming that the database is encrypted.
For more information about using the GBAK -b and -r options to perform database backups
and restores, see the InterBase Operations Guide.
Collation Orders
This chapter discusses the following topics:
• Available character sets and their corresponding collation orders
• Character set storage requirements
• Specifying default character set for an entire database
• Specifying an alternative character set for a particular column in a table
• Specifying a client application character set that the server should use when translating
data between itself and the client
• Specifying the collation order for a column
• Specifying the collation order for a value in a comparison operation
• Specifying the collation order in an ORDER BY clause
• Specifying the collation order in a GROUP BY clause
Each character set also has an implicit collation order that specifies how its symbols are
sorted and ordered. Some character sets also support alternative collation orders. In all
cases, choice of character set limits choice of collation orders. InterBase supports four
different types of collation order: Windows, dBASE, Paradox, and ISO. The ISO collation
sequence is recommended in preference to the other three.
DOS437 437
DOS850 850
DOS852 852
DOS857 857
DOS860 860
DOS861 861
DOS863 863
DOS865 865
The names of collation orders for these character sets that are specific to Paradox begin
“PDOX”. For example, the DOS865 character set for DOS code page 865 supports a
Paradox collation order for Norwegian and Danish called “PDOX_NORDAN4”.
The names of collation orders for these character sets that are specific to dBASE begin
“DB”. For example, the DOS437 character set for DOS code page 437 supports a dBASE
collation order for Spanish called “DB_ESP437”.
For more information about DOS code pages, and Paradox and dBASE collation orders,
see the appropriate Paradox and dBASE documentation and driver books.
Note InterBase 2008 does not support UNICODE collations in this release. The default collation
is binary sort order for UNICODE.
Specifying defaults
This section describes the mechanics of specifying character sets for databases, table
columns, and client connections. In addition, it describes how to specify collation orders
for columns, comparisons, ORDER BY clauses, and GROUP BY clauses.
To specify a default character set, use the DEFAULT CHARACTER SET clause of CREATE
DATABASE. For example, the following statement creates a database that uses the
ISO8859_1 character set:
CREATE DATABASE 'europe.ib' DEFAULT CHARACTER SET ISO8859_1;
Important If you do not specify a character set, the character set defaults to NONE. Using character set
NONE means that there is no character set assumption for columns; data is stored and
retrieved just as you originally entered it. You can load any character set into a column
defined with NONE, but you cannot later move that data into another column that has been
defined with a different character set. In this case, no transliteration is performed between
the source and destination character sets, and errors may occur during assignment.
For the complete syntax of CREATE DATABASE, see Language Reference.
For the complete syntax of SET NAMES, see Language Reference. For the complete syntax
of CONNECT, see the Language Reference.
...
ORDER BY LNAME COLLATE FR_CA, FNAME COLLATE FR_CA;
For the complete syntax of the ORDER BY clause, see the Language Reference.
I-1
column names syntax 9-4 to 9-5
length 6-2 CREATE SHADOW 3-1, 3-10 to 3-13
modifying 6-22 CREATE TABLE 1-2, 6-2 to 6-13
specifying 6-2 EXTERNAL FILE option 6-13 to 6-17
views 8-3 CREATE TRIGGER 10-2 to 10-9
column-level encryption POSITION clause 10-7
about 13-2 syntax 10-3
commands used 13-9 CREATE VIEW 8-3 to 8-7
decrypting columns 13-11 creating metadata 1-2
of blob columns 13-10
columns D
adding 6-19 to 6-20
attributes 6-2 to 6-3 data
BLOB 4-17 dropping 6-24
circular references 6-10 to 6-11 exporting 6-16 to 6-17
computed 6-5 to 6-6 importing 6-15 to 6-16
datatypes 6-3 protecting See security
default values 6-6 retrieving 9-11, 9-20
defining 2-9, 5-1, 6-2 to 6-13 multiple rows 9-3, 9-12
domain-based 6-5 saving 6-18
dropping 6-19, 6-21 sorting 14-2
encrypting 13-2 storing 14-1
inheritable characteristics 5-1 updating 10-8
local 5-1, 5-2, 5-3 data definition 1-1
NULL status 2-10 data definition files 1-4, 3-2
NULL values 6-7 stored procedures and 9-2 to 9-3
sorting 6-4 triggers and 10-2
specifying character sets 14-9 Data Encryption Standard (DES)
specifying datatypes 6-3 to 6-4 about 13-2
comments 9-14 data entry, automating 10-1
comparing values 10-8 data manipulation statements 1-1
composite keys 2-14 stored procedures and 9-5
computed columns 6-5 to 6-6 triggers and 10-4
conditional shadows 3-12 data model 2-2, 2-6
conditions, testing 9-12, 9-13 database cache buffers 2-16
constraints database objects 2-2
adding 6-20 Database Security Owner (SYSDSO)
declaring 6-11 to 6-12 about 13-3
defining 2-10 to 2-12, 6-7 to 6-13 creating 13-3
dropping 6-21 database-level encryption
triggers and 10-12 about 13-1
context variables 10-8 command used 13-9
See also triggers decrypting 13-11
converting datatypes 4-24 databases
CREATE DATABASE 1-2, 3-1, 3-2 to 3-6 designing 2-1 to 2-17
CREATE DOMAIN 5-1 to 5-5, 6-5 dropping 3-8
CREATE ENCRYPTION command encrypting 13-1
about 13-6 file naming conventions 3-2
using 13-6 multifile 3-4 to 3-5
CREATE EXCEPTION 9-26 naming 3-2
CREATE GENERATOR 10-9, 11-1 to 11-2 normalization 2-1, 2-12 to 2-15
CREATE INDEX 7-2 to 7-5 page size
CREATE PROCEDURE 9-4 to 9-17 changing 3-3, 3-5
RETURNS clause 9-8 default 3-5
Index I-3
encrypting backup files 13-18 expression-based columns See computed columns
granting decrypt permissions 13-11 EXTERNAL FILE option 6-13 to 6-17
of blob columns 13-10 restrictions 6-14 to 6-15
overview of tasks 13-4 external files 6-13
requirements 13-4 See also external tables
revoking permissions 13-12 EXTERNAL_FILE_DIRECTORY 6-14
setting the System Encryption Password (SEP) 13-5 location 6-14
SYSDSO, about 13-3 removing 6-24
table owner external tables 6-13 to 6-17
about 13-3 exporting 6-16
tasks 13-4 importing 6-15
users 13-3 location 6-14
using IBConsole to setup and perform permitted operations 6-15
encryption 13-13 record length 6-14
using isql to enable and perform encryption 13-5 uses 6-14
encryption keys VARCHAR format 6-15
about 13-6 EXTERNAL_FILE_DIRECTORY 6-14
creating 13-6 extracting metadata 3-1, 3-14
dropping 13-8
granting permission to use 13-9 F
END 9-15 to 9-17
END keyword 9-9 factorials 9-15
entities 2-2, 2-4, 2-6 files
attributes 2-4 See also specific files
error codes 9-29 data definition 1-4, 3-2
error messages 9-26, 10-15 exporting 6-16 to 6-17
stored procedures 9-7 external 6-13
triggers 10-6 importing 6-15 to 6-16
error-handling routines naming 3-2
SQL 9-28 naming conventions 3-2
stored procedures 9-27 to 9-32 primary 3-3
triggers 10-15 to 10-16 secondary 3-3, 3-4 to 3-5, 3-7
errors 9-29 firing triggers 10-3, 10-7, 10-12
stored procedures 9-7, 9-16, 9-17, 9-29 security 10-13
syntax 9-7, 10-6 fixed-decimal datatypes 4-5 to 4-8
triggers 10-6, 10-7, 10-13, 10-16 FLOAT datatype 4-3, 4-10 to 4-11
user-defined See exceptions floating-point datatypes 4-10 to 4-11
events 9-13 FOR SELECT . . . DO 9-12
See also triggers FOREIGN KEY constraints 2-10 to 2-12, 6-8 to 6-9,
posting 10-13 7-2
exact numerics 4-5 functions
EXCEPTION 9-27 user-defined See UDFs
exceptions 9-26 to 9-27, 10-1
behavior 10-15 G
dropping 9-26
gbak 7-5
handling 9-28
GEN_ID() 10-9, 11-2 to 11-3
in triggers 10-15
generators 10-9, 11-2 to ??
raising 10-15
defined 11-1
triggers and 10-15
initializing 10-9
executable procedures 9-3, 9-20
resetting, caution 11-2
terminating 9-15
gpre
EXECUTE PROCEDURE 9-11, 9-20
BLOB data 4-18
EXIT 9-15 to 9-17
GRANT 12-1 to 12-13
exporting data 6-16 to 6-17
decrypt 13-11
Index I-5
altering 1-2 output parameters 9-8, 9-10, 9-16
creating 1-2 See also stored procedures
dropping 1-2 viewing 9-20
extracting 3-1, 3-14 owner
name length 6-2 stored procedures 9-2
modifying See altering;updating
MS-DOS code pages 14-6 P
multi-column indexes 7-1, 7-4 to 7-5
defined 7-2 page size
multifile databases 3-4 to 3-5 indexes 2-16
multifile shadows 3-11 shadowing 3-11
multiple triggers 10-7 Paradox for Windows 14-7
parameters
N input 9-8, 9-10
output 9-8, 9-10, 9-16
naming viewing 9-20
database files 3-2 partial key dependencies, removing 2-14
metadata name length 6-2 passwords
objects 2-17 See also security
stored procedures 9-4 specifying 3-3, 3-5
triggers 10-7 permissions
variables 9-14 to decrypt 13-11
NATIONAL CHAR datatype 4-12, 4-14 to 4-15 precision of datatypes 4-8
NATIONAL CHAR VARYING datatype 4-12 preprocessor See gpre
NATIONAL CHARACTER datatype 4-12 primary files 3-3
NATIONAL CHARACTER VARYING datatype 4-12 PRIMARY KEY constraints 2-7, 2-10 to 2-12, 6-7 to
NCHAR datatype 4-12, 4-15 to 4-16 6-8, 7-2
NCHAR VARYING datatype 4-12 privileges See security
nested stored procedures 9-14 to 9-15 procedures See stored procedures
NEW context variables 10-8 protecting data See security
NONE keyword 3-6, 4-13 to 4-14 PUBLIC keyword 12-7
normalization 2-1, 2-12 to 2-15
NOT NULL 5-3 Q
NULL status 2-10
NULL values queries
columns 6-7 See also SQL
domains 5-3 optimizing 7-4
numbers
incrementing 10-9 R
NUMERIC datatype 4-3, 4-5 to 4-8, 4-9
raising exceptions 9-27, 10-15
numeric datatypes 4-4 to 4-11
RDB$RELATION_CONSTRAINTS system table 6-11
numeric values See values
read-only databases 3-6
read-only views 8-5 to 8-6
O recursive stored procedures 9-14 to 9-15
objects 2-2 REFERENCES privilege 6-10, 12-5
naming 2-17 referential integrity See integrity constraints
relationships 2-10 relational model 2-10
OLD context variables 10-8 repeating groups, eliminating 2-12 to 2-13
ON DELETE 2-11, 6-9 repetitive statements 9-12
ON UPDATE 2-11, 6-9 retrieving data 9-11, 9-20
optimizing multiple rows 9-3, 9-12
queries 7-4 return values, stored procedures 9-8, 9-10
ORDER BY clause 7-4 incorrect 9-24
output 9-20 REVOKE 12-13 to 12-17
Index I-7
stored procedures 9-20 to 9-25 System Encryption Password (SEP)
altering 9-2, 9-17 about 13-5
arrays and 9-8, 9-24 to 9-25 removing 13-6
calling 9-3, 9-20 setting 13-5
creating 9-2, 9-3, 9-4 to 9-17 system tables 1-2
data definition files and 9-2 to 9-3 system-defined indexes 7-2, 7-7
dependencies system-defined triggers 10-12
viewing 9-17
documenting 9-2, 9-14 T
dropping 9-18
error handling 9-27 to 9-32 tables 6-1 to 6-24
exceptions 9-26 to 9-27, 9-28 altering 6-17 to 6-23
events 9-13 caution 6-19
exiting 9-15 circular references 6-10 to 6-11
headers 9-4, 9-8 creating 6-2 to 6-13
output parameters 9-11 declaring 6-1
isql and 9-2 defined 2-6
naming 9-4 designing 2-6
nested 9-14, 9-15 dropping 6-24
overview 9-1 to 9-2 external 6-13 to 6-17
powerful SQL extensions 9-5 testing
privileges 9-3 applications 10-7
procedure body 9-4, 9-9 to 9-17 triggers 10-7
input parameters 9-8, 9-10 text 14-1
local variables 9-9, 9-11 TIME datatype 4-3
output parameters 9-8, 9-10, 9-16 time indicator (triggers) 10-7, 10-10
viewing 9-20 TIMESTAMP datatype 4-3, 4-24
recursive 9-14, 9-15 tokens, unknown 9-8, 10-6
retrieving data 9-3, 9-11, 9-12, 9-20 transactions
return values 9-8, 9-10 triggers and 10-12
incorrect 9-24 transitively-dependent columns, removing 2-14 to 2-15
security 12-8, 12-11 triggers 10-1 to 10-16
suspending execution 9-15 access privileges 10-13
syntax errors 9-7 altering 10-2, 10-10 to 10-11
testing conditions 9-12, 9-13 creating 10-2 to 10-9
types, described 9-3 data definition files and 10-2
storing dropping 10-11 to 10-12
Blob IDs 4-17 duplicating 10-7
data 14-1 error handling 10-16
structures, database 1-1, 2-2 exceptions 10-15
subscripts (arrays) 4-23 to 4-24 exceptions, raising 10-15
SUSPEND 9-15 to 9-17 firing 10-3, 10-7, 10-12, 10-13
syntax headers 10-2, 10-7, 10-10
assignment statements 9-11 inserting unique values 10-9
context variables 10-8 isql and 10-2
generators 10-9 multiple 10-7
stored procedures 9-4 to 9-5 naming 10-7
syntax errors posting events 10-13
stored procedures 9-7 raising exceptions 9-26, 10-15
triggers 10-6 referencing values 10-8
SYSDSO status 10-7
about 13-3 syntax errors 10-6
creating 13-3 system-defined 10-12
grant permission to use keys to encrypt 13-9 testing 10-7
Index I-9
I-10 Data Definition Guide