图像数据库设计

时间:2010-07-01 13:45:04

标签: database database-design

我想了解有关数据库设计的建议。 我有4个不同的数据元素(表A,B,C,D)示例: A - 内容 B - 类别 C - 作者 和 D - 图像

表A,B,C中的每条记录都可以在表D中关联一个或多个不同的图像, 但是,D中的每个图像必须唯一地仅与A,B,C中的记录相关联。 这意味着无法共享图像(在其他表之间)。

我的想法是使用ONE到MANY关联类型为每个数据元素创建不同的Image表。 例: 内容 - >图像内容 和 分类 - >图像分类

有问题吗? 我的数据库设计很好吗?

由于表格“图像内容”和“图像类别”可能具有类似“File-Url”或“Image-Title”的属性,因此我担心是否存在最合适的数据库设计解决方案。

感谢您的时间

4 个答案:

答案 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

等等。