1

我正在尝试以一种我认为约束无法实现的方式在表上强制执行完整性...

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”,不应有任何具有重叠日期的条目。

笔记:

invalid_from 是有效期之后的瞬间。
这意味着以下两个时期都很好......

  • '2008 Jan 01 00:00' -> '2008 Feb 01 00:00' (整个 1 月)
  • '2008 年 2 月 1 日 00:00' -> '2008 年 3 月 1 日 00:00'(整个 2 月)

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

(如果insert包含两条有效记录和两条无效记录,我可以只停止两条无效记录吗?)

干杯,
德姆斯。

编辑:

在我上面的情况下,使用函数的约束效果很好。但我从来没有弄清楚为什么 RAISERROR 在触发器版本中不起作用。

我认为这是因为触发器是 AFTER 触发器,我需要一个 BEFORE 触发器,但这似乎不是一个选项......

4

4 回答 4

3

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

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 );
于 2009-01-09T15:07:42.113 回答
3

不要从插入的表中删除记录......这是无声的失败。通往地狱的道路是在 Partial Commits 中铺就的。

您需要RAISERROR,这本质上是约束的作用。

于 2009-01-09T15:19:38.763 回答
0

引发错误。

于 2009-01-09T15:08:15.357 回答
0

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

于 2009-01-09T15:09:18.833 回答