插入具有多个值的外键

时间:2012-02-14 21:21:14

标签: database oracle

我想知道,有没有可能创建一个表,我有一个表接受外键但可能有同一行的多个值。

例如:

Employee(id,name,skillid);
Skill(Skillid,skillname);

这里的Employee实例可能是

Employee(311,"john", (01,02) );
Skill (01,Java); Skill (02,C++);

我为表格实现了相同的制作主键(是,skillid)

但是在我有桌子的情况下:

create table Movie (Movie_ID varchar(5),                              
                            Cast varchar(5),
                            foreign key(Cast) references Person(Person_ID), 
                            primary key(movie_id, Cast));

和另一张表:

create table Awards  (Award_Id varchar(5),
                                Person_Id varchar(5), 
                                Movie_Id varchar(5),
                                Award_Name  varchar(30),
                                Year number(4),
                                Organization_Id varchar(5),
                                primary key (Award_id,year,Organization_Id),
                                foreign key(Person_Id) references Person(Person_ID),
--                                foreign key(Movie_ID) references Movie(Movie_ID),
                                foreign key(Organization_Id) references Organization(Organization_Id));

在这种情况下,我无法将Movie_ID用作外键,因为它所引用的表具有两个组合作为其主键。我没有在奖项表中使用其中第二个属性。

任何提示如何实现这一点?

3 个答案:

答案 0 :(得分:6)

不幸的是,你刚刚问过这个古老的问题;

  

如何将两件事放在一列?

答案当然是你没有;你有两列。要扩展您的员工示例,您的员工表将变为:

create table employees (
   id number
 , name varchar2(4000)
 , skill_1 number
 , skill_2 number
 , constraint employee_pk primary key (id)
 , constraint employee_skill_1_fs 
      foreign key ( skill_1 ) 
   references skills(skillid)
 , constraint employee_skill_2_fs 
      foreign key ( skill_2 ) 
   references skills(skillid) 
   );

正如你所看到的,这不是一件特别漂亮的事情,并打破了正常化;如果您希望您的员工(或您的员工当然想要)拥有3项技能,会发生什么?还是10?

创建第三个表并使用单个主键和外键完成所有连接可能会更好;所以你会有

employees ( employee_id, ..., pk employee_id);
employee_skills ( employee_id, skill_id, ..., pk employee_id, skill_id, fk skill_id );
skills ( skill_id, description, ..., pk skill_id );

答案 1 :(得分:0)

如果要在父表中创建复合主键,则需要在子表中创建复合外键。换句话说,如果您希望父表使用由三个不同列组成的自然主键

CREATE TABLE car_type (
  make  VARCHAR2(100),
  model VARCHAR2(100),
  year  NUMBER,
  PRIMARY KEY pk_car_type( make, model, year )
);

然后子表也需要包含所有三列

CREATE TABLE car (
  vin   VARCHAR2(17) PRIMARY KEY,
  make  VARCHAR2(100),
  model VARCHAR2(100),
  year  NUMBER,
  FOREIGN KEY fk_car_car_type( make, model, year )
    REFERENCES car_type( make, model, year )
);

在外键定义中使用多个列通常会变得很痛苦,因为模式变得更大并且您需要将更多表连接在一起,这就是人们引入合成主键(即由序列填充的无意义键)的原因。这可以让你简化事情

CREATE TABLE car_type (
  car_type_id NUMBER PRIMARY KEY,
  make        VARCHAR2(100),
  model       VARCHAR2(100),
  year        NUMBER,
  UNIQUE uk_car_type( make, model, year )
);

CREATE TABLE car (
  vin   VARCHAR2(17) PRIMARY KEY,
  car_type_id NUMBER REFERENCES car_type( car_type_id )
);

答案 2 :(得分:0)

如果(movie,cast)是父表的主键,则任何引用表都必须在外键中包含两个列。这只是规则。

有两种方法可以解决这个问题。要么你的主键错了,在这种情况下你需要修改MOVIES表上的约束。或者,您需要将CAST列添加到AWARDS表。

当涉及到外键时,复合键是一个痛苦的问题。这就是为什么许多从业者更喜欢使用代理(或合成)主键,因此子表只需要引用单个列。原始 - 复合 - 密钥仍然是强制执行的,但作为一个唯一的密钥。