SQL Server触发器比较插入的表

时间:2017-05-19 12:28:26

标签: sql sql-server triggers

我试图在IF语句中比较触发器中的插入表。 在IF语句的第一个块中,我正在过滤插入的表,以便插入的电影室号码(filmzaal_zaalnummer)等于议程表中的电影室号码。

议程表给了我3列 1)电影室号码 2)电影的开始日期_时间 3)电影的结束日期_时间。

所以在我将agenda.filmzaal_zaalnummer与inserted.filmzaal_zaalnummer进行比较之后,我试图找出电影的插入开始日期_时间是否已经在议程上的电影的开始日期_时间和结束日期_时间之间。

我认为如果插入的开始date_time没有中断任何其他现有的电影我的SELECT TOP 1 inserted.id应该为空,这就是为什么我将它与最初插入的id进行比较,这样如果插入的议程正在中断任何现有的电影,IF语句将被激活并且应该击退回滚。 但现在我的触发器始终被激活。 我该如何解决这个问题?

ALTER TRIGGER [dbo].[trg_controlleer_afspeeldatum]
ON  [dbo].[agenda]
AFTER INSERT
AS 
BEGIN
if  (
        select top 1    i.id
        from    (   select filmzaal_zaalnummer, datum_tijd, DATEADD(minute,f.speelduur,datum_tijd) as eind_datum_tijd
                    from agenda a, film f
                    where a.film_titel = f.titel ) AS agenda,
                inserted i
        where   i.filmzaal_zaalnummer = agenda.filmzaal_zaalnummer 
        and     i.datum_tijd between agenda.datum_tijd and agenda.eind_datum_tijd
    ) =
    (
        select top 1    i.id
        from            inserted i
    )
    begin
    rollback transaction
    print 'Er draait dan al een film op die tijd in die zaal'
    return
    end    
END

1 个答案:

答案 0 :(得分:1)

首先是一些提示:
- 在所有代码中使用英语
- 给出数据库模式
- 创建脚本
- 给一些成功/失败的测试用例
- 用可理解的英语描述你想要完成的事情

代码中有两个问题:
1.在您的查询中,您正在查看已经列入议程的电影,因此总是存在重复。因此,只比较agenda.id<>inserted.id的记录。见Use the inserted and deleted Tables

  

insert表在INSERT期间存储受影响行的副本   和UPDATE语句。在插入或更新事务期间, new   行被添加到插入的表和触发器表。该   inserted表中的行是触发器中新行的副本   表。

  1. 您必须始终考虑可能存在多个插入的记录或重复项,因为您可以使用多插入查询。 请参阅Create DML Triggers to Handle Multiple Rows of Data
  2. 这是正确的代码和一些测试用例:

    drop trigger [trg_Check_Agenda_For_Double_Bookings];
    go
    
    create TRIGGER [trg_Check_Agenda_For_Double_Bookings]
    ON  agenda
    after INSERT
    AS 
    BEGIN
        declare @count int;
    
        set @count = (
            select count(*) as countDuplicates
            from (
                select id,filmzaal_zaalnummer, datum_tijd, DATEADD(minute,f.speelduur,datum_tijd) as eind_datum_tijd
                from agenda a, film f
                where a.film_titel = f.titel) AS agenda, inserted i
                where   i.filmzaal_zaalnummer = agenda.filmzaal_zaalnummer 
                and     i.id<>agenda.id
                and     i.datum_tijd between agenda.datum_tijd and agenda.eind_datum_tijd
            )
    
        if (@count>0)
            begin
                rollback transaction
                print 'There is already a movie playing during the same time in that theatre.'
                return
            end    
    END;
    go
    
    delete from agenda
    --must succeed (first planned movie in agenda)
    INSERT [dbo].[agenda] ([film_titel], [filmzaal_zaalnummer], [datum_tijd]                                , [taalversie], [projectie]) VALUES 
                          (    N'Logan',                     1, CAST(N'2017-01-01T00:00:00.000' AS DateTime),    N'Engels',    N'TweeD');
    
    --must fail because Logan movie takes 137 minutes
    INSERT [dbo].[agenda] ([film_titel], [filmzaal_zaalnummer], [datum_tijd]                                , [taalversie], [projectie]) VALUES 
                          (    N'Logan',                     1, CAST(N'2017-01-01T01:00:00.000' AS DateTime),    N'Engels',    N'TweeD');
    INSERT [dbo].[agenda] ([film_titel], [filmzaal_zaalnummer], [datum_tijd]                                , [taalversie], [projectie]) VALUES 
                          (    N'Logan',                     1, CAST(N'2017-01-01T02:00:00.000' AS DateTime),    N'Engels',    N'TweeD');
    
    --must succeed because this one is 3 hours later and Logan only takes 137 minutes
    INSERT [dbo].[agenda] ([film_titel], [filmzaal_zaalnummer], [datum_tijd]                                , [taalversie], [projectie]) VALUES 
                          (    N'Logan',                     1, CAST(N'2017-01-01T03:00:00.000' AS DateTime),    N'Engels',    N'TweeD');
    
    --multi insert of a good and bad planned movie (above 2 records) but both will fail because whole transaction/insert will be rolled back!
    INSERT [dbo].[agenda] ([film_titel], [filmzaal_zaalnummer], [datum_tijd]                                , [taalversie], [projectie]) VALUES 
                          (    N'Logan',                     1, CAST(N'2017-01-01T02:00:00.000' AS DateTime),    N'Engels',    N'TweeD'),
                          (    N'Logan',                     1, CAST(N'2017-01-01T03:00:00.000' AS DateTime),    N'Engels',    N'TweeD');