Massachusetts Institute of Technology
Department of Urban Studies and Planning


11.521: Spatial Database Management and Advanced Geographic Information Systems
11.523: Fundamentals of Spatial Database Management

Enforcing Referential Integrity

Thomas H. Grayson


Creating an Entity-Relationship Diagram for the PARCELS Database

By now the PARCELS database should be very familiar to you. Feel free to review the PARCELS database schema. We'll use a subset of the PARCELS database for this discussion: parcels, owners, fires, and tax. Treat each of these tables as an entity. [NOTE: These notes were originally written for use with Oracle.  However, they use standard SQL so there are few differences between Oracle and Postgres.]

You can use Microsoft Access's "Relationships" feature to create an entity-relationship (E-R) diagram for this database. To do so, link in to your Access database the tables listed above. Next, open the "Relationships" window using the Tools > Relationships menu item. You'll be asked to add tables; add all the tables listed above. You define relationships by clicking-and-dragging from the primary key to the foreign key, much like adding joins to a query. Notice that a "Relationships" dialog box appears when you draw a relationship. This dialog gives you the opportunity to edit the relationship. Since some of the tables have multiple-column primary keys, you will need to use this interface to add the additional columns. You can bring back this dialog box by clicking on one of black relationship lines in the window. Your diagram should include:

Since Access will not let you print out the relationships window, the only way to preserve the diagram is to copy-and-paste an image of it into in another application such as Microsoft Word. To copy the image of the current window, press the "Alt" key, then press the "Print Screen" key. Open Word, then use Edit > Paste to paste the image into a Word document.

Consider listing of the foreign key relationships among the tables in the following format:

FK_TABLE (FK_COL1, FK_COL2, ...) references PK_TABLE (PK_COL1, PK_COL2)
where For example, for the fires and parcels tables, you would have the following entry:
FIRES (PARCELID) references PARCELS (PARCELID)

Defining Primary and Foreign Keys in Oracle

Once we have defined the primary and foreign keys in a database schema, it is important that the proper relationships be maintained so that the database does not become inconsistent. For example, once we've determined that the column fires.parcelid constitutes a foreign key that refer to the columns of the same name in the parcels table, we want to ensure that for every parcelid in fires has is a corresponding row in parcels. To restate this wish in database jargon, we want to ensure that the referential integrity of the database is maintained. Fortunately, Oracle has the power to enforce referential integrity, but to do so, we must inform the database of the relationships involved. We do so by adding constraints on the tables.

Once you've created tables in Oracle using the CREATE TABLE statement, you can use the ALTER TABLE ADD CONSTRAINT statement to add primary key and foreign key designations to the tables. For example, to define the primary key parcelid for the parcels table, we would use the following SQL statement:

Constraints in Oracle have names just as tables and views do. Since a constraint can have the same name as a table, I recommend giving primary key constraints names the same name as that of the table it applies to. If you omit the constraint name, Oracle assigns a default name of the form 'SYS_Cnnnnn', where nnnnn are digits. By defining constraint names in this fashion, it is easy to identify what a constraint is for. When you run a SQL statement that violates a constraint, the Oracle will display the name of the constraint in the error message. An informative constraint name will save you the trouble of querying the data dictionary to figure out the nature of the constraint you violated.

Similarly, we can define the multi-column primary key (parcelid, fdate) for the fires table:

The foreign key parcelid in the fires table, refers to the primary key parcelid in the parcels table. We can specify this constraint with the following SQL statement:

ALTER TABLE fires 
  ADD CONSTRAINT fires$parcelid 
  FOREIGN KEY (parcelid) 
  REFERENCES parcels (parcelid);
Here, we've used a more elaborate convention for naming the foreign key constraint. Specifically, we use constraint names of the following form:
table$foreign_key_column
table$foreign_key_column_1#foreign_key_column_2
table$foreign_key_column_1#foreign_key_column_2#foreign_key_column_3
Here, 'table' is the name of the table that is being constrained (here, the table fires). The 'foreign_key_columns' in the list are column names from the constrained table (here, fires.parcelid). This naming convention uses the dollar sign ($) to separate the table name from the column names and the pound sign (#) to separate the column names, if necessary. There are some pitfalls with this approach:

If you need to drop a constraint, use the ALTER TABLE DROP CONSTRAINT command. For example, to drop the primary key constraint we created on the table parcels earlier, we can could try the following SQL statement:

ALTER TABLE parcels
  DROP CONSTRAINT parcels;

However, this statement will fail if the foreign key constraint fires$parcelid we created earlier still exists, since the foreign key constraint references this primary key constraint. To get around this, we can either drop the referencing constraints individually or we can add the keyword CASCADE to the end of the command; this instructs Oracle to drop all other constraints that depend on this constraint:

ALTER TABLE parcels
  DROP CONSTRAINT parcels
  CASCADE;

Similarly, we will not be able to drop the table parcels if any constraints refer to primary (or unique) keys in the table. To circumvent this, we could either drop the referencing constraints individually first or we can add the CASCADE phrase to the end of the DROP TABLE statement:

DROP TABLE parcels
  CASCADE ;

When creating new tables and defining constraints, I recommend that you write a SQL script that performs these tasks in the following order:

Following this order avoids most chicken-and-egg problems that may occur in this process. Keep in mind, however, that you cannot define a foreign key in the fires table that references the primary key in the parcels table unless the primary key in parcels has been defined first. (Technical note: a foreign key can actually reference a uniqueness constraint instead of primary key constraint, but that it is of little import here.)

This is all you need to know to use primary and foreign keys in Oracle. Note that while many modern relational database systems allow you to define the primary and foreign keys, the SQL syntax for doing so varies a bit from one database system to another. Hence, while the concepts presented here should apply to most relational database systems, your SQL statements to implement them may look slightly different if you are not using Oracle.


 Home | Syllabus | Lectures | Labs | CRL | MIT

For more information about this page, please contact the 11.521 Staff Mailing List <11.521staff@MIT.EDU>.
Created 5 November 1998
Last modified: 28 February 2002