如何正确设计数据库?外键与二键?

时间:2012-02-17 18:25:43

标签: database database-design foreign-keys

这里有一些通用表,我试图完全理解如何正确设置数据库表。这些设置是否正确?我希望能够尽快查找用户的项目和项目详细信息。此示例的FYI ItemDetailsX不共享相同的数据字段。

我有点卡在外键和辅助键上。什么时候使用辅助密钥和外键?

tbl_Users 1:* tbl_Item // relationship

tbl_Item 1:1 tbl_ItemDetail1& tbl_ItemDetail2 // relationship

tbl_Item 1:N tbl_ItemDetail3 // releationship

tbl_Users

-UserID - PK

tbl_Item

-ItemID - PK

-UserID - FK

tbl_ItemDetail1

-ItemDetail1ID - PK //如果我有ItemID,我甚至需要这个吗?它与

的关系是1:1

-ItemID - FK

-Count

-duration

- 频率

tbl_ItemDetail2

-ItemDetail2ID - PK //如果我有ItemID,我甚至需要这个吗?它与

的关系是1:1

-ItemID - FK

-OnOff

- 温度

- 电压

tbl_ItemDetail3

-ItemDetail3ID - PK //具有1:N关系

-ItemID - FK

-Contrived Value1

-Contrived Valu2

编辑:

感谢您的回复,我已更新原始帖子以正确反映我的数据库。

在我创建的数据库中,Item有~9项详细信息。每个项目的详细信息是5-15列数据。

拥有100个列的1个表没有意义......?

2 个答案:

答案 0 :(得分:7)

数据库强制执行3种声明完整性:

  • 的完整性 - 字段的类型和CHECK约束。
  • 密钥的完整性 - PRIMARY KEY或UNIQUE约束。
  • 参考完整性 - FOREIGN KEY。

唯一标识表中的行。所有密钥在逻辑上都是等价的,但出于实际原因,其中一个被选为“主要”,其余的被认为是“备用”(有一些涉及NULL的并发症,但我们不在这里讨论)。

另一方面,FOREIGN KEY是一种从一个表到另一个表的“指针”,DBMS本身保证这个“指针”永远不会"dangle"。外键引用“父”表中的(主要或备用)键,但“子”端点本身不需要是键(通常不是)。

  • 当从父表中修改或删除行时,此更改要么级联到子表(ON [UPDATE / DELETE] [CASCADE / SET NULL / SET DEFAULT])或者整个操作被阻止(ON [UPDATE / DELETE] RESTRICT)。
  • 如果插入或修改了子项,则会根据父表检查子项以确保该值存在。

约束会更改数据的含义。另一方面,索引不会改变数据的含义 - 它们纯粹是出于性能的原因。有些数据库甚至可以让你拥有一个没有底层索引的密钥,尽管这在性能方面通常是一个坏主意。主键下面的索引称为“主索引”,所有其他索引都是“辅助索引”。

顺便说一下,有“二级索引”并且有“备用密钥”,但没有“二级密钥”这样的东西。


我不太确定你的设计目标是什么,但我猜这样的事情将是一个不错的起点:

enter image description here

我认为没有任何目的可以将细节提取到单独的表如果,它们始终与项目保持1:1的关系。


---编辑---

在能够达到最佳数据库设计之前,您需要先问自己一些问题:

项目与细节之间是否存在真正的1:1关系,还是实际上是1:0..1(即某些细节是可选的?)。

  • 如果1:1,只使用列是最自然的表示。顺便说一下,一个不错的DBMS可以毫不费力地处理100列。
  • 如果1:0..1,您将必须决定是使用可以使用NULL的列还是使用单独的表。请记住,大多数DBMS在存储NULL方面非常有效(通常每行只有一个小位图),因此将数据分离到不同的表可能不会对您造成太大影响,实际上可能会因查询性能的提高而大大恶化查询性能。接合。

是否预先确定了所有详细信息(即您是否可以放心地说,您不需要在应用程序生命周期的后期添加任何新的细节)?

  • 如果是,请使用列。
  • 如果不是,在现有的大型数据库上添加列可能会很昂贵 - 是否足够昂贵以保证使用单独的表由您来衡量。

您还可以考虑将所有细节概括为名称/值对,并在单个1:N表中表示它们(此处未显示)。这是非常灵活和“可演化的”,但有其自身的一系列问题。

您打算如何查询数据?这是一个很大的问题,可能会影响是否采用“列”或“单独表格”方法,索引等...


顺便说一下,带有单独表格的1:0..1可以像这样建模......

enter image description here

......和1:1可以这样建模......

enter image description here

...但是这引入了循环依赖,必须以特殊方式处理(通常由deferring FOREIGN KEY之一。)

1:N细节当然是另一回事,并且通过单独的表自然建模。


由于你说“细节1”和“细节2”是1:(0 ..)1而“细节3”是1:N,你的“更新”数据模型可能看起来像这样:

enter image description here

顺便说一句,上面的模型使用识别关系,这导致更“自然”的关键。 非识别关系/代理键方法如下所示:

enter image description here

每种方法都有其优点,但这篇文章已经变得有点长了;)......

答案 1 :(得分:0)

您的问题无法在一篇简单的SO帖子中回答。创建数据库时需要考虑很多事情。我曾经做过的关于数据库以及如何创建它们的最好的事情是阅读Michael Hernandez撰写的一本名为“数据库设计为真人”的书。

See my post on Programmers问题您如何处理数据库设计?