Re: primary and foregin keys

From: Tony Andrews <andrewst_at_onetel.com>
Date: 24 Dec 2004 03:07:15 -0800
Message-ID: <1103886435.878792.107430_at_c13g2000cwb.googlegroups.com>


rallyka..._at_hotmail.com wrote:
> Okey, I get your point. This solution will make me do a transfer of
> data from the "product" table into the "product_history" table each
> time the "product" table is updataded with an already existing
> "product_number". Let's imagine that I go with my solution. How would
> you solve the problem if you only got the tables "products" and
> "storage". Would you use a foregin key pointing out the
> "product_number" in "products" from "storage" even if the
> "product_number" itself not is the primary key in "products" or is
this
> totaly against the constraint concept?

Your solution will not work, since a foreign key MUST reference the whole of a primary or unique key in the "parent" table. If you don't want a separate history table, then perhaps you should consider adding the date column to the storage table as part of the foreign key?

Otherwise, you will have to come up with a solution that does not use a foreign key, which seems unwise. This could be done with a materialized view and a check consraint:

SQL> create materialized view product_storage_mv 2 build immediate
3 refresh complete on commit as
4 select s.prod_number sp, p.prod_number pp, s.rowid sr, p.rowid pr 5 from storage s, product p
6 where p.prod_number (+) = s.prod_number;

Snapshot created.

SQL> alter table product_storage_mv
2 add constraint product_storage_mv_chk 3 check (pp is not null);

Table altered.

The check constraint is validated on commit:

SQL> insert into storage values (1,100);

1 row created.

SQL> commit;
commit
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path ORA-02290: check constraint (TANDREWS.PRODUCT_STORAGE_MV_CHK) violated

SQL> insert into product values (1,sysdate);

1 row created.

SQL> insert into storage values (1,100);

1 row created.

SQL> commit;

Commit complete.

SQL> delete product where prod_number=1;

1 row deleted.

SQL> commit;
commit
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path ORA-02290: check constraint (TANDREWS.PRODUCT_STORAGE_MV_CHK) violated

BUT having said all that, isn't the problem that your tables are the "wrong way round"? The STORAGE table appears to be keyed on prod_number, which makes it the product "master" table. So perhaps:

SQL> drop materialized view product_storage_mv;

Snapshot dropped.

SQL> rename product to product_history;

Table renamed.

SQL> rename storage to product;

Table renamed.

SQL> alter table product add constraint prod_pk primary key (prod_number);

Table altered.

SQL> alter table product_history add constraint prod_hist_fk_prod foreign key (prod_number) references product;

Table altered. Received on Fri Dec 24 2004 - 12:07:15 CET

Original text of this message