【问题标题】:Trigger to check if the combination of two field exist触发检查两个字段的组合是否存在
【发布时间】:2021-08-26 22:24:59
【问题描述】:

我想创建一个触发器,它会检查我的放映时间是否存在 Cinema Hall Id。这将阻止我在两个相同的放映时间预订一个电影院。 其次,在这个触发器中,我还要检查我分配给电影的放映时间是否在电影发行和最后日期范围内。 但我不知道为什么这些语句都不起作用。

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

【问题讨论】:

  • 您犯了触发 101 新手错误 - 假设 inserted 将只包含一条记录。我可以包含 0-N 条记录,因此您应该使用基于集合的操作来处理它。我推荐阅读Using Inserted and Deleted
  • 请解释...自学很难...我现在卡住了
  • 我无法比我提供的链接更好地解释它......这是一个复杂的领域......学习没有捷径。
  • 而这阻止我在两个不同的时间预订一个电影院是不正确的要求。当 2 个不同的放映重叠时,您想防止预订屏幕(电影院)。但是您(电影业)希望在所有可能的时间都在每个屏幕上播放一些东西,以最大限度地提高收入。
  • trigger 101 问题是每个 statement 触发一次,而不是每个 row。如果update 影响五行,则inserteddeleted 将分别包含五行,触发器将触发一次。请注意,您还需要触发器来处理对MovieShowtime 的更改,例如如果有人更改Showtime.Time,您需要验证它不会导致多个图像同时出现在大屏幕上。对Movie.Runtime 的更改也可能导致冲突。

标签: sql sql-server tsql triggers


【解决方案1】:

我认为这就是您要寻找的。更改/改进/最佳做法是:

  • 使用基于集合的逻辑,您应该始终致力于在关系数据库中执行此操作。
  • Inserted 用作表而不是单行
  • 分号行终止符
  • set nocount on
  • 使用throw
  • 使用[] 而不是""
  • 修复了“范围内”逻辑和重复逻辑检测
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;

注意:我强烈推荐阅读Using Inserted and Deleted,因为它非常清楚地解释了如何编写触发器。

【讨论】:

  • 非常感谢Youuuuu,我发现我在发布和最后日期范围内犯了错误,但我不知道我应该使用连接来做到这一点......我不胜感激谢谢...... .....有一条线我没有得到。你能解释一下 WHERE I.Showtime_DATE M.Last_Date 这条线是如何比较的,因为我只在电影时间表表中插入了 Showtime_ID 。所以这条线是如何检索 Showtime_Date 的......
  • 抱歉忘记加入 ShowTime...现在查看。
  • 说真的,这让我理解了我几周以来一直试图理解的问题......看到这个我意识到我将所有东西存储在变量中的方式是如此草率......再次非常感谢并保持祝福....
  • 答案没有使用Movie.Runtime来判断是否有足够的时间放映电影并在为以下@987654330开始下一组“即将到来的景点”之前对Cinema Hall进行消毒@。这是留给 OP 的练习吗?
  • @HABO 猜猜……我个人不会重新发明调度轮……但是,嘿
猜你喜欢
  • 1970-01-01
  • 2017-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 1970-01-01
  • 1970-01-01
  • 2017-03-11
相关资源
最近更新 更多