2

我正在尝试创建一个相当简单的触发器,该触发器将在列中添加一个触发器,以跟踪类似于 Netflix 的电影发行公司的租赁数量。

我关注的专栏是:

  • 电影( movie_id, movie_title, release_year, num_rentals)
  • 客户租金( item_rental_id, movie_id, rental_date_out, rental_date_returned)

我当前的触发器如下所示:

CREATE TRIGGER tr_num_rented_insert
ON customer_rentals FOR INSERT
AS
BEGIN 
UPDATE movies
SET num_rentals=num_rentals+1
WHERE customer_rentals.movie_id=movies.movie_id;
END;

它返回错误:

消息 4104,级别 16,状态 1,过程 tr_num_rented_insert,第 7 行
无法绑定多部分标识符“customer_rentals.movi​​e_id”。

我只希望它与movie_id 匹配并将租赁数量加1。

4

2 回答 2

7

您需要加入inserted伪表:

CREATE TRIGGER dbo.tr_num_rented_insert
ON dbo.customer_rentals 
FOR INSERT
AS
BEGIN 
  UPDATE m
    SET num_rentals = num_rentals + 1
  FROM dbo.movies AS m
  INNER JOIN inserted AS i
  ON m.movie_id = i.movie_id;
END
GO

但我不得不问,在电影表中保持这个计数最新有什么意义?您始终可以在查询中获取计数,而不是冗余地存储它:

SELECT m.movie_id, COALESCE(COUNT(r.movie_id))
  FROM dbo.moves AS m
  LEFT OUTER JOIN dbo.customer_rentals AS r
  ON m.movie_id = r.movie_id
  GROUP BY m.movie_id;

如果该查询的性能成为问题,您可以创建一个索引视图来维护计数,这样您就不必使用触发器使其保持最新:

CREATE VIEW dbo.rental_counts
WITH SCHEMABINDING
AS
  SELECT movie_id, num_rentals = COUNT_BIG(*)
  FROM dbo.customer_rentals
  GROUP BY movie_id;

这会导致与您的触发器相同类型的维护,但在没有您的触发器的情况下执行此操作,并且不会影响movies表。现在要获得租金计数,您可以说:

SELECT m.movie_id, m.other_columns, 
    num_rentals = COALESCE(r.num_rentals, 0)
  FROM dbo.movies AS m
  LEFT OUTER JOIN dbo.rental_counts AS r
  ON m.movie_id = r.movie_id;

(我们在这里使用 LEFT JOIN,因为电影可能还没有被租用。)

这里的另一个好处是您不必执行任何技巧即可将电影表中的其他列获取到结果中。即使删除了租赁,它也可以确保数据准确(您的触发器将继续愉快地为计数添加 +1)。

于 2012-08-08T19:02:44.953 回答
-1

您的代码对于简单的插入触发器是正确的。假设这些列确实存在于两个表中,您的问题可能是您在 WHERE 语句的末尾放置了一个分号。分号只能在 END 语句之后。

于 2016-07-28T01:47:03.263 回答