【问题标题】:How do you constrain a composite key that has a large number of non-unique combinations?如何约束具有大量非唯一组合的复合键?
【发布时间】:2016-01-09 05:45:02
【问题描述】:

所以给定一个看起来像这样的表结构:

 Order_date DATE
 Order_id   NUMBER
 State      VARCHAR2(16)
 ...
 other properties/attributes

请记住,我可以在此处使用整数序列并生成 PK,但由于我在主应用程序中使用此表的方式,我对此并不感兴趣。

所以复合键由 Order_date、Order_id 和 State 组成。这种组合的问题在于它不一定是唯一的,但它在某种程度上受到了限制。

例如:

Order_date  |  Order_id  |  State
21-09-2014     7218821      Pending
22-09-2014     2771272      Pending
20-09-2014     3277127      Approved
13-08-2014     2218765      Done
13-08-2014     2218765      Cancelled

约束:

  • 无法将相同的 order_date 和 order_id 和状态 Done 在此重复
  • 可以有任意数量的相同 order_date 和 order_id 具有任何其他状态而不是 Done
  • 您不能添加状态为 DONE 或 ERROR 的记录
  • 您无法通过绕过其自然顺序(已注册 -> 待处理 -> 已批准 -> 完成 | 取消 | 错误)从一种状态跳到另一种状态

对我来说,为 Oracle 数据库实现这些约束的最佳方式是什么?

【问题讨论】:

  • 我会考虑业务规则是否应该作为约束来实现
  • 为什么不呢?这是我将应用程序逻辑与一些基本的已知约束分开的一种方式。很适合测试。
  • 我发现很难理解这个表代表什么实体。是否会更改订单状态?或者客户是否在不同日期向订单添加额外说明,并跟踪每个添加的状态?

标签: sql oracle database-design data-modeling


【解决方案1】:

第一个由主键或唯一键处理。

第二个很棘手。第二个可以使用基于函数的唯一键来处理,因为 Oracle 允许 NULL 有多个值:

create unique index unq_order_date_id_done on 
    orders(order, order_date, order_id, 
           (case when state = 'DONE' then state end));

我认为第三个和第四个需要一个触发器来防止值被添加。

【讨论】:

  • 首先,我的意思是相同的 order_id、相同的 order_date 和状态 DONE。
  • @user3046061 。 . .我明白了。唯一索引只允许一个状态为 'DONE' 和任意数量的其他值。
【解决方案2】:

逐个项目符号:

  • 这很可能是真实的,不需要监控。尽管您没有显示它,但 DATE 字段包含时间到秒。为了有重复,同一订单的状态必须在同一秒内更改两次。
  • 值得怀疑。除非您的处理允许在一秒钟内对同一订单进行多次状态更改。
  • 您的示例数据显示状态为 DONE。这是怎么做到的?
  • 您的描述指出,在批准后,唯一允许的状态是 DONE 或 CANCELED 或 ERROR。您的示例数据显示了从 DONE 到 CANCELED 的订单。这似乎是不允许的。实际上,您的第二个项目符号表明在任何情况下都不允许出现 ERROR 状态。

如果状态更改发生得非常快——在同一秒内,您可以重复(订单、日期)值的唯一方法。或者...您从日期字段中截断时间值。这似乎不太可能,因为没有理由丢弃记录状态更改时间等有价值的信息。您没有任何好处,处理变得更加困难:输/输。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2016-04-12
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 2017-04-23
    • 1970-01-01
    相关资源
    最近更新 更多