如何约束具有大量非唯一组合的组合键?
How do you constrain a composite key that has a large number of non-unique combinations?
所以给定一个看起来像这样的 table 结构:
Order_date DATE
Order_id NUMBER
State VARCHAR2(16)
...
other properties/attributes
请记住,我可以在此处使用整数序列并生成 PK,但是我对此不感兴趣,因为我在主应用程序中使用 table。
所以复合键是由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 并声明“完成”在此
中复制
- 可以有任意数量的相同 order_date 和 order_id 具有除 Done
之外的任何其他状态
- 您不能添加状态为 DONE 或 ERROR 的记录
- 您不能通过绕过它们的自然顺序(注册 -> 待定 -> 批准 -> 完成 | 取消 | 错误)从一个状态跳到另一个状态
我对 Oracle 数据库实施这些约束的最佳方式是什么?
第一个由主键或唯一键处理。
第二个是棘手的。第二个可以用基于函数的唯一键来处理,因为 Oracle 允许 NULL
:
的多个值
create unique index unq_order_date_id_done on
orders(order, order_date, order_id,
(case when state = 'DONE' then state end));
我认为第三个和第四个需要一个触发器来防止添加值。
逐个子弹:
- 这很可能是真实的,不需要监控。尽管您没有显示它,但 DATE 字段包含精确到秒的时间。为了复制,同一订单的状态必须在同一秒内更改两次。
- 存疑。除非您的处理允许同一订单在一秒内发生多个状态更改。
- 您的示例数据显示“完成”状态。那是怎么到那里的?
- 您的描述表明,在 APPROVED 之后,唯一允许的状态是 DONE 或 CANCELED 或 ERROR。您的示例数据显示从完成到取消的订单。这似乎是不允许的。实际上,您的第二个项目符号表明在任何情况下都不允许出现 ERROR 状态。
您可以拥有重复(订单、日期)值的唯一方法是状态变化发生得非常快——在同一秒内。或者...您截断日期字段中的时间值。这似乎不太可能,因为没有理由丢弃像记录状态更改的时间这样有价值的信息。您没有任何好处,处理变得更加困难:lose/lose.
所以给定一个看起来像这样的 table 结构:
Order_date DATE
Order_id NUMBER
State VARCHAR2(16)
...
other properties/attributes
请记住,我可以在此处使用整数序列并生成 PK,但是我对此不感兴趣,因为我在主应用程序中使用 table。
所以复合键是由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 并声明“完成”在此 中复制
- 可以有任意数量的相同 order_date 和 order_id 具有除 Done 之外的任何其他状态
- 您不能添加状态为 DONE 或 ERROR 的记录
- 您不能通过绕过它们的自然顺序(注册 -> 待定 -> 批准 -> 完成 | 取消 | 错误)从一个状态跳到另一个状态
我对 Oracle 数据库实施这些约束的最佳方式是什么?
第一个由主键或唯一键处理。
第二个是棘手的。第二个可以用基于函数的唯一键来处理,因为 Oracle 允许 NULL
:
create unique index unq_order_date_id_done on
orders(order, order_date, order_id,
(case when state = 'DONE' then state end));
我认为第三个和第四个需要一个触发器来防止添加值。
逐个子弹:
- 这很可能是真实的,不需要监控。尽管您没有显示它,但 DATE 字段包含精确到秒的时间。为了复制,同一订单的状态必须在同一秒内更改两次。
- 存疑。除非您的处理允许同一订单在一秒内发生多个状态更改。
- 您的示例数据显示“完成”状态。那是怎么到那里的?
- 您的描述表明,在 APPROVED 之后,唯一允许的状态是 DONE 或 CANCELED 或 ERROR。您的示例数据显示从完成到取消的订单。这似乎是不允许的。实际上,您的第二个项目符号表明在任何情况下都不允许出现 ERROR 状态。
您可以拥有重复(订单、日期)值的唯一方法是状态变化发生得非常快——在同一秒内。或者...您截断日期字段中的时间值。这似乎不太可能,因为没有理由丢弃像记录状态更改的时间这样有价值的信息。您没有任何好处,处理变得更加困难:lose/lose.