我试图在我的电影数据库中名为Cast的表上设置INSTEAD OF DELETE触发器。如果CastFilmID计数大于2,我希望它防止删除行
CREATE TRIGGER Prevent_Cast_Delete ON Cast
INSTEAD OF DELETE
AS
WHERE COUNT CastFilmID > 2
RAISERROR ('Contains more than 2 cast memebers',16,1)
ROLLBACK TRAN
RETURN;
答案 0 :(得分:1)
CREATE TRIGGER Prevent_Cast_Delete ON Cast
INSTEAD OF DELETE
AS
BEGIN
DELETE FROM Cast WHERE id IN (
--Identify only people who work in films with 0 or 1 cast members
SELECT d.id
FROM
--The list of people we try to delete (request from elsewhere)
Deleted d
LEFT OUTER JOIN
--This query counts the cast for every film
(SELECT CastFilmID, COUNT(*) as CastCount FROM Cast GROUP BY CastFilmId) c
ON
c.CastFilmID = d.CastFilmID
--This where clause reduces the list of actor IDs we try to delete, to actually
--just those actors who are in a film of 1 cast member
WHERE c.CountCast < 2 OR d.CastFilmID IS NULL
);
END;
您忘记在触发器内实际执行删除操作,因此不会从表中删除任何内容。
我已经颠倒了逻辑:对于您尝试删除的所有记录,只能删除与没有其他演员共享电影的演员有关的记录
为此,我们将应用程序试图删除的人员列表(例如,伪表-deleted d
伪表,加入到强制转换表的摘要中,并仅选择摘要计数少于2个参与者的记录) :
Cast.ID, Cast.CastFilmID
KEANU, MATRIX
LAURE, MATRIX
HUGOW, MATRIX
JARAN, MOBYDI
JESUS, null
假设我说delete from cast where id in ('KEANU','JARAN','JESUS')
-这试图从我们认识的每部电影中删除人物。它将实现以下内容的deleted
伪表:
Cast.ID, Cast.CastFilmID
KEANU, MATRIX
JARAN, MOBYDI
JESUS, null
左上角是电影计数:
Cast.ID, Cast.CastFilmID, CastCount
KEANU, MATRIX, 3
JARAN, MOBYDI, 1
JESUS, null, null
WHERE子句将KEANU从结果中删除,因为他正在拍摄3名演员(包括他本人)的电影
原始请求的3条记录中的以下2条记录被删除(DELETE FROM cast WHERE ID IN (...this list...)
:
Cast.ID
JARAN
JESUS
请注意,关于数据库的假设如下:
这里要理解的关键是,运行删除查询的人将在触发器中给您X的行数。这些是该人要删除的行,但在此之前,您想从该组数据之外额外的知识(例如“有多少其他人与每个人一起制作同一部电影”)可以决定是否删除它们。这就是为什么我们计算那部电影的人数,将其加入要删除的人的数据,然后决定是否应该删除该人的原因
真的,这种魔术应该在前端完成。当您告诉数据库删除某件事时,事情变得非常混乱。同样,您还必须注意DELETE查询一次可以删除数百行,因此您不能采用“删除只会尝试删除一个强制转换行”的简单方法-您必须像处理这些事情一样数据集,将它们与其他数据集结合,并提出一组要删除的数据