我正在尝试为电影分类创建数据库模型,其中每部电影可以从多个评级系统中的每一个(例如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
表,其约束条件允许来自同一系统的多个分类,而理想情况下,它只允许来自给定系统的零个或一个分类。
有没有合理的方法对其进行重组,以便在给定以下要求的情况下,数据库约束强制执行任何给定系统中具有零或一个分类的影片?
ClassificationSystemId
表中重复MovieClassification
不是一个好的解决方案,因为这可能与Classification
中的值不同步表)还要注意Advice
列 - 电影到分类的每个映射都需要有一个文本描述,说明为什么要为该电影分类。任何设计都需要支持这一点。
答案 0 :(得分: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表。
答案 1 :(得分:0)
根据您的说法,ClassificationSystemId
是MovieClassification
的密钥的一部分,因为对于给定系统,给定系统只能有一个(或零)MovieClassification
电影。
现在,有三种情况可以改变Classification
表:
在第一种情况下,一个例子是在现有的体裁系统中添加新的类型。你需要对属于新类型的电影进行重新分类是有意义的,因此模型成立。
在第二种情况下,一个例子是从现有系统中删除一个类型。你需要对属于旧类型的电影进行重新分类仍然有意义,因此该模型仍然存在。
在第三种情况下,您将更改例如类型的名称。已经归类为该类型的电影改变其类型名称是有道理的。该模型仍然存在。
根据我的理解,正确的规范化是将ClassificationSystemId
放入MovieClassification
并使其成为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)
);
答案 2 :(得分: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
)
但是你购买了另一个问题,即可以在其预期系统之外使用分类。
答案 3 :(得分:0)
同一分类系统中有多少不同的分类可归因于您设计的一部电影?
这是否符合您的“分类”概念?
答案 4 :(得分:0)
答案 5 :(得分:0)
行。我曾希望我的问题会引发一些思考,但我的观点似乎已经错过了。
您的分类表必须是{movieID,classificationScheme classification},并且键为{movieID classificationScheme}。
它可以通过{movieID}引用电影,它可以通过{classificationScheme分类}引用分类表。
此分类表列出/枚举/命名每个方案的所有有效分类。由于分类方案只存在并且有意义,从它至少有一个分类的那一刻起,可能没有真正需要第四个表,其唯一目的是列出/命名/列举所有相关的分类方案。 / p>
答案 6 :(得分: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))
现在,通过电影分类,您可以获得电影和系统的复合视频,因此每个系统只能获得一部电影评级(即使您添加新系统)。您还可以创建从电影分类到分类表的关系,以便提供数据。