代码之家  ›  专栏  ›  技术社区  ›  Robert Koritnik

防止使用SQL触发器插入重叠的日期范围

  •  7
  • Robert Koritnik  · 技术社区  · 14 年前

    我有一张简化了的桌子,看起来像这样:

    create table Test
    (
     ValidFrom date not null,
     ValidTo date not null,
     check (ValidTo > ValidFrom)
    )
    

    我想编写一个触发器,以防止插入与现有日期范围重叠的值。我写了一个这样的触发器:

    create trigger Trigger_Test
    on Test
    for insert
    as
    begin
     if exists(
      select *
      from Test t
       join inserted i
       on ((i.ValidTo >= t.ValidFrom) and (i.ValidFrom <= t.ValidTo))
     )
     begin
      raiserror (N'Overlapping range.', 16, 1);
      rollback transaction;
      return
     end;
    end
    

    但它不起作用,因为我新插入的记录是这两个表的一部分 试验 插入 在扳机里。因此,插入表中的新记录总是在测试表中连接到自身。触发器将始终恢复转换。

    我无法区分新记录和现有记录。所以如果排除相同的日期范围,我就可以在表中插入多个完全相同的范围。

    主要问题是

    是否可以在不向测试表中添加额外的标识列的情况下编写一个可以按预期工作的触发器,以便将新插入的记录从 exists() 陈述如下:

    create trigger Trigger_Test
    on Test
    for insert
    as
    begin
     if exists(
      select *
      from Test t
       join inserted i
       on (
        i.ID <> t.ID and /* exclude myself out */
        i.ValidTo >= t.ValidFrom and i.ValidFrom <=t.ValidTo
       )
     )
     begin
      raiserror (N'Overlapping range.', 16, 1);
      rollback transaction;
      return
     end;
    end
    

    重要 如果 没有身份是不可能的 是唯一的答案,我欢迎你提出一个合理的解释为什么。

    2 回复  |  直到 11 年前
        1
  •  3
  •   Bill    14 年前

    select *
      from testdatetrigger t
       join inserted i
       on ((i.ValidTo >= t.ValidFrom) and (i.ValidFrom <= t.ValidTo))
      Where not (i.ValidTo=t.Validto and i.ValidFrom=t.ValidFrom)