代码之家  ›  专栏  ›  技术社区  ›  MatBailie

使用触发器强制约束

  •  1
  • MatBailie  · 技术社区  · 16 年前

    我试图以一种我认为约束不能实现的方式来强制表的完整性…

    CREATE TABLE myData
    (
       id             INTEGER IDENTITY(1,1) NOT NULL,
       fk_item_id     INTEGER               NOT NULL,
       valid_from     DATETIME              NOT NULL,
       invlaid_from   DATETIME              NOT NULL
    )
    

    我要应用的约束是,同一个“fk_item_id”的日期不应该重叠。

    注:

    无效的“从”是指在有效期之后立即生效。
    这意味着接下来的两个时期是好的…

    • '2008年1月01日00:00'->'2008年2月01日00:00'(1月全部)
    • '2008年2月01日00:00'->'2008年3月01日00:00'(全部2月)

    我可以在触发器中检查该规则。但是,当触发器确实发现非法插入/更新时,防止“非法”插入/更新的最佳方法是什么?

    (如果 插入的 包括两个有效记录和两个无效记录,我可以只停止两个无效记录吗?)

    干杯,
    民主党。

    编辑:

    在上面的例子中,使用函数的约束工作得很好。但我从来没有弄明白为什么raiserror在触发器版本中不起作用。

    我以为这是因为触发器是后触发器,我需要前触发器,但这似乎不是一个选项…

    4 回复  |  直到 16 年前
        1
  •  3
  •   cmsjr    16 年前

    不能直接从插入的表中删除(对逻辑表的更新会引发错误),但可以按如下所示重新联接到源表

    create table triggertest (id int null, val varchar(20))
    Go
    create trigger after  on [dbo].triggertest
    for Update  
    as
    Begin
    
        delete tt from triggertest tt inner join 
        inserted i on tt.id = i.id 
        where i.id = 9
    
    End
    GO
    insert into triggertest values (1,'x')
    insert into triggertest values (2,'y')
    Update triggertest set id = 9 where id = 2
    select * from triggertest
    1, x
    

    此外,您不必执行触发器路由,也可以将检查约束绑定到函数的返回值。

    Alter table myData WITH NOCHECK add 
    Constraint  CHK_VALID CHECK (dbo.fx_CheckValid(id, valid_from , invalid_from) = 1 );
    
        2
  •  3
  •   Amy B    16 年前

    不要从插入的表中删除记录…那是无声的失败。通往地狱的道路是以部分承诺铺平的。

    你需要 RAISERROR 这基本上是 constraint 会的。

        3
  •  0
  •   Doug Currie    16 年前

    你的触发器可以修改 valid_from 和/或 invlaid_from DATETIME s的“非法”记录为特殊值。随后的清理步骤可以识别“非法”记录。

        4
  •  0
  •   lc.    16 年前

    提出错误。

    推荐文章