表之间的菱形关系中的标识符

时间:2008-12-10 19:41:22

标签: database oracle database-design ddl

我有四个表(A,B,C,D),其中A是与B和C的一对多关系的父对象.C和D是与表D的一对多关系的父对象。从概念上讲,主要是这些表的键可以是:

  • A:援助
  • B:援助,bnum(带有A的外键)
  • C:援助,cnum(带有A的外键)
  • D:援助,bnum,cnum(带有B和C的外键)

其中'num'列根据关系中的每个父ID而不是每条记录自动递增。我在之前的应用程序中使用了这种方法,这不是问题,因为B和C记录的创建是通过顺序进程完成的,通过'select max()'查询生成一个新的'num'值。我从来没有真正满意这种方法,但它完成了工作。

对于我现在正在处理的特定情况,用户输入表A和表B中的记录,因此自动生成id不是问题。对于表C和D,这些表中的记录由多个并发批处理生成,因此需要生成其标识符。我列出的上一个方法对竞争条件无效。

请注意,这是针对Oracle数据库的,因此我将使用序列而不是自动增加列。

鉴于上述限制,您如何设计表来表示A,B,C和D,以便正确实施实体之间的关系,并且不需要应用程序代码来生成任何标识符?

2 个答案:

答案 0 :(得分:0)

序列或自动编号应始终由数据库系统生成,而不是由应用程序生成。对于MSSQL,可以使用存储过程并从存储过程返回“select @@ identity”来为应用程序提供插入行的ID。

序列非常适合主键imo,但有些阵营崇拜“自然键”之神。

表中存储的数据的含义以及关系的含义对于完全回答您的问题很重要,但关系可以允许级联删除。

就个人而言,我会在每个表中创建主键序列,并允许不属于主键的外键。您可以通过主要对象(如员工,商品,商店)定义您的表,然后它们之间的关系将由组合组成因此,商店中的员工将拥有一个表'storeemployee'并且主键将是empid ,没有定义序列的storeid。通常我会把事情看作对象(它们总是有主键序列),以及对象之间的关系(使用其他表的ID作为组合主键)。

希望有所帮助!

编辑:我应该补充说,这很好地允许钻石关系。想想“商店”和“员工”。一个表可以是storeemployees,另一个表可以是'storeales'。两者都会识别商店和员工,但它们意味着完全不同的东西。一个是工作时间,另一个是销售。

答案 1 :(得分:0)

如果我理解正确,你就有了解决方案

Table A
-------
100
101
102

Table B
-------
100 1
100 2
101 1

Table C
-------
100 1
100 2
101 1


Table D
-------
100 1 1
100 2 1
100 1 2
101 1 1

现在,'num'值是否很小且无间隙序列是否重要? 如果没有,那么只需使用序列。所以你可能会得到

Table B
-------
100 29125
100 29138
101 29130

Table D
-------
100 29125 401907
100 29138 404911
101 29130 803888

我会为bnum和cnum使用单独的序列。 在选择时你可以(如果需要)使用像

这样的东西
SELECT AID, 
      RANK(BNUM) OVER (PARTITION BY AID ORDER BY BNUM) bnum_seq,
      RANK(CNUM) OVER (PARTITION BY AID ORDER BY CNUM) cnum_seq