双向外键约束(Bidirectional foreign key constraint)

2019-08-31 11:21发布

我想设计类似下面的数据库模式的:

Person (
  PersonID int primary key,
  PrimaryAddressID int not null,
  ...
)

Address (
  AddressID int primary key,
  PersonID int not null,
  ...
)

Person.PrimaryAddressID和Address.PersonID会外键对应表。

最明显的问题是,它不可能将任何物品进入任何一个表。 有没有办法设计一个具有强制执行的主要地址的每个人工作的模式?

Answer 1:

“我认为这是不可能的。直到你知道这个人的ID,你不能插入个人记录,直到您知道PrimaryAddressId领域的AddressId不能创建一个地址记录。”

在它面前,这种说法似乎很吸引人。 然而,这是相当propostrous。

这是一个很常见的一种问题,即SQL数据库管理系统供应商一直试图攻击的甚至几十年了。

最关键的是,所有的约束检查必须是“推迟”,直到两个刀片完成。 这可以在不同的形式来实现。 数据库事务可以提供像做“SET延迟的约束检查ON”的可能性,你就大功告成了(如果不是事实,在这个特殊的例子,你可能要惹很难与您的设计,以能够只定义两个FK约束,因为他们中的一个根本不是一个“真正的” FK在SQL感!)。

这里描述基本达到同样的效果,但这些都暴露在与应用实施的完整性存在的所有维修问题触发的解决方案。

在他们的工作,克里斯日期和休·达文描述什么是海事组织真正的解决问题的方法:多重分配。 也就是说,实际上,可能组成几个不同的更新语句,并有DBMS作用于它,就好像那是一个单独的语句。 这一概念的实现确实存在,但你不会找到任何会谈SQL。



Answer 2:

我们在地址表中标注的主要地址,然后有每人只强制触发记录可以拥有它(但一个记录都必须有它)。 如果更改了主地址,它会更新旧的主地址,以及新的。 如果您删除主地址和其它地址存在,它会促进他们中的一个(basesd ONA一系列的规则)的主地址。 如果该地址被插入并且被插入在第一地址,这将自动标记的一个作为主地址。



Answer 3:

这是很多一对多的关系,一个很好的例子。 要解决,你应该有中间PERSON_ADDRESS表。 换一种说法;

PERSON table
person_id (PK)

ADDRESS table
address_id (PK)

PERSON_ADDRESS
person_id (FK) <= PERSON
address_id (FK) <= ADDRESS
is_primary (BOOLEAN - Y/N)

这样,您就可以将多个地址,一个人,也重新,多者地址记录(家庭成员,同一家公司的员工等)。 在PERSON_ADDRESS表使用is_primary场,你可以找出如果person_addrees组合是主地址的人。



Answer 4:

第二FK(PERSONID从地址到人)的限制过于严格,恕我直言。 你是在暗示一个地址只能有一个人?



Answer 5:

从您的设计,似乎是一个地址可以应用到只有一个人,所以只使用,将personId为重点,以地址表,并删除AddressID重点领域。



Answer 6:

我知道我可能会被钉在十字架上或什么的,但在这里不用...

我已经做了这样的对我的“特殊自己独特的,非标准的”业务需求(=(上帝,我开始听起来像SQL DDL,甚至当我说话)。

下面是一个exaxmple:

CREATE TABLE IF NOT EXISTS PERSON(
    ID INT, 
    CONSTRAINT PRIMARY KEY (ID), 
    ADDRESS_ID INT NOT NULL DEFAULT 1, 
    DESCRIPTION VARCHAR(255), 
    CONSTRAINT PERSON_UQ UNIQUE KEY (ADDRESS_ID, ...));

INSERT INTO PERSON(ID, DESCRIPTION) 
    VALUES (1, 'GOVERNMENT');

CREATE TABLE IF NOT EXISTS ADDRESS(
    ID INT, 
    CONSTRAINT PRIMARY KEY (ID), 
    PERSON_ID INT NOT NULL DEFAULT 1, 
    DESCRIPTION VARCHAR(255), 
    CONSTRAINT ADDRESS_UQ UNIQUE KEY (PERSON_ID, ...), 
    CONSTRAINT ADDRESS_PERSON_FK FOREIGN KEY (PERSON_ID) REFERENCES PERSON(ID));

INSERT INTO ADDRESS(ID, DESCRIPTION) 
    VALUES (1, 'ABANDONED HOUSE AT THIS ADDRESS');

ALTER TABLE PERSON ADD CONSTRAINT PERSON_ADDRESS_FK FOREIGN KEY (ADDRESS_ID) REFERENCES ADDRESS(ID);

<...生活还要继续......你是否提供和地址,或没有的人,反之亦然>

我定义一个表,那么其他表参考第一,然后改变所述第一,以反映参照第二(其没有在第一表的创建的时间存在)。 它不是为特定的数据库; 如果我需要它,我只是尝试一下,如果它工作,然后我用它,如果没有的话我尽量避免在设计中需要(我总是无法控制的是,有时设计是交给我的,是) 。 如果你没有一个人有一个地址,然后它属于“政府”的人。 如果你有一个“无家可归者”,那么它获得的“废弃的房子”的地址。 我运行一个进程,以确定哪些房屋没有用户



文章来源: Bidirectional foreign key constraint