先大致描述一下问题,这个是出入库单据的复核程序,复核通过后,在台帐(tb_Wh_AccountBook)中增加一条,然后该单据变为审核状态(也就是不能再增加了),复核时先检查是否是已经复核了,如果时的话就跳过。但这个程序偶尔会出现增加了两条数据的现象,我不知道是哪儿出了问题,请高手指正,100分相送!
ALTER PROCEDURE [dbo].[Up_Wh_Bill_Check]
(
@WhBillGuid   uniqueidentifier,
@SDNumber  nvarchar(20),
@CheckStatus nvarchar(10),
@TypeCode nvarchar(10),
@WhPreDate    datetime,
@CheckCode nvarchar(20)=null,
@CheckName nvarchar(30)=null
)
ASdeclare @strSQL nvarchar(4000),@ParmDefinition NVARCHAR(500);  set  @strSQL=''
declare @LastError int
set @LastError=-1 --发生异常
begin tran
if(dbo.Fn_Wh_Bill_ISCheck(@WhBillGuid)=1)
set @LastError=-2 --已被审核
else
begin
if(dbo.Fn_Wh_Bill_HasNull(@WhBillGuid)=0)
begin
if((@TypeCode='E2' or @TypeCode='E8' or @TypeCode='I2' or @TypeCode='I7') And dbo.Fn_OF_ClientForm_IsBlank(@SDNumber)=1)
set @LastError=-3 --已作废
if(@LastError<>-3)
begin
set @strSQL=@strSQL+'INSERT INTO tb_Wh_AccountBook (ClientGuid, WhBillNo, WhABookDate, WhBillType, WhGuid,
 WhNumGuid,WhPos, GoodsGuid,ProdDate, SerialNum, StatusGuid,WareHouseNo,IOCount,Batch,Default1,Default2) '

if(left(@TypeCode,1)='I')
set @strSQL=@strSQL+'SELECT  A.ClientGuid, A.WhBillNo,A.WhPreDate, @WhBillType,A.WhRGuid, 
A.WhRNumGuid, B.WhPosNew, B.GoodsGuid, B.ProdDate, B.SerialNum,B.StatusGuid,B.WareHouseNoNew, 
(ISNULL(B.LargeActualCount*C.MaxConverRate/C.ConverRate, 0)+ ISNULL(B.SmallActualCount*D.MaxConverRate/D.ConverRate, 0)),B.Batch,Default1,Default2' 
else if(left(@TypeCode,1)='E')
set @strSQL=@strSQL+'SELECT  A.ClientGuid, A.WhBillNo,A.WhPreDate, @WhBillType,A.WhRGuid, 
       A.WhRNumGuid, B.WhPosNew, B.GoodsGuid, B.ProdDate, B.SerialNum,B.StatusGuid,B.WareHouseNoNew, 
   -(ISNULL(B.LargeActualCount*C.MaxConverRate/C.ConverRate, 0)+ ISNULL(B.SmallActualCount*D.MaxConverRate/D.ConverRate, 0)),B.Batch,Default1,Default2 ' set @strSQL=@strSQL+' FROM tb_Wh_Bill A 
  INNER JOIN tb_Wh_bill_mx B ON A.WhBillGuid = B.WhBillGuid 
  LEFT  JOIN vw_Bas_GoodsUnit C ON B.UnitLargeGuid = C.GoodsUnitGuid And B.GoodsGuid=C.GoodsGuid  
  LEFT  JOIN vw_Bas_GoodsUnit D ON B.UnitSmallGuid = D.GoodsUnitGuid And B.GoodsGuid=D.GoodsGuid  
             Where A.WhBillGuid=@WhBillGuid '

declare @WhBillType nvarchar(10),@WhBillType1 nvarchar(10)
if(@TypeCode='I0')  set @WhBillType='期初入库'
if(@TypeCode='I2')  set @WhBillType='仓储入库'
if(@TypeCode='IX')  set @WhBillType='其他入库'
if(@TypeCode='E2')  set @WhBillType='配送出库'
if(@TypeCode='EX')  set @WhBillType='其它出库'
if(@TypeCode='MP')  begin set @WhBillType='移位出库'; set @WhBillType1='移位入库' end 
SET @ParmDefinition = N'@WhBillGuid   uniqueidentifier,
@WhBillType nvarchar(10),
@WhBillType1 nvarchar(10)'
--#############################################################################################################################
-- begin tran
begin
EXECUTE sp_executesql @strSQL,@ParmDefinition,@WhBillGuid,@WhBillType,@WhBillType1
if(@@ERROR<>0) goto LastCommit UPDATE tb_Wh_Bill SET CheckStatus=@CheckStatus,WhPreDate=@WhPreDate,CheckCode=@CheckCode,CheckName=@CheckName/**/ Where WhBillGuid=@WhBillGuid
if(@@ERROR<>0) goto LastCommit if(@TypeCode='E2' or @TypeCode='E8' or @TypeCode='I2' or @TypeCode='I7')
begin
set @strSQL=' Select A.GoodsGuid,A.OldCount,B.NewCount From (SELECT B.GoodsGuid, SUM(ISNULL(B.LargeActualCount / C.ConverRate, 0) 
  + ISNULL(B.SmallActualCount / D.ConverRate, 0)) AS OldCount,C.MaxConverRate 
FROM tb_Wh_Bill A  
INNER JOIN tb_Wh_bill_mx B ON A.WhBillGuid = B.WhBillGuid  
LEFT  JOIN vw_Bas_GoodsUnit C ON B.GoodsGuid = C.GoodsGuid AND B.UnitLargeGuid = C.GoodsUnitGuid  
LEFT  JOIN vw_Bas_GoodsUnit D ON B.GoodsGuid = D.GoodsGuid AND B.UnitSmallGuid = D.GoodsUnitGuid 
WHERE (A.SDNumber=@SDNumber) AND (A.CheckStatus=@CheckStatus) AND (A.TypeCode=@TypeCode1) 
GROUP BY B.GoodsGuid,C.MaxConverRate) A 
LEFT JOIN 
(SELECT B.GoodsGuid, SUM(ISNULL(B.LargeActualCount / C.ConverRate, 0)  
  + ISNULL(B.SmallActualCount / D.ConverRate, 0)) AS NewCount 
FROM tb_Wh_Bill A  
INNER JOIN tb_Wh_bill_mx B ON A.WhBillGuid = B.WhBillGuid  
LEFT  JOIN vw_Bas_GoodsUnit C ON B.GoodsGuid = C.GoodsGuid AND B.UnitLargeGuid = C.GoodsUnitGuid  
LEFT  JOIN vw_Bas_GoodsUnit D ON B.GoodsGuid = D.GoodsGuid AND B.UnitSmallGuid = D.GoodsUnitGuid 
WHERE (A.SDNumber=@SDNumber) AND (A.CheckStatus=@CheckStatus) AND (A.TypeCode=@TypeCode2)
GROUP BY B.GoodsGuid) B 
ON A.GoodsGuid=B.GoodsGuid 
Where B.NewCount is null or (A.OldCount-isnull(B.NewCount,0))*A.MaxConverRate>=1'
set @strSQL='Select @LastRows=count(*) From ( '+@strSQL +' ) A '
declare @LastRows  int,@TypeCode1 nvarchar(10),@TypeCode2 nvarchar(10),@OrderType nvarchar(10)
if(@TypeCode='I2') begin set @TypeCode1='I1' ; set @TypeCode2=@TypeCode; set @OrderType='S' end
if(@TypeCode='E2') begin set @TypeCode1='E1' ; set @TypeCode2=@TypeCode; set @OrderType='T' end
if(@TypeCode='E8' or @TypeCode='I7') begin set @TypeCode1='E8' ; set @TypeCode2='I7'     ; set @OrderType='M' end
SET @ParmDefinition = N'@LastRows  int output,
@SDNumber  nvarchar(20),
@CheckStatus nvarchar(10),
@TypeCode1 nvarchar(10),
@TypeCode2 nvarchar(10)'
EXECUTE sp_executesql @strSQL,@ParmDefinition,@LastRows output,@SDNumber,@CheckStatus,@TypeCode1,@TypeCode2
if(@LastRows is null )  begin  set @LastError=10000;  rollback tran;  end declare @OrderStatus nvarchar(10),@StatusID int
if(@OrderType='S')
if(@LastRows=0)
begin set @OrderStatus='完成';     set @StatusID=20; end
else
begin set @OrderStatus='部分到货'; set @StatusID=3; end
else if(@OrderType='T')
if(@LastRows=0)
begin set @OrderStatus='在途';     set @StatusID=6; end
else
begin set @OrderStatus='部分发货'; set @StatusID=3; end

UPDATE tb_OF_OrderForm SET OrderStatus=@OrderStatus,StatusID=@StatusID where GTN=@SDNumber
end
end
--#############################################################################################################################
LastCommit:
set @LastError=@@ERROR
if(@LastError=0)
commit tran
else
rollback tran
end
end
else
set @LastError=-4 --[仓单号]、 [排位号]、[生产日期]、[序列号]、[货物状态]不能为空...
end
LastEnd:
select @LastError

解决方案 »

  1.   

    先在里面多加点print 输出打印SQL 
    看看事件探查器SQL怎么执行的
    F11单步调试存储过程
    我都是这么做的
      

  2.   

    这是早期编程的常见弊端
    把大量的业务逻辑用过程或者规则写在数据库里面。。设置几个print 输出sql,看看什么时候插入的数据
    慢慢调吧
      

  3.   

    未详细阅读,估计是锁的问题,应选择合适的锁定或事务隔离级别,保证多用户操作时不会冲突你的操作,在读单据是否复核时,就应用可重复读锁或排它锁,一直到update后再提交事务.
      

  4.   

    呵呵,哥们,你也是做ERP开发的吗?做ERP开发有时候真是痛苦呀,
    存储过程最少也要上千行的,还很少注释,整一个杀脑细胞呀,呵呵呵楼主,你应该再详细说说这个存储过程的数据流向,要不谁会有心情去揣摩你的意思呀?