表之间钻石关系中的标识符

发布于 2024-07-09 18:08:27 字数 624 浏览 3 评论 0原文

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

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

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

对于我现在正在处理的具体情况,表 A 和 B 中的记录是由用户输入的,因此自动生成 id 不是问题。 对于表 C 和 D,这些表中的记录是由多个并发批处理生成的,因此需要以某种方式生成它们的标识符。 我之前列出的方法对于竞争条件不起作用。

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

考虑到上述约束,您将如何设计表来表示 A、B、C 和 D,以便正确执行实体之间的关系,并且不需要应用程序代码生成任何标识符?

I have four tables (A,B,C,D) where A is the parent of one to many relationships with B and C. C and D are parents to a one to many relationship with table D. Conceptually, the primary keys of these tables could be:

  • A: Aid
  • B: Aid, bnum (with foreign key to A)
  • C: Aid, cnum (with foreign key to A)
  • D: Aid, bnum, cnum (with foreign keys to B and C)

Where the 'num' columns auto increment based on each parent id in the relationship rather then on each record. I used this approach on a previous application, and it was not an issue since the creation of B and C records was done by a sequential process by generating a new 'num' value via a 'select max()' query. I was never really satisfied with the approach, but it got the job done.

For the specific case I am working on now, records in tables A and B are entered by users so auto-generation of id's is not an issue. In the case of tables C and D, records in these tables are being generated by multiple concurrent batch processes so their identifiers will need to be generated some how. The previous method I listed will not work do to the race condition.

Note that this is for an Oracle database so I will be using sequences and not auto-increment columns.

Given the constraints above, how you would you design tables to represent A,B,C, and D so that the relationships between the entities are properly enforced AND application code would not be required to generate any identifiers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

傾城如夢未必闌珊 2024-07-16 18:08:27

如果我理解正确的话,您可能有一个解决方案,

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

If I understand it right, you had a solution where you may have

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

etc.

Now, does it matter whether the 'num' values are small and in a gap-less sequence?
If not, then simply use sequences for those too. So you may get

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

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

I'd use separate sequences for bnum and cnum.
On selecting you could (if desired) use something like

SELECT AID, 
      RANK(BNUM) OVER (PARTITION BY AID ORDER BY BNUM) bnum_seq,
      RANK(CNUM) OVER (PARTITION BY AID ORDER BY CNUM) cnum_seq
枕头说它不想醒 2024-07-16 18:08:27

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

在我看来,序列对于主键来说非常有用,但也有一些阵营崇拜“自然键”之神。

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

就个人而言,我会在每个表中创建主键序列,并允许不属于主键的外键。 您可以通过主要对象(如员工、商品、商店)来定义表,然后它们之间的关系将由组合组成,因此商店中的员工将有一个表“storeemployee”,主键将为 empid 、storeid,未定义序列。 通常,我将其视为对象(始终具有主键序列)和对象之间的关系(使用其他表的 ID 作为组合主键)。

希望有帮助!

编辑:我应该补充一点,这很好地允许了钻石关系。 想想“商店”和“员工”。 一张表可以是商店员工,另一张表可以是“商店销售”。 两者都可以识别商店和员工,但它们的含义截然不同。 一是工作时间,二是销售额。

Sequences or Autonumbers should always be generated by the database system, and not by the application. For MSSQL, this can be done using a stored procedure and returning "select @@identity" from the stored procedure to give the app the ID of the inserted row.

Sequences are great for primary keys imo, but there are camps that worship the god of 'natural keys'.

The meaning of the data stored in the table, and the meaning of the relationship is important to answer your question fully, but relationships can allow for cascading deletions.

Personally, I would make the primary keys sequences in each table and allow for foreign keys that are not part of the primary key. You would define your tables by the major objects (like employee, merchandise, store), and then the relationships between them would be made up of combinations So an employee in a store would have a table 'storeemployee' and the primary key would be empid, storeid with no sequence defined. Normally I think about it in terms of things as objects (which always have sequences for primary keys), and relationships between objects (with use other table's IDs as combo-primary keys).

Hope that helps!

Edit: I should add that this nicely allows for diamond relationships. Think about 'stores' and 'employees'. One table can be storeemployees, and another can be 'storesales'. Both would identify a store and an employee, but they mean drastically different things. One is maybe hours worked, and the other is sales made.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文