具有多个一对多关联的引用完整性

时间:2013-01-28 13:58:14

标签: sql database referential-integrity

我将用一个例子解释我的案例。

我有以下表格:personsplacespictures。人和地都有很多照片。在保持参照完整性的同时,在数据库方案中表达这一点的最佳方法是什么?

  1. 我可以为每个可能的关联添加一个列,但是当有其他东西有图片时,这会创建很多空字段。
  2. 我可以在personspictures以及placespictures之间创建关联表。但是外键会在关联表中,我不能强制删除地图等时删除的图片。
  3. 目前我倾向于第二种方法,但我不喜欢它。

2 个答案:

答案 0 :(得分:2)

没有任何一种尺寸适合所有解决方案,可以打勾你想要的所有方框。但我以前见过的是

3)为将共享关系的项目引入基表:

CREATE TABLE Entities (
    EntityID int not null primary key,
    EntityType varchar(10) not null,
    constraint CK_EntityTypes CHECK (EntityType in ('Person','Place')),
    constraint UQ_Entities_WithTypes UNIQUE (EntityID,EntityType)
)

然后构建您的PeoplePlaces表:

CREATE TABLE People (
    PersonID int not null PRIMARY KEY,
    EntityType AS CAST('Person' as varchar(10)) persisted,
    ...Other columns...
    constraint FK_People_Entities FOREIGN KEY (PersonID,EntityType) references Entities (EntityID,EntityType)
)

CREATE TABLE Places (
    PlaceID int not null PRIMARY KEY,
    EntityType AS CAST('Place' as varchar(10)) persisted,
    ...Other columns...
    constraint FK_Places_Entities FOREIGN KEY (PlaceID,EntityType) references Entities (EntityID,EntityType)
)

(我不确定Entities在考虑地方时是完全正确的 - 一个更好的名字可能会向你暗示。)

然后,您可以Pictures引用EntityID


否则,如果我必须在1和1之间选择2,我通常建议1.除非涉及的“类型”数量变大,否则它仍然不会使Pictures表太宽,正如您所观察到的,您至少可以使用正常如有必要,FK机制可以强制执行级联。


4)如果Pictures目前只是一张非常裸的表,可能会查询是否应该有一个图片表,或者每个类型一个。人们的照片和地方的图片经常会一起查询(即使它们是,基于UNION ALL的查询是否可以隐藏您使用单独表格的事实?)

答案 1 :(得分:1)

我认为有三种方法。一种是将每个实体映射到图片的单独表格。类似的东西:

create table PersonPictures . . .
    PersonId int not null,
    PictureId int not null

. . .

create table PlacesPictures . . .
    PlaceId int not null,
    PictureId int not null

当人物和地方是独立的实体并且可能有关于图片的其他信息时,这种情况有所不同(说明该人穿着的地方或地点的观点)。

如果人物和地方真的只是图片的属性,那么你可以拥有:

create table AttributesPictures . . .
    PictureId int not null,
    AttributeType varchar(255),  -- 'Person', 'Place'
    PersonId int,
    PlaceId int

在这种情况下,您可以设置约束以确保AttributeType仅采用明确定义的值(或使用带有单独查找表的AttributeId)。对外键的约束:当AttributeType ='Person'时,PersonId不为null,Place Id为null。

如果一张图片最多只有一个人和一个地方,那么你可以将这些ID存储在图片记录本身中 - 这种特殊情况下非常方便。

您采取的哪种方法应该更多地受到应用程序要求的驱动。在任何方法中,您都可以使用外键关系和级联删除来确保记录被删除。或者,您也可以使用触发器来强制执行关系完整性(尽管这不是我最喜欢的解决方案)。