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

PostgreSQL表设计-如何避免重复使用ID

  •  1
  • Watusimoto  · 技术社区  · 14 年前

    我正在使用Postgres数据库设计一个具有相当复杂的表设计的应用程序,我一直在坚持一点,我希望有人能提供建议。

    我有几个表,每个表都有一个特性ID(或FID)。不同类型的实体具有不同的属性模式,因此我必须为每种类型创建不同的表。但是,我要确保FIDS在所有实体类型中都是唯一的。

    如果我有三种实体类型,Entity1/2/3,由以下三个表表示:

    Entity1             Entity2             Entity3
        fid                 fid                 fid
        attribute1          attribute2          attribute3
    

    如何确保系统中没有重复的FID?

    谢谢!

    3 回复  |  直到 14 年前
        1
  •  0
  •   Matt    14 年前

    听起来像Watsuimoto和MKV在考虑类似的事情——让一个基表保存FIDS,并从中继承一些特定的实体表。Watsuimoto提到它不起作用…如果你能让它发挥作用,那么我同意你们两个的观点,这是正确的解决方案。也许用整数ID上的FK来模拟它还不够紧密,无法帮助Watusimoto的客户将两个实体分配给同一个EntityBase。

    可能的解决方法是使用具有实体类型的复合键来帮助识别它。一个例子:

    EntityTypes     EntityBase     Entity1      Entity2
    -------------   ------------   ---------    ---------
    TypeName (PK)   EntityID       ID           ID
                    EntityType     EntityType   EntityType
                    CommonAtts     Attribute1   Attribute2
                    FID
    
    Constraints:
    -----------------------------------------------------------------
    EntityBase:
            PK... lots of options.  Probably PK(EntityID, EntityType)
            UNIQUE(FID)
            FK(EntityType) on EntityTypes(TypeName)
    Entity1   :
            PK(ID)  (or PK(ID, EntityID))
            EntityType NOT NULL
            CHECK(EntityType = "Entity1")  (e.g., it is constant)
            FK(EntityType) on EntityTypes(TypeName)
            FK(ID, EntityType) on EntityBase (ID, EntityType)
    Entity2   :  <Ditto>
    

    你有很大的灵活性。您可以设置每种类型的FIDS。您可以使每种类型的EntityID唯一,也可以使所有实体的EntityID唯一。可以使EntityBase具有与EntityID分开的ID。您甚至可以使EntityType成为某种计算列,或者将其设为默认列,这样就不必向它写入值。

    如果这不是你的茶杯,因为头顶有一个实体,那么我不情愿地提供:

    Entity1      Entity2           Features
    ---------    ---------   ...   ----------
    ID (PK)      ID (PK)           FID (PK, arbitrary)
    Attribute1   Attribute2        Entity1ID (FK)
                                   Entity2ID (FK)
                                   Entity3ID (FK)
    
    Constraints:
    -----------------------------------------------------------------
    Features  :
            One and only one EntityID is NOT NULL
    

    喜欢将表视为“实体记录”的人通常不喜欢这种方法。对于超过六个实体来说,这是不方便的。但它 正确,并且允许您保留单个整数行ID(如果需要)。

    当涉及到这样的问题时,我会去KenDowns的博客看看。他对关系设计有一些很好的想法。如果我能找到他发表的关于这个话题的文章,那将是我的第一个建议。 This article 是我能找到的最接近的。

        2
  •  5
  •   Edmund    14 年前

    PostgreSQL(和Oracle)使用名为sequence的对象生成顺序值。与MySQL和SQL Server的顺序值生成方法不同,序列不绑定到表。所以你可以定义一个序列( documentation link ):

    CREATE SEQUENCE your_seq 
    

    这将创建一个名为 your_seq ,它将从1开始,每次检索下一个值时递增1-如果要以不同的方式设置最小值和递增值,请参阅文档链接。

    要使用它,任何insert语句都需要包括:

    NEXTVAL('your_seq')
    

    …在insert语句中填充相应列的位置。IE:

    INSERT INTO entity1
      (fid)
    VALUES
      (NEXTVAL('your_seq'))
    

    而且,为了使这自动化一点,您可以设置 NEXTVAL('your_seq') 作为所有使用它的表的默认值。

        3
  •  0
  •   sasfrog    14 年前

    我建议使用 guids 对于您的FID字段。这样,您就可以确保没有重复的FID,并且比(i)在某个地方维护一个“最高的FID”并在每次执行插入操作时查询它,或者(i i)每次执行插入操作时,将代码放入其中检查所有表中的所有FID都要优雅得多。