我在 SQL Server 中有一个非常简单的数据库,其中包含以下三个表:
Theater
(ID, is3D,
其他值...)Show
(ID, Theater_ID, Movie_ID, date, time,
其他值...)Movie
(ID, is3D,
其他值...)
我想确保3D 电影只能在 3D 影院中播放。仅在 2D 影院中的 2D 电影,并且只能通过外键(无触发器等)进行。
我在 SQL Server 中有一个非常简单的数据库,其中包含以下三个表:
Theater
(ID, is3D,
其他值...)Show
(ID, Theater_ID, Movie_ID, date, time,
其他值...)Movie
(ID, is3D,
其他值...)我想确保3D 电影只能在 3D 影院中播放。仅在 2D 影院中的 2D 电影,并且只能通过外键(无触发器等)进行。
要仅通过外键执行此操作,您还需要添加一is3D
列Show
以及几个逻辑上冗余的UNIQUE
约束。
CREATE TABLE Theater
(
ID INT PRIMARY KEY,
is3D BIT NOT NULL,
/*Other columns*/
UNIQUE(ID, is3D)
)
CREATE TABLE Movie
(
ID INT PRIMARY KEY,
is3D BIT NOT NULL,
/*Other columns*/
UNIQUE(ID, is3D)
)
CREATE TABLE Show
(
ID INT PRIMARY KEY,
Theater_ID INT NOT NULL,
Movie_ID INT NOT NULL,
is3D BIT NOT NULL,
/*Other columns*/
FOREIGN KEY(Theater_ID, is3D) REFERENCES Theater (ID, is3D),
FOREIGN KEY(Movie_ID, is3D) REFERENCES Movie (ID, is3D)
)
索引视图也可用于以声明方式强制执行此操作,而无需如下所示的附加列或唯一约束。
CREATE TABLE dbo.TwoRows
(
X INT PRIMARY KEY
);
INSERT INTO dbo.TwoRows
VALUES (1), (2)
GO
CREATE VIEW V
WITH SCHEMABINDING
AS
SELECT S.Theater_ID,
S.Movie_ID
FROM dbo.Show S
JOIN dbo.Theater T
ON S.Theater_ID = T.ID
JOIN dbo.Movie M
ON S.Movie_ID = M.ID
CROSS JOIN dbo.TwoRows
WHERE T.is3D <> M.is3D
GO
CREATE UNIQUE CLUSTERED INDEX IX
ON V(Theater_ID, Movie_ID)
如果满足规则,基础查询应始终不返回任何行。如果返回任何行,则交叉连接dbo.TwoRows
会将其相乘,从而导致违反唯一约束并防止出现这种情况。