3

我正在尝试为电影分类创建一个数据库模型,其中每部电影都可以从多个评级系统(例如 BBFC、MPAA)中的每一个中获得一个分类。这是当前的设计,包含所有隐含的 PK 和 FK:

TABLE Movie 
( 
    MovieId INT -- PK
)

TABLE ClassificationSystem 
( 
    ClassificationSystemId TINYINT -- PK
)

TABLE Classification 
(
    ClassificationId INT,          -- PK
    ClassificationSystemId TINYINT -- FK
)

TABLE MovieClassification 
(
    MovieId INT,          -- composite PK, FK
    ClassificationId INT, -- composite PK, FK
    Advice NVARCHAR(250)  -- description of why the classification was given
)

问题在于MovieClassification表的约束条件将允许来自同一系统的多个分类,而理想情况下它应该只允许来自给定系统的零或一个分类。

考虑到以下要求,是否有任何合理的方法来重组它,以便从任何给定系统中精确地具有零或一个分类的电影由数据库约束强制执行?

  • 不要复制可以查找的信息(即ClassificationSystemIdMovieClassification表中复制不是一个好的解决方案,因为这可能与表中的值不同步Classification
  • 保持可扩展到多个分类系统(即一个新的分类系统不需要对表结构进行任何更改)?

还要注意该Advice列 - 电影到分类的每个映射都需要有一个文本描述,说明为什么将该分类给予该电影。任何设计都需要支持这一点。

4

7 回答 7

1

您可以使用调用用户定义函数的检查约束来强制执行此操作。例如:

create function dbo.ClassificationSystemCheck()
returns int
as begin
    return (select max(cnt)
    from (
        select count(*) as cnt
        from MovieClassification mc
        left join Classification c
        on c.ClassificationId = mc.ClassificationId
        group by mc.MovieId, c.ClassificationSystemId
    ) qry)
end
go
alter table MovieClassification
add constraint chk_MovieClassification
check (dbo.ClassificationSystemCheck() <= 1)
go
alter table Classification
add constraint chk_Classification
check (dbo.ClassificationSystemCheck() <= 1)
go
insert into Classification select 1,1
insert into MovieClassification select 1,1
insert into MovieClassification select 1,1 -- Boom!

随着分类数量的增加,这可能效率低下。或者,您可以删除 Classification 表并将 ClassificationSystemId 移至 MovieClassification 表。

于 2010-05-10T11:16:41.923 回答
0

如果您从分类表中删除分类系统 id 并仅将其保留在电影分类中怎么办?

TABLE Movie 
( 
    MovieId INT
)

TABLE ClassificationSystem 
( 
    ClassificationSystemId TINYINT
)

TABLE Classification 
(
    ClassificationId INT,
)

TABLE MovieClassification 
(
    MovieId INT,
    ClassificationId INT,
    ClassificationSystemId TINYINT,
    Advice NVARCHAR(250) -- description of why the classification was given
)

但是您购买了另一个问题,即分类可以在其预期系统之外使用。

于 2010-05-10T11:32:28.240 回答
0

在你的设计下,同一个分类系统有多少不同的分类可以归于一部电影?

这是否符合您预期的“分类”概念?

于 2010-05-10T14:38:15.403 回答
0

从您所说的来看,ClassificationSystemId是 a 的键的一部分MovieClassification,因为给定电影的给定系统只能有一个(或零)MovieClassification

Classification现在,表格可以更改的三种情况:

  1. 您将新分类添加到系统。
  2. 您从系统中删除现有分类。
  3. 您更改分类的元数据(未在您发布的架构中显示)。

在第一种情况下,一个例子是向现有的流派系统添加新的流派。您需要重新分类属于新类型的电影是有道理的,因此该模型成立。

在第二种情况下,一个例子是从现有系统中删除一个流派。您需要重新分类属于旧类型的电影仍然是有道理的,因此该模型仍然成立。

在第三种情况下,您将更改例如流派的名称。已经归类为该类型的电影更改其类型名称是有道理的。该模型仍然成立。

据我所知,正确的规范化是放入ClassificationSystemIdMovieClassification使其成为MovieClassification键的一部分(并使其成为所提供模式中行ClassificationSystemId的键的一部分):Classification

-- Tables Movie, ClassificationSystem not included for brevity

CREATE TABLE Classification
(
  ClassificationId INT,
  ClassificationSystemId INT,
  PRIMARY KEY(ClassificationId, ClassificationSystemId),
  FOREIGN KEY(ClassificationSystemId) REFERENCES ClassificationSystem(ClassificationSystemId)
);

CREATE TABLE MovieClassification
(
  ClassificationId INT,
  ClassificationSystemId INT,
  MovieId INT,
  Advice NVARCHAR(MAX),
  PRIMARY KEY(ClassificationId, ClassificationSystemId, MovieId),
  FOREIGN KEY(ClassificationId, ClassificationSystemId) REFERENCES Classification(ClassificationId, ClassificationSystemId),
  FOREIGN KEY(MovieId) REFERENCES Movie(MovieId),
  UNIQUE(ClassificationSystemId, MovieId)
);
于 2010-05-10T10:54:19.757 回答
0
  1. 在分类上添加唯一约束 (ClassificationId,ClassificationSystemId)
  2. 从 MovieClassification 表中添加一个引用它的 FK
  3. 在 MovieClassification (MovieId,ClassificationSystemId) 上添加唯一约束
于 2010-05-10T17:54:47.977 回答
0

好的。我曾希望我的问题会引发一些思考,但我的观点似乎被忽略了。

您的分类表需要为 {movieID, classificationScheme 分类},键为 {movieID classificationScheme}。

它可以通过 {movieID} 引用电影,它可以通过 {classificationScheme 分类} 引用分类表。

此分类表列出/枚举/命名每个方案的所有有效分类。由于分类方案仅存在并且有意义,从它具有至少一个分类的那一刻起,可能并不真正需要第四个表,其唯一目的是列出/命名/枚举所有相关分类方案。

于 2010-05-10T18:21:52.060 回答
0

老实说,我只是稍微改变一下数据模型。

create table #Movies (PK_moID int identity(1,1), moName varchar(50) primary key(PK_moID))
create table #ClassificationSystem (PK_csID int identity(1,1), csName varchar(50) primary key(PKcsID))
create table #Classification (PK_clID int identity(1,1), FK_csID int)
create table #MovieClassification (FK_moID int, FK_csID int, FK_clID int primary key (FK_moID, FK_csID))

现在,通过您的电影分类,您拥有电影和系统的复合 pk,因此每个系统只能获得一个电影评分(即使您添加了新系统)。您还可以创建从电影分类到分类表的关系,以添加数据。

于 2011-08-18T13:22:42.923 回答