[英]How do I create a conditional unique constraint across multiple tables?
我正在使用Hibernate 4和Oracle 11g开发Web应用程序。
我在这个场景中有以下表格。 表格已经更改和简化,以保护无辜者。
entry
ID | name |
1 | thing1 |
2 | thing2 |
entry_number
ID | value | entry_id| type_id |
1 | 11111 | 1 | 1 |
2 | 22222 | 1 | 2 |
3 | 33333 | 1 | 2 |
4 | aaaaa | 2 | 1 |
5 | bbbbb | 2 | 2 |
6 | ccccc | 2 | 2 |
type
ID | name |
1 | unique |
2 | regular |
3 | etc. |
...
我的想法是,我想有条件地限制entry_number的插入,以便只能为任何给定条目分配一个类型“unique”。 不幸的是,许多直接的约束方法不适用于这种情况。 经过一番研究,我发现以下解决方案有效:
create unique index unique_entry_number on entry_number(CASE WHEN TYPE_ID = 1 THEN entry_id ELSE null END);
我唯一不喜欢的是我引用了“type_id”的id,我不相信我必须依赖它才能保持一致。 Oracle不会让我在唯一索引中使用子查询来加入“type.name”,我可以依赖它来保持一致。
是否有我应该使用的不同方法,我不知道或有任何关于如何缓解此问题的建议? 优选地,在代码变化或数据模型变化方面尽可能不干扰? 或者这只是一个我必须学会处理的现实?
事实证明,您可以对物化视图进行检查约束; 所以,你应该能够写出这样的东西:
CREATE MATERIALIZED VIEW LOG
ON entry_number
WITH ROWID
;
CREATE MATERIALIZED VIEW LOG
ON type
WITH ROWID
;
CREATE MATERIALIZED VIEW entry_number_counter
REFRESH FAST
ON COMMIT
AS SELECT en.entry_id, COUNT(1) AS row_count
FROM entry_number en
JOIN type ON entry_number.type_id = type.id
WHERE type.name = 'unique'
GROUP BY en.entry_id, type.name
;
ALTER TABLE entry_number_counter
ADD CONSTRAINT entry_id_conditionally_unique
CHECK (row_count = 1)
;
(免责声明:未经过测试。这是根据Tom Kyte的“触发器故障”中的一个例子改编的。如果你决定走这条路,你首先要阅读文档并理解所有这些;特别是我对“物化视图日志”部分不太清楚,可能需要进行一些调整。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.