我正在考虑设计类似于以下内容的数据库模式:

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

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

Person.PrimaryAddressID和Address.PersonID将是相应表的外键。

显而易见的问题是,无法在任何一个表中插入任何内容。有没有办法设计一个工作模式来强制每个具有主要地址的人员?

有帮助吗?

解决方案

<!>“我相信这是不可能的。在知道人员的ID之前,您无法创建地址记录,并且在知道PrimaryAddressId字段的AddressId之前无法插入人员记录。<!> quot;

从表面上看,这种主张似乎很有吸引力。但是,这很有道理。

这是一个非常常见的问题,SQL DBMS供应商已经尝试攻击了几十年了。

关键是所有约束检查必须是<!> quot; deferred <!> quot;直到两个插入完成。这可以通过不同的形式实现。数据库事务可以提供类似<!>“SET延迟约束检查ON <!>”的操作的可能性,并且你已经完成了(如果不是因为在这个特定的例子中,你可能不得不你的设计非常困难,以便能够定义两个FK约束,因为其中一个只是在SQL意义上不是'真正的'FK!)。

此处所述的基于触发器的解决方案实现了基本相同的效果,但这些解决方案暴露于应用程序强制完整性所存在的所有维护问题。

在他们的作品中,Chris Date <!> amp; Hugh Darwen描述了什么是这个问题的真正解决方案:多重任务。也就是说,基本上,可以组成几个不同的更新语句并让DBMS对其进行操作,就好像这是一个单一的语句。这个概念的实现确实存在,但你找不到任何谈论SQL的东西。

其他提示

我们在地址表中标记主要地址,然后使用仅强制执行每人记录的触发器(但必须有一条记录)。如果更改主地址,它将更新旧的主地址以及新的主地址。如果删除主地址并且存在其他地址,则会将其中一个(基于一系列规则)提升为主地址。如果插入了地址并且插入了第一个地址,则会自动将该地址标记为主地址。

这是多对多关系的完美范例。要解决这个问题,您应该拥有中间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分配多个地址,并在多个PERSON中重复使用ADDRESS记录(适用于家庭成员,同一公司的员工等)。使用PERSON_ADDRESS表中的is_primary字段,您可以识别该person_addrees组合是否是某人的主要地址。

第二个FK(PersonId from Address to Person)限制性太强,恕我直言。你是建议一个地址只能有一个人吗?

从您的设计来看,地址似乎只适用于一个人,因此只需使用PersonID作为地址表的键,然后删除AddressID键字段。

我知道我可能会被钉在十字架上或者其他什么,但是这里......

我已经为我的<!>做了这样的事情;特别是非常独特且非标准的<!>业务需求(=(即使我说话,上帝我开始听起来像SQL DDL)。

这是一个例子:

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);

<!> LT; ...生活还在继续......无论你是否为这个人提供和解决,反之亦然<!> gt;

我定义了一个表,然后另一个表引用第一个表,然后更改第一个表以反映对第二个表的引用(在第一个表创建时不存在)。它不适用于特定的数据库;如果我需要它我只是尝试它,如果它工作,然后我使用它,如果没有那么我尽量避免在设计中有这种需要(我不能总是控制它,有时设计是按原样交给我) 。如果你有一个没有人的地址,那么它属于<!> quot; government <!> quot;人。如果你有一个<!>“无家可归的人<!>”;然后它得到<!>“废弃的房子<!>”;地址。我运行一个流程来确定哪些房屋没有用户

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top