外键是否可以作为同一个表中的候选键?

时间:2015-12-23 23:32:21

标签: mysql database

我将尝试通过一个例子来解释这种情况:

我有2个表,A和B,它们之间的“一对多”关系,B由单个键(pk_B)标识,A由几个键(pk_A1和pk_A2)标识。所以我们有两个表:

B(pk_B, attr1, attr2, attr3);

A(pk_A1, pk_A2, attr1, attr2, fk_B);

由于某些原因,A表中的fk_B可以是几个主键的一部分,因此主键是

pk_A1 + pk_A2 + fk_B. 

有可能吗? 如果我太通用了,我很抱歉。如果你愿意,我可以尝试用一个具体的例子来更清楚地解释这种情况。

更新:

实施例

我有两个表,“房间”和“区域”,处于“一对多”的关系中(1个房间,N个区域; 1个区域,1个房间)。房间是建筑物的内部环境,由墙壁限定;区域只是空间的一部分。 房间由一个主键(Room_ID)标识;区域由几个键标识:coordinate_X + coordinate_Y。 举一个具体的例子,我添加了第三个表,我称之为“对象”,由ID标识。可以将对象放置在N个区域中,在可以放置单个对象的区域中。所以我们有三个表:

Room (Room_ID, temperature, capacity)

Area(coordinate_X, coordinate_Y, dimension, FK_Room_ID, FK_Object_ID)

Object(Object_ID, name, weight, size)

现在,如果你想一下,我们有N个区域,每个区域都可以通过坐标X& Y,但如果我们说在每个区域都可以有一个物体,如果我在一个区域放置一个物体并不意味着所有有一定区域的房间都放置了一个物体,这并不好;因为我需要区分区域X = 1&在房间A中Y = 1并且区域X = 1&在房间B中Y = 1.所以我必须做一个主键由三个属性组成:X坐标+ Y坐标+房间ID(所以,当我将一个对象添加到一个区域时,我需要指定X坐标, Y坐标和我想放置物体的房间。)

4 个答案:

答案 0 :(得分:1)

是。外键可以同时到另一个键。例如,考虑树中的“父”键,或Paypal IPN事务表来考虑它。我已经实现了几个这样的例子。

答案 1 :(得分:1)

正如其他人所说,这是可能的。但是,我要加0.02美元。

根据您的说法,如果pk_A1pk_A2已经唯一标识A,为什么要添加第3列作为主键的一部分?就个人而言,我没有看到这样做的任何好处。

此外,假设C和A之间存在一对多的关系,A&C的主键将成为C中的外键。通过本书,C必须继承"继承&# 34;来自A的pk_A1pk_A2fk_B。不是本书,也可以声明C仅引用pk_A1pk_A2,让fk_B再次毫无意义。还要记住,当加入A和C时,您的联接将不必要地延长。

这就是为什么我们通常从表的候选键集中选择最短的主键。

请记住,我所说的只是基于你的陈述,(pk_A1, pk_A2)本身就是主键。

答案 2 :(得分:1)

使用您的示例,以下代码成功执行。请指定您收到的错误消息,以防止您添加主键?

create table Room (
    Room_ID int primary key,
    temperature numeric(5,2),
    capacity int
)

create table Obj (
    Obj_ID int primary key,
    name varchar(max),
    obj_weight numeric(10,2),
    obj_size numeric(10,2)
)

create table Area (
    coordinate_X int,
    coordinate_Y int,
    dimension int,
    FK_Room_ID int,
    FK_Obj_ID int,
    primary key (coordinate_x, coordinate_Y, FK_Room_ID),
    foreign key (FK_Room_ID) references Room (Room_ID),
    foreign key (FK_Obj_ID) references Obj (Obj_ID)
)

(为MySql编辑)

答案 3 :(得分:1)

虽然您可以将坐标x,y和room_id组合作为主键,但请考虑在重新构建该房间及其坐标更改时可能需要进行的更改。建议主键不要更改。

另外,房间

我推荐以下设计:

-- contains information about just the room
create table room (
  id int not null auto_increment,
  capacity int,
  temperature_c int
  primary key (id)
);

-- contains information about area
create table area (
  id int not null auto_increment,
  nickname varchar(100), -- e.g. dresser by bed
  coordinate_x int,
  coordinate_y int,
  dimension_m2 int,
  primary key (id)
);

-- gives the ability to manage one room and many areas; 
-- or even many rooms and many areas (flexible for future needs)
create table room_area (
  id int not null auto_increment,
  room_id int not null,
  area_id int not null,
  primary key (id),
  constraint uk_room_area_ids unique key (room_id, area_id)
);

-- master table of objects
create table object (
  id int not null auto_increment,
  name varchar(100),
  weight_kg int,
  size_m2 int,
  primary key (id)
);

-- define which object goes in what area of what room
create table room_area_object (
  id int not null auto_increment,
  object_id int not null,
  room_area_id int not null,
  quantity int,
  primary key (id),
  constraint uk_room_area_object_ids unique key (room_area_id, object_id)
);

这种设计可以更灵活地定义房间,区域和对象主表,并将它们的特定专业结合在一个联结表中。如果您有2张完全相同的床,他们可以作为单一条目进入对象表,但数量= 2.然后可以将它们分配到房间卧室1和区域休眠区。