我当前的数据库设计使用多列主键来使用现有数据(无论如何都是唯一的),而不是创建为每个条目分配任意键的附加列。我知道这是允许的,但我想知道这是否是我可能要谨慎使用并可能避免的做法(就像C中的goto)。
那么,我可能会在这种方法中看到哪些缺点,或者是我想要一个单列键的原因呢?
我当前的数据库设计使用多列主键来使用现有数据(无论如何都是唯一的),而不是创建为每个条目分配任意键的附加列。我知道这是允许的,但我想知道这是否是我可能要谨慎使用并可能避免的做法(就像C中的goto)。
那么,我可能会在这种方法中看到哪些缺点,或者是我想要一个单列键的原因呢?
Answers:
通常,当您有一个带有多列主键的表时,这是联接表(多对多)的结果,该表被提升为自己的实体(因此值得拥有自己的主键)。有很多人认为默认情况下任何联接表都应该是实体,但这是另一天的讨论。
让我们看一下假设的多对多关系:
学生* --- *班级
(一个学生可以在多个班级中,一个班级可以有多个学生)。
在这两个表之间将是一个称为StudentClass(或ClassStudent,取决于您如何编写)的联结表。有时,您想跟踪学生上课时的情况。因此,您将其添加到StudentClass表中。至此,StudentClass已经成为一个独特的实体...并且应该被赋予一个名称来识别它,例如注册。
学生1 --- *入学人数* --- 1班
(一个学生可以有多个注册,每个注册都针对一个班级(或者相反,一个班级可以拥有多个注册,每个注册都针对一个学生)。
现在,您可以查询类似的信息,例如,去年有多少学生参加了化学101课程?或者,约翰·多伊(John Doe)参加Acme University的学生参加了哪些课程?如果没有单独的主键,这是可能的,但是一旦您有了注册的主键,一个简单的查询就会是这些注册(按ID),有多少学生获得及格分数?
确定某个实体是否值得PK的决定归结为您将对该实体进行多少查询(或操作)。举例来说,您想将为某位学生完成的作业附在班上。附加此实体(分配)的逻辑位置将在“注册”实体上。为注册提供自己的主键将使Assignment查询更简单。
有一个单独的id列很有意义。当您想从数据库表中获取某些信息时,这样做会更容易:
SELECT whatever FROM table WHERE id=13
比从表中选择任何内容都更合适col1 ='val1'AND col2 ='val2'AND col3 ='val3'
例如,在Web应用程序中,它将转换为如下所示的URL:
www.somewebsite.com/somepage.php?id=13
或像这样:
www.somewebsite.com/somepage.php?col1=val1&col2=val2&col3=val3
SELECT
查询。而且,B),我不知道这实际上是如何导致任何类型的URL要求的(除非您使用的框架不好)。我的网址中没有任何查询字符串?id=13
,更不用说了?col1=val1&col2=val2&col3=val3
。
基本上,您是在问是否应该使用代理键或自然键(在您的情况下,听起来像复合自然键)。这是一篇很棒的文章:http : //www.agiledata.org/essays/keys.html
我更喜欢替代密钥,因为它们可以简化数据库生命周期内的管理(您不必担心密钥更改含义的隐含性,这种含义永远不会发生,但是在涉及人类的任何实际系统中都是如此)。 但是,如果数据库中有很多“查找”表(即基本上是键:值对的表),则代理键会变得很麻烦,因为必须将这些表加入查询中才能获得有意义的结果。
例如,假设您有两个实体:地址和国家/地区。
select * from Address where CountryCode = 'US'
select Address.* from Address join Country on Address.CountryID = Country.ID where Country.Code = 'US'
如果我很确定自然键不会经常更改(如果有的话),我很乐意为查找表强制使用自然键,而对其他所有命令都使用代理键。
如果您发现您的复合密钥实际上可以重复,那么将PK用作自动增量int可以减少麻烦。