UP,最后一句话或者设置成Visible = False状态应当改成或者设置成Enabled = False状态即其它用户把字典设置成不可用状态

解决方案 »

  1.   

    其实即使使用了 约束(Constraints),仍然存在这个问题因为用户可以把字典状态设置成 Visible = False, 相当于软删除但记录在数据库中仍然存在,T表还是不应当使用这个字典记录
      

  2.   

    而且外键在很多时候无法使用,比方T表中有这样的字段(DictType, DictID)当DictType=1时,DictID引用的是 D1的记录
    当DictType=2时,DictID引用的是 D2的记录...这样的 T 表我相信绝大部分人都用过吧
      

  3.   

    --以sql server数据库为例子--要插入记录的各字段值
    declare @vFD1 int,@vFD2 int,@vFDn int
    select @vFD1=1,@vFD2=1,@vFDn=2--插入数据时的处理--出错时回滚事务并终止处理
    set xact_abort on--开启事务,以备进行处理
    begin tran 
    --有效性检查
    if not exists(
    select * from D1 with(XLOCK,PAGLOCK) --用排它锁,防止其他用户对表进行操作
    where D=@vFD1 and Enable = 1)
    begin
    raiserror('违反约束,%d 在D1中无效',1,16,@vFD1)
    rollback tran
    return
    end --有效性检查
    if not exists(
    select * from D2 with(XLOCK,PAGLOCK) --用排它锁,防止其他用户对表进行操作
    where D=@vFD2 and Enable = 1)
    begin
    raiserror('违反约束,%d 在D2中无效',1,16,@vFD2)
    rollback tran
    return
    end --有效性检查
    if not exists(
    select * from Dn with(XLOCK,PAGLOCK) --用排它锁,防止其他用户对表进行操作
    where D=@vFDn and Enable = 1)
    begin
    raiserror('违反约束,%d 在Dn中无效',1,16,@vFDn)
    rollback tran
    return
    end --通过有效性检查,则插入记录
    insert T(vFD1,vFD2,vFD1)
    values(@vFD1,@vFD2,@vFDn)
    commit tran
      

  4.   

    关于对表加锁的方案我也曾想过,但是有几个问题1.有些老式的数据库不支持Lock Table这种语句2.DB2这样的数据库Lock Table 后,其它用户读取记录也不行了
      这给那些正在出报表的用户带来很大的麻烦
      因为一般情况下单据的录入几乎是不间断的,这就意味着
      那些做报表或作查询的客户端几乎无法查询出结果3.我曾试过用软锁(就是自己插入记录到一张表中表示记录被使用
      完成后再删除记录)的方法控制, 但是对于这样的T表,需要插入
      n条记录锁,再删除,效率的确不高4.另外每次插入一条记录都在再次到数据库中检查相关的字典记录是否存在
      实在是导致效率低下的罪魁祸首5.如果数据库本身能提供一个Lock Data [Table Name] [PK id] 这样的功能就好了这个问题的确很麻烦, 我甚至看过Kingdee K3的SP, 也存在不小的漏洞
    (他们是先到每个表中查询记录是否存在,
    但仍然不能排除在查询过后用户删除字典,虽然时间很短)
      

  5.   

    感谢 zj
       with(XLOCK,PAGLOCK) 正是我所要的功能可惜这个只能在Sql2000以上用, 实在很佩服你对MS SQL的了解程度 :)