Question

I am working on a school database project that requires a trigger-based solution for some of the optional restrictions my database has. My database model represents and online-based video viewing service where users have access to a large number of videos( similar principle as that of YouTube). Table history stores up to 100 viewed videos for every user. What my trigger is supposed to do is:

  • Delete previous entries for the same video and user (or change the date of viewing to current time)
  • Insert new entry (or update an existing one, i.e. possible step 1)
  • Delete any entries older than the 100th one

Here is the code i wrote:

 CREATE TRIGGER [History_Update] ON dbo.History INSTEAD OF INSERT AS
BEGIN
DECLARE @user_id bigint, @video_id bigint, @history_count smallint 
SELECT @user_id=user_id, @video_id=video_id FROM inserted

DELETE FROM History where user_id = @user_id AND video_id=@video_id
INSERT INTO History(user_id, video_id) VALUES (@user_id, @video_id)

SET @history_count = (select count(*) FROM History WHERE user_id= @user_id AND video_id = @video_id)

IF( @history_count >= 100)
BEGIN
    WITH temp AS (SELECT TOP 1 * FROM History WHERE user_id= @user_id AND video_id=@video_id ORDER BY viewtime ASC) 
    DELETE FROM temp
END
END

Now, I have few questions regarding this:

  • Is it better to Use CTE as written above or something like this:

    SET @viewtime = (SELECT TOP 1 viewtime FROM History WHERE user_id= @user_id AND video_id=@video_id ORDER BY viewtime ASC) 
    DELETE FROM History where user_id = @user_id AND video_id=@video_id AND viewtime = @viewtime
    
  • Also, would it be better to check if a specific user-video entry exists in History and then update the viewtime attribute. Also, since I am using INSTEAD OF trigger, would this violate any rule regarding the use of this kind of trigger since I am not sure if I understood it well. From what I read online, INSTEAD OF triggers must perform the specified action within the body of the trigger. Thanks!

Était-ce utile?

La solution

Given the choice between your expression and the set, I would choose the CTE. I find that using set with a subquery somewhat icky. After all, the following does the same thing:

SELECT TOP 1 @viewtime = viewtime
FROM History
WHERE user_id = @user_id AND video_id = @video_id
ORDER BY viewtime ASC; 

In other words, the set is redundant.

In addition, separating the set from the delete introduces an opportunity for a race condition. Perhaps another query might insert a row or delete the one you are trying to delete.

As for the CTE itself, it is okay. You need the CTE (or subquery) if you are going to delete rows in a particular order.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top