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

具有读提交隔离级别和表约束的事务

  •  1
  • reticent  · 技术社区  · 15 年前

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

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

    看起来函数运行时对事务一无所知,函数中的select返回表中事务之前的行。

    有解决方法吗?还是我遗漏了什么?谢谢。

    以下是事务和约束的代码:

    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
    
    1 回复  |  直到 15 年前
        1
  •  3
  •   ahains    15 年前

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

    未验证检查约束 在删除语句期间。因此, 在表上执行DELETE语句 对某些类型的支票 约束可能会产生意外的 结果。

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

    编辑2-@reticent,如果您正在添加行,那么由check约束调用的函数实际上应该看到行。如果没有,那么检查约束将是无用的。下面是一个简单的例子,您将发现前两个插入成功,第三个插入失败,如预期的那样:

    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)