For Oracle support & training call (800) 766-1884
Free Oracle Tips

Home
Oracle Tips
Oracle Code Depot
Oracle Monitoring
Oracle Consulting
Oracle Training
Oracle News
Oracle Forum
Oracle Support





 

Free Oracle Tips

image

 
HTML Text

Free Oracle App Server Tips

image

 
HTML Text


Privacy Policy

Redneck

Dress Code

Oracle tuning

Oracle training

Oracle support

Remote Oracle


 



Foreign Key Constraints

A foreign key constraint will validate the values of an INSERT or UPDATE against the values in another column. Normally the column is in another table, but it could be another column in the same table. This is a parent/child relationship. The parent is the column (or columns) referenced in the foreign key. The child is the column (or columns) that contain the foreign key constraint.

When data is inserted or updated in the child column, the foreign key will verify that the value exist in the parent column. If the value does not exist, the foreign key constraint will not allow the value in the child column. Let’s look at the EMP table.

SQL> desc emp
 Name 					   Null?     Type
 ----------------------------------------- -------- -------------- 
EMP_KEY 					     VARCHAR2(9)
 JOB_KEY 					     NUMBER(5)
 PUB_KEY    					     VARCHAR2(4)
 EMP_FIRST_NAME 				     VARCHAR2(20)
 EMP_MI 					     VARCHAR2(1)
 EMP_LAST_NAME 					     VARCHAR2(30)
 EMP_DATE_OF_HIRE      				     DATE
 EMP_SALARY 					     NUMBER(6)
 MANAGER 					     VARCHAR2(9)

Each employee has a manager, except the manager. You can find the manager by looking at the manager column for each employee. The manager column contains the employee key of the manager for that employee. One of our business rules is that all managers must be an employee. We can enforce this rule with a foreign key constraint.

The parent column is emp_key. The child column is manager. When I insert or update a value in the manager column (change the employee’s manager), the foreign key will first check the parent (emp_key) column to see that the manager exists (the emp_key exists in the emp_key column).

First, we need to create the foreign key.

alter table emp
add (constraint manger_fk foreign key (manager)
references emp (emp_key)
on delete set null);

We will discuss the ON DELETE part shortly, but first let’s look at the table and how the foreign key protects our data.

SQL> select
2 emp_key,
3 emp_last_name,
4 manager
5 from
6 emp;

EMP_KEY EMP_LAST_NAME MANAGER
--------- ------------------------------ ---------
E101 king
E102 jackson E101
E103 korn E101
E104 linus E101
E105 tokheim E101
E106 levender E101
E107 johnson E101
E108 baker E101
E109 coleman E101
E110 brannigan E101

Here, we see that King (emp_key E101) is the manager for all the employees. King is getting over worked, so the boss wants us to make Baker the manager for Linus and Johnson. We can do this with an easy UPDATE.

SQL> update emp
2 set manager = 'E108'
3 where emp_key in ('E104','E107');

2 rows updated.

SQL> select
2 emp_key,
3 emp_last_name,
4 manager
5 from
6 emp;

EMP_KEY EMP_LAST_NAME MANAGER
--------- ------------------------------ ---------
E101 king
E102 jackson E101
E103 korn E101
E104 linus E108
E105 tokheim E101
E106 levender E101
E107 johnson
E108
E108 baker E101
E109 coleman E101
E110 brannigan E101

10 rows selected.

No problem there. Behind that UPDATE, the foreign key made sure that E108 was listed in the emp_key column before it allowed the UPDATE. Now, the boss has decided that he will be King’s manager. No problem, the boss’s emp_key is E000, so we just use another UPDATE.

SQL> update emp
2 set manager = 'E000'
3 where emp_key = 'E101';
update emp
*
ERROR at line 1:
ORA-02291: integrity constraint (PUBS.MANGER_FK) violated - parent key not Found

The boss cannot be listed as King’s manager, because he is not in the EMP table. More correctly, his emp_key is not a value in the emp_key column. If we add him to the table, then he can be King’s manager. This example showed a foreign key on a table. The foreign key can also be used to between tables. Look at the JOB and EMP tables.

The boss just made a new rule; no one can be an employee unless they have a job (kind of obvious). In other words, when they are assigned a job, it must already be in the JOB table. The EMP table contains a job key column that matches the job key column in the JOB table. Since we want to insure that the job is defined before the employee is assigned the job, the JOB table becomes the parent table and the EMP table the child table in this foreign key relationship.

Let’s create the constraint.

SQL> alter table emp
2 add (constraint job_fk foreign key (job_key)
3 references job (job_key)
4 on delete cascade);

Table altered.

Now, when INSERT or UPDATE the job key column in the EMP table, the foreign key constraint will check to insure that the job already exists in the JOB table (or at least the job key exist in the JOB table).

Foreign key constraints can also be disabled, enabled and dropped.

alter table emp disable constraint job_fk;

alter table emp enable constraint job_fk;

alter table emp drop constraint job_fk;

Now, let’s talk about the ON DELETE part of the constraint. When we created the foreign key constraint we included ON DELETE SET NULL or ON DELETE CASCADE. This clause tells the database what to do with the child records when the parent record is deleted. In the example above, we created the job_fk constraint with ON DELETE CASCADE. This will cause the database to cascade the deletes. If I go to the JOB table and DELETE a job, all the employees that have that job will also be deleted as the DELETE will cascade to the child rows. If we use the ON DELETE SET NULL, then when we delete the parent record, the child records with that value will be set to NULL. Why would we want to cascade foreign key deletes? One great example is the STATSPACK package that Oracle provides with the database. This package has over twenty tables, and it gathers performance statistics from the database and loads them into the tables.

The statistics are gathered periodically, say once every hour. As time goes by, the STATSPACK tables will grow very large. If I only want to maintain 30 days of data, I need to delete the data that is older than 30 days. Because STATSPACK creates it tables with a foreign key ON DELETE CASCADE to one main table called stats$snapshot, I can delete the old rows in that one table and all the data in the other tables will also be deleted.

delete from stats$snapshot where snap_time < sysdate - 30;

This one command deletes all the data over 30 days old from all the STATSPACK tables. This is the power of ON DELETE CASCADE.

Foreign keys will allow you to make a column NULL, even if there is not a NULL in the parent table.

SQL> update emp
2 set job_key = NULL
3 where emp_key = 'E106';

1 row updated.

This is not surprising given that ON DELETE SET NULL will, in fact, set a column to NULL when the parent value is deleted.

When you use a foreign key on multiple columns, you can end up with invalid data in your table if you are not careful. If I have a four column foreign key, the constraint is ensuring that the combined four values are in the parent table. If one of the values in the UPDATE/INSERT contains a NULL, then none of the other values are checked. So, if I created a multi-column foreign key on the EMP table that included the emp_key, job_key and pub_key to some parent table with those columns (the PUBS schema does not have such a table so this example is hypothetical) and inserted a row with the job_key set to NULL, the foreign key will not check the emp_key or the pub_key values. In this way, you could enter a row with an invalid emp_key (someone who is not an employee), an invalid pub_key (unknown publisher), and a NULL job_key, and the database will accept it.

  
 

 
 
 
 
Oracle performance tuning software
 
 

 

 
 
 
Oracle performance Tuning 10g reference poster
 
 
 
Oracle training in Linux commands
 
Oracle training Excel
 
Oracle training & performance tuning books
 

 

Fast-Track Oracle Support
PO Box 511
Kittrell, NC 27544


Email BC: