2012-08-08 7 views
2

J'essaie de créer un déclencheur assez simple qui ajouterait un déclencheur à une colonne qui conserve une trace du nombre de locations d'une société de distribution de films similaire à Netflix.Déclencheur SQL Server: l'identificateur en plusieurs parties n'a pas pu être lié

Les colonnes que je me concentre sur sont:

  • Films (movie_id, movie_title, release_year, num_rentals)
  • Customer_rentals (item_rental_id, movie_id, rental_date_out, rental_date_returned)

Mon déclencheur actuel ressemble à ceci:

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; 

Il renvoie l'erreur:

Msg 4104, Level 16, State 1, Procedure tr_num_rented_insert, Line 7
The multi-part identifier "customer_rentals.movie_id" could not be bound.

Je veux juste faire correspondre les années movie_id et ajouter 1 au nombre de locations.

Répondre

6

Vous devez joindre à la inserted pseudo-tableau:

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 

Mais je dois demander, quel est le point de garder ce compte jusqu'à ce jour dans la table des films? Vous pouvez toujours obtenir le nombre dans une requête au lieu de les stocker de manière redondante:

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; 

Et si l'exécution de cette requête devient un problème, vous pouvez créer une vue indexée pour maintenir le compte de sorte que vous ne devez pas tenir à jour avec un déclencheur:

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

Cela provoque le même genre d'entretien comme déclencheur, mais le fait sans votre déclencheur, et il ne sans affecter la table movies. Maintenant, pour obtenir les comptes de location, vous pouvez simplement dire:

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; 

(Nous utilisons un LEFT JOIN ici parce qu'un film peut-être pas encore été loués.)

Un bonus supplémentaire est que vous n'avez pas avoir à effectuer des astuces pour obtenir d'autres colonnes de la table des films dans le résultat. Il garantit également que les données sont exactes même si une location est supprimée (votre déclencheur continuera à ajouter heureusement +1 au compte).

+0

Ceci est une tâche que j'essaie de passer en revue - les paramètres sont une colonne nouvellement insérée (num_rentals) et il doit augmenter avec chaque location ... Je suis d'accord, il pourrait y avoir des moyens beaucoup plus faciles à faire. Merci de votre aide. Corrigé tout de suite! –

-1

Votre code est correct pour un déclencheur d'insertion simple. En supposant que ces colonnes existent dans les deux tables, votre problème peut être que vous mettez un point-virgule à la fin de l'instruction WHERE. Le point-virgule doit être uniquement après l'instruction END.

Questions connexes