Delphi 7-Interbase Tutorial
Delphi 7-Interbase Tutorial
InterBase
This tutorial takes you step-by-step through the process of creating and using a database using the
InterBase Windows ISQL dialog. You learn to create data structures that enforce referential integrity
constraints and maintain security. You populate your tables, create triggers and stored procedures,
and learn a number of techniques for retrieving the data with precision.
There are five parts in this tutorial.
g In Part I, you learn how to use this tutorial, you start the InterBase server and log in to it, and you
create a user and a database.
g In Part II, you learn the fundamentals of database design and how to work in the InterBase Windows
ISQL environment; you create the data structures for your database, and you learn a little about how
to recover from errors.
g In Part III, you put data into the database (you populate it).
g In Part IV, you get the data out again (you access or retrieve it).
g In Part IV, you work with database security, and create some triggers and stored procedures to
automate some of your database tasks.
INTERBASE 5 TUTORIAL 1
PART I GETTING STARTED ■ Topic: USING THIS TUTORIAL
Typographic conventions
This tutorial document and the SQL scripts that accompany it use the following typographic
conventions:
· Database names, keywords, and domain names are in ALL CAPS.
· Table names have initial caps and are in italic.
· Names of columns, indexes, stored procedures, and triggers are lowercase italic.
· File and path names are in italic.
INTERBASE 5 TUTORIAL 3
PART I GETTING STARTED ■ Topic: STARTING THE LOCAL INTERBASE SERVER
SQL statements When you’re entering SQL statements into InterBase Windows ISQL, you can ignore the
capitalization. The conventions listed above are to make it easy to read and understand the
examples. You can enter the exercises in all lower case if you prefer.
Strings Strings (anything inside of quotation marks) are case sensitive. There are a lot of strings in single
quotes in this tutorial, and you must enter the case exactly as it’s shown.
External references When you refer to something outside of InterBase, such as a filename, the reference is case sensitive.
TABLE 1
Line breaks
g Line breaks are added within example statements to make them easy to read and understand. They
are not required.
g When you’re entering statements in InterBase Windows ISQL you don’t have to follow the line breaks
in the examples. Enter ones that make it easy for you to keep track of what you’re doing. InterBase
ignores line breaks within input SQL statements.
INTERBASE 5 TUTORIAL 4
PART I GETTING STARTED ■ Topic: CONNECTING TO A SERVER FROM SERVER MANAGER
2. To log in to the Local InterBase server, click the Server Login button or choose File | Server
Login to display the InterBase Login dialog.
Server Login
button
3. Click the Local Engine radio button and fill in the password for the SYSDBA user. By default,
this password is masterkey. If you have changed the password (highly recommended!),
use the current password. Click OK. In either case, you must log on as SYSDBA in order to
create a new user account.
INTERBASE 5 TUTORIAL 5
PART I GETTING STARTED ■ Topic: CREATING A NEW USER
An icon for the local server appears in the left pane of Server Manager.
INTERBASE 5 TUTORIAL 6
PART I GETTING STARTED ■ Topic: CREATING A NEW USER
2. In the InterBase Security dialog, click the Add User button to display the User
Configuration dialog.
3. Type TUTOR in the User Name field and tutor4ib in the Password and Confirm Password
fields.
4. Click OK to close the User Configuration dialog. Click OK to close the InterBase Security
dialog.
You have now created a user on the server you’re logged into. Users are defined server-wide and
can connect to any database that resides on that server. Tables within these databases have
additional security, however. Being able to connect to a database won’t do you much good if you
don’t have privileges on any of its tables.
5. Now choose File | Exit. Choose Yes when InterBase asks you if you want to log out from all
servers and exit Server Manager.
Note If you want to logout from a server without exiting Server Manager, choose File | Server Logout or
click the Server Logout button .
INTERBASE 5 TUTORIAL 7
PART I GETTING STARTED ■ Topic: CREATING A DATABASE
Creating a database
Now that you have used Server Manager to create a valid user name, you are ready to use InterBase
Windows ISQL to create the TUTORIAL database that you will use for the exercises in this tutorial.
InterBase databases are stored in files that, by convention, have a .gdb extension.
Status Bar
This dialog is described in more detail in “Using InterBase Windows ISQL” on page 12.
2. Choose a location for your TUTORIAL database. This example and the SQL script files use
C:\interbase5\tutorial\tutorial.gdb. If you choose a different location, you must edit the
CONNECT statement in the SQL script files to reflect the new location. (You’re instructed
how to do this a little later.)
3. Choose File | Create Database or click the Create Database button to display the Create
Database dialog.
Create
Database
button
INTERBASE 5 TUTORIAL 8
PART I GETTING STARTED ■ Topic: CREATING A DATABASE
Notice that this looks a lot like the dialog you saw when you connected to a server from Server
Manager. But there’s a difference: InterBase Windows ISQL combines logging in to a server with
connecting to a database. Creating a database is a special case of this: you log in to a server, create
a database, and connect to the new database all in one dialog.
4. Choose Local Engine.
5. In the Database field, type the full path to your new database, including the file name:
C:\interbase5\tutorial\tutorial.gdb
6. Type TUTOR in the User Name field. You can type it in lower case; it displays in caps
anyway. The User Name field displays the login of the last user who connected, so in the
future, you may find this field already filled in correctly.
7. Enter the tutor4ib password in the Password field. You can ignore the Database Options
field.
8. Click OK to create the TUTORIAL database. Its filename is tutorial.gdb.
You’ve now created a database named TUTORIAL that belongs to user TUTOR. You’re also logged in to
the server and connected to the new database. Look at the Status Bar at the bottom of the InterBase
Windows ISQL window: you should see the path and name of the database you just created. Whenever
you’re connected to a database, the name and path appear in the Status Bar.
INTERBASE 5 TUTORIAL 9
PART II DATA DEFINITION ■ Topic: DATABASE DESIGN
Database design
The crucial first step in constructing any database is database design. This step is so important that
volumes have been written about it. You can’t create a functional, efficient database without first
thinking through its components and desired functionality in great detail. Chapter 2 of the Data
Definition Guide provides a good introduction to the topic.
INTERBASE 5 TUTORIAL 10
PART II DATA DEFINITION ■ Topic: DATABASE DESIGN
You will see, as you progress through this tutorial, that the TUTORIAL database contains ten tables that
correspond exactly to the ten items above. To get an overview now, you can look at an article about
the EMPLOYEE database, since the EMPLOYEE database and the finished TUTORIAL database are identical.
Go to http://www.interbase.com/tech/exampledb/exampledb.html on the InterBase website.
INTERBASE 5 TUTORIAL 11
PART II DATA DEFINITION ■ Topic: AN OVERVIEW OF SQL
An overview of SQL
SQL statements fall into two major categories:
g Data definition language (DDL) statements
g Data manipulation language (DML) statements
DDL statements define, change, and delete the structures that hold data. These include the database
itself, tables, and other elements that are part of the database such as domains, indexes, triggers,
stored procedures, roles, and shadows. Collectively, the objects defined with DDL statements are
known as metadata. DDL statements begin with the keywords CREATE, ALTER, and DROP. For example,
CREATE TABLE defines a table, ALTER TABLE modifies an existing table, and DROP TABLE deletes a table.
DML statements manipulate data within these data structures. The four fundamental DML statements
are INSERT, UPDATE, DELETE, and SELECT. INSERT adds data to a table, UPDATE modifies existing data, and
DELETE removes data. The SELECT statement retrieves or queries information from the database. It is
the most important—and most complex—of all the SQL statements, because it is the means by which
you access all the information that you have so meticulously stored.
In Part II of this tutorial, you use several DDL statements—CREATE DOMAIN, CREATE TABLE, ALTER TABLE,
CREATE VIEW, and CREATE INDEX—to create data structures for your TUTORIAL database. In Part III, you
use the DML statements INSERT, UPDATE, and DELETE to add data to your database and modify it. Part
IV teaches you the all-important SELECT statement—also a DML statement. In Part V, you learn two
advanced DDL statements, CREATE PROCEDURE and CREATE TRIGGER.
Status Bar
INTERBASE 5 TUTORIAL 12
PART II DATA DEFINITION ■ Topic: AN OVERVIEW OF SQL
Executing statements
There are three ways to execute a statement in InterBase Windows ISQL:
g You can choose Query | Execute
g You can click the Execute Query button
g You can press w-u
You must execute each statement before entering the next one.
Note Although this method of entering SQL statements by hand one at a time is an option in
InterBase, users often use SQL scripts (data definition files) as a more convenient way of entering data.
See “Running an SQL script” on page 17 for more information.
INTERBASE 5 TUTORIAL 13
PART II DATA DEFINITION ■ Topic: CREATING DOMAINS
2. Check to see that the Auto Commit DDL box is checked. If necessary, enable the feature.
For further information on how to use InterBase Windows ISQL, see the Operations Guide.
Creating domains
A domain is a customized column definition that you use to create tables. When you create a table,
you specify the characteristics of each column in the table. Often, across the tables in a database, there
will be several columns that have the same characteristics. Rather than entering the same complex
definition for each column, you can create a name for the collection of characteristics. This named
set of column characteristics is called a domain. You can use this domain name in a column definition
rather than typing out the full definition.
IMPORTANT If you are going to use domains in your column definitions, you must create the domains before you
use them in table definitions.
Column characteristics include:
g Datatype
g Default value: a literal value, NULL, or the name of the current user (USER)
g Nullability: NOT NULL prohibits NULL values in the column (columns are nullable by default)
g CHECK constraints: checks that the value being entered meets specified criteria
g Character set and optional collation order (output sort order for CHAR and VARCHAR columns)
When you specify a column, only a column name and datatype are required. All other characteristics
are optional.
INTERBASE 5 TUTORIAL 14
PART II DATA DEFINITION ■ Topic: CREATING DOMAINS
Shortcuts You can skip this step if the correct path and name is already showing. If another name
is showing, but you have connected to this database recently, you can choose it from the dropdown
Database list. If it’s not on the dropdown list and you’ve forgotten the exact name and path of the
database, you can click the Browse button to locate it.
4. Type TUTOR in the User Name field and type tutor4ib in the Password field.
The Role field does not require an entry. The Role parameter is optional and is discussed in “Access
privileges” on page 63.
5. Choose OK.
TIP Look in the Status Bar to confirm that you are connected to the TUTORIAL database.
INTERBASE 5 TUTORIAL 15
PART II DATA DEFINITION ■ Topic: DATA DEFINITION FILES
1. Type the following code in the SQL Statement Area to define a domain called FIRSTNAME
that has a datatype of VARCHAR(15).
CREATE DOMAIN FIRSTNAME AS VARCHAR(15)
2. Execute the statement: click the button, press w-u, or choose Query | Execute.
3. Now create two more domains, LASTNAME and EMPNO. Execute each statement before
entering the next one.
CREATE DOMAIN LASTNAME AS VARCHAR(20)
TIP When you’re typing an SQL statement that has parentheses, take a moment to count the left
parentheses and the right parentheses and make sure that there are the same number of each.
Mismatched parentheses are a major source of errors in SQL code. In the example above, there are
nested parentheses: the CHECK clause is enclosed in parentheses because it contains three parts
(“A OR B OR C”) and the second part of the clause has parentheses because it also contains multiple
parts (“A AND B”).
The CREATE DOMAIN statement above is divided into several lines to make it easy for humans to follow
the syntax. InterBase ignores the line breaks when parsing the statement. Enter the whole statement
before executing it.
Note You don’t need to commit your work, because CREATE statements are DDL (data definition
language) statements. You turned Autocommit DDL on in the Session Settings earlier in this tutorial, so
all these DDL statements have been committed automatically.
INTERBASE 5 TUTORIAL 16
PART II DATA DEFINITION ■ Topic: RUNNING AN SQL SCRIPT
CONNECT ’C:\interbase5\tutorial\tutorial.gdb’
USER ’TUTOR’ PASSWORD ’tutor4ib’
If this is not the correct information for you, you must edit each SQL file and make the CONNECT string
correct. The SQL scripts are text files that you can modify in any text editor. If you use an application
that saves by default in a proprietary format, be sure to save the files as text.
5. Navigate to the location where you have stored the tutorial SQL files and highlight
Domains.sql. Click Open.
6. A dialog box appears, asking if you want to save the results to a file. Click No, since you
want to see the results in the SQL Output Area of the ISQL window.
(If you choose Yes, InterBase Windows ISQL prompts you for a filename in which to store the
output. No output appears in the SQL Output Area.)
InterBase reads the file and executes each statement and posts a message that says “Script
completed successfully.”
INTERBASE 5 TUTORIAL 17
PART II DATA DEFINITION ■ Topic: RUNNING AN SQL SCRIPT
Troubleshooting If you receive a message stating that there are errors, click the Details button and
read the information; it is often useful. Also check that the CONNECT information (database, user, and
password) in the script file is correct.
7. To confirm that the domains now exist, choose Metadata | Show, select Domain from the
View Information On list, and click OK.
You should see all the domains defined for the database displayed in the SQL Output area. (Note:
If you were not connected to tutorial.gdb before running the script, you will need to connect now
before the Show command is available.) You should see the following domains:
INTERBASE 5 TUTORIAL 18
PART II DATA DEFINITION ■ Topic: CREATING TABLES
Creating tables
A table is a data structure consisting of an unordered set of rows, each containing a specific number
of columns. Conceptually, a database table is like an ordinary table. Much of the power of relational
databases comes from defining the relations among the tables.
The CREATE TABLE statement has the following general form:
CREATE TABLE tablename (colname1 characteristics[, colname2 characteristics, …]
[, tableconstraint …])
g Characteristics must include a datatype and can also include several other things. See “Creating
domains” on page 14 for a list of column characteristics.
g A table constraint can be a CHECK, UNIQUE, FOREIGN KEY, or PRIMARY KEY constraint on one or more
columns.
For the full syntax of the CREATE TABLE statement, see the Language Reference.
In the following steps, you create three of the ten tables for the TUTORIAL database.
Notice that the collection of column definitions is surrounded by parentheses and that the columns
are separated by commas.
3. Execute the statement (click the button, press w-u or choose Query | Execute). If you
entered the code without errors, it appears in the SQL Output Area.
The dept_no column is the primary key for the table and is therefore UNIQUE. Primary keys are
discussed on page 21. Notice that the department column value must be unique and that neither
column can be null.
INTERBASE 5 TUTORIAL 19
PART II DATA DEFINITION ■ Topic: CREATING TABLES
The CHECK constraint at the end checks that the minimum salary is less than the maximum salary.
The three-column primary key guarantees that the combination of the three columns identifies a
unique row in the table.
The foreign key checks that any country listed in the Job table also exists in the Country table.
The BLOB datatype used for the job_requirement column is a dynamically sizable datatype that has
no specified size and encoding. It is used to store large amounts of data such as text, images,
sounds, and other multimedia content.
2. To check that the tables now exist in the database, choose Metadata | Show, choose Table
from the View Information On list, and choose OK. The SQL Output Area should list three
tables: Country, Department, and Job.
INTERBASE 5 TUTORIAL 20
PART II DATA DEFINITION ■ Topic: CREATING TABLES
If you are specifying the foreign key as a table-level constraint, the syntax is nearly the same except
that you have to identify the column for which it is being defined, so the syntax becomes:
CREATE TABLE table_name (column_defs,
FOREIGN KEY (column_name) REFERENCES other_table(columns)
[ON UPDATE {NO ACTION | CASCADE | SET DEFAULT | SET NULL}]
[ON DELETE {NO ACTION | CASCADE | SET DEFAULT | SET NULL}],
[, more table constraints])
A little later, you will use ALTER TABLE to add columns and table constraints to the Department table,
including some cascading referential integrity constraints.
INTERBASE 5 TUTORIAL 21
PART II DATA DEFINITION ■ Topic: BACKING UP A DATABASE
Naming constraints
When you declare a constraint at either the column level or the table level, you have the option of
naming the constraint using the optional CONSTRAINT keyword, followed by a constraint name. When
a constraint is named, you can drop it using the ALTER TABLE statement. In the Job table definition, two
of the constraints have names “pkjob” and “fkjob”), but the CHECK constraint does not have a name
(although it could have). When you alter the Department table a little later, you will add two named
constraints.
Computed columns
When you are creating a table, you can define columns whose value is based on the values of one or
more other columns in the table. The computation can include any arithmetic operations that are
appropriate to the datatypes of the columns. Open Tables.sql and look at the following column
definition for the Employee table:
full_name COMPUTED BY (last_name || ’, ’ || first_name)
The value of the full-name column consists of the value in the same row of the last_name column
plus a comma plus the value of the first_name column.
Look at the new_salary column of the Salary_history table.
new_salary COMPUTED BY (old_salary + old_salary * percent_change / 100)
To find the value of new_salary, InterBase multiplies the value of old_salary by the value of
percent_change, divides the result by 100, and adds that to the original value of old_salary.
Backing up a database
This is a good time to back up your database, because you’ve finished entering some tables. In the
next part of the tutorial, you run a script to create more tables. Throughout this tutorial, you will be
instructed to back up your database frequently. That way, if you run into difficulties, you can restore
the last correct version and try again.
In a production database, a full backup and restore performs several functions:
g It preserves your data by making a copy of both the data and the data structures (metadata).
g It improves database performance by balancing indexes and performing garbage collection on
outdated records.
g It reclaims space occupied by deleted records, and packs the remaining data.
g When you restore, it gives you the option of changing the database page size and of distributing the
database among multiple files or disks.
IMPORTANT If you restore a database to a name that is already in use, be sure that no users are connected to it at
the time you restore. For this tutorial, it is sufficient to close InterBase Windows ISQL and make sure
that there are no connections to the database from Server Manager.
INTERBASE 5 TUTORIAL 22
PART II DATA DEFINITION ■ Topic: BACKING UP A DATABASE
4. In the Backup File or Device field, name your backup file Tutor1.gbk and include the
complete path to it. Your entry should look like this:
C:\interbase5\tutorial\backups\tutor1.gbk
By convention, backups have a .gbk extent, but it is not required. Enable Verbose Output in order
to see a detailed description of what InterBase does when it backs up a database. Choose OK.
5. InterBase posts a dialog describing its progress. When the process is complete, dismiss the
dialog and choose File | Exit to exit Server Manager.
INTERBASE 5 TUTORIAL 23
PART II DATA DEFINITION ■ Topic: CREATING TABLES WITH A SCRIPT
Time to back up If you have successfully run Tables.sql, this is a good time to back up your database
to Tutor2.gbk.
INTERBASE 5 TUTORIAL 24
PART II DATA DEFINITION ■ Topic: TROUBLESHOOTING
Troubleshooting
If you made any typing mistakes when you were entering the domain definitions, you’ll get an error
message when you run the Tables.sql script or when you are defining the tables manually. InterBase
posts a message that looks like this:
Look in the SQL Output area for more information. The SQL Output area echoes the contents of the
script. If there were problems with a particular table, the SQL code for that table is followed by an
error message such as the following:
Statement failed, SQLCODE = -607
Dynamic SQL Error
-SQL error code = -607
-Invalid command
-Specified domain or source column does not exist
INTERBASE 5 TUTORIAL 25
PART II DATA DEFINITION ■ Topic: VIEWING AN OBJECT DEFINITION
Altering tables
You can change the structure of existing tables with the ALTER TABLE statement. In the previous section
of the tutorial, you created a simple Department table. Now you use the ALTER TABLE statement to add
to this table. The syntax for altering a table—in simplified form—is:
ALTER TABLE table_name operation [, operation]
Notice that you can drop a constraint only if you gave it a name at the time you created it.
INTERBASE 5 TUTORIAL 26
PART II DATA DEFINITION ■ Topic: MORE TROUBLESHOOTING
More troubleshooting
If you receive error messages when you are altering tables or inserting data, use the Metadata | Show
command as your resource.
g Show the definition for each table that you entered by hand and compare the output to the SQL code
that this document instructs you to enter.
g When you find a problem, you can either drop the table and recreate it, or use ALTER TABLE to drop a
column and then add the column again with the correct definition. If you misspelled the name of the
table itself, you must drop the table and recreate it.
g The DROP TABLE statement has the following syntax:
DROP TABLE tablename
g To change a column definition, first drop it using the ALTER TABLE statement:
ALTER TABLE tablename DROP columnname
g Then add the column back in using the ALTER TABLE statement again:
ALTER TABLE tablename ADD columnname columndef
If you made any typing errors when creating the domains and tables, you will get errors when you
try to insert data by hand or to run the Inserts.sql and Update.sql scripts. If you follow the steps above,
you will be able to fix your errors and run the scripts successfully. The remainder of the tutorial is less
demanding, in that it focuses on the SELECT command. Once you detect and fix any errors in the
domain and table definitions, you will get the correct results from your SELECT statements.
Creating views
A view is a virtual table that contains selected rows and columns from one or more tables or views.
InterBase stores only the definition of a view. The contents of a view are essentially pointers to data
in the underlying tables. When you create a view, you are not copying data from the source tables to
the view. You are looking at the original data.
A view often functions as a security device, because you can give people permissions on a view but
not on the underlying tables. Thus, the people can access a defined part of the data (the part defined
in the view), but the rest of the data remains private.
In the following exercise, you use the CREATE VIEW statement to create a phone list by choosing the
employee number, first name, last name, and phone extension from the Employee table and the
employee’s location and department phone number from the Department table. Views are frequently
created to store an often-used query or set of queries in the database.
You can select from a view just as you can from a table. Other operations are more restricted. See
“Working with Views” in the Data Definition Guide for more on views.
INTERBASE 5 TUTORIAL 27
PART II DATA DEFINITION ■ Topic: CREATING INDEXES
The WHERE clause tells InterBase how to connect the rows: the dept_no column in the Department
table is a foreign key that references the dept_no column in the Employee table. Both columns are
UNIQUE and NOT NULL, so the dept_no value in a Department row uniquely identifies a row in the
Employee table. (In case you’re wondering, the dept_no column in the Employee table is UNIQUE
because all primary key columns automatically acquire the UNIQUE property.)
Notice that when the same column name appears in two tables in a query, you reference the
columns by giving both the table name and the column name, joined by a period:
table_name.column_name
2. Now look at the structure of the Phone_list view by choosing Metadata | Show->View and
type phone_list in the Object Name field. You should see the following output:
Creating Indexes
An index is based on one or more columns in a table. It orders the contents of the specified columns
and stores that information on disk in order to speed up access to those columns. Although they
improve the performance of data retrievals, indexes also take up disk space and can slow inserts and
updates, so they are typically used on frequently queried columns. Indexes can also enforce
uniqueness and referential integrity constraints.
InterBase automatically generates indexes on UNIQUE and PRIMARY KEY columns. See the Data
Definition Guide for more information about constraints.
You use the CREATE INDEX statement to create an index. The simplified syntax is as follows:
CREATE INDEX name ON table (columns)
Optionally, you can add one or more of the ASCENDING, DESCENDING, or UNIQUE keywords following
the CREATE INDEX keywords.
INTERBASE 5 TUTORIAL 28
PART II DATA DEFINITION ■ Topic: CREATING INDEXES
This statement defines an index called namex for the last_name and first_name columns in the
Employee table.
INTERBASE 5 TUTORIAL 29
PART II DATA DEFINITION ■ Topic: CREATING INDEXES
Modifying indexes
To change an index definition—which columns are indexed, sort order, or UNIQUE requirement—you
must first drop the index and then create a new index.
2. Enter and execute the following line to redefine namex so that it includes the UNIQUE
keyword:
CREATE UNIQUE INDEX namex ON Employee (last_name, first_name)
Time to back up If you have successfully altered the Department table definition, created the
phone_list view, created the three indexes, and altered the namex index, this is a good time to back
up your database to Tutor3.gbk.
INTERBASE 5 TUTORIAL 30
PART III POPULATING THE DATABASE ■ Topic: INSERTING DATA
Inserting data
The INSERT statement is the mechanism by which you store one or more rows of data in an existing
table. In its simplest form, the syntax is:
INSERT INTO table_name [(columns)] VALUES (values)
If you don’t specify column names, InterBase inserts the supplied values into columns in the order in
which they were defined, and there must be as many values as there are columns in the table. When
you specify columns, you supply the values in the order you name the columns. Columns not specified
are given default values or NULL values, depending on the column definitions.
The values supplied can be constants or can be calculated. In embedded SQL, they can also be
variables.
An important variation of this syntax is one that allows you to add rows to a table by selecting rows
from another table. The two tables must have columns occurring in the same order for this to work.
The syntax for this form is:
INSERT INTO table_name (columns) SELECT columns FROM table_name WHERE conditions
Reminder Anything you type inside the quotation marks is case sensitive.
2. Enter and execute the following line to add a row to the Department table:
INSERT INTO Department
(dept_no, department, head_dept, budget, location, phone_no)
VALUES ('000', 'Corporate Headquarters', NULL, 1000000, 'Monterey',
'(408) 555-1234')
Notice that strings are all enclosed in single quotes, while numeric values are not. The department
number and default phone number, for example, are strings, not numeric values.
3. The next row of data for the Department table is similar to the previous one. To simplify
The Previous entry, click the Previous Query button. This redisplays the previous query in the SQL
Query button
Statement Area.
INTERBASE 5 TUTORIAL 31
PART III POPULATING THE DATABASE ■ Topic: INSERTING DATA
4. Now substitute into the previous query so that it reads as follows and execute the
statement.
INSERT INTO Department
(dept_no, department, head_dept, budget, location, phone_no)
VALUES (’100’, ’Sales and Marketing’, ’000’, 200000, ’San Francisco’,
’(415) 555-1234’)
Notice that the new value for head_dept is a string, not a numeric value.
5. Check the accuracy of your insertions by entering and executing each of the following
statements in turn. Examine the output to make sure it matches the instructions above.
SELECT * from Country
In Part IV of this tutorial, you learn (much!) more about the important SELECT statement.
There should be 14 entries in the Country table. If this one is correct, the others probably are, too.
Now run three more SELECT statements. Remember, you must execute each one before proceeding
to the next.
SELECT * FROM Job
SELECT * FROM Employee
SELECT * FROM Department
Time to back up If you have successfully entered three INSERTs and run the Inserts.sql script, this is a
good time to back up your database to Tutor4.gbk.
INTERBASE 5 TUTORIAL 32
PART III POPULATING THE DATABASE ■ Topic: UPDATING DATA
Updating data
You use UPDATE statements to change values for one or more rows of data in existing tables.
Using UPDATE
A simple update has the following syntax:
UPDATE table
SET column = value
WHERE condition
The UPDATE statement changes values for columns specified in the SET clause; columns not listed in
the SET clause are not changed. To update more than one column, list each column assignment in the
SET clause, separated by a comma. The WHERE clause determines which rows to update. If there is no
WHERE clause, all rows are updated.
For example, the following statement would increase the salary of salespeople by $2,000, by updating
the salary column of the Employee table for rows where the value in the job_code column is “sales.”
(Don’t do this yet.)
UPDATE Employee
SET salary = salary + 2000
WHERE job_code = ’Sales’
A WHERE clause is not required for an update. If the previous statements did not include a WHERE
clause, the update would increase the salary of all employees in the Employee table.
INTERBASE 5 TUTORIAL 33
PART III POPULATING THE DATABASE ■ Topic: UPDATING DATA
This query returns “623” as the department. Then, using 623 as the search condition in an UPDATE,
you change the manager number of all the employees in the department with the following statement:
UPDATE Department
SET mngr_no = 107 Note: Don’t do this yet!
WHERE dept_no = ’623’
A more efficient way to perform the update is to combine the two previous statements using a
subquery. A subquery is one in which a SELECT clause is used within the WHERE clause to determine
which rows to update.
INTERBASE 5 TUTORIAL 34
PART III POPULATING THE DATABASE ■ Topic: DELETING DATA
This returns 15. (If you select first_name and last_name from the Employee table where emp_no
equals 15, you will see that the manager of department 623 is Katherine herself.)
2. Enter the following UPDATE statement with a subquery to simultaneously find out
Katherine’s department number and assign a new manager number to that department:
UPDATE Department
SET mngr_no = 107
WHERE dept_no = (SELECT dept_no FROM Employee
WHERE full_name = ’Young, Katherine’)
The rows returned by the SELECT statement within the parentheses are the rows that the UPDATE
statement acts on.
3. Execute and commit the UPDATE statement you just entered.
4. Now run the query in step 1 again to see the change. The manager of department 623 is
manager number 107, rather than 15.
5. This isn’t a change we want to keep, so enter and execute the following statement to
reinstate Katherine Young as manager of department 123:
UPDATE Department SET mngr_no = 15 WHERE dept_no = ‘623’
Deleting data
To remove one or more rows of data from a table, use the DELETE statement. A simple DELETE has the
following syntax:
DELETE FROM table
WHERE condition
As with UPDATE, the WHERE clause specifies a search condition that determines the rows to delete.
Search conditions can be combined or can be formed using a subquery.
IMPORTANT The DELETE statement does not require a WHERE clause. However, if you do not include a WHERE
clause, you delete all the rows of a table.
There should be only one order returned. Notice that the SELECT statement requires that you specify
columns. You can also use “*” to specify all columns.
INTERBASE 5 TUTORIAL 35
PART III POPULATING THE DATABASE ■ Topic: DELETING MORE PRECISELY
3. Enter the following DELETE statement. To make it easier, you can display the previous
SELECT statement and substitute DELETE for “SELECT *”. You can use either the Previous
Statement button or w-P to display previous statements:
DELETE FROM Sales
WHERE order_date < ’31-DEC-1991’ Note: Don’t do this yet!
Notice that the DELETE statement does not take any column specification. That’s because it deletes
all columns for the rows you have specified.
4. Now repeat your original SELECT query. There should be no rows returned.
5. Oops. You just realized that you didn’t want to delete that data after all. Fortunately, you
committed previous work before executing this statement, so choose File | Rollback Work and
click OK at the prompt. This “undoes” all statements that were executed since the last
Commit.
6. Perform the SELECT again to see that the deleted row is back.
Time to back up Now that you have created your database and its tables and finished inserting and
updating data, this is a good time to back up your database to Tutor6.gbk.
You can try entering this statement, but you’ll get an error because there’s a foreign key column in
the Employee_project table that references the Employee table. If you were to delete these rows, some
values in the Employee_project table would no longer have matching values in the Employee table,
violating the foreign key constraint that says any employee who has a project must also have an entry
in the Employee table.
In addition, you can use subqueries to delete data, just as you use them to update. The following
statement would delete all rows from the Employee table where the employees were in the same
department as Katherine Young.
DELETE FROM Employee
WHERE dept_no = (SELECT dept_no FROM Employee Note: Don’t do this yet!
WHERE full_name = ’Young, Katherine’)
Again, you cannot actually execute this statement because it would violate foreign key constraints on
other tables.
INTERBASE 5 TUTORIAL 36
PART IV RETRIEVING DATA ■ Topic: OVERVIEW OF SELECT
Overview of SELECT
Part III presented the simplest form of the SELECT statement. The full syntax is much more complex.
Take a minute to look at the entry for SELECT in the Language Reference. Much of SELECT’s power
comes from its rich syntax.
In this chapter, you learn a core version of the SELECT syntax:
SELECT [DISTINCT] columns
FROM tables
WHERE <search_conditions>
[GROUP BY column [HAVING <search_condition>]]
[ORDER BY <order_list>]
The SELECT syntax above has six main keywords. A keyword and its associated information is called a
clause. The clauses above are:
Clause Description
You have already used SELECT statements to retrieve data from single tables. However, SELECT can also
retrieve data from multiple tables, by listing the table names in the FROM clause, separated by commas.
INTERBASE 5 TUTORIAL 37
PART IV RETRIEVING DATA ■ Topic: REMOVING DUPLICATE ROWS WITH DISTINCT
As you can see, the results of this query are rather long, and some job codes are repeated a number
of times. What you really want is a list of job codes where each value returned is distinct from the
others. To eliminate duplicate values, use the DISTINCT keyword.
2. Re-enter the previous query with the DISTINCT keyword:
SELECT DISTINCT job_code FROM Job
This produces the desired results: each job code is listed only once in the results.
3. What happens if you specify another column when using DISTINCT? Enter the following
SELECT statement:
SELECT DISTINCT job_code, job_grade FROM Job
INTERBASE 5 TUTORIAL 38
PART IV RETRIEVING DATA ■ Topic: USING THE WHERE CLAUSE
DISTINCT applies to all columns listed in a SELECT statement. In this case, duplicate job codes are
retrieved. However, DISTINCT treats the job code and job grade together, so the combination of
values is distinct.
4Using WHERE
1. Enter the following statement to return only rows for which “Green” is the value in the
last_name column.
SELECT last_name, first_name, phone_ext
FROM Employee
WHERE last_name = ’Green’
2. Now display the statement again (use the Previous button or w-P) and change the
equal sign to a greater than sign. This retrieves rows for which the last name is
alphabetically greater than (after) “Green.” There should be 29 rows.
Something extra To make the results more readable, execute the last query once again, but add an
ORDER BY clause. This is just a preview: the ORDER BY clause is discussed starting on page 52.
SELECT last_name, first_name, phone_ext
FROM Employee
WHERE last_name > ’Green’
ORDER BY last_name
INTERBASE 5 TUTORIAL 39
PART IV RETRIEVING DATA ■ Topic: USING THE WHERE CLAUSE
Search conditions
The text following the WHERE keyword is called a search condition, because a SELECT statement
searches for rows that meet the condition. Search conditions consist of a column name (such as
“last_name”), an operator (such as “=”), and a value (such as “Green”). Thus, WHERE clauses have
the following general form:
WHERE column_name operator value
In general, column is the column name in the table being queried, operator is a comparison operator
(Table 3), and value is a value or a range of values compared against the column. Table 4 describes
the kinds of values you can specify.
Comparison operators
Search conditions use the following operators. Note that for two-character operators, there is no space
between the operators.
Operator Description
Comparison operators Used to compare data in a column to a value in the search condition. Examples include <, >, <=,
>=, =, !=, and < >. Other operators include BETWEEN, CONTAINING, IN, IS NULL, LIKE, and STARTING
WITH.
Arithmetic operators Used to calculate and evaluate search condition values. The operators are +, −, *, and /.
Logical operators Used to combine search conditions or to negate a condition.The keywords are NOT, AND, and OR.
TABLE 3 Search condition operators
Literal values Numbers and text strings whose value you want to test literally; for
example, the number 1138 or the string “Smith”
Derived values Functions and arithmetic expressions; for example
salary * 2 or last_name || first_name
Subqueries A nested SELECT statement that returns one or more values. The
returned values are used in testing the search condition.
TABLE 4 Types of values used in search conditions
INTERBASE 5 TUTORIAL 40
PART IV RETRIEVING DATA ■ Topic: USING THE WHERE CLAUSE
You should get two rows, one for PO number V93F3088 and one for PO number V93N5822.
Negation
You can negate any expression with the negation operators !, ^, and ~. These operators are all
synonyms for NOT.
Pattern matching
Besides comparing values, search conditions can also test character strings for a particular pattern. If
data is found that matches a given pattern, the row is retrieved.
Wildcards Use a percent sign (%) to match zero or more characters. Use an underscore (_) to match
a single character.
Table 5 gives examples of some common patterns. Only CONTAINING is not case sensitive.
WHERE Matches
INTERBASE 5 TUTORIAL 41
PART IV RETRIEVING DATA ■ Topic: USING THE WHERE CLAUSE
1. LIKE is case sensitive and takes wildcards. Execute this statement to find all employees
whose last name ends in “an”:
SELECT last_name, first_name, emp_no FROM Employee
WHERE last_name LIKE ’%an’
Ramanathan Ashok 45
Steadman Walter 46
2. Now enter the following SELECT statement to find employees whose last names begin with
“M”, have exactly two more characters and then a “D”, followed by anything else in the
remainder of the name:
SELECT last_name, first_name, emp_no FROM Employee
WHERE last_name LIKE ’M__D%’
This returns
MacDonald Mary S. 85
This returns:
LAST_NAME FIRST_NAME EMP_NO
==================== =============== ======
Burbank Jennifer M. 71
Bender Oliver H. 105
Brown Kelly 109
The STARTING WITH operator tests whether a value starts with a particular character or sequence of
characters. STARTING WITH is case sensitive, but does not support wildcard characters.
1. Execute the following statement to retrieve two employee last names that start with “Le”:
SELECT last_name, first_name FROM Employee
WHERE last_name STARTING WITH ’Le’
INTERBASE 5 TUTORIAL 42
PART IV RETRIEVING DATA ■ Topic: USING THE WHERE CLAUSE
2. To negate the STARTING WITH operator, precede it with the logical operator NOT.
(Note: That’s a “one” in the quotes at the end of the statement.)
SELECT dept_no, department, location from department
WHERE dept_no NOT starting with ’1’
The CONTAINING operator is similar to STARTING WITH, except it matches strings containing the specified
string anywhere within the string. CONTAINING is not case sensitive and does not support or require
wildcards.
1. Execute the following statement to find last names that have a “g” or “G” anywhere in
them.
SELECT last_name, first_name FROM Employee
WHERE last_name CONTAINING ’G’
2. Now execute the same query, except substitute a lower-case “g.” You should get exactly
the same result set.
SELECT last_name, first_name FROM Employee
WHERE last_name CONTAINING ’g’
INTERBASE 5 TUTORIAL 43
PART IV RETRIEVING DATA ■ Topic: USING THE WHERE CLAUSE
1. Execute the following query to retrieve the names of employees who do not have phone
extensions:
SELECT last_name, first_name, phone_ext FROM Employee
WHERE phone_ext IS NULL
The query should return rows for last names Sutherland, Glon, and Osborne.
2. Now execute the statement using IS NOT NULL to retrieve the names of employees who do
have phone extensions:
SELECT last_name, first_name, phone_ext FROM Employee
WHERE phone_ext IS NOT NULL
1. Execute the following query to find all the last names that start with letters between C and
H. Notice that the query does not include names that begin with the final value (“H”). This
is because BETWEEN finds values that are less than or equal to the terminating value. A
name that begins with the letter but includes other letters is greater than H. If there were
someone whose last name was just “H”, the query would return it.
SELECT last_name, first_name FROM Employee
WHERE last_name BETWEEN ’C’ AND ’H’
INTERBASE 5 TUTORIAL 44
PART IV RETRIEVING DATA ■ Topic: USING THE WHERE CLAUSE
2. To demonstrate that BETWEEN is case sensitive, repeat the previous query using lower-case
letters. There are no names returned.
SELECT last_name, first_name FROM Employee
WHERE last_name BETWEEN ’a’ AND ’p’
3. Execute the following query to retrieve names of employees whose salaries are between
$62,000 and $98,000, inclusive:
SELECT last_name, first_name, salary FROM Employee
WHERE salary BETWEEN 60000 AND 80000
ORDER BY salary
The result set should return 12 rows, with salaries that include both the low figure and the high
figure in the range. (See page 52 for a discussion of the ORDER BY clause.)
LAST_NAME FIRST_NAME SALARY
==================== =============== ======================
4Find what’s IN
The IN operator searches for values matching one of the values in a list. The values in the list must be
separated by commas, and the list must be enclosed in parentheses. Use NOT IN to search for values
that do not occur in a set
Execute the following query to retrieve the names of all employees in departments 120, 600, and 623:
SELECT dept_no, last_name, first_name FROM Employee
WHERE dept_no IN (120, 600, 623)
ORDER BY dept_no, last_name
INTERBASE 5 TUTORIAL 45
PART IV RETRIEVING DATA ■ Topic: USING THE WHERE CLAUSE
Logical operators
You can specify multiple search conditions in a WHERE clause by combining them with the logical
operators AND or OR.
It should return two rows, one each for employees Parker and Johnson.
INTERBASE 5 TUTORIAL 46
PART IV RETRIEVING DATA ■ Topic: USING THE WHERE CLAUSE
This query produces unexpected results because AND has higher precedence than OR. This means that
the expressions on either side of AND are tested before those associated with OR. In the example as
written, the search conditions are interpreted as follows:
( WHERE dept_no = 623 )
OR
( WHERE dept_no = 600 AND hire_date > ’01-JAN-1992’ )
The restriction on the hire date applies only to the second department. Employees in department 623
are listed regardless of hire date.
INTERBASE 5 TUTORIAL 47
PART IV RETRIEVING DATA ■ Topic: USING SUBQUERIES
Order of precedence is not just an issue for AND and OR. All operators are defined with a precedence
level that determines their order of interpretation. You can study precedence levels in detail by reading
any number of books about SQL, but in general, the following rule of thumb is all you need to
remember.
TIP Always use parentheses to group operations in complex search conditions.
Using Subqueries
Subqueries are a special case of the WHERE clause, but they are an important tool and deserve a
discussion of their own.
Recall that in a WHERE clause, you provide a column name, a comparative operator, and a value.
WHERE tests the column contents against the value using the operator. You can use a SELECT statement
in place of the value portion of a WHERE clause. This internal SELECT clause is the subquery. InterBase
executes the SELECT subquery and uses its result set as the value for the WHERE clause.
Suppose, for example, that you want to retrieve a list of employees who work in the same country as
a particular employee whose ID is 144. If you don’t use a subquery, you would first need to find out
what country this employee works in:
SELECT job_country FROM Employee
WHERE emp_no = 144
This query returns “USA.” With this information, you would issue a second query to find a list of
employees in the USA, the same country as employee number 144:
SELECT emp_no, last_name FROM Employee
WHERE job_country = ’USA’
In this case, the subquery retrieves a single value, “USA.” The main query interprets “USA” as a value
to be tested by the WHERE clause. The subquery must return a single value because the WHERE clause
is testing for a single value (“=”); otherwise the statement produces an error.
The result set for this query is a list of 33 employee numbers and last names. These are the employees
who work in the same country as employee number 144.
INTERBASE 5 TUTORIAL 48
PART IV RETRIEVING DATA ■ Topic: USING SUBQUERIES
Multiple-result subqueries
If a subquery returns more than one value, the WHERE clause that contains it must use an operator
that tests against more than one value. IN is such an operator.
INTERBASE 5 TUTORIAL 49
PART IV RETRIEVING DATA ■ Topic: USING SUBQUERIES
Using ALL
The IN operator tests only against the equality of a list of values. What if you want to test some
relationship other than equality? For example, suppose you want to find out who earns more than the
people in department 623. Enter the following query:
SELECT last_name, salary FROM Employee
WHERE salary > ALL
(SELECT salary FROM Employee WHERE dept_no = 623)
This example uses the ALL operator. The statement tests against all values in the subquery and
retrieves the row if the salary is greater. The manager of department 623 can use this output to see
which company employees earn more than his or her employees.
This statement retrieves 34 rows for which salary is greater than any of the values from the subquery.
The ANY keyword has a synonym, SOME. The two are interchangeable.
Two other subquery operators are EXISTS and SINGULAR.
g For a given value, EXISTS tests whether at least one qualifying row meets the search condition specified
in a subquery. EXISTS returns either true or false, even when handling NULL values.
g For a given value, SINGULAR tests whether exactly one qualifying row meets the search condition
specified in a subquery.
INTERBASE 5 TUTORIAL 50
PART IV RETRIEVING DATA ■ Topic: USING AGGREGATE FUNCTIONS
However, this is not what you want, because the query included duplicate job codes in the count.
2. To count only the unique job codes, use the DISTINCT keyword as follows:
SELECT COUNT(DISTINCT job_code) FROM Job
3. Enter the following to retrieve the average budget of departments from the Department
table:
SELECT AVG(budget) FROM Department
INTERBASE 5 TUTORIAL 51
PART IV RETRIEVING DATA ■ Topic: GROUPING AND ORDERING QUERY RESULTS
4. A single SELECT can retrieve multiple aggregate functions. Enter the following statement to
retrieve the number of employees, the earliest hire date, and the total salary paid to all
employees:
SELECT COUNT(emp_no), MIN(hire_date), SUM(salary)
FROM Employee
(The value in the sum column may vary, depending on which exercises you have done and
whether you have done some of them more than once.)
IMPORTANT If a value involved in an aggregate calculation is NULL or unknown, the function ignores the entire
row to prevent wrong results. For example, when calculating an average over fifty rows, if ten rows
contain a NULL value, then the average is taken over forty values, not fifty.
5. To see for yourself that aggregate functions ignore NULL rows, perform the following test:
first, look at all the rows in the Department table:
SELECT dept_no, mngr_no FROM Department
Notice that there are 21 rows, but four of them have NULLs in the mngr_no column.
6. Now count the rows in mngr_no:
SELECT COUNT(mngr_no) FROM Department
The result is 17, not 21. COUNT did not count the NULL rows.
Notice that you can specify more than one column. As an alternative to naming the columns, you can
provide an integer that references the order in which you named the columns in the query. The second
column that you named in the SELECT can be referenced as 2.
By default, InterBase uses ASCENDING order, so you only need to specify the order if you want it to be
DESCENDING.
INTERBASE 5 TUTORIAL 52
PART IV RETRIEVING DATA ■ Topic: GROUPING AND ORDERING QUERY RESULTS
There’s no particular order to the returned rows. The result set should look like this:
CUST_NO TOTAL_VALUE
=========== ===========
1010 18000.40
1012 450000.49
1001 60000.00
1006 399960.50
1008 16000.00
2. Execute the same query, but order the results by the cust_no column:
SELECT cust_no, total_value FROM Sales
WHERE total_value > 10000
ORDER BY cust_no
Notice that the result set now has the cust_no column in ascending order. Ascending order is the
default.
3. Order the result set by the total value of the sales:
SELECT cust_no, total_value FROM Sales
WHERE total_value > 10000
ORDER BY total_value
4. Execute the query above, but order the result set by the descending order of the
total_value column:
SELECT cust_no, total_value FROM Sales
WHERE total_value > 10000
ORDER BY total_value DESC
5. To see the effect of ordering by more than one column, execute the following query:
SELECT last_name, first_name, phone_ext FROM Employee
ORDER BY last_name DESC, first_name
Notice that there are 42 rows with the last names are in descending order, as requested, and the
first names in ascending order, the default.
INTERBASE 5 TUTORIAL 53
PART IV RETRIEVING DATA ■ Topic: GROUPING AND ORDERING QUERY RESULTS
1 Canada
3 England
1 France
1 Italy
2 Japan
1 Switzerland
33 USA
INTERBASE 5 TUTORIAL 54
PART IV RETRIEVING DATA ■ Topic: GROUPING AND ORDERING QUERY RESULTS
INTERBASE 5 TUTORIAL 55
PART IV RETRIEVING DATA ■ Topic: JOINING TABLES
Now the result set should have the second column in ascending order.
DEPARTMENT AVG
========================= ======================
Field Office: Singapore 300000.00
Quality Assurance 300000.00
Finance 400000.00
Field Office: Italy 400000.00
Field Office: France 400000.00
Software Development 400000.00
Research and Development 460000.00
Field Office: Japan 500000.00
Field Office: Canada 500000.00
Field Office: East Coast 500000.00
Field Office: Switzerland 500000.00
Pacific Rim Headquarters 600000.00
Customer Support 650000.00
European Headquarters 700000.00
Customer Services 850000.00
Corporate Headquarters 1000000.00
Engineering 1100000.00
Consumer Electronics Div. 1150000.00
Software Products Div. 1200000.00
Marketing 1500000.00
Sales and Marketing 2000000.00
Joining tables
Joins enable a SELECT statement to retrieve data from two or more tables in a database. The tables are
listed in the FROM clause. The optional ON clause can reduce the number of rows returned, and the
WHERE clause can further reduce the number of rows returned.
From the information in a SELECT that describes a join, InterBase builds a table that contains the results
of the join operation, the results table, sometimes also called a dynamic or virtual table.
InterBase supports two types of joins: inner joins and outer joins.
Inner joins link rows in tables based on specified join conditions and return only those rows that match
the join conditions. If a joined column contains a NULL value for a given row, that row is not included
in the results table. Inner joins are the more common type because they restrict the data returned and
show a clear relationship between two or more tables.
Outer joins link rows in tables based on specified join conditions but return rows whether they match
the join conditions or not. Outer joins are useful for viewing joined rows in the context of rows that
do not meet the join conditions.
INTERBASE 5 TUTORIAL 56
PART IV RETRIEVING DATA ■ Topic: JOINING TABLES
Correlation names
Once you begin to query multiple tables, it becomes important to identify unambiguously what table
each column is in. The standard syntax for doing this is to state the table name followed by a period
and the column name:
table_name.col_name
In complex queries, this can get very tedious, so InterBase permits you to state a shorter version of
the table name in the FROM clause of a join. This short name is called a correlation name or an alias.
You will see many examples of correlation names in the next few pages. The form is as follows:
SELECT a.col, b.col FROM table_1 a, table_2 b
ON a.some_col = b.some_col
WHERE a.conditional_col <condition>
…
Notice the FROM clause, where table_1 is given the correlation name of a and table_2 is named b.
These abbreviated names are used even in the initial select list.
IMPORTANT If you include a subquery in a join, you must assign new correlation names to any tables that
appeared in the main query.
Inner joins
There are three types of inner joins:
g Equi-joins link rows based on common values or equality relationships in the join columns.
g Joins that link rows based on comparisons other than equality in the join columns. There is not an
officially recognized name for these joins, but for simplicity’s sake they can be categorized as
comparative joins, or non-equi-joins.
g Reflexive or self-joins compare values within a column of a single table.
To specify a SELECT statement as an inner join, list the tables to join in the FROM clause, and list the
columns to compare in the ON clause. Use the WHERE clause to restrict which rows are retrieved. The
simplified syntax is:
SELECT <columns> | *
FROM left_table [INNER] JOIN right_table
ON left_table.col = right_table.col
[WHERE <searchcondition>]
INTERBASE 5 TUTORIAL 57
PART IV RETRIEVING DATA ■ Topic: JOINING TABLES
2. The next query uses a subquery to display all departments and department managers
where the manager’s salary is at least 20% of a department’s total salary:
SELECT D.department, D.mngr_no, E.salary
FROM Department D JOIN Employee E
ON D.mngr_no = E.emp_no
WHERE E.salary*5 >= (SELECT SUM(S.salary) FROM Employee S
WHERE D.dept_no = S.dept_no)
ORDER BY D.department
The subquery sums the salaries for one department at a time and hands out the result to be
compared to the manager’s salary (multiplied by 5).
INTERBASE 5 TUTORIAL 58
PART IV RETRIEVING DATA ■ Topic: JOINING TABLES
Note Joins are not limited to two tables. There is theoretically no limit to how many tables can be
joined in one statement, although on the practical level of time and resources, 16 is usually considered
the workable maximum.
Outer joins
Outer joins produce a results table containing columns from every row in one table and a subset of
rows from another table. Outer join syntax is very similar to that of inner joins.
SELECT col [, col …] | *
FROM left_table {LEFT | RIGHT | FULL} OUTER JOIN
right_table ON joincondition
[WHERE <searchcondition>]
The joincondition is of the form left_table.col = right_table.col where the equality operator
can be replaced by any of the comparison operators.
With outer joins, you must specify the type of join to perform. There are three types:
g A left outer join retrieves all rows from the left table in a join, and retrieves any rows from the right
table that match the search condition specified in the ON clause.
g A right outer join retrieves all rows from the right table in a join, and retrieves any rows from the left
table that match the search condition specified in the ON clause.
g A full outer join retrieves all rows from both the left and right tables in a join regardless of the search
condition specified in the ON clause.
Outer joins are useful for comparing a subset of data in the context of all data from which it is
retrieved. For example, when listing the employees that are assigned to projects, it might be
interesting to see the employees that are not assigned to projects, too.
INTERBASE 5 TUTORIAL 59
PART IV RETRIEVING DATA ■ Topic: JOINING TABLES
This should produce a list of 48 names. Notice that some employees are not assigned to a project;
the proj_id column displays <null> for them.
2. Now reverse the order of the tables and execute the query again.
SELECT e.full_name, p.proj_id
FROM Employee_project p LEFT OUTER JOIN Employee e
ON e.emp_no = p.emp_no
ORDER BY p.proj_id
This produces a list of 28 names. Notice that you get different results because this time the left
table is Employee_project. The left outer join is only required to produce all the rows of the
Employee_project table, not all of the Employee table.
3. As a last experiment with joins, repeat the query in Exercise 2 (the one you just did), but
this time do a right outer join. Before you execute the query, think about it for a moment.
What do you think this query will return?
SELECT e.full_name, p.proj_id
FROM Employee_project p RIGHT OUTER JOIN Employee e
ON e.emp_no = p.emp_no
ORDER BY p.proj_id
You should get the same result set as in Exercise 1. Did you realize that performing a right outer
join on tables B JOIN A is the same as a left outer join on tables A JOIN B?
INTERBASE 5 TUTORIAL 60
PART IV RETRIEVING DATA ■ Topic: FORMATTING DATA
Formatting data
This section describes three ways to change data formats:
g Using CAST to convert datatypes
g Using the string operator to concatenate strings
g You can convert characters to uppercase
For example, the following WHERE clause uses CAST to translate a CHAR datatype, INTERVIEW_DATE, to a
DATE datatype. This conversion lets you compare INTERVIEW_DATE to another DATE column, hire_date:
. . . WHERE hire_date = CAST(interview_date AS DATE)
You can use CAST to compare columns in the same table or across tables. CAST allows the conversions
listed in the following table:
From datatype To datatype
NUMERIC CHARACTER, DATE
INTERBASE 5 TUTORIAL 61
PART IV RETRIEVING DATA ■ Topic: FORMATTING DATA
2. You can concatenate as many strings as you like. The following query is a slight variation
on the previous one: it concatenates the first name to the other output strings:
SELECT D.dept_no, D.department, E.first_name || ’ ’ || E.last_name ||
’ is the manager’
FROM Department D, Employee E
WHERE D.mngr_no = E.emp_no AND D.department NOT CONTAINING ’Field’
ORDER BY D.dept_no
Notice that in order to get a space between the first and last names, you have to concatenate a
string that consists solely of a space. The result set should look like this:
DEPT_NO DEPARTMENT
======= ========================= =========================================
000 Corporate Headquarters Oliver H. Bender is the manager
100 Sales and Marketing Mary S. MacDonald is the manager
110 Pacific Rim Headquarters Janet Baldwin is the manager
120 European Headquarters Roger Reeves is the manager
600 Engineering Robert Nelson is the manager
622 Quality Assurance Phil Forest is the manager
623 Customer Support Kevin Cook is the manager
670 Consumer Electronics Div. Kevin Cook is the manager
671 Research and Development Chris Papadopoulos is the manager
672 Customer Services Randy Williams is the manager
900 Finance Walter Steadman is the manager
Converting to uppercase
The UPPER function converts character values to uppercase. For example, you could include a CHECK
constraint that ensures that all column values are entered in uppercase when defining a table column
or domain. The following CREATE DOMAIN statement uses the UPPER function to guarantee that column
entries are all upper case:
CREATE DOMAIN PROJNO
AS CHAR(5)
CHECK (VALUE = UPPER (VALUE));
INTERBASE 5 TUTORIAL 62
PART V ADVANCED TOPICS ■ Topic: ACCESS PRIVILEGES
Access privileges
Initially, only a table’s creator, its owner, and the SYSDBA user have access to a table. On UNIX servers
that have a superuser, or a user with root privileges, those users also have access to all database
objects.
You can grant other users the right to look at or change your tables by assigning access privileges
using the GRANT statement. Table 9 lists the available access privileges:
Privilege Access
ALL SELECT, DELETE, INSERT, UPDATE, and REFERENCES; note that ALL does not include the EXECUTE
privilege
SELECT Read data
DELETE Delete data
INSERT Write new data
UPDATE Modify existing data
EXECUTE Execute or call a stored procedure
REFERENCES Reference a primary key with a foreign key
ROLE All privileges assigned to the role
TABLE 9 SQL access privileges
The GRANT statement assigns access privileges for a table or view to specified users, roles, or
procedures. The REVOKE statement removes previously granted access privileges.
INTERBASE 5 TUTORIAL 63
PART V ADVANCED TOPICS ■ Topic: ACCESS PRIVILEGES
The following statement assigns two privileges (INSERT and UPDATE) on the Department table to three
users:
GRANT INSERT, UPDATE ON Department TO EMIL, RAVI, HELGA
To grant privileges to everyone, use the PUBLIC keyword. The following statement grants all privileges
except EXECUTE on the Department table to anyone who connects to the database:
GRANT ALL ON Department to PUBLIC
This is a very brief introduction to an important topic: security. For more information about granting
access, see the Data Definition Guide.
Revoking privileges
The REVOKE statement removes access privileges that were granted with GRANT. The following
statement removes the insert and update privileges on the Department table that were granted to
Emil, Ravi, and Helga in an earlier example.
REVOKE INSERT, UPDATE ON Department FROM EMIL, RAVI, HELGA
When the access is restricted to certain columns, as in the second line, only UPDATE and REFERENCES
can be granted. EXECUTE must always be granted in a separate statement.
INTERBASE 5 TUTORIAL 64
PART V ADVANCED TOPICS ■ Topic: ACCESS PRIVILEGES
The users have now have all the privileges that were granted to the role_name role. But there’s an
additional step they must take before those privileges are available to them. They must specify the
role when the connect to a database.
4. Specify the role when connecting to a database.
InterBase issues an error statement, because all those tables you’ve created in this tutorial belong
to user TUTOR. User CHRIS doesn’t have permission to do anything at all with them.
INTERBASE 5 TUTORIAL 65
PART V ADVANCED TOPICS ■ Topic: ACCESS PRIVILEGES
You can click the Details button to get more information about the problem. In this case, it says
that the current user has no read/select permissions on the table.
4. Now connect to the TUTORIAL database again, this time as TUTOR. Leave the Role field
empty. Create a role called SALESPEOPLE.
CREATE ROLE SALESPEOPLE
5. Execute the following GRANT statements to assign privileges to the SALESPERSON role.
Remember that you must execute each GRANT statement before entering the next one.
GRANT SELECT, UPDATE, INSERT ON Sales to SALESPEOPLE
GRANT update (contact_first, contact_last, phone_no) ON Customer to SALESPEOPLE
7. Connect to the TUTORIAL database as user CHRIS. Choose Yes when InterBase asks you if
you want to commit your work. In the Role field, enter SALESPEOPLE.
8. Now enter the same query that failed in Step 3. This time, InterBase retrieves all the rows
in the Sales table, because CHRIS now has the required permissions, thanks to the role.
9. Now reconnect to the database as user TUTOR.
INTERBASE 5 TUTORIAL 66
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
Triggers
Triggers have a great variety of uses, but in general, they permit you to automate tasks that would
otherwise have to be done manually. You can use them to define actions that should occur
automatically when data is inserted, updated, or deleted in a particular table. Triggers are a versatile
tool, with a wide range of uses.
The triggers defined in the TUTORIAL database perform the following actions:
g The set_emp_no trigger generates and inserts unique employee numbers when a row is inserted into
the Employee table and the set_cust_no trigger does the same for customer numbers in the Customer
table.
g The save_salary_change trigger maintains a record of employees’ salary changes.
g The new_order trigger posts an event when a new row is inserted into the Sales table.
INTERBASE 5 TUTORIAL 67
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
See Triggers.sql for an example. The Language Reference, Data Definition Guide, and Programmer’s
Guide all contain more discussion of triggers.
Context variables
Context variables are unique to triggers. Triggers are often used to change a value, and in the process
of doing so, they must temporarily store both the old and new values. The context variables, Old and
New, are the mechanisms by which they do this. As you perform the exercises in this section, look for
them in contexts such as New.emp_no = gen_id(emp_no_gen, 1). For more information about context
variables, see the Data Definition Guide
INTERBASE 5 TUTORIAL 68
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
4Create a generator
1. Begin by checking the employee numbers in the Employee table, to confirm that the
highest employee number currently in use is 145:
SELECT emp_no from Employee
ORDER BY emp_no
Note The statement above returns all the employee numbers so that you can confirm that 145 is
the highest. The following statement produces the same information more efficiently:
SELECT max(emp_no) from Employee
2. Triggers often use generators, and the trigger you create in the next exercise is an example
of one. Execute the following statement to create a generator called emp_no_gen.
CREATE GENERATOR emp_no_gen
3. Now initialize the generator to 145, the highest value currently in use.
SET GENERATOR emp_no_gen TO 145
This statement says that the set_emp_no trigger will fire before an insert operation, and that it will
create a new value for emp_no by calling the gen_id() function on the emp_no_gen generator with
an increment of 1.
2. To test the generator, execute the following INSERT statement:
INSERT INTO Employee (first_name, last_name, dept_no, job_code, job_grade,
job_country, hire_date, salary, phone_ext)
VALUES (’Reed’, ’Richards’, ’671’, ’Eng’, 5, ’USA’, ’07/27/95’,
’34000’, ’444’)
Notice that you did not include a value for the emp_no column in the INSERT statement. Look at
the new record by entering
SELECT * from Employee WHERE last_name = ’Richards’
The employee number is 146. Remember that the highest employee number before you created
the generator and inserted a new row was 145. The trigger has automatically assigned the new
employee the next employee number.
3. If your INSERT ran without errors and your SELECT returns the correct result set, commit
your work.
INTERBASE 5 TUTORIAL 69
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
Remember, these are two separate statements, and you must execute each one before entering the
next.
2. Now execute the following CREATE TRIGGER statement to create the set_cust_no trigger.
CREATE TRIGGER set_cust_no FOR Customer
BEFORE INSERT AS
BEGIN
new.cust_no = gen_id(cust_no_gen, 1);
END
3. To test this trigger, first select max(cust_no) from Customer to confirm that the highest
customer number is 1015. Then insert the following row:
INSERT INTO Customer (customer, contact_first, contact_last,
phone_no, address_line1, address_line2, city, state_province,
country, postal_code, on_hold)
VALUES (’Big Rig’, ’Henry’, ’Erlig’, ’(701) 555-1212’, ’100 Big Rig Way’,
NULL, ’Atlanta’, ’GA’, ’USA’, ’70008’, NULL)
Now perform the following SELECT to confirm that the new customer number is, as you expect,
1016:
SELECT cust_no FROM Customer WHERE customer = ’Big Rig’
INTERBASE 5 TUTORIAL 70
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
This trigger fires AFTER UPDATE of the Employee table. It compares the value of the salary column
before the update to the value after the update and if they are different, it enters a record in
Salary_history that consists of the employee number, date, previous salary, and percentage change in
the salary.
Notice that when the values to be entered in the Salary_history table are to be taken from the
Employee table, they are always preceded by the Old or New context variable. That is because
InterBase creates two versions of a record during the update process, and you must specify which
version the value is to come from.
In addition, note that this example makes use of two other InterBase features: it inserts the current
date into a column of DATE datatype by supplying the string ’NOW’ in single quotes, and it inserts the
name of the user who is currently connected to the database by supplying the keyword USER.
Update an employee record and change the salary to see how this trigger works.
An event is a message passed by a trigger or stored procedure to the InterBase event manager to notify
interested applications of the occurrence of a particular condition. Applications that have registered
interest in an event can pause execution and wait for the specified event to occur. For more
information on events, see the Programmer’s Guide.
The post_new_order trigger fires after a new record is inserted into the Sales table—in other words
when a new sale is made. When this event occurs, interested applications can take action, such as
printing an invoice or notifying the shipping department.
INTERBASE 5 TUTORIAL 71
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
Stored procedures
Stored procedures are programs stored with a database’s metadata that run on the server. Applications
can call stored procedures to perform tasks, and you can also use stored procedures in InterBase
Windows ISQL. See the Programmer’s Guide for more information on calling stored procedures from
applications.
There are two types of stored procedures:
g Select procedures that an application can use in place of a table or view in a SELECT statement. A select
procedure must be defined to return one or more values (output parameters), or an error results. Since
select procedures can return more than one row, they appear as a table or view to a calling program.
g Executable procedures that an application can call directly with the EXECUTE PROCEDURE statement.
Executable procedures can perform a variety of tasks; they might or might not return values to the
calling program.
Both kinds of procedures are defined with CREATE PROCEDURE and have essentially the same syntax.
The difference is in how the procedure is written and how it is intended to be used.
Like trigger definitions, procedure definitions in SQL scripts, embedded SQL, and command-line isql
must be preceded by a SET TERM statement that sets the terminator to something other than a
semicolon. When all procedure statements have been entered, the SET TERM statement must be used
again to set the terminator back to a semicolon. See Procs.sql for an example. The Language
Reference, Data Definition Guide, and Programmer’s Guide all contain more information on stored
procedures.
INTERBASE 5 TUTORIAL 72
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
This is a select procedure that takes an employee number as its input parameter (v_empno,
specified in parentheses after the procedure name) and returns all the projects to which the
employee is assigned (project_id, specified after RETURNS). The variables are named in the header
as varname and then referenced in the body as :varname.
It uses a FOR SELECT … DO statement to retrieve multiple rows from the Employee_project table. This
statement retrieves values just as a normal SELECT statement does, but retrieves them one at a time
into the variable listed after INTO, and then performs the statements following DO. In this case, the
only statement is SUSPEND, which suspends execution of the procedure and sends values back to
the calling application (in this case, InterBase Windows ISQL).
2. See how the procedure works by entering the following query:
SELECT * FROM get_emp_proj(71)
This query looks at first as though there were a table named get_emp_proj, but you can tell that
it’s a procedure rather than a table because of the input parameter in parentheses following the
procedure name. The results are:
project_id
==========
VBASE
MAPDB
These are the projects to which employee number 71 is assigned. Try it with some other employee
numbers.
INTERBASE 5 TUTORIAL 73
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
3. If your procedure returns the correct result set, commit your work.
Once defined, this exception can be raised in a trigger or stored procedure with the EXCEPTION
clause. The associated error message is then returned to the calling application.
2. Execute the following statement to create the add_emp_proj stored procedure:
CREATE PROCEDURE add_emp_proj (v_empno SMALLINT, v_projid CHAR(5))
AS
BEGIN
INSERT INTO Employee_project (emp_no, proj_id)
VALUES (:v_empno, :v_projid);
WHEN SQLCODE -530 DO
EXCEPTION UNKNOWN_EMP_ID;
END
INTERBASE 5 TUTORIAL 74
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
This procedure takes an employee number and project ID as input parameters and adds the
employee to the specified project using an INSERT statement. The error-handling WHEN statement
checks for SQLCODE -530, violation of foreign key constraint, and then raises the previously-defined
exception when this occurs.
3. Practice using this procedure by executing the following SQL statement:
EXECUTE PROCEDURE add_emp_proj(20, ’DGPII’)
You should see that employee 20 is now assigned to both the DGPII project and the GUIDE project.
4. Now try adding a non-existent employee to a project, for example:
EXECUTE PROCEDURE add_emp_proj(999, ’DGPII’)
The statement fails and the exception message displays on the screen.
5. Click the Details button to view the text that you specified when you created the exception
(“Invalid employee number or project ID.”).
Recursive procedures
Stored procedures support recursion, that is, they can call themselves. This is a powerful
programming technique that is useful in performing repetitive tasks across hierarchical structures
such as corporate organizations or mechanical parts.
INTERBASE 5 TUTORIAL 75
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
This statement executes dept_budget with input parameter rdno, and puts the output value in sumb.
Notice that when using EXECUTE PROCEDURE within a procedure, the input parameters are not put in
parenthesis, and the variable into which to put the resultant output value is specified after the
RETURNING_VALUES keyword. The value of sumb is then added to total_budget, to keep a running total
of the budget. The result is that the procedure returns the total of the budgets of all the reporting
departments given as the input parameter plus the budget of the department itself.
1. Execute the following SQL statement:
CREATE PROCEDURE dept_budget (v_dno CHAR(3))
RETURNS (total_budget NUMERIC(15, 2))
AS
DECLARE VARIABLE sumb DECIMAL(12, 2);
DECLARE VARIABLE rdno CHAR(3);
DECLARE VARIABLE cnt INTEGER;
BEGIN
total_budget = 0;
SELECT budget FROM Department WHERE dept_no = :v_dno INTO :total_budget;
SELECT COUNT(budget)
FROM Department
WHERE head_dept = :v_dno
INTO :cnt;
IF (cnt = 0) THEN
SUSPEND;
FOR SELECT dept_no
FROM Department
WHERE head_dept = :v_dno
INTO :rdno
DO
BEGIN
EXECUTE PROCEDURE Dept_budget :rdno RETURNING_VALUES :sumb;
total_budget = total_budget + sumb;
END
END
2. To find the total budget for department 620, including all its subdepartments, execute the
following SQL statement:
EXECUTE PROCEDURE dept_budget(620)
INTERBASE 5 TUTORIAL 76
PART V ADVANCED TOPICS ■ Topic: TRIGGERS AND STORED PROCEDURES
More procedures
There are a number of other procedures, some quite complex, defined in Procs.sql for the TUTORIAL
database. Now that you have a basic understanding of procedures, it will be worth your while to read
them over so that you understand them. Then try using them. Notice that comments are often
included within the text of a statement to make it easier for people to understand what the code is
doing.
INTERBASE 5 TUTORIAL 77