JAX*_*JAX 45 sql database database-design relational-database
我一直在为在线商店系统设计数据库.通过阅读本网站上的一些帖子,我遇到的问题是,虽然我可以使用复合主键,但我会在下面解释一下,这是不是很糟糕的做法(根据我在这方面阅读的帖子)在stackoveflow上,很多人说这是一个不好的做法所以这就是我要问的原因.
我想在单独的表格中存储订单付款.原因在于,订单可以包含许多项目,这些项目以多对多关系的形式在单独的表格中处理.现在,如果我不使用复合主键作为我的付款表,我将失去我的独特性PaymentID:
[PaymentId] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[OrderId] INT NOT NULL PRIMARY KEY --Also a Foreign Key--
Run Code Online (Sandbox Code Playgroud)
现在,如果我只删除主键OrderId,我会在这里丢失我的一对一关系Many OrderIds can be associated to many PaymentIds,我不想要这个.
这就是为什么这里先前提出的问题已经(大多数时候)得出结论,复合键是一个坏主意.所以我想为自己澄清一下; 如果不好,那么最佳做法是什么?
Bil*_*win 50
没有结论复合主键是坏的.
最佳做法是使一些列或列唯一标识一行.但是在某些表中,单个列本身不足以唯一标识行.
SQL(和关系模型)允许复合主键.在某些情况下,这是一个很好的做法.或者,另一种看待它的方式是,在所有情况下这都不是一个坏习惯.
有些人认为每个表都应该有一个自动生成唯一值的整数列,并且应该作为主键.有些人还声称应始终调用此主键列id.但那些是惯例,不一定是最佳实践.公约有一些好处,因为它简化了某些决策.但惯例也是限制性的.
您可能有多次付款的订单,因为有些人在分期付款,或者他们有多个付款来源(例如两张信用卡),或者两个不同的人想要支付订单的一部分(我经常去一个有朋友的餐厅,我们每个人都为自己的餐费付费,所以工作人员处理我们每张信用卡的一半订单.
我会设计你描述的系统如下:
Products : product_id (PK)
Orders : order_id (PK)
LineItems : product_id is (FK) to Products
order_id is (FK) to Orders
(product_id, order_id) is (PK)
Payments : order_id (FK)
payment_id - ordinal for each order_id
(order_id, payment_id) is (PK)
Run Code Online (Sandbox Code Playgroud)
这也与识别关系的概念有关.如果定义仅仅因为订单存在而存在付款,则将订单作为主键的一部分.
请注意,LineItems表也缺少自己的自动增量单列主键.多对多表是很好地使用复合主键的典型示例.
Gor*_*off 21
这个问题非常接近于提出可能产生宗教战争的意见.作为一个高度偏向于在我的表中使用自动增加的整数主键(称为类似TablenameId,而不是"Id")的人,有一种情况是可选的.
我认为其他答案解决了你想要主键的原因.
一个非常重要的原因是出于参考目的.在关系数据库中,理论上任何实体都可以通过外键关系被另一个实体引用.对于外键,您肯定希望一列唯一地定义一行.否则,您必须处理彼此对齐的不同表中的多个列.这是可能的,但很麻烦.
您所指的表不是"实体"表,而是"联结"表.它是用于处理多对多关系的关系数据库构造.因为它实际上并不代表实体,所以它不应该具有外键关系.因此,复合主键是合理的.在某些情况下,例如当您担心数据库大小时,甚至需要省去人工主键.
磁盘空间很便宜,因此聚集在以约定命名的int标识(1,1)上的主键(如pk +表名)是一种很好的做法.它将使查询,连接,索引和其他约束易于管理.
但是有一个很好的理由不这样做(至少在MS SQL Server中):如果你想管理底层存储系统中数据的物理排序.
群集主键确定物理排序顺序.如果在标识列上执行此操作,则物理排序顺序基本上是插入顺序.但是,这可能不是最好的,特别是如果您始终以相同的方式查询表.在非常大的表上,获得正确的物理排序顺序可以使查询更快.例如,您可能希望聚合索引在两列的组合上.
最佳做法充其量是有用的,但最坏的情况是盲目的。违背最佳实践并不是罪过。只要确定您知道要进行哪种折衷即可。
数据库引擎可能是非常复杂的事情。如果不知道给定引擎进行了哪些特定的优化,将很难确定哪种类型的结构将产生最佳性能(因为我假设我们在这里谈论的问题是性能)。复合键对于一种数据库中的大型表可能有问题,但对另一种数据库则没有任何明显的影响。
我学到的一种有用的做法是,始终努力使我的应用程序尽可能简单。使用复合键是否使您不必在插入之前执行查找或其他麻烦操作?使用它们。但是,如果您发现使用它们使您的应用程序不再满足某些重要的性能要求,请考虑不使用它们的解决方案。