我想了解有关数据库设计的建议。 我有4个不同的数据元素(表A,B,C,D)示例: A - 内容 B - 类别 C - 作者 和 D - 图像
表A,B,C中的每条记录都可以在表D中关联一个或多个不同的图像, 但是,D中的每个图像必须唯一地仅与A,B,C中的记录相关联。 这意味着无法共享图像(在其他表之间)。
我的想法是使用ONE到MANY关联类型为每个数据元素创建不同的Image表。 例: 内容 - >图像内容 和 分类 - >图像分类
有问题吗? 我的数据库设计很好吗?
由于表格“图像内容”和“图像类别”可能具有类似“File-Url”或“Image-Title”的属性,因此我担心是否存在最合适的数据库设计解决方案。
感谢您的时间
答案 0 :(得分:2)
实现此设计的最常见方式可能是您提到的“每个所有者类型一个表”方案(图像表,“所有者A”,“所有者A图像”,以及所有者B,C等的重复) )。实现此目的的另一种常见方法是使用一个“中央”表格,其中单个所有者的Id存储在该表中。您的标准特别有限,因为图像可能只与一个所有者相关联,但有多种类型的所有者。在数据库中实现这样的约束是很棘手的,但是在数据库之外实现它们要困难得多,并且出于所有常见原因(应用程序执行数据库工作,以及当有人在专用应用程序之外修改数据库时会发生什么?)< / p>
以下是如何在数据库中实现这些结构和约束的示例。它可能看起来挑剔,详细,过于复杂,但它会完成工作,一旦正确实施,您将永远不必担心您的数据是否一致且有效。
首先,所有图像都存储在下表中。必须知道可以为图像分配所有者的“类型”;在ImageType中设置它,并且(根据后面表格中的约束)不能将图像分配给任何其他类型的所有者。永远。 (您还可以在ImageType上放置一个CHECK约束,以确保只能在表中加载有效的图像类型。)
CREATE TABLE Image
(
ImageId int not null
,ImageType char(1) not null
,constraint PK_Image
primary key clustered (ImageId, ImageType)
)
接下来,构建一些所有者表。你可以有任意数量的这些,我只是为了这个例子而做两个。
CREATE TABLE A
(
AId int not null
constraint PK_A
primary key clustered
)
CREATE TABLE B
(
BId int not null
constraint PK_B
primary key clustered
)
构建关联表,注意约束定义旁边的注释。 (这是过于挑剔的部分......)
CREATE TABLE Image_A
(
ImageId int not null
constraint PK_Image_A
primary key clustered -- An image can only be assigned to one owner
,AId int not null
,ImageType char(1) not null
constraint DF_Image_A
default 'A'
constraint CK_Image_A__ImageType
check (ImageType in ('A')) -- Always have this set to the type of the owner for this table
,constraint FK_Image_A__A
foreign key (AId) references A (AId) -- Owner must exist
,constraint FK_Image_A__Image
foreign key (ImageId, ImageType) references Image (ImageId, ImageType) -- Image must exist *for this type of owner*
)
-- Same comments for this table
CREATE TABLE Image_B
(
ImageId int not null
constraint PK_Image_B
primary key clustered
,BId int not null
,ImageType char(1) not null
constraint DF_Image_B
default 'B'
constraint CK_Image_B__ImageType
check (ImageType in ('B'))
,constraint FK_Image_B__B
foreign key (BId) references B (BId)
,constraint FK_Image_B__Image
foreign key (ImageId, ImageType) references Image (ImageId, ImageType)
)
加载一些样本数据
INSERT图像值(1,'A')
INSERT Image values (2, 'A')
INSERT Image values (3, 'B')
INSERT Image values (4, 'B')
INSERT A values (101)
INSERT A values (102)
INSERT B values (201)
INSERT B values (102)
查看表格的当前内容:
SELECT * from A
SELECT * from B
SELECT * from Image
SELECT * from Image_A
SELECT * from Image_B
做一些测试:
-- Proper fit
INSERT Image_A (ImageId, AId) values (1, 101)
-- Run it again, can only assign once
-- Cannot assign the same image to a second owner of the proper type
INSERT Image_A (ImageId, AId) values (1, 102)
-- Can't assign image to an invalid owner type
INSERT Image_B (ImageId, BId) values (1, 201)
-- Owner can be assigned multiple images
INSERT Image_A (ImageId, AId) values (2, 101)
(这会删除测试表)
drop table Image
drop table A
drop table B
drop table Image_A
drop table Image_B
(Techincally,这是关于独占类型/子类型数据建模“问题”的变体的一个很好的例子。)
答案 1 :(得分:1)
我想你会想要一张将每张ABC映射到图像的表格。例如:
Content -> ContentImages -> Images
--------- ------------- ------
ContentId ImageId ImageId
ContentId
Categories -> CategoryImages -> Images
---------- ---------------- ------
CategoryId ImageId ImageId
CategoryId
Authors -> AuthorImages -> Images
---------- ---------------- ------
AuthorId ImageId ImageId
AuthorId
看起来有点麻烦,但我认为这是normal form。
答案 2 :(得分:1)
create table A (IDA int not null, primary key(IDA));
create table B (IDB int not null, primary key(IDB));
create table C (IDC int not null, primary key(IDC));
create table Image(IDI int, A int null, B int null, C int null, Contents image,
foreign key (A) references A(IDA),
foreign key (B) references B(IDB),
foreign key (C) references C(IDC),
check (
(A is not null and B is null and C is null) or
(A is null and B is not null and C is null) or
(A is null and B is null and C is not null)
));
答案 3 :(得分:1)
是的,你正朝着正确的方向前进。
保留四个表的当前设置,然后创建另外三个表,仅保存元数据,告诉您例如内容表和图像表之间的链接。
例如,images-content表将包含列:id,content-id,image-id
等等。