我有一张表记录家庭成员之间的关系,我想确保始终只有一条记录,其中有两个相同的人-但是现在有两列和两个值需要考虑。我已经做了几个小时的搜索,但是我确定它在那里,但是我还没有找到。
我有一个人的表,该人的外键(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中。
答案 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)
当要防止插入“相反”的行时,需要在一对具有特定属性的列上实施唯一约束(例如,第一个始终低于第二个)。
对于无向图,一种简单的方法是在表上检查约束,然后确保插入数据以匹配约束。
但是,关系往往是定向关系。例如。我将创建一个包含FromID
,ToID
和Relationship
的表,其中后者是对诸如“父亲到女儿”(您可以使用隐式“ From”读取)的值的查找。一开始),就可以清楚地知道FromID
和ToID
。
这种结构清楚地表明,只有一种正确的方法可以存储这些关系-但是您可能仍然无法保证例如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”的“女儿”