7

我正在尝试为我的“Blockbuster-like”电影公司编写一个 sql server 更新触发器。在我的 MOVIES 表中,我有 movie_id 作为 PK 和另一个名为 num_rented 的列,它保留了电影被租用的总次数。这个总数是通过我的插入、删除和更新触发器完成的。(我知道有更好的方法可以做到这一点,但我的任务特别要求这样做,所以请理解这一点)。CUSTOMER_RENTALS 表有 item_rental_id 作为 PK,MOVIES 中的 movie_id 是 FK。

我需要一个更新触发器,只要对 CUSTOMER_RENTALS 进行更新,它就会更新 MOVIES 中的 num_rentals 列。例如,假设输入了 movie_id 1,但这是一个错误,实际上是 movie_id 2。我希望 num_rentals 反映更新。

这是我到目前为止所拥有的,但我真的不知道在 SET 部分中放入什么来实现这一点:

CREATE TRIGGER tr_num_rentals_update
ON customer_rentals
AFTER UPDATE
AS
BEGIN
UPDATE m
SET num_rentals = ??????
FROM movies AS m
INNER JOIN inserted as i on m.movie_id=i.movie_id;
END;

我在想我需要访问已删除表的值以将 num_rental 列恢复到以前的值,但我不知道如何。提前十亿谢谢!

4

3 回答 3

10

您需要考虑到 DML 语句可能会影响多行(在这种情况下,INSERTEDandDELETED表也将有多行。

您还需要考虑到,如果电影更新为不同的 id,您应该减少电影的租借次数(以及增加新电影的计数)。

下面合并了插入和删除的计数,并将净更改应用于相关的电影 ID。

CREATE TRIGGER tr_num_rentals_update
ON customer_rentals
AFTER INSERT, UPDATE, DELETE
AS
  BEGIN
      IF UPDATE(movie_id) /*If column not affected skip*/
        BEGIN
            WITH T1(Cnt, movie_id)
                 AS (SELECT COUNT(*),
                            movie_id
                     FROM   inserted
                     GROUP  BY movie_id
                     UNION ALL
                     SELECT -COUNT(*), /*negative for deletes*/
                            movie_id
                     FROM   deleted
                     GROUP  BY movie_id),
                 T2
                 AS (SELECT SUM(Cnt) AS NetCnt,
                            movie_id
                     FROM   T1
                     GROUP  BY movie_id)
            UPDATE m
            SET    num_rentals = num_rentals + NetCnt
            FROM   movies AS m
                   INNER JOIN T2
                     ON m.movie_id = T2.movie_id;
        END
  END; 
于 2015-04-06T14:25:44.887 回答
1

我相信您可以通过添加 m.num_rentals + 1 来完成此操作

还为已删除的一个添加更新语句

UPDATE M
SET num_rentals = m.numrentals - 1
FROM
Movies M
INNER JOIN Deleted D ON
M.movie_id = D.Movie_ID

但是,与其在触发器中使用它,我宁愿创建一个应用程序可以用来获取它的视图。从而消除了每次更新、插入和删除时需要执行的额外数据处理

CREATE VIEW MoviesVW AS
SELECT M.Movie_ID, COUNT(R.*) AS Num_Rental
FROM Movies M
LEFT JOIN customer_rentals R ON
R.movies_id = M.movies_ID
GROUP BY
M.Movie_ID
于 2013-04-20T21:14:53.433 回答
-1

您需要在更新触发后执行。您可以尝试以下方法。为了更好地理解触发器,我强烈推荐这个链接 http://www.codeproject.com/Articles/25600/Triggers-Sql-Server

CREATE TRIGGER trgAfterUpdate ON [dbo].[customer_rentals] 
FOR UPDATE
AS
    declare @num_rentals int;
    declare @movie_id int;

    SELECT @movie_id =i.movie_id from inserted i;   
    SELECT @num_rentals =num_rentals from MOVIES where movie_id =@movie_id 
    SET @num_rentals =@num_rentals +1;

      -- perform update here in movies table    

    UPDATE MOVIES SET num_rentals=@num_rentals WHERE movie_id =@movie_id 

GO
于 2013-04-20T20:55:36.423 回答