一对多,但将其中一个识别为“默认”

时间:2012-01-23 21:13:34

标签: database-design

我有一个表地址 Person 可以有多个地址记录,因此与地址的简单1 .. *关系具有引用“人员ID”的字段。

现在,对于给定的 Person ,我希望识别他们的“默认”或“主要”地址

我想出了两个想法,但我也不相信。在我决定之前,任何人都可以提出任何关于潜在问题的评论我可以面对任何选项...

(a)中。可以在 Person 上设置一个“默认地址ID”来存储     默认地址记录的ID。这里可能存在的陷阱是     可以在此处设置不属于此 Person 地址,所以     需要一个额外的检查约束来防止这种情况。

(b)中。可以在地址表上有一个“默认”标志,但这有     允许多次选择的可能性,因此需要进一步     检查以便在设置标志时,它也会被清除     属于同一的记录。

任何

7 个答案:

答案 0 :(得分:1)

我会选择(B)然后保护默认位的设置。

通过阅读您对问题的评论,我想补充一点,强制总是至少有1个地址设置,您需要在存储过程中处理默认位。

类似的东西:

表示插入:

DECLARE @IsDefault bit;
SET @IsDefault = 0;

IF NOT EXISTS (SELECT * from tblAddresses WHERE PersonID = @PersonID And Default = 1)
BEGIN
   SET @IsDefault = 1;
END

INSERT INTO tblAddress (.... Default ... )
       VALUES (... @IsDefault ... );

更新:

IF (@Default = 1)
BEGIN
   Update tblAddress
   SET
   tblAddress.Default = 0
   FROM tblAddress
   WHERE tblAddress.PersonID = @PersonID;

   Update tblAddress
   SET
   tblAddress.Default = 1
   WHERE ID = @AddressID;
END
ELSE
BEGIN
   IF EXISTS (SELECT * FROM tblAddresses WHERE PersonID = @PersonID AND Default = 1 AND AddressID != @AddressID)
   BEGIN
      UPDATE tblAddresses 
      SET Default = 0
      WHERE AddressID = @AddressID;
   END
END

此外,您也可以从用户界面中阻止这种情况,但在数据库中增加一层保护并没有什么坏处。

答案 1 :(得分:1)

另一个选项是(通过标准化数据)添加另一个表DefaultAddress

Person
------
PersonId
... other stuff
PRIMARY KEY (PersonId)

Address
-------
AddressId
PersonId 
... other stuff
PRIMARY KEY (AddressId)
FOREIGN KEY (PersonId)
  REFERENCES Person(PersonId)

DefaultAddress
--------------
AddressId
PersonId 
PRIMARY KEY (AddressId)
UNIQUE KEY (PersonId)           --- every person has (max) one default address
FOREIGN KEY (PersonId, AddressId)
  REFERENCES Address(PersonId, AddressId)

答案 2 :(得分:0)

选项(a) - 如果您更改了默认地址的值,则将对地址的引用存储为默认地址可能会导致问题。

答案 3 :(得分:0)

我可以使用B的子集,我会在地址表中添加一个AddressType字段,您可以在其中定义主要和辅助或某些通用类型,然后您还可以为将来的地址类型设置自己必须修改架构。

答案 4 :(得分:0)

我们有一个默认的标志字段和一个触发器,用于确保一个且只有一个记录的默认值为1.确保编写触发器以处理多个记录插入/更新和删除并测试它们。因此,如果它是插入的第一个记录,则该字段自动设置为1.如果删除了字段设置为1的记录,我们有一个业务规则inteh触发器,它确定哪个剩余记录将获得默认值。如果将不同的记录更新为1,则将具有1的现有记录更新为在该字段中为0。如果您不使用触发器,很可能在某些时候您会遇到数据完整性问题。

答案 5 :(得分:0)

而不是 (a)可以在Person 上有一个'默认地址ID' 布尔值怎么样? isDefaultAddr

为了进一步解释,不是在Person表中有一个类似defaultAddressID的字段,你可以在Person表中有一个布尔字段,比如isDefaultAddress。如果这是该人的默认地址,则其值为true,否则为false。

HTH

答案 6 :(得分:0)

我会选择带有AddresspersonId标志的default表上具有UNIQUE索引的选项B,但只用于其中default = true的行。像这样:

CREATE UNIQUE INDEX address_default ON address (personId, default) WHERE (default = true);

这样,您可以确保一个人的默认地址不多。

如果没有默认地址,请选择第一个。