为每个多对多关系创建唯一编号的最佳方式

时间:2009-02-19 12:34:05

标签: database django database-design postgresql

我有一个学生表和一个课程表,通过中间表连接创建多对多关系(即学生可以注册多个课程,一个课程可以有多个学生)。问题是客户希望每门课程都有一个唯一的学生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对于课程A具有ID = 2,但对于课程B,ID = 1)。一旦分配了ID,它就是固定的,不能改变。我通过对表格“SELECT Student from table WHERE Course = A ORDER BY rowid”的rowid进行排序,然后根据结果的顺序返回一个数字来实现解决方案。

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

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

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

4 个答案:

答案 0 :(得分:2)

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

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

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

相反,创建一个单独的表用作sequence,用SELECT FOR UPDATE锁定每个课程的行,然后插入新学生的ID并使用新的{{更新行1}}在单个事务中,如下所示:

Courses:

Name     NextID
-------  ---------
Math     101
Physics  201

Attendants:

Student Course   Id
------- ------   ----
Smith   Math     99
Jones   Math     100
Smith   Physics  200
ID

答案 1 :(得分:0)

您的第一个建议似乎很好:在课程表中有一个last_id字段,只要您在该课程中注册学生,就会增加1。

答案 2 :(得分:0)

  

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

我是怎么做的。没有必要计算它。并且id不应该因为某人退出而改变。

  

添加“已禁用”列并进行设置   当学生离开时,这是真的   课程。

是的,这是个好主意。另一个是创建另一个具有相同结构的表,您将存储掉落的学生。当然,你必须从这两个表的联合中选择max(id)。

答案 3 :(得分:0)

我认为您需要两个概念来帮助您。

  1. Sequences数据库自动为您获取ID的下一个值
  2. Composite keys其中可以组合多个列以生成表的主键。
  3. 从快速谷歌看起来Django可以处理序列而不是复合键,所以你需要以某种方式模拟它。但是,您可以同样拥有两个外键和课程/学生关系的序列

    至于如何处理删除,这取决于您的应用程序需要什么,您可能会发现状态字段可以帮助您,因为您可能想要区分离开的学生和被踢出的学生,或获取统计数据有多少学生留下不同的课程。