I want to create a trigger which will check if my showtime with Cinema Hall Id exist or not. This will prevent me from booking one Cinema hall at two same Showtimes. Secondly in this trigger I am also checking if the showtime I am assigning to movie lies in movie release and last date range or not. But I don’t know why none of the statement is working.
Create table Movie([Movie_ID] int primary key not null,[Movie_Name] varchar(50) Unique not null,[Realease_Date] date not Null,[Last_Date] date,Runtime time(0) not null ,Status varchar(20) not null,Rating float) Create table [Showtime]([Showtime_ID] int primary key not null,Date date not null,Time time(0) not Null) Create table [Cinema Halls]([Cinema_Halls_ID] int primary key not null,[Total_Seats] int not Null) Create table [Movie Schedule] ( [Movie_Schedule_ID] int primary key not null, [Movie_ID] int NOT null, [Showtime_ID] int not null, Cinema_Halls_ID int not null Constraint fk_M_ID FOREIGN KEY ([Movie_ID]) REFERENCES Movie([Movie_ID]), Constraint fk_Sh_ID FOREIGN KEY ([Showtime_ID]) REFERENCES Showtime([Showtime_ID]), Constraint fk_C_ID FOREIGN KEY ([Cinema_Halls_ID]) REFERENCES [Cinema Halls] ([Cinema_Halls_ID]) ) /*Trigger Stops duplicate booking of Cinema halls and invalid showtime of movie*/ Create Trigger Trigger_Movie_Shedule On "Movie Schedule" After Insert,Update As declare @Cinema_Halls_ID int ,@Showtime_ID int,@Movie_ID int,@Release_Date Date,@Last_Date Date, @Showtime_Date date; Select @Cinema_Halls_ID =Cinema_Halls_ID from inserted ; Select @Showtime_ID=Showtime_ID from inserted; Select @Movie_ID=Movie_ID from inserted; Select Showtime_Date=Date from Showtime where Showtime_ID=@Showtime_ID Select @Release_Date= Release_Date from Movie where Movie_ID=@Movie_ID; Select @Last_Date=Last_Date from Movie where Movie_ID=@Movie_ID; IF EXISTS (select count (Showtime_ID) from "Movie Schedule" where Showtime_ID = @Showtime_ID and Cinema_Halls_ID = @Cinema_Halls_ID ) BEGIN PRINT'This Cinema Hall is Already Booked' Rollback Transaction; return END ELSE IF (@Showtime_DATE >= @Release_Date and @Showtime_Date<= @Last_Date) BEGIN PRINT'Movie Showtime not in Range' Rollback Transaction; return END
Advertisement
Answer
I think this is what you are looking for. The changes/improvements/best practices are:
- Uses set-based logic, which you should always aim to do in a relational database.
- Uses
Inserted
as a table rather than a single row - Semi-colon line terminators
set nocount on
- Uses
throw
- Uses
[]
instead of""
- Fixed “in range” logic and detection of duplicate logic
CREATE TRIGGER Trigger_Movie_Shedule ON [Movie Schedule] AFTER INSERT, UPDATE AS BEGIN SET NOCOUNT ON; IF EXISTS ( SELECT 1 FROM [Movie Schedule] S -- Restrict the check to the inserted/updated records INNER JOIN Inserted I on I.Showtime_ID = S.Showtime_ID and I.Cinema_Halls_ID = S.Cinema_Halls_ID GROUP BY S.Showtime_ID, S.Cinema_Halls_ID -- If more than one row exists we have a problem Houston HAVING COUNT(*) > 1 ) BEGIN -- Rolls back, returns and provides an error message all in one. THROW 51000, 'This Cinema Hall is Already Booked',1; END; ELSE IF EXISTS ( SELECT 1 FROM Inserted I INNER JOIN Movie M ON M.Movie_ID = I.Movie_ID INNER JOIN ShowTime S ON S.ShowTime_ID = I.ShowTime_ID -- WHERE S.Showtime_DATE >= M.Release_Date and S.Showtime_Date < M.Last_Date -- Think you logic detects when it *is* in range, whereas the error is when its out of range WHERE S.Showtime_DATE < M.Release_Date or S.Showtime_Date > M.Last_Date ) BEGIN -- Rolls back, returns and provides an error message all in one. THROW 51000, 'Movie Showtime not in Range',1; END; END;
Note: I highly recommend reading Using Inserted and Deleted as it explains very clearly how to write triggers.