“一对多”上的唯一约束(无触发器)关系

发布于 2024-08-29 10:34:15 字数 1929 浏览 6 评论 0原文

为了说明问题,我举一个例子:

一个tag_bundle由一个或多个标签组成。 唯一的标签组合可以映射到唯一的tag_bundle,反之亦然。

 tag_bundle                   tag            tag_bundle_relation
 +---------------+        +--------+      +---------------+--------+
 | tag_bundle_id |        | tag_id |      | tag_bundle_id | tag_id |
 +---------------+        +--------+      +---------------+--------+
 |       1       |        | 100    |      |       1       |  100   |
 +---------------+        +--------+      +---------------+--------+
 |       2       |        | 101    |      |       1       |  101   |
 +---------------+        +--------+      +---------------+--------+ 
                          | 102    |      |       2       |  101   |
                          +--------+      +---------------+--------+  
                                          |       2       |  102   |
                                          +---------------+--------+

不可能有另一个 tag_bundle 具有与标签 100 和标签 101 完全相同的组合。 不可能有另一个 tag_bundle 具有与标签 101 和标签 102 完全相同的组合。

“并发”执行 SQL 时如何确保这样的唯一约束! 也就是说,为了防止同时添加两个具有完全相同相同标签组合的捆绑包,

在任何表上添加简单的唯一约束是行不通的, 除了触发器或显式锁定之外还有其他解决方案吗?

我只想到了这个简单的方法:将标签组合成字符串,并让它成为一个唯一的列。

tag_bundle  (unique on tags)         tag            tag_bundle_relation
 +---------------+-----------+      +--------+      +---------------+--------+
 | tag_bundle_id |  tags     |      | tag_id |      | tag_bundle_id | tag_id |
 +---------------+-----------+      +--------+      +---------------+--------+
 |       1       | "100,101" |      | 101    |      |       1       |  101   |
 +---------------+-----------+      +--------+      +---------------+--------+
                                    | 100    |      |       1       |  100   |
                                    +--------+      +---------------+--------+ 

但这似乎不是一个好方法:(

To illustrate the problem, I make an example:

A tag_bundle consists of one or more than one tags.
A unique tag combination can map to a unique tag_bundle, vice versa.

 tag_bundle                   tag            tag_bundle_relation
 +---------------+        +--------+      +---------------+--------+
 | tag_bundle_id |        | tag_id |      | tag_bundle_id | tag_id |
 +---------------+        +--------+      +---------------+--------+
 |       1       |        | 100    |      |       1       |  100   |
 +---------------+        +--------+      +---------------+--------+
 |       2       |        | 101    |      |       1       |  101   |
 +---------------+        +--------+      +---------------+--------+ 
                          | 102    |      |       2       |  101   |
                          +--------+      +---------------+--------+  
                                          |       2       |  102   |
                                          +---------------+--------+

There can't be another tag_bundle having exactly the same combination from tag 100 and tag 101.
There can't be another tag_bundle having exactly the same combination from tag 101 and tag 102.

How can I ensure such unique constraint when executing SQL "concurrently"!!
that is, to prevent concurrently adding two bundles with exactly the same tag combination

Adding a simple unique constraint on any table does not work,
Is there any solution other than Trigger or explicit lock.

I come to only this simple way: make tag combination into string, and let it be a unique column.

tag_bundle  (unique on tags)         tag            tag_bundle_relation
 +---------------+-----------+      +--------+      +---------------+--------+
 | tag_bundle_id |  tags     |      | tag_id |      | tag_bundle_id | tag_id |
 +---------------+-----------+      +--------+      +---------------+--------+
 |       1       | "100,101" |      | 101    |      |       1       |  101   |
 +---------------+-----------+      +--------+      +---------------+--------+
                                    | 100    |      |       1       |  100   |
                                    +--------+      +---------------+--------+ 

but it seems not a good way :(

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

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

发布评论

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

评论(2

深海蓝天 2024-09-05 10:34:16

为什么要有“无触发器”的限制?有了它,再加上一些数据复制,您就可以得到您需要的东西。将解决方案中的“标签”字段更改为 INTEGER 的数组字段(或 tag_id 的任何类型)

虽然认识到该解决方案的令人不快,但我没有看到解决方法。虽然我会使用数组而不是字符串作为“标签”,但将其放在与 tag_bundle 不同的表中,仍然使其唯一并在 tag_bundle_relation 上放置触发器以使用 array_agg(tag_id) (>8.4) 更新标签字段,如果失败,则触发器更新失败。

Why the constraint of 'without a trigger'? With it, combined with a bit of data duplication, you can get what you need. Change your 'tags' field in your solution to an array field of INTEGERs (or whatever type tag_id is)

While recognising the unpleasantness of the solution, I don't see a way round it. Though I would use an array instead of a string for 'tags', put it in a separate table from tag_bundle, still make it unique and put a trigger on tag_bundle_relation to update the tags field with array_agg(tag_id) (>8.4), and if that fails, fail the trigger update.

成熟稳重的好男人 2024-09-05 10:34:16

为了在多个事务更新表时正常工作,您需要创建一个可延迟的、初始延迟的 约束触发器.

In order to work correctly when multiple transactions will be updating the tables, you will need to create a deferable, initially deferred, constraint trigger.

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