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

如何使用非唯一外键强制实现数据库完整性?

  •  5
  • Dzinx  · 技术社区  · 17 年前

    (name, version)

    TABLE PERSONS:
        id:      int,
        name:    varchar(30),
        version: int,
        ... // some data assigned to that person.
    

    因此,如果用户想更新个人数据,他们不会进行更新,而是创建一个具有相同内容的新PERSONS行 name 但不同 version 价值。向用户显示的数据(给定 .

    TABLE DOGS:
        id:         int,
        name:       varchar(30),
        owner_name: varchar(30),
        ...
    

    owner_name PERSONS.name 人员姓名 不是唯一的!

    问题 :那么,在MS SQL Server 2008中,我应该如何确保数据库的完整性(即,对于每个DOG,PERSONS中至少存在一行,使其PERSON.name==DOG.owner_name)?


    上面的设计有以下优点,如果需要,我可以“记住”一个人的当前状态 id (或 (名称、版本) pair),我确信该行中的数据永远不会改变。这很重要,例如,如果我将此人的数据作为随后打印的文档的一部分,并且在5年内有人可能希望打印一份完全不变的副本(例如,使用与今天相同的数据),那么他们很容易做到这一点。


    8 回复  |  直到 17 年前
        1
  •  5
  •   A-K    17 年前

        2
  •  2
  •   Michael Gattuso    17 年前

    或者,您可以为具有历史价值的数据维护一个人员历史表。通过这种方式,您可以保持“人和狗”表的整洁,参考文献简单,但也可以访问历史上有趣的信息。

        3
  •  1
  •   Jon Seigel    17 年前

    好吧,首先你需要规范化你的表。谷歌“数据库规范化”,你会得到很多阅读材料。PERSONS表尤其需要注意。

    第二件事是,当你创建外键引用时,99.999%的时间你想引用一个ID(数字)值。即[狗]。[所有者]应指[个人]。[id]。

    编辑:添加一个示例模式(原谅松散的语法)。我假设每只狗只有一个主人。这是 实现人员历史的方法。并非所有列都为空。

    Persons Table:
    int Id
    varchar(30) name
    ...
    
    PersonHistory Table:
    int Id
    int PersonId (foreign key to Persons.Id)
    int Version (auto-increment)
    varchar(30) name
    ...
    
    Dogs Table:
    int Id
    int OwnerId (foreign key to Persons.Id)
    varchar(30) name
    ...
    

        4
  •  0
  •   Preet Sangha    17 年前

    我会使用关联表将多个版本链接到一个pk。

        5
  •  0
  •   andyb    17 年前

    在您的示例中,这将转换为一个详细信息表(detailsid,otherldetails列)、一个名为DetailsVersion的链接表(detainsid,personid)和一个Person表(personid,不变数据)。把狗和人联系起来。

        6
  •  0
  •   shahkalpesh    17 年前




    activeVersion(这将是personVersionInfo中的UID)





    versionId(将为每个人生成)

    狗


    狗名

    带狗的人

    UID,

    编辑:您必须加入PersonWithDogs、PersianVersionInfo、Dogs才能获得完整的图片(截至今天)。这种结构将帮助您将狗链接到所有者(具有特定版本)。

    如果该人的信息发生变化,而您希望获得与该狗相关的最新信息,则必须更新PersonWithDogs表,以获得给定狗所需的UID(该人的)。

    您可以设置限制,例如DogID在PersonWithDogs中应该是唯一的。

    您的场景(可以更改/限制等)将有助于更好地设计模式。

        7
  •  0
  •   Dzinx    17 年前

    在PERSONS表中,我们只留下名称(唯一标识符)和链接 当前的 个人数据:

    TABLE PERSONS:
        name:            varchar(30),
        current_data_id: int
    

    我们创建了一个新表PERSONS_DATA,其中包含该人的所有数据历史记录:

    TABLE PERSONS_DATA:
        id:      int
        version: int (auto-generated)
        ... // some data, like address, etc.
    

    DOGS表保持不变,它仍然指向一个人的名字(FK到PERSONS表)。

    1. 添加新的PERSONS_DATA行
    2. 更新此人的PERSONS条目以指向新的PERSONS_DATA行。
        8
  •  0
  •   Dzinx    17 年前

    在PERSONS表中,我们只留下名称(唯一标识符)和指向 第一 (非最新!)个人数据:

    TABLE PERSONS:
        name:            varchar(30),
        first_data_id: int
    

    我们创建了一个新表PERSONS_DATA,其中包含该人的所有数据历史记录:

    TABLE PERSONS_DATA:
        id:      int
        name:    varchar(30)
        version: int (auto-generated)
        ... // some data, like address, etc.
    

    DOGS表保持不变,它仍然指向一个人的名字(FK到PERSONS表)。

    • 对于每只狗,至少有一个PERSONS_DATA行包含其主人的数据(这就是我想要的)

    • 选择具有给定名称和最高版本的PERSONS_DATA(可能很昂贵)
    • 选择具有特殊版本的PERSONS_DATA,例如“-1”,但这样每次添加新的PERSONS.DATA时,我都必须更新两行PERSONS__DATA,在这个解决方案中,我想避免更新两行。..

    你怎么认为?