Defining Integrity Constraints on a Table
Go Up to Creating Tables (Data Definition Guide)
Contents
InterBase allows you to optionally apply certain constraints to a column, called integrity constraints, which are the rules that govern column-to-table and table-to-table relationships, and validate data entries. They span all transactions that access the database and are automatically maintained by the system. Integrity constraints can be applied to an entire table or to an individual column.
PRIMARY KEY and UNIQUE Constraints
The PRIMARY KEY
and UNIQUE
integrity constraints ensure that the values entered into a column or set of columns are unique in each row. If you try to insert a duplicate value in a PRIMARY KEY
or UNIQUE
column, InterBase returns an error. When you define a UNIQUE
or PRIMARY KEY
column, determine whether the data stored in the column is inherently unique. For example, no two social security numbers or driver’s license numbers are ever the same. If no single column has this property, then define the primary key as a composite of two or more columns which, when taken together, are unique.
The EMPLOYEE table
EMP_NO
|
LAST_NAME
|
FIRST_NAME
|
JOB_TITLE
|
PHONE_EXT
|
---|---|---|---|---|
10335 |
Smith |
John |
Engineer |
4968 |
21347 |
Carter |
Catherine |
Product Manager |
4967 |
13314 |
Jones |
Sarah |
Senior Writer |
4800 |
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.
Using the FOREIGN KEY to Enforce Referential Integrity
A foreign key is a column or set of columns in one table that correspond in exact order to a column or set of columns defined as a primary key in another table. For example, in the PROJECT
table, TEAM_LEADER
is a foreign key referencing the primary key, EMP_NO
in the EMPLOYEE
table.
The PROJECT table
|
|
|
|
|
---|---|---|---|---|
|
44 |
Automap |
blob data |
hardware |
|
47 |
Video database |
blob data |
software |
|
24 |
Translator upgrade |
blob data |
software |
The EMPLOYEE table
|
|
|
|
|
|
|
---|---|---|---|---|---|---|
24 |
Smith |
John |
100 |
Eng |
4968 |
64000 |
48 |
Carter |
Catherine |
900 |
Sales |
4967 |
72500 |
36 |
Smith |
Jane |
600 |
Admin |
4800 |
37500 |
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
andON DELETE
options to theREFERENCES
statement. When you create a foreign key by defining a column or tableREFERENCES
constraint, you can specify what should happen to the foreign key when the referenced primary key changes. The options are:
Action specified | Effect on foreign key |
---|---|
|
[Default] The foreign key does not change (can cause the primary key update or delete to fail due to referential integrity checks) |
|
The corresponding foreign key is updated or deleted as appropriate to the new value of the primary key |
|
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 |
|
Every column of the corresponding foreign key is set to |
- If you do not use the
ON UPDATE
andON 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 theEMP_NO
column of theEMPLOYEE
table (the primary key), that value must also be updated in theTEAM_LEADER
column of thePROJECT
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 thePROJECT
table, that value must first exist in theEMP_NO
column of theEMPLOYEE
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.
CREATE TABLE PROJECT {
. . .
TEAM LEADER INTEGER REFERENCES EMPLOYEE (EMP_NO)
ON DELETE SET NULL
ON UPDATE CASCADE
. . .};
Referencing Tables Owned by Others
If you want to create a foreign key that references a table owned by someone else, that owner must first use the GRANT
command to grant you REFERENCES
privileges on that table. Alternately, the owner can grant REFERENCES
privileges to a role and then grant that role to you. See Planning Security and the Language Reference for more information on granting privileges to users and roles. See the Language Reference for more on creating and dropping roles.
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 primary key of the EMPLOYEE
table, 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 theEMP_NO
primary key column, and aNULL
in theDEPT_NO
foreign key column. - Insert a new row into the
DEPARTMENT
table, placing “2” in theDEPT_NO
primary key column, and “1” in the foreign key column. - Use
ALTER TABLE
to modify theEMPLOYEE
table. Change theDEPT_NO
column fromNULL
to “2.”
How to Declare Constraints
When declaring a table-level or a column-level constraint, you can optionally name the constraint using the CONSTRAINT
clause. If you omit the CONSTRAINT
clause, InterBase generates a unique system constraint name which is stored in the RDB$RELATION_CONSTRAINTS
system table.
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}]
</pre>
The syntax for a table-level constraint is:
<source lang=sql>
<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>)
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));