避免在SQL表中使用重复的“成对”值(两列)

时间:2019-01-28 09:27:45

标签: sql tsql azure-sql-database

我有一张表记录家庭成员之间的关系,我想确保始终只有一条记录,其中有两个相同的人-但是现在有两列和两个值需要考虑。我已经做了几个小时的搜索,但是我确定它在那里,但是我还没有找到。

我有一个人的表,该人的外键(Persons.ID)在这里将出现在aID和bID中(两个人)。我还有另一个角色表(母亲,女儿,叔叔,兄弟姐妹等),其外键(Roles.ID)将出现在aID_role和bID_role中)。 (我试图在此表中仅存储整数,因为它最终可能会有很多记录。)

Relationships
----------------------------------------
aID     aID_role     bID     bID_role
----------------------------------------
 4        1           5        2

说aID 4是John,而bID 5是Carla。 aID_role 1是“父亲”,bID_role 2是“女儿”。

如何防止输入下面的第二条记录?

Relationships
----------------------------------------
aID     aID_role     bID     bID_role
----------------------------------------
 4        1           5        2
 5        2           4        1 <-- sort of a duplicate

请注意,我对比较“ _role”列不感兴趣。它们在这里无关紧要。我想避免Person.ID 4和5出现在Relationships表中的多个记录中。

数据库在Azure SQL中。

3 个答案:

答案 0 :(得分:2)

您可以创建反映ID的计算列,如下所示:

id1 AS (CASE WHEN aID < bID THEN aid ELSE bid END),
id2 AS (CASE WHEN aID < bID THEN bid ELSE aid END),

这两个 duplicate 行看起来像:

aID  bID  id1  id2
4    5    4    5
5    4    4    5

您只需要创建一个UNIQUE约束:

CONSTRAINT IX_Relationships UNIQUE (id1, id2)

答案 1 :(得分:1)

当要防止插入“相反”的行时,需要在一对具有特定属性的列上实施唯一约束(例如,第一个始终低于第二个)。

对于无向图,一种简单的方法是在表上检查约束,然后确保插入数据以匹配约束。

但是,关系往往是定向关系。例如。我将创建一个包含FromIDToIDRelationship的表,其中后者是对诸如“父亲到女儿”(您可以使用隐式“ From”读取)的值的查找。一开始),就可以清楚地知道FromIDToID

这种结构清楚地表明,只有一种正确的方法可以存储这些关系-但是您可能仍然无法保证例如FromID总是比ToID低,并且可能希望防止不正确的意外插入(防止某人同时成为其他人的母女)

因此,我们引入了indexed view,它利用这种关系合成了一对列,然后对其施加唯一约束。

CREATE VIEW dbo.Relationships_DRI_Unique
WITH SCHEMABINDING
AS
    SELECT
         CASE WHEN FromID < ToID THEN FromID ELSE ToID   END as Col1,
         CASE WHEN FromID < ToID THEN ToID   ELSE FromID END as Col2
    FROM
        dbo.Relationships
GO
CREATE UNIQUE INDEX IX_Relationships_DRI_Unique on dbo.Relationships_DRI_Unique (Col1,Col2)

({DRI =声明式参照完整性。按照我的惯例,在命名对象时使用这些字母纯粹是为了强制执行约束。我不希望有人会 query 查看)

答案 2 :(得分:0)

新模型的主张

table persons
id PK
first_name,
second_name


table roles
id PK
role_id
role_name (ex. Father, daugther,)

table relationship
id PK
person    (ex. persons.id = 1, JOHN)
role      (roles.id = 5, FATHER
person_to (persons.id = 3, CARLA,

所以简而言之,“人”是“角色”到“人”。

您的问题的示例:您只需为以下表关系添加1条记录:

“ JOHN”是“ CARLA”的“父亲”。

无需添加第二个LIKE

“ CARLA”是“ JOHN”的“女儿”