方案

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

问题

外键是否必须与主键同名?或者我可以在images表中调用一般的外键,例如“PKTableID”。这样我只需要一张图像表。

非常感谢。

此致

编辑:

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

有帮助吗?

解决方案

修改

如果一张图像仅由二十张表中的一张拥有,则此设计可能有效:

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

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

这样可以在图像表或20个关联表中保存20个FK。然后,在联接中,您将指定OwnerTable,具体取决于您要加入的表。

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

/ EDIT

您需要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属于哪个表。你怎么知道的?有一些讨厌的解决方法,例如错开id增量,向Images添加类型列或使用GUID。

可替换地:

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

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

编辑:在Cylon Cat的建议中,方案4:

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

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

其他提示

彼得指出你真的需要多对多的关系,除非你想把你的图像限制在只有一个人的照片上,一个好的地方指数也会反映地名的等级性质(蒙马特,巴黎,法国) =一个地方有三个可能的名字。)

现在从技术上讲,您可以调用索引和表格中任何非保留字并且尚未使用的内容,X,Y,Z12345和WOBBLY都是索引的有效名称。

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

您可以在理论上添加两个外键到images表,一个用于People,一个用于Places。然后,您可以在运行查询时允许空值并连接到相应的列。这不是一个很好的解决方案,因为当你有14个表需要加入它时,这个表是什么样的?

如果你不打算使用GUID,那么为了下一个必须理解它的人,我说你把它设置为多对多。

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

怎么样

Person (PersonId PK, Name, ImageId FK)
Image (ImageId PK, Name)
Place (PlaceId PK, Name, ImageId FK)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top