Sql Server更新触发器:如何使其工作

Sql Server更新触发器:如何使其工作,sql,sql-server,triggers,Sql,Sql Server,Triggers,我正试图为我的“轰动一时的”电影公司编写一个sql server更新触发器。在我的MOVIES表中,我有movie_id作为主键,还有一个名为num_rendered的列,它记录了一部电影被租用的总次数。这个总数是通过插入、删除和更新触发器完成的。(我知道有更好的方法可以做到这一点,但我的任务特别要求这样做,所以请理解这一点)。CUSTOMER_RENTALS表的主键为item_rental_id,MOVIES中的movie_id为FK 我需要一个更新触发器,每当对CUSTOMER_rental

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

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

以下是我目前所拥有的,但我真的不知道如何在设定的部分中实现这一点:

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列恢复为其以前的值,但我不知道如何恢复。提前多谢了

您需要在更新触发器之后执行。你可以试试下面的方法。为了更好地理解触发器,我强烈推荐这个链接


我相信您可以通过添加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

您需要考虑DML语句可能会影响多行(在这种情况下,
INSERTED
DELETED
表也会有多行)

您还需要考虑,如果一部电影更新为不同的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; 

您可以在更新触发器中执行
SET num_rentals=num_rentals+1
,在删除触发器中执行
SET num_rentals=num_rentals-1
,这正是我在删除触发器rs中执行的操作,我的插入触发器设置为num_rentals=num_rentals+1。有了更新触发器,我不需要双重功能来添加到相应的触发器中吗ct num_rentals列并从错误的num_rentals列中减去?我一定会查看提供的链接,谢谢。我完全不熟悉declare命令。我们在课堂上还没有遇到过这个命令。这不是正确的方法。触发器需要处理多行更新。谢谢Christer。我必须通过触发器,因为这是对触发器的赋值。
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;