没有主元的行之间的声明性完整性约束

发布于 2024-10-22 07:39:21 字数 608 浏览 29 评论 0原文

我遇到类似于以下连接表的情况:

A_ID  B_ID
1     27
1     314
1     5

我需要在表上施加约束,以防止输入重复的组。换句话说:

A_ID  B_ID
2     27
2     314
2     5

应该失败,但

A_ID  B_ID
3     27
3     314

应该成功,因为它是一个独特的群体。

我想到的两种方法是:

  1. 根据顺序在物化视图中透视表,并在透视字段上放置唯一的键。我不喜欢这个,因为在 Oracle 中,由于旋转规则和 32 列索引限制,我必须限制组中的行数(想到了解决第二个问题的方法,但仍然如此)。
  2. 在 B_ID 的组合上创建一些唯一的哈希值并使其唯一。也许我还不够数学家,但我想不出一种方法来做到这一点,而不限制我可以用于 B_ID 的值的数量。

我觉得这里明显缺少一些东西,就像我可以添加某种排序列并设置不同的唯一键,但我已经做了相当多的阅读,但还没有想出任何东西。也可能是我继承的数据模型有缺陷,但我想不出任何能给我类似灵活性的东西。

I have a situation like the following join table:

A_ID  B_ID
1     27
1     314
1     5

I need to put a constraint on the table that will prevent a duplicate group from being entered. In other words:

A_ID  B_ID
2     27
2     314
2     5

should fail, but

A_ID  B_ID
3     27
3     314

should succeed, because it's a distinct group.

The 2 ways I've thought of are:

  1. Pivot the table in a materialize view based upon the order and put a unique key on the pivot fields. I don't like this because in Oracle I have to limit the number of rows in a group because of both the pivoting rules, and the 32-column index limitation (thought of a way around this second problem, but still).
  2. Create some unique hash value on the combination of the B_IDs and make that unique. Maybe I'm not enough of a mathematician, but I can't think of a way to do this that doesn't limit the number of values that I can use for B_ID.

I feel like there's something obvious I'm missing here, like I could just add some sort of an ordering column and set a different unique key, but I've done quite a bit of reading and haven't come up with anything. It might also be that the data model I inherited is flawed, but I can't think of anything that would give me similar flexibility.

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

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

发布评论

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

评论(1

残花月 2024-10-29 07:39:21

首先,常规约束不起作用。

如果 A_ID 为 1 的集合存在,然后会话 1 插入一条 A_ID 为 2、B_ID 为 27 的记录,会话 2 插入 (2,314),会话 3 插入 (2,5),那么这些都不会导致冲突违反约束。触发器也不起作用。同样,如果存在 (6,99) 的集合,则另一个会话将很难创建新的 (6,99,300) 集合。

具有“提交刷新”功能的 MV 可以正常工作,从而阻止最后一个会话成功提交。我会更多地关注哈希选项,总结每个 A_ID 的哈希 B_ID

select table_name, sum(ora_hash(column_id)), count(*)
from user_tab_columns
group by table_name

虽然哈希冲突是可能的,但可能性很小。

如果您使用 11g,也请查看 LISTAGG。

select table_name, listagg(column_id||':') within group (order by column_id) 
from user_tab_columns
group by table_name

Firstly a regular constraint can't work.

If the set with A_ID of 1 exists, and then session 1 inserts a record with A_ID 2 and B_ID of 27, session 2 inserts (2,314) and session 3 inserts (2,5), then none of those would see a conflict to cause a constraint violation. Triggers won't work either. Equally, if a set existed of (6,99), then it would be difficult for another session to create a new set of (6,99,300).

The MV with 'refresh on commit' could work, preventing the last session from successfully committing. I'd look more at the hashing option, summing up the hashed B_ID's for each A_ID

select table_name, sum(ora_hash(column_id)), count(*)
from user_tab_columns
group by table_name

While hash collisions are possible, they are very unlikely.

If you are on 11g check out LISTAGG too.

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