如何跨多个表创建条件唯一约束?

问题描述 投票:0回答:2

我正在使用 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的插入,以便只能有一个类型“唯一”分配给任何给定的条目。不幸的是,许多简单的约束方法不适用于这种情况。经过一番研究,我发现以下解决方案有效:

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”,我可以依赖它来保持一致。

是否应该使用我不知道的不同方法,或者是否有任何关于如何缓解此问题的建议?最好是在代码更改或数据模型更改方面尽可能不具有干扰性?或者这只是我必须学会应对的现实?

sql oracle hibernate constraints unique-constraint
2个回答
1
投票

事实证明,您可以对物化视图进行检查约束;所以,你应该能够写这样的东西:

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 的“触发器的麻烦” 中的示例。如果您决定走这条路,您需要先通读文档并理解所有内容;在特别是,我对“物化视图日志”部分不是很清楚,可能需要一些调整。)


0
投票

您可以在 Oracle 中使用复合触发器来确保多个表之间的唯一性。 这篇文章描述了如何在 DML 级别实现检查。 https://rammpeter.blogspot.com/2023/08/oracle-db-ensure-uniqueness-across.html?m=1

© www.soinside.com 2019 - 2024. All rights reserved.