0

设想

我有 3 个数据库表。一个是图像,另外两个是人物和地点。由于每个人都可以有很多图像,每个地方可以有很多图像,我希望人和图像之间以及地点和图像之间都有一对多的关系。

问题

外键是否必须与主键同名?或者我是否可以将图像表中的外键称为通用名称,例如“PKTableID”。这样我只需要一个图像表。

非常感谢帮助。

问候,

编辑:

想要只有一个图像表的原因是因为每个图像只引用一个其他表。除此之外,我在这里使用了两个表的示例,我将使用的实际数据库将有 20 个表,所以我想知道是否仍然可以为 20 个一对多关系使用单个图像表?

4

5 回答 5

5

编辑

如果一张图片只属于二十张桌子中的一张,那么这种设计可能会奏效:

People (PersonId, Name)
Places (PlaceId, Name)
Dogs (DogId, Breed)
Doors (DoorId, Height, Width)
Images (ImageId, ImageBinary, OwnerId, OwnerTable)

其中 OwnerTable 是 OwnerId 所属表的名称或代码。

这将在图像表中为您节省 20 个 FK,或 20 个关联表。然后,在连接中,您将指定 OwnerTable,具体取决于您要连接的表。

您需要为 Id 使用可转换类型(例如,TINYINT、SMALLINT 和 INT),最好是为所有类型使用一种类型(例如,INT),并且您必须自己通过触发器或其他代码来管理引用完整性。

/编辑

您需要 5 个表,而不是 3 个:

People (PersonId, Name)
Places (PlaceId, Name)
Images (ImageId, ImageBinary)
ImagesPeople (ImageId, PersonId)
ImagesPlaces (ImageId, PlaceId)

您可以随意调用这些字段。People.Id、ImagesPeople.PersonId 等。

但是你不能做的是这样的:

People (PersonId, Name)
Places (PlaceId, Name)
Images (ImageId, ImageBinary, PlaceOrPersonId)

好吧,你可以,但是数据库不会帮助你强制执行关系,或者告诉你 FK 属于哪个表。你怎么知道的?有一些 hackish 变通办法,例如错开 id 增量、向图像添加类型列或使用 GUID。

或者:

Things (ThingId PK, Type)
People (ThingId PK/FK, Name, Age)
Places (ThingId PK/FK, Name, LatLon)
Images (ImageId PK, ImageBinary, ThingId FK)

您还可以将图像作为“事物”。有时你会看到这样的设计。它确实为您提供了参照完整性,但不提供类型排他性。您可以在人物、地点和图像中拥有相同的 ThingId,而数据库不会在意。您必须自己编写该规则。

编辑:根据 Cylon Cat 的建议,场景 4:

People (PersonId, Name)
Places (PlaceId, Name)
PeopleImages (PeopleImageId, ImageBinary)
PlaceImages (PlaceImageId, ImageBinary)

在这里,图像由一个人或一个地方独家拥有。与版本 2 类似,但具有声明的外键。与 5 表设计相比,它可能具有一些性能优势,因为需要的连接更少。你失去了“图像”作为一个独特的实体,取而代之的是“人物图像”和“地方图像”。

于 2009-10-26T00:55:35.657 回答
1

正如彼得指出的那样,您确实需要多对多关系,除非您想将图像限制为只有一个人的图片,而且,一个好的地点索引将反映地名的层次性质(蒙马特,巴黎,法国 = 三个可能一个地方的名称)。

现在从技术上讲,您可以将索引和表称为任何不是保留字且尚未使用过的东西,X、Y、Z12345 和 WOBBLY 都是索引的有效名称。

然而,在实践中,最好遵循指向存储内容和用途的命名约定。因此,在您的情况下,表 PEOPLE_X_IMAGES 和 PLACES_X_IMAGES 将是一个好主意。在实际图像表中,您真的不需要任何关于人或地点的信息。同样,您不需要关于 PEOPLE 和 PLACES 表中的图像的任何内容。

于 2009-10-26T01:29:35.527 回答
1

理论上,您可以将两个外键添加到图像表中,一个用于人物,一个用于位置。然后,您可以在运行查询时允许空值并加入相应的列。不过,这并不是一个很好的解决方案,因为当您有 14 个需要加入的表时,该表会是什么样子?

如果您不打算使用 GUID,那么我说您将其设置为多对多,以便下一个必须理解它的人。

于 2009-10-26T13:08:06.490 回答
0

您可以使用一张表,但您需要 20 个不同的字段用于关系。如果设置了外键关系,那么所有的数据都必须与父表相关,不能在一张表中存储两个外键关系。所以你必须为你想要的每个 fk 设置一个列。

于 2009-10-26T13:06:31.543 回答
0

怎么样

Person (PersonId PK, Name, ImageId FK)
Image (ImageId PK, Name)
Place (PlaceId PK, Name, ImageId FK)
于 2009-10-26T14:24:19.437 回答