适用于用户反馈系统的数据库模型(一个有趣的案例)

时间:2015-02-06 11:00:38

标签: mysql database database-design relational-database foreign-key-relationship

Database Model (Simplified)

我正在使用PHP和Yii Framework开发应用程序。我一直在考虑针对给定功能的最合适的数据库结构,以及我所提出的内容。然而,我并不是百分之百地肯定应该怎么做,所以我决定向社区提问。

应用说明:

注册用户可以参加活动。每个活动都可以有 无限数量的用户,称为"活动的参与者")。

一旦事件结束,每个参与者都可以留下关于同一事件的每个其他参与者的反馈。

数据库结构:

由于每个活动都可以拥有无​​限数量的用户,而且用户可以参与无限数量的活动,因此我创建了一个表"参与者",它解决了多对多关系

其他表格不言自明。

这是最重要的事情:

事件的每个参与者可以具有最大数量的反馈,其等于除了给定参与者之外的相同事件的参与者的数量(例如,如果该事件有5个参与者,则给定参与者可以从参与者接收4个反馈同一事件)。

让我强调一下,只有同一事件的参与者可以留下关于给定参与者的反馈(并且只有一个)。

以下是我为确保数据库的完整性而采取的步骤:

  1. 我创建了" id" "参与者"中的列table为每个参与某个事件的用户提供唯一ID。此ID是复合的(user_id和practice_id连接在一起)。因此,参与事件14的用户23的参与者ID将是14-23。
  2. 您可能会问为什么我决定使用此ID创建一个单独的列,而不是像这样简单地定义主键:

    PRIMARY KEY (user_id, event_id)
    

    继续阅读。

    活动结束后,每位参与者都可以留下有关其他参与者的反馈。现在,该参与者ID可以通过外键引用" sender_id"和" recipient_id"在反馈表中。

    此外,反馈表的主键也将通过组合" sender_id"并且" recipient_id",因此如果用户23想要留下关于用户45的反馈(均参与事件71),则反馈的主键将是:71-45-71-23

    这种方法允许我们在数据库级别确保没有参与者两次留下关于同一参与者的反馈,并且用户不能两次参与同一事件。

    问题:

    • 这种方法是否有权存在?
    • 有什么优点和 其他更好的方法来实现这个功能?
    • 我可以根据其他列的值生成主键吗? 自动记录插入?

1 个答案:

答案 0 :(得分:3)

这是一个糟糕的设计。只需制作一个2列主键和2列外键即可。这是一种称为“密钥中的编码信息”的基本反模式,因此被称为“智能”,“智能”或“连接”密钥。一把好钥匙是一把“笨”的钥匙。

Eg:

  

尽管现在很容易实现智能钥匙,但很难   建议您创建一个不属于自然键的自己的键,   因为他们往往最终会遇到麻烦,无论他们是谁   优点,因为它使数据库更难以重构,强加   订单是   难以改变,可能不是最适合您的查询,需要   如果智能钥匙包含非数字字符,则进行字符串比较,   并且在帮助基于范围的方面不如复合键有效   聚合。它也违反了基本的关系准则   每列应存储原子值

     

智能密钥也往往超出其原始编码约束

此外,没有需要来执行此操作。

许多DBMS允许“计算列”,其值是从其他列自动计算的。要使一个主键或外键,你通常需要它“持久化”,即占用像普通列的内存,而不是像需要一样在需要时计算。 MySQL没有这些,但5.7.5有一些功能,它们被称为“生成列”,可以“存储”。但是不要为PK或FK这样做!

实际的设计问题是处理database/SQL subtypes/hierarchies/inheritance/polymorphism