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

时间:2010-08-20 01:10:59

标签: sql postgresql

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

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

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

Entity1             Entity2             Entity3
    fid                 fid                 fid
    attribute1          attribute2          attribute3

如何确保系统中的任何地方都没有重复的fid?

谢谢!

3 个答案:

答案 0 :(得分:5)

PostgreSQL(和Oracle就此而言)使用名为Sequences的对象来生成顺序值。与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')设置为使用它的所有表的默认值。

答案 1 :(得分:0)

我建议您使用guids作为您的fid字段。通过这种方式,您可以确保不会出现重复的fid,并且比以下任何一种都更优雅(i)在某处保持“最高fid”并在每次执行插入操作时查询它,或者(ii)将代码放入其中每次进行插入操作时都会检查所有表中的所有fid。

答案 2 :(得分:0)

听起来像Watsuimoto和MkV正在考虑类似的东西 - 有一个基表持有FID和一些特定的实体表继承。 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>

你在这里有很多灵活性。您可以设置每种类型的FID。您可以使EntityID在每个类型中都是唯一的,或者在所有实体中使其唯一。您可以使EntityBase具有与EntityID分开的ID。您甚至可以使EntityType成为某种计算列,或者默认它,因此您不必为其写入值。

如果由于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。

当涉及到这样的问题时,我会去Ken Downs博客并环顾四周。他对关系设计有一些很好的想法。如果我能找到他在这个主题上发表的文章,这将是我的第一个建议。 This article是我能找到的最接近的。