23

这就是让我感到困惑的地方。我经常在数据库表中有复合主键。这种方法的不好的一面是,当我删除或编辑条目时,我有很多额外的工作。但是,我觉得这种方法是本着数据库设计的精神。

另一方面,我的一些朋友从不使用复合键,而是在表中引入另一个“id”列,所有其他键都只是 FK。在编写删除和编辑程序时,他们的工作量要少得多。但是,我不知道它们如何保持数据条目的唯一性。

例如:
方式 1

create table ProxUsingDept (
    fkProx int references Prox(ProxID) NOT NULL,    
    fkDept int references Department(DeptID) NOT NULL,    
    Value int,    
    PRIMARY KEY(fkProx,fkDept)
)

方式二

create table ProxUsingDept (
        ID int NOT NULL IDENTITY PRIMARY KEY
        fkProx int references Prox(ProxID) NOT NULL,    
        fkDept int references Department(DeptID) NOT NULL,    
        Value int
)

哪种方式更好?使用第二种方法有什么不好的方面?有什么建议么?

4

4 回答 4

29

我个人更喜欢您的第二种方法(并且几乎 100% 的时间都会使用它) - 引入一个代理ID字段。

为什么?

  • 使引用您的表的任何表的生活变得更加轻松 -只需一个 ID 列(而不是始终需要加入的 2、3 甚至更多列), JOIN 条件要简单得多

  • 让生活变得更轻松,因为任何引用您的表的表只需要携带一个ID作为外键字段 - 而不是复合键中的几列

  • 由于数据库可以处理唯一ID列的创建(使用INT IDENTITY) ,因此生活变得更加轻松

但是,我不知道它们如何保持数据条目的唯一性。

非常简单:在复合列上放置一个 UNIQUE INDEX,否则将用作主键!

CREATE UNIQUE INDEX UIX_WhateverNameYouWant 
   ON dbo.ProxUsingDept(fkProx, fkDept)

现在,你的桌子保证你的桌子上永远不会有重复的一对(fkProx, fkDept)- 问题解决了!

于 2011-01-19T15:54:28.347 回答
18

你问以下问题:

但是,我不知道它们如何保持数据条目的唯一性。

可以通过在将形成自然主键的列上声明单独的复合 UNIQUE 索引来保留唯一性。

哪种方式更好?

不同的人有不同的意见,有时持有强烈的意见。我想你会发现更多的人使用代理整数键(并不是说它是“正确”的解决方案)。

使用第二种方法有什么不好的方面?

以下是使用代理键的一些缺点:

  1. 您需要一个额外的索引来维护自然主键的唯一性。

  2. 在选择数据以获得所需结果时,有时需要额外的 JOIN(当您可以仅使用复合自然键中的列满足查询要求时会发生这种情况;在这种情况下,您可以使用外键列而不是 JOINing回到原来的表)。

于 2011-01-19T15:57:07.237 回答
0

在某些情况下,例如 M:N 连接表,复合键最有意义(如果性质或 M:N 链接发生变化,无论如何您都必须重新设计此表)。

于 2011-01-19T15:55:24.533 回答
-3

我知道自从这篇文章发表以来已经很长时间了。但是我不得不遇到关于复合键的类似情况,所以我发表了我的想法。

假设我们有两个表 T1 和 T2。

T1 具有列 C1 和 C2。

T2 具有 C1、C2 和 C3 列

C1 和 C2 是表 T1 的复合主键和表 T2 的外键。

假设我们使用了表 T1 的代理键 (T1_ID) 并将其用作表 T2 中的外键,如果表 T1 的 C1 和 C2 的值发生变化,则对表 T1 实施引用完整性约束是额外的工作表 T2,因为我们只查看表 T1 中的代理键,其值在表 T1 中没有改变。这可能是第二种方法的一个问题。

于 2013-04-29T19:58:45.800 回答