2013-07-14 170 views
17

我目前正在为我们团队的项目设计一个数据库结构。目前我有这个问题:是否可以将外键作为另一个表上的主键?外键可以作为主键吗?

下面是我们的一些系统的数据库设计的表:

user_accounts 
students 
guidance_counselors 

我希望发生的是,user_accounts表应包含的ID(所谓的登录凭证到系统)和密码学生用户和指导顾问用户。简而言之,studentsguidance_counselors表的主键也是user_accounts表的外键。但我不确定是否允许。

的另一个问题是:一个student_rec表中也存在,这需要一个student_number(这是在user_accountsuser_id)和guidance_counsellor_id(这也是在user_accountsuser_id)它的每个记录的。如果学生和辅导员的ID都来自user_accounts table,我如何设计student_rec表?并且为了将来的参考,我如何手动将它写入SQL代码?

这一直在窃听我,我找不到任何具体或肯定的答案来解决我的问题。

+1

虽然你的问题的答案是“是的,主键也可以作为外键”,我的建议是避免这种情况。使用离散主键和外键可以表达同样的关系,并且负担多重责任的列可能会造成困难。例如,如果主键也是标识列,或者通过ORM使用GuidComb策略自动分配,那么您可能会查看两个或更多个事务,而不是一个。单一责任原则也适用于数据库设计。 –

回答

21

当然。这是一种常见的技术,称为supertyping表。就像在你的例子中,这个想法是一个表包含实体的超集,并且具有描述一般实体的公共属性,而其他表包含具有特定属性的那些实体的子集。它与面向对象设计中的简单类层次结构不同。

对于第二个问题,一个表可以有两列,这两列分别是同一个其他表的外键。当数据库建立查询时,它会将该表连接两次。为了在一个SQL查询中进行说明(不确定MySQL语法,我很久没有使用它了,所以这是MS SQL语法),当选择数据时,您将为该表提供两个不同的别名。事情是这样的:

SELECT 
    student_accounts.name AS student_name, 
    counselor_accounts.name AS counselor_name 
FROM 
    student_rec 
    INNER JOIN user_accounts AS student_accounts 
     ON student_rec.student_number = student_accounts.user_id 
    INNER JOIN user_accounts AS counselor_accounts 
     ON student_rec.guidance_counselor_id = counselor_accounts.user_id 

这基本上采取student_rec表,并与user_accounts表结合了两次,一次在每一列,而当将它们结合起来,从而分开告诉他们分配两个不同的别名。

+0

这只是一个列集既是FK也是PK的情况。每种密钥都是独立定义的。 – philipxy

2

是的,应该没有问题。外键和主键彼此正交,对于一列或一组列来说,它们都是该表的主键(这要求它们是唯一的),并且还要与主键/唯一约束关联在另一张桌子。