我想知道,有没有可能创建一个表,我有一个表接受外键但可能有同一行的多个值。
例如:
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用作外键,因为它所引用的表具有两个组合作为其主键。我没有在奖项表中使用其中第二个属性。
任何提示如何实现这一点?
答案 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表。
当涉及到外键时,复合键是一个痛苦的问题。这就是为什么许多从业者更喜欢使用代理(或合成)主键,因此子表只需要引用单个列。原始 - 复合 - 密钥仍然是强制执行的,但作为一个唯一的密钥。