代码之家  ›  专栏  ›  技术社区  ›  Dave

分解BOM表样式关系中的空值

  •  1
  • Dave  · 技术社区  · 16 年前

    PERSON { name, spouse }
    

    如果PERSON.party是PERSON.name的外键,则当某人未婚或我们没有任何信息时,必须为null。

    关于反对空值的论点,在这种情况下如何避免它们?

    我有另一个模式

    PERSON { name }
    SPOUSE { name1, name2 }
    

    其中,partnery.name*是个人的FKs。我在这里看到的问题是,无法确保一个人只有一个配偶(即使有所有可能的独特限制,也有可能有两个配偶)。

    7 回复  |  直到 16 年前
        1
  •  2
  •   Adam Bellaire    16 年前

    我认为,对这种类型的关系强制执行无空和无重复会使模式定义方式比实际需要的更加复杂。即使允许为空,一个人仍有可能有多个配偶,或有冲突的记录,例如:

    PERSON { A, B }
    PERSON { B, C }
    PERSON { C, NULL }
    

    你需要引入更多的数据,比如性别(或者同性婚姻的“配偶号码”),以确保,例如,只允许一种类型的人有配偶。另一个人的配偶将由第一个人的记录决定。例如。:

    PERSON { A, FEMALE, B }
    PERSON { B, MALE, NULL }
    PERSON { C, FEMALE, NULL }
    

        2
  •  1
  •   BobbyShaftoe    16 年前

    首先,我会使用自动递增的ID,当然,某人可以有相同的名字。但是,我想你打算这么做,不会喋喋不休。然而,反对空值的论点究竟是如何进行的呢?我对null没有任何问题,我认为这是解决这个问题的合适方法。

        3
  •  1
  •   Tom H    16 年前

    我不知道为什么还没有人指出这一点,但事实上很容易确保一个人只有一个配偶,使用的模型与你在问题中提出的几乎相同。

    我暂时不考虑使用名称作为主键(它可能会更改,而且重复的情况相当普遍,因此这是一个糟糕的选择),我还将忽略可能需要的历史跟踪(你可能想添加一个生效日期,这样你就知道他们是什么时候的配偶了——乔·塞尔科(Joe Celko)写了一些关于时间建模的好东西,但我不记得当时是哪本书中的).否则,如果我离婚并再婚,你会失去我在另一个时间有另一个配偶的机会——也许这对你来说并不重要。

    此外,您可能希望将名称分为名、中名、姓、前缀、后缀等。

    CREATE TABLE People
    (
         person_name     VARCHAR(100),
         CONSTRAINT PK_People PRIMARY KEY (person_name)
    )
    GO
    CREATE TABLE Spouses
    (
         person_name     VARCHAR(100),
         spouse_name     VARCHAR(100),
         CONSTRAINT PK_Spouses PRIMARY KEY (person_name),
         CONSTRAINT FK_Spouses_People FOREIGN KEY (person_name) REFERENCES People (person_name)
    )
    GO
    

    如果您希望配偶也出现在人员表中,那么您也可以为此添加一个FK。然而,此时您正在处理一个双向链接,这变得有点复杂。

        4
  •  0
  •   Brian Rudolph    16 年前

    好的,首先使用一个键而不是名称,也许是一个int种子。但为了防止一个人有多个配偶,只需在配偶表中为父母(name1)添加一个唯一索引。这将防止您两次插入相同的名称1。

        5
  •  0
  •   BobbyShaftoe    16 年前

    好的,使用自动ID,然后使用检查约束。“Name1”列(只能是一个int ID)将被强制只有奇数编号的ID,而Name2只有偶数编号的ID。

    然后为Column1和Column2创建唯一约束。

        6
  •  0
  •   James Anderson    16 年前

    您需要一个person表和一个单独的“Partner\u Off”表来定义关系。

    合作伙伴关闭(id、合作伙伴id、关系);

        7
  •  0
  •   Steven Huwig    16 年前

    可以使用触发器强制执行约束。PostgreSQL已经 constraint triggers ,这是一种将约束计算推迟到事务中适当时间的特别好的方法。

    数据库管理中的实际问题 ,第66-67页:

    存储过程是否已触发 “不”比“应用”更可取 级别完整性代码,但它们是 实际上低于和风险更大 而不是声明性支持,因为它们 写起来更麻烦,错误 易受影响,且不能从充分的 数据库管理系统优化。

    选择具有更好声明性的DBMS 诚信支持。鉴于 产品,知识渊博的用户将 DBMS不支持。