外键引用oracle中两个表的一个字段

时间:2013-05-06 11:09:44

标签: database oracle plsql

我试图通过引用不同的表来设置外键。

想象一下表格:

Active_Card((主键)Num_id号,num_card号,is_active varchar2);

TMP_CARD((PK)num_card number,reg_date date);

DEFINITIVE_CARD((PK num_card number,name varchar,create_date date)

所以num_card是Active_Card的外键。我的问题是如何在Active_card中引用两个表(TMP_CARD和DEFINITIVE_CARD)。

最好的问候,

3 个答案:

答案 0 :(得分:2)

让我们解释为什么这不是一个好主意并从那里开始:

第一个让我们说RDBMS允许你这样做。

因此,Active_Card中的FK与Definitive_CardTmp_Card都有关联。

现在假设我们有一个definitive_card#s 123,456和一个tmp_card#s 123,789

外键强制引用完整性。所以123可以,因为它存在于两者中。 456和789不会在两个表中都不存在。

但这不是通缉。你表示它需要在两个表中,而不是在注释中指出:*为了在Active_Card中有一个条目,它必须在DEFINITIVE_CARD或TMP_CARD中存在条目*

因此,既然你不想要同一个card_number,那么你真的有2-3个选择:

  1. 将Card_numbers放在一个单独的表中,并通过关联表连接回Active_card
  2. 在Active_card中放置第二个card_number列,具体取决于填充的字段,告诉您要转到哪个表以获取更多信息。
  3. 将Definitive_Card和tmp_card中的所有字段放在同一个表中
  4. 这些选项中的每一个都有自己的优缺点列表:但如果没有完全理解业务需求,我们就不能说哪种选择最适合您的情况。

    我们可以说你的尝试根本不会在RDBMS中起作用;但上述3个选项中的任何一个都将满足能够添加适当外键的要求

答案 1 :(得分:2)

我认为拟议的设计要求是可疑的。我之前看到这个设计要求是由于构造不良的对象模型所造成的,这些模型正在进入构造不良的关系模型。

尽管如此,如果active_card.num_card必须引用两个表,那么物化视图可以实现设计要求。

create table active_card( 
   num_id number primary key, 
   num_card number, 
   is_active varchar2(5) );
create table tmp_card( 
   num_card number primary key, 
   reg_date date );
create table definitive_card( 
   num_card number primary key, 
   name varchar(256), 
   create_date date );

create or replace view card_v as
select tc.num_card
  from tmp_card tc
 where exists ( select null 
                  from definitive_card dc 
                 where dc.num_card = tc.num_card );

alter table active_card 
   add constraint active_card_num_card_fk 
   foreign key (num_card) 
   references card_v (num_card); -- won't work

但是你不能创建针对视图的外键......所以......创建一个物化视图:

create materialized view log on tmp_card;
create materialized view log on definitive_card;

create materialized view card_mv
   build immediate 
   refresh fast 
   on commit
   as 
   select tc.num_card
     from tmp_card tc
    where exists ( select null 
                     from definitive_card dc 
                    where dc.num_card = tc.num_card )
;

alter table active_card 
   add constraint active_card_num_card_fk 
   foreign key (num_card) 
   references card_mv (num_card); -- works

insert into tmp_card values ( 123, sysdate );
insert into tmp_card values ( 456, sysdate );
insert into tmp_card values ( 789, sysdate );
insert into definitive_card values ( 123, 'OneTwoThree', sysdate );
insert into definitive_card values ( 789, 'SevenEightNine', sysdate );
insert into definitive_card values ( 111, 'OneOneOne', sysdate );

commit;

现在...

insert into active_card values ( 1, 123, 'true' ); -- succeeds
insert into active_card values ( 1, 456, 'true' ); -- fails
insert into active_card values ( 1, 111, 'true' ); -- fails

delete from tmp_card where num_card = 789; -- succeeds
commit;

delete from tmp_card where num_card = 123; -- succeeds, but
commit; --fails

如果设计要求是active_card.num_card必须存在于两个表中的任何一个而不是两个表中,则需要调整物化视图定义。

答案 2 :(得分:0)

我怀疑你不想同时引用这两个表。您想引用另一个

为此,请使用单独的专用FK。或者,使用继承。更多信息here