一列中有多个外键?

时间:2015-03-29 14:27:02

标签: php mysql sql database-design

我正在尝试为狗的主页创建一个数据库 我用mysql和php。每只狗都有一个dog_id(PRIMARY KEY),可以用它来识别。

现在,我希望能够将狗与其兄弟姐妹联系起来。这里的问题是,兄弟姐妹的数量可能在0到25之间,因此,我不确定如何做到这一点。

这是我的第一次尝试

TABLE `dogs` (
    `dog_id` INT(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'auto incremented PRIMARY KEY',
    `dog_sibling1` INT(11) COLLATE utf8_unicode_ci NULL COMMENT 'FOREIGN KEY dog_id of the dog\'s 1st sibling',
    `dog_sibling2` INT(11) COLLATE utf8_unicode_ci NULL COMMENT 'FOREIGN KEY dog_id of the dog\'s 2nd sibling',
     and so on....
     );

我在这里看到的问题是,在最坏的情况下,我最终得到25列NULL,大部分时间都有很多NULL列。

我的第二次尝试

TABLE `dogs` (
        `dog_id` INT(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'auto incremented PRIMARY KEY',
        `dog_sibling_ids` INT(11) COLLATE utf8_unicode_ci NULL COMMENT 'FOREIGN KEY dog_ids of the dog\'s siblings',
         );

像这样我只有一列,但我不知道是否可以在一列中保存一组外键?而且我也不确定如何在php中处理这个问题。

有没有更好的方法来解决这个问题?

2 个答案:

答案 0 :(得分:1)

你最好的选择可能是建立第二张桌子,将兄弟姐妹组合在一起。

CREATE TABLE dog_siblings (
   sibling_group_id INTEGER,
   dog_id integer
);

这样,如果dog_ids 5-9都是相关的,他们只需要在新表中共享一个共同的sibling_group_id,你可以使用类似下面的查询找到所有相关的狗

SELECT ds2.dog_id
FROM dogs d
    INNER JOIN dog_siblings ds
        ON d.dog_id = ds.dog_id AND d.dog_id = 1
    INNER JOIN dog_siblings ds2 
        ON ds.sibling_group_id = ds2.sibling_group_id

那将会给你所有狗的兄弟姐妹id 1(包括狗1)

(编辑:愚蠢的无法发表评论,对我的评论出现了,而我正在制作这个,诚实)

答案 1 :(得分:1)

我会提出类似于您在问题中建议的解决方案:创建一个名为siblings的表并从dogs表引用它:

CREATE TABLE `siblings` (
    `siblings_id` INTEGER PRIMARY KEY
);

CREATE TABLE `dogs` (
    `dog_id` INTEGER PRIMARY KEY,
    `dog_sibling_id` INTEGER REFERENCES `siblings`
);

我不会将siblings表中的任何引用放到dogs表中,因为它显然是一对多的关系(一个兄弟姐妹组可以有很多只狗,但只有一只狗可以属于一个兄弟姐妹组)。那些没有兄弟姐妹的狗怎么样?您也可以为这些狗创建一个兄弟姐妹组,或者将dog_sibling_id留给NULL

如果您想知道一窝(同时出生的一群幼犬)的兄弟姐妹,之前的作品。如果您需要跟踪不同窝之间的兄弟姐妹,请添加motherfather引用:

CREATE TABLE `litters` (
    `litter_id` INTEGER PRIMARY KEY,
    `mother_id` INTEGER REFERENCES `dogs`,
    `father_id` INTEGER REFERENCES `dogs`
);

CREATE TABLE `dogs` (
    `dog_id` INTEGER PRIMARY KEY,
    `dog_litter_id` INTEGER REFERENCES `litters`
);

您也可以将motherfather列添加到dogs表并删除litters表(在这种情况下,特定于垃圾邮件的信息将会丢失)