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

Mau*_*imo 2 database database-design foreign-keys

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

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

tbl_Users 1:*tbl_Item //关系

tbl_Item 1:1 tbl_ItemDetail1&tbl_ItemDetail2 //关系

tbl_Item 1:N tbl_ItemDetail3 //关联

tbl_Users

-UserID - PK

tbl_Item

-ItemID - PK

-UserID - FK

tbl_ItemDetail1

-ItemDetail1ID - PK //如果我有ItemID,我甚至需要这个吗?与...有1:1的关系

-ItemID - FK

-计数

-duration

-频率

tbl_ItemDetail2

-ItemDetail2ID - PK //如果我有ItemID,我甚至需要这个吗?与...有1:1的关系

-ItemID - FK

-开关

-温度

-电压

tbl_ItemDetail3

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

-ItemID - FK

- 受控价值1

-Contrived Valu2

编辑:

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

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

有一个100列的表没有意义......?

Bra*_*vic 7

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

  • 域的完整性- 字段的类型和CHECK约束.
  • 密钥的完整性- PRIMARY KEY或UNIQUE约束.
  • 参照完整性 - 外键.

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

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

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

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

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


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

在此输入图像描述

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


---编辑---

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

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

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

是否所有细节都预先确定(即您是否可以放心地说您不需要在应用程序的生命周期中添加任何新类型的细节)?

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

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

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


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

在此输入图像描述

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

在此输入图像描述

...但是这引入了循环依赖,必须以特殊方式处理(通常通过推迟其中一个FOREIGN KEY).

1:N细节当然是另一个问题,并且通过单独的表自然地建模.


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

在此输入图像描述

顺便说一句,上述模型使用识别关系,这导致更"自然"的键.非识别关系/代理键方法看起来像这样:

在此输入图像描述

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