首页 > 解决方案 > 处理m2m字段时的关系数据库设计

问题描述

假设我有以下表格:

User : id, login, password

Card : id, name, value

并且 anUser可以Card多次重复。例如:Userid 为 1 的 id 可以有多个Cardid 为 1 的。

我将创建下表:

UserCard : id, user_id, card_id

因此,例如,UserCard可能看起来像:

| id | user_id | card_id |
|1   | 1       | 1       |
|2   | 1       | 1       |
|3   | 1       | 2       |

然而,与我讨论过这个问题的一位同事告诉我,有一些具有相同值的行是糟糕的设计,并且

| id | user_id | card_id | quantity |
|1   | 1       | 1       | 2        |
|2   | 1       | 2       | 1        |

将是最好的方法,因为它会删除重复的行。

在我看来,这是错误的,原因如下:

我同事的观点是:


问题:

这种情况下最好的数据库设计是什么?一个用户可以有0张或任意一张ID相同的卡

编辑 :

我们正在使用带有 postgrsql 的 Django 没有同事,我只是想知道什么是最好的数据库设计

标签: sqldatabase-design

解决方案


你的同事是对的。我会给你一个理论的解释和一个为什么的例子,但你最好阅读 CJ Date 的教科书。

您的 UserCard 表的基本问题是它没有自然键。你在它上面加上了一个没有意义id的东西来使它“唯一”,但是 id 1 和 id 2 之间没有有意义的区别:它们的值没有差异,因此它们所代表的东西是无法区分的。当您发现自己在跟踪无法区分的事物时,通常的解决方案是对它们进行计数。这就是你的银行用美元做的事情。

关系理论基于不同(非重复)元素的集合。你忽视这个基础,后果自负。

作为一个实际问题——并且只有一个例子——当用户丢弃一张卡片时会发生什么?您将如何删除无法区分的行?你的同事可能会说

update UserCard set quantity = quantity - 1 where user = 1 and card = 1
delete UserCard where quantity = 0

你会怎么做?用另一个非理论性的组合来解决这个问题,比如limit 1?如果限制不是 1,因为任意一组用户丢了卡怎么办?

你部分地用你的人为独特性帮助了自己:

delete UserCard where id = 
       (select min(id) from UserCard where user = 1 and card = 1)

这说明了独特性是如何有帮助的。但是quantity是你的朋友。因此,如果您使用理论而不是反对它,那么您的设计和查询都会变得更简单。


推荐阅读