1

表约束是否在同一个事务中执行?

我有一个具有已提交读隔离级别的事务,它在表中插入一些行。该表有一个约束,它调用一个函数,该函数又从同一个表中选择一些行。

看起来函数在不了解事务的情况下运行,并且函数中的选择返回表中在事务之前存在的行。

有解决方法还是我错过了什么?谢谢。

以下是交易和约束的代码:

insert into Treasury.DariaftPardakhtDarkhastFaktor
    (DarkhastFaktor, DariaftPardakht, Mablagh, CodeVazeiat, 
    ZamaneTakhsiseFaktor, MarkazPakhsh, ShomarehFaktor, User) 
values
    (@DarkhastFaktor, @DariaftPardakht, @Mablagh, @CodeVazeiat,
    @ZamaneTakhsiseFaktor, @MarkazPakhsh, @ShomarehFaktor, @User);


constraint expression (enforce for inserts and updates):
([Treasury].[ufnCheckDarkhastFaktorMablaghConstraint]([DarkhastFaktor])=(1))

ufnCheckDarkhastFaktorMablaghConstraint:

returns bit
as
begin
    declare @SumMablagh float
    declare @Mablagh    float

    select @SumMablagh = isnull(sum(Mablagh), 0)
    from Treasury.DariaftPardakhtDarkhastFaktor
    where DarkhastFaktor= @DarkhastFaktor

    select @Mablagh = isnull(MablaghKhalesFaktor, 0) 
    from Sales.DarkhastFaktor
    where DarkhastFaktor= @DarkhastFaktor

    if @Mablagh - @SumMablagh < -1
      return 0

    return 1
end
4

1 回答 1

3

删除操作不强制检查约束,请参阅http://msdn.microsoft.com/en-us/library/ms188258.aspx

在 DELETE 语句期间不验证 CHECK 约束。因此,对具有某些类型的检查约束的表执行 DELETE 语句可能会产生意想不到的结果。

编辑 - 要回答您有关解决方法的问题,如果您的函数调用显示不变量已损坏,您可以使用删除触发器回滚。

编辑#2 - @reticent,如果你要添加行,那么检查约束调用的函数实际上应该看到行。如果没有,检查约束将毫无用处。这是一个简单的例子,你会发现前 2 次插入成功,而第三次插入失败,正如预期的那样:

create table t1 (id int)
go
create function t1_validateSingleton () 
returns bit
as
begin
declare @ret bit
set @ret = 1
if exists (
    select count(*)
    from t1
    group by id
    having count(*) > 1
)
begin
    set @ret = 0
end
return (@ret)
end
go
alter table t1
add constraint t1_singleton
    check (dbo.t1_validateSingleton()=1)
go
insert t1 values (1)
insert t1 values (2)
insert t1 values (1)
于 2009-05-27T13:26:16.883 回答