sql - 处理m2m字段时的关系数据库设计
问题描述
假设我有以下表格:
User : id, login, password
Card : id, name, value
并且 anUser
可以Card
多次重复。例如:User
id 为 1 的 id 可以有多个Card
id 为 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 |
将是最好的方法,因为它会删除重复的行。
在我看来,这是错误的,原因如下:
quantity
可以计算,因此该字段无用- 添加该
quantity
字段会添加很多不必要的东西,例如在向用户添加卡之前,我必须检查用户是否已经拥有这张卡(如果他拥有,我增加数量字段,否则我添加卡) - 我应该让 DBMS 处理这种事情
我同事的观点是:
- 表中的重复行仅用于其他两个表的关系是脏的
- 嗯,不记得他提出的其他观点,但对他来说,我提出的建议非常不理想。
问题:
这种情况下最好的数据库设计是什么?一个用户可以有0张或任意一张ID相同的卡
编辑 :
我们正在使用带有 postgrsql 的 Django 没有同事,我只是想知道什么是最好的数据库设计
解决方案
你的同事是对的。我会给你一个理论的解释和一个为什么的例子,但你最好阅读 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
是你的朋友。因此,如果您使用理论而不是反对它,那么您的设计和查询都会变得更简单。
推荐阅读
- reactjs - 使用 React.useMemo 进行异步调用
- c# - Asp Identity 导航属性
- django - ReactJS 和 Django axios.post(403 错误代码)
- jmeter - 你能告诉我 Jmeter 中 Min、Max、Throughput 和 Deviation 的标准值吗
- javascript - ReferenceError:计时器未在 Timeout._onTimeout 处定义
- python - 无法将 python pip 安装到 docker 容器
- sql-server - SQL SERVER:当用户选中复选框时更新 dB 字段
- python - Python初学者查询
- spring-boot - java.lang.ClassNotFoundException:org.springframework.kafka.listener.RecordInterceptor
- php - 数组不会显示相同的名称一次