Sql 多对多中的唯一性

Sql 多对多中的唯一性,sql,postgresql,many-to-many,Sql,Postgresql,Many To Many,我不知道谷歌用什么术语,所以帮我标记这个问题或者帮我指出一个相关的问题会很有帮助 我相信我有一种典型的多对多关系: CREATE TABLE groups ( id integer PRIMARY KEY); CREATE TABLE elements ( id integer PRIMARY KEY); CREATE TABLE groups_elements ( groups_id integer REFERENCES groups, elements_id intege

我不知道谷歌用什么术语,所以帮我标记这个问题或者帮我指出一个相关的问题会很有帮助

我相信我有一种典型的多对多关系:

CREATE TABLE groups (
  id integer PRIMARY KEY);

CREATE TABLE elements (
  id integer PRIMARY KEY);

CREATE TABLE groups_elements (
  groups_id integer REFERENCES groups,
  elements_id integer REFERENCES elements,
  PRIMARY KEY (groups_id, elements_id));
我希望有一个约束,对于给定的元素集,只能有一个groups\u id

例如,以下内容是有效的:

groups_id | elements_id
        1 | 1
        1 | 2
        2 | 2
        2 | 3
以下内容无效,因为第1组和第2组是等效的

groups_id | elements_id
        1 | 1
        1 | 2
        2 | 2
        2 | 1
并非每个元素子集都必须有一个组(这不是幂集),但可以形成新的子集。我怀疑我的设计是不正确的,因为我真正谈论的是将组添加为单个实体


如何为元素子集创建标识符而不存在重复子集的风险?

这是一个有趣的问题

一种解决方案(尽管不太明确)是在groups表1-1-2中存储groups\u id和elements\u id的串联,并使其成为唯一索引


在插入新行之前尝试搜索重复的组将对性能造成巨大的影响。

以下查询将抛出有问题的组ID:

with group_elements_arr as (
    select groups_id, array_agg(elements_id order by elements_id) elements 
    from group_elements 
    group by groups_id )
select elements, count(*), array_agg(groups_id) offending_groups 
    from group_elements_arr 
    group by elements 
    having count(*) > 1;
根据
group\u元素的大小及其变化率,您可能不需要沿着这条线将某些内容填充到触发器中即可观看
group\u元素。如果这不够快,您可以将
组元素\u arr
具体化为一个由触发器管理的实际表


我认为,每个语句的触发器应该是
初始延迟
,以便于建立新的组。

来自用户ypercube的链接非常有用:。简言之,每个人所说的有一点是正确的

这是一个权衡的问题,但以下是最佳选择:

a) 向groups表中添加散列或其他元素值组合,使其唯一,然后使用触发器填充groups\u elements表。这种方法的优点是,只要您拒绝对组和元素进行裸更新,它就可以保留查询能力并强制执行约束。缺点是它增加了复杂性,现在您已经在数据库中引入了“如何唯一地表示一组元素”之类的逻辑


b) 保持表不变,并使用访问层控制对组元素的访问,无论是存储过程还是其他。这样做的优点是保留了查询能力并使数据库本身保持简单。但是,这意味着您正在将分析约束移动到访问层中,这必然意味着您的访问层需要更加复杂。另一点是,它将数据应该是什么与数据本身分开,这既有优点也有缺点。如果您需要更快地访问集合是否已存在,可以单独解决该问题。

这也是我的想法。对于任何一组元素,创建一个排序组_id_表示'elem1-elem2-…'。然后表示是唯一的,您可以在groups表中使用它(并删除groups\u elements表)。我也想过存储元素id的哈希,但这可能过于工程化了。您可以将其存储为group\u id、成员位图,设置的位n将指代元素n。让这个专栏也独一无二,会给你你想要的。您可能还希望保留链接表,因为它更容易加入。您可以使用触发器维护链接表。但是,不确定这将扩展到多少个元素。请检查SQL Server的相同问题:这种复杂的需求可以通过
断言来解决,但没有DBMS实现这些。因此,最好的解决方案可能是通过触发器。