【问题标题】:Best way to create a unique number for each many to many relationship为每个多对多关系创建唯一编号的最佳方法
【发布时间】:2010-10-08 14:00:28
【问题描述】:

我有一个学生表和一个课程表,它们通过中间表连接以创建多对多关系(即,一个学生可以注册多个课程,一个课程可以有多个学生)。问题是客户希望每门课程都有一个唯一的学生 ID。例如:

rowid Course Student      ID (calculated)
1     A      Ben          1
2     A      Alex         2
3     A      Luis         3
4     B      Alex         1
5     B      Gail         2
6     B      Steve        3

ID 应该从 1 开始编号,并且学生可以为不同的课程使用不同的 ID(例如,Alex 的 ID=2 用于课程 A,但 ID=1 用于课程 B)。一旦分配了 ID,它就是固定的,不能更改。我通过对通过表“SELECT Student from table WHERE Course=A ORDER BY rowid”的rowid进行排序来实现一个解决方案,然后根据结果的顺序返回一个数字。

这个解决方案的问题是,如果一个学生离开课程(从表中删除),其他学生的人数将会改变。有人可以推荐更好的方法吗?如果重要的话,我正在使用 PostgreSQL 和 Django。以下是我的想法:

  • 为 ID 创建一列而不是计算它。创建新关系时,根据课程中学生的 max(id)+1 分配 ID
  • 在学生离开课程时添加“禁用”列并将其设置为 True。这将涉及更改我的所有代码以确保只使用活跃的学生

我认为第一个解决方案更好,但有没有更“以数据库为中心的方式”,数据库可以自动为我计算?

【问题讨论】:

  • 不。我在工作中遇到的真正问题。 :)
  • 真正的问题实际上更复杂,但我在这里简化了它,这确实使它看起来像一个家庭作业问题......
  • 不确定我是否已经完全理解了这一点,但是您可以在连接学生和课程的中间表中添加一个 IDENTITY 列吗?

标签: database django database-design postgresql


【解决方案1】:

如果您想拥有稳定的ID,您肯定需要将它们存储在表中。

您需要为每个加入课程的学生分配一个新的连续ID,如果学生离开,只需将其删除,不要接触其他人。

如果您可以同时访问您的表,请不要使用MAX(id),因为两个查询可以在将其插入表之前选择相同的MAX(id)

相反,创建一个单独的表用作sequence,用SELECT FOR UPDATE 锁定每门课程的行,然后在单个事务中插入新学生的ID 并用新的ID 更新行,像这样:

培训班: 名称 NextID -------- --------- 数学 101 物理 201 服务员: 学生课程编号 -------- ------ ---- 史密斯数学 99 琼斯数学 100 史密斯物理学 200
BEGIN TRANSACTION;

SELECT NextID
INTO   @NewID
FROM   Courses
WHERE  Name = 'Math'
FOR UPDATE;

INSERT
INTO Attendants (Student, Course, Id)
VALUES ('Doe', 'Math', @NewID);

UPDATE
  Courses
SET NextID = @NewID + 1
WHERE Course = 'Math';

COMMIT;

【讨论】:

  • 另一个微妙的问题。如果从表中删除具有 MAX(id) 的学生,添加新学生将重复相同的 ID...
  • 为您的 MAX 值保留一个单独的表格。不要从 student_course 关系中得到它。
【解决方案2】:

我认为这里有两个概念可以帮助你。

  1. Sequences 数据库会自动为您获取 ID 的下一个值
  2. Composite keys 可以将多个列组合成表的主键。

从一个快速的 google 看来,Django 可以处理序列但不能处理复合键,因此您需要以某种方式模拟它。但是,您同样可以拥有两个外键和一个用于课程/学生关系的序列

至于如何处理删除,这取决于您对应用程序的需求,您可能会发现状态字段会对您有所帮助,因为您可能希望区分离开的学生和被踢出的学生,或者获取统计信息有多少学生离开了不同的课程。

【讨论】:

    【解决方案3】:

    改为创建 ID 列 计算它。当一个新的 创建关系并分配一个 ID 基于 max(id)+1 的 课程中的学生

    我会这样做。计算它没有意义。身份证不应该因为有人辍学而改变。

    添加“禁用”列并设置 学生离开学校时为真 课程。

    是的,这是个好主意。另一个是创建另一个具有相同结构的表,您将在其中存储丢弃的学生。然后当然你必须从这两个表的并集中选择 max(id)。

    【讨论】:

      【解决方案4】:

      您的第一个建议似乎不错:在课程表中有一个 last_id 字段,您可以在每次为该课程注册学生时增加 1。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-02
        • 1970-01-01
        相关资源
        最近更新 更多