, parent_id number(12,0) constraint chd_par_fk foreign key references parent(parent_id)But what is the fewest number of words required to implement the same constraint? Two. This does exactly the same thing:
, parent_id references parentThe neat thing about this minimalist declaration is the child column inherits the datatype of the referenced primary key column. Here's what it looks like (with an odd primary key declaration, just to prove the point):
SQL> create table parent1 2 (parent_id number(15,3) primary key) 3 / Table PARENT1 created. SQL> create table child1 2 ( id number(12,0) primary key 3 ,parent_id references parent1) 4 / Table CHILD1 created. SQL> desc child1 Name Null? Type --------- -------- ------------ ID NOT NULL NUMBER(12) PARENT_ID NUMBER(15,3) SQL>If we want to specify a name for the foreign key we need to include the
constraint
keyword:
SQL> create table parent2 2 (parent_id number(15,3) constraint par1_pk primary key) 3 / Table PARENT2 created. SQL> create table child2 2 ( id number(12,0) constraint chd2_pk primary key 3 ,parent_id constraint chd2_par2_fk references parent2) 4 / Table CHILD2 created. SQL> desc child2 Name Null? Type --------- -------- ------------ ID NOT NULL NUMBER(12) PARENT_ID NUMBER(15,3) SQL>This minimal declaration always references the parent table's primary key. Suppose we want to reference a unique key rather than the primary key. (I would regard this as a data model smell, but sometimes we need to do it.) To make this work we need merely explicitly reference the unique key column:
SQL> create table parent3 2 ( parent_id number(15,3) constraint par3_pk primary key 3 ,parent_ref varchar2(16) not null constraint par3_uk unique 4 ) 5 / Table PARENT3 created. SQL> create table child3 2 ( id number(12,0) constraint chd3_pk primary key 3 ,parent_ref constraint chd3_par3_fk references parent3(ref)) 4 / Table CHILD3 created. SQL> desc child3 Name Null? Type ---------- -------- ------------ ID NOT NULL NUMBER(12) PARENT_REF VARCHAR2(16) SQL>Hmmm, neat. What if we have a compound primary key? Well, that's another data model smell but it still works. Because we're constraining multiple columns we need to use a table level constraint and so the syntax becomes more verbose; we need to include the magic words
foreign key
:
SQL> create table parent4 2 ( parent_id number(15,3) 3 ,parent_ref varchar2(16) 4 ,constraint par4_pk primary key (id, ref) 5 ) 6 / Table PARENT4 created. SQL> create table child4 2 ( id number(12,0) constraint chd4_pk primary key 3 ,parent_id 4 ,parent_ref 5 ,constraint chd4_par4_fk foreign key (parent_id, parent_ref) references parent4) 6 / Table CHILD4 created. SQL> desc child4 Name Null? Type ---------- -------- ------------ ID NOT NULL NUMBER(12) PARENT_ID NUMBER(15,3) PARENT_REF VARCHAR2(16) SQL>Okay, but supposing we change the declaration of the parent column, does Oracle ripple the change to the child table?
SQL> alter table parent4 modify parent_ref varchar2(24); Table PARENT4 altered. SQL> desc child4 Name Null? Type ---------- -------- ------------ ID NOT NULL NUMBER(12) PARENT_ID NUMBER(15,3) PARENT_REF VARCHAR2(16) SQL>Nope. And rightly so. This minimal syntax is a convenience when we're creating a table, but there's no object-style inheritance mechanism.
Generally I prefer a verbose declaration over minimalism, because clarity trumps concision. I appreciate the rigour of enforcing the same datatype on both ends of a foreign key constraint. However, I hope that in most cases our CREATE TABLE
statements have been generated from a data modelling tool. So I think this syntactical brevity is a neat thing to know about, but of limited practical use.