与多对多关系中的表的唯一关系集

时间:2019-05-08 07:39:17

标签: sql postgresql

假设我们有Parent1Parent2Child1Child2

如果Parent1Child1Child2都相关,那么如何也禁止Parent2Child1Child2都相关。


示例:

CREATE TABLE parent (
  id INTEGER PRIMARY KEY
);

CREATE TABLE child (
  id INTEGER PRIMARY KEY
);

CREATE TABLE parent_child (
  parent_id INTEGER REFERENCES parent,
  child_id INTEGER REFERENCES child
);

INSERT INTO parent VALUES (1);
INSERT INTO parent VALUES (2);
INSERT INTO child VALUES (1);
INSERT INTO child VALUES (2);

INSERT INTO parent_child (parent_id, child_id) VALUES (1, 1);
INSERT INTO parent_child (parent_id, child_id) VALUES (1, 2);
INSERT INTO parent_child (parent_id, child_id) VALUES (2, 1);

-- Should not allow the following insert:
INSERT INTO parent_child (parent_id, child_id) VALUES (2, 2);

parent1已经有孩子[1,2]
插入后,parent2也将有子[1,2]。因为[1,2] == [1,2],所以不允许这样做。

但是,如果我添加了第三个孩子:
parent1有孩子[1,2]
parent2有孩子[1,2,3]
可以,因为[1,2] != [1,2,3]


在某些情况下:我正在建模Apriori,并且不想重复的“项集”。

2 个答案:

答案 0 :(得分:0)

如果您要在表parent_child中插入parent_id和child_id(如果还不存在相同的组合),则可以按以下方法尝试在SQL中如果不存在-

IF NOT EXISTS
(
    SELECT * 
    FROM parent_child
    WHERE parent_id = 2
    AND child_id = 2
)
BEGIN
    INSERT INTO parent_child (parent_id, child_id) 
    VALUES (2, 2);
END

答案 1 :(得分:0)

您可以使用触发器。

为每个父项下的子项添加行号,按child_id排序。

然后,您可以将当前的父级与其余的父级进行比较,并找到具有完全相同的子级的Parnet。

如果找到这样的匹配项,请阻止INSERT操作。

if EXISTS(
    SELECT  parent_id
    FROM (
            (       SELECT 
            ROW_NUMBER() OVER(PARTITION BY parent_id ORDER BY child_id ) 
            AS RowNum, 
            child_id 
            FROM parent_child WHERE parent_id =2
            ) AS a 
            INNER JOIN
            (       SELECT ROW_NUMBER() OVER(PARTITION BY parent_id ORDER BY child_id ) 
            AS RowNum, 
            child_id,
            parent_id
            FROM parent_child WHERE parent_id <>2
            ) AS b 
            ON a.child_id = b.child_id AND a.RowNum = b.RowNum
        )
            ) then ---...block the INSERT